Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Printing bitmaps in Delphi 4

Posted on 1999-07-07
21
Medium Priority
?
330 Views
Last Modified: 2010-04-06
I can't seem to be able to print bitmaps reliably in Delphi 4. My code is as follows:

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  i : integer;
  bm : tbitmap;
begin
  printer.BeginDoc;

  for i := 1 to 20 do
  begin
    bm := tbitmap.create;
    try
      bm.handletype := bmDIB;
      bm.pixelformat := pf32bit;
      bm.width := 1000;
      bm.height := 100;
      bm.canvas.font.color := clBlack;
      bm.canvas.font.size := 40;
      bm.canvas.font.name := 'ARIAL';
      bm.canvas.textout(0, 0, 'Using tbitmap ' +inttostr(i));

      printer.canvas.textout(1000, 100 + 100*i, 'Using textout ' + inttoStr(i));
      printer.Canvas.Draw(100,100 + 100 * i,bm);
    finally
      bm.free;
    end;
  end;

  printer.EndDoc;
end;

The printout should have two columns, the first with text printed via a tbitmap, the second with text printed directly. However, bitmaps in the first column seem to randomly go missing. I've tried using an HP Laserjet 6L and an IBM 4039 LaserPrinter Plus both  with the same result. Using Acrobat 2.11 writer causes a GPF.

Is there something wierd going on here, or am I being totally stupid?

Any help would be greatly appreciated.

Regards,

Jon.
0
Comment
Question by:jonwcroft
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 6
  • 4
  • +2
21 Comments
 
LVL 7

Expert Comment

by:RBertora
ID: 1386908
it sounds like something is screwing up there, why don't you toss in a
 except on excetption do
 begin
   showmessage('haha!');
  end;
 end;
 
forget the finally freeing for now... if haha is displayed then use the trace to see which line is bombing out...
 
if this is the case then write another comment and tell us which one...

0
 

Author Comment

by:jonwcroft
ID: 1386909
RBertora:

Thank-you for your comment.

The crash is a white box "An error has occurred in your application" job. Certainly not trapped by "try except" & "on except do"

The line that causes the crash is the "printer.canvas.draw(100, 100 + 100 * i, bm)" - I know this because the program does not crash when the line is removed. Don't forget that the program only crashes when printing to Acrobat - bitmaps dissappear when printing to normal printers.

This is only a simple little program that you can cut and paste into a new delphi 3/4 application - why don't you try it?

Regards,

Jon.

0
 
LVL 2

Expert Comment

by:CalvinDay
ID: 1386910
I could not even run this in Run mode. I had to step through it. The first time, it showed 2-6 and 12-20. The second time, I got 2-20. Some process is not quite finished after the Create. I added a Application.Processmessages; line after the create and all worked fine.

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:jonwcroft
ID: 1386911
CalvinDay:

Thank-you for your answer.

I tried your suggestion and got it to work only by adding "processmessages" before and after the printer.canvas.draw line.

I want to reopen this question because I'm sure that there must be a better answer than just chucking in processmessages everywhere (particularly as this will routine will become part of a very large multithreading application) and I'm not totally convinced that it will work with a large veriety of bitmaps.

Obviously the VCL does not work completely propperly when printing DIBS: do Borland fix bugs like these and supply patches?

If no-one comes up with a better answer within a few days then I will give you the points.

0
 
LVL 2

Expert Comment

by:CalvinDay
ID: 1386912
Good point. I have seen this happen when the setting the pallete. It seems to trigger a flurry of messages.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386913
0
 

Author Comment

by:jonwcroft
ID: 1386914
Epsylon:

Thank-you for your comment.

In fact I have tried something simillar using StretchDIBits with some success.

But what is the point of setting TBITMAP.HANDLETYPE to bmDIB if not so that you can print reliably? I have checked the VCL source and can not find any trace of StretchDIBits.

Lets face it: this is a dirty great big omission in the VCL: bmDIBs have not been implemented propperly in the TBITMAP.DRAW method.

I shall award the points to CALVINDAY unless someone can explain the point of HANDLETYPE=bmDIB, or can deny or confirm that this is a VCL omission/bug.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386915
Quoted from the Delphi help:

TBitmap.HandleType "Indicates whether the bitmap is a DDB, Device Dependent Bitmap, or a DIB, Device Independent Bitmap."


bmDDB:

This means that the actual data stored in the bitmap is in a format that is asociated with a certain device. Some devices can handle it, others not.

bmDIB:

This means that the actual data stored in the bitmap is universal. Whatever device wants to use the bitmap should convert it for its own use. TPrinter provides a canvas for that purpose.


Did you try TCanvas.StretchDraw?
See TBitmap.PixelFormat := pfDevice too....

Epsylon.
0
 

Author Comment

by:jonwcroft
ID: 1386916
Epsylon:

Thank-you for your comment. Yes, I have read the same section of help several times myself.

A note for Borland:
Why should I care how bitmaps are stored? I just want them to work.

I understood that the practical upshot of using bmDIBs are that they print correctly, and that bmDDBs are faster.

I would have thought that the tbitmap should be able to detect an incompatible canvas and convert itself to a DIB should it need to. Whatever they should always work.

This not my question. My problem is that even bmDIBs, randomly don't work! Also when trying StretchDraw, or whatever pixelformat.

CalvinDay:
Repost your orriginal answer tomorrow, and I'll give you the points.
0
 
LVL 15

Expert Comment

by:simonet
ID: 1386917
Is this question closed? I mean: has a solution already been found?

Alx
0
 
LVL 2

Accepted Solution

by:
CalvinDay earned 400 total points
ID: 1386918
thanks
0
 
LVL 2

Expert Comment

by:CalvinDay
ID: 1386919
simonet,
The question is still really not answered. I just gave jonwcroft a hack (application.processmessages) to keep his problem from happening. I don't think we really know why it happens.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386920
Give this one a shot. It uses GetDIBSizes and GetDIB:

procedure PrintBitmap(BitmapOut : TBitmap);
var
  Info: PBitmapInfo;
  InfoSize: Integer;
  Image: Pointer;
  ImageSize: DWORD;
  YPos   : integer;
begin
  inherited;
  with BitmapOut do
  begin
    { Call GetDIBSizes to get the Info header and image size }
    GetDIBSizes(Handle, InfoSize, ImageSize);
    { Allocate memory for the info header }
    Info := AllocMem(InfoSize);
    try
      { Allocate memory for the Image }
      Image := AllocMem(ImageSize);
      try
        { Retrieve the bitmap bits in device-independent format, the
          palette  adn the Info header }
        GetDIB(Handle, Palette, Info^, Image^);
        with Info^.bmiHeader do begin
        { Call StretchDIBits to print the bitmap }
          Printer.title := 'Resistências dos Materiais - Diagramas';
          Printer.BeginDoc;
          Printer.title := 'Resistências dos Materiais - Diagramas';
          YPos := PrintHeader;
          try
            StretchDIBits(Printer.Canvas.Handle, 0, YPos, Printer.PageWidth,
              Printer.PageHeight - YPos, 0, 0, biWidth, biHeight, Image, Info^,
              DIB_RGB_COLORS, SRCCOPY);
          finally
            Printer.EndDoc;
          end;
        end;
      finally
        FreeMem(Image, ImageSize); // Free the memory allocated
      end;
    finally
      FreeMem(Info, InfoSize);
    end;
  end;
end;


Cheers,

Epsylon.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386921
0
 
LVL 15

Expert Comment

by:simonet
ID: 1386922
Epsylon,

The reason I asked if this question had already been answered is because I was planning on posting that code you just posted.

That's code I wrote for an application I developed years ago and had just used it to answer another similar question. You didn't even bother to remove the sentences that are in Portuguese and make up the header on the printed bitmap.

I relly resent you posting this code.

Alex
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386923
You are right, Alex, I should have at least have mentioned your name. But as you say this question is CalvinDay's and I was just collecting stuff on this subject to get it all solved. I'm sorry about it. Hope you are not to mad at me.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386924
Jon, please treat that comment as if it came from Alex.
0
 

Author Comment

by:jonwcroft
ID: 1386925
Thanks for your help guys.

In the end I used the StretchDIBits thing, and got it to work reliably.

As far as HANDLETYPE = bmDIB is concerned, I shall lodge a bug report with Borland.... (I wonder if they'll take any notice).

Oh bugger, I guess I'll have to help loads of other people before I can post another tricky one..
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386926
You can't use points you get by answering questions for asking your own questions.
0
 

Author Comment

by:jonwcroft
ID: 1386927
eh?

So what is the point of the points system? Can you cash your points in for money or something?


0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1386928
Nope!
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Suggested Courses

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question