Board index » delphi » binding HFONTS to the Canvas

binding HFONTS to the Canvas

If I map a logical font to a HFONT called hfNewFont, and test it with two
buttons as follows,

procedure TForm1.Button1Click(Sender: TObject);
begin
  SelectObject(canvas.Handle, hfNewFont);
  TextOut(canvas.handle, 200, 200, 'Testline', 8);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 TextOut(canvas.handle, 200, 200, 'Testline', 8);
end;

Button 1 displays the new font OK, but button 2 always displays the original
font, even if it is hit second.
With a bit of messing around, it is seems that if the program returns to the
application message loop, the original font is remapped to the canvas device
context.

I feel I missing something that I should know, but what?

Dave

 

Re:binding HFONTS to the Canvas


is NewFont scoped globally?

Good luck!!
-DrDelphi
http://www.drdelphi.com

Quote
"David Reeve" <drscienti...@powerup.com.au> wrote in message

news:39c8901f@grissom...
Quote
> If I map a logical font to a HFONT called hfNewFont, and test it with two
> buttons as follows,

> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   SelectObject(canvas.Handle, hfNewFont);
>   TextOut(canvas.handle, 200, 200, 'Testline', 8);
> end;

> procedure TForm1.Button2Click(Sender: TObject);
> begin
>  TextOut(canvas.handle, 200, 200, 'Testline', 8);
> end;

> Button 1 displays the new font OK, but button 2 always displays the
original
> font, even if it is hit second.
> With a bit of messing around, it is seems that if the program returns to
the
> application message loop, the original font is remapped to the canvas
device
> context.

> I feel I missing something that I should know, but what?

> Dave

Re:binding HFONTS to the Canvas


Yep!!

Quote
Dr. Delphi <DrDel...@DrDelphi.com> wrote in message

news:8qajjs$kv8$1@bob.news.rcn.net...
Quote
> is NewFont scoped globally?

> Good luck!!
> -DrDelphi
> http://www.drdelphi.com

> "David Reeve" <drscienti...@powerup.com.au> wrote in message
> news:39c8901f@grissom...
> > If I map a logical font to a HFONT called hfNewFont, and test it with
two
> > buttons as follows,

> > procedure TForm1.Button1Click(Sender: TObject);
> > begin
> >   SelectObject(canvas.Handle, hfNewFont);
> >   TextOut(canvas.handle, 200, 200, 'Testline', 8);
> > end;

> > procedure TForm1.Button2Click(Sender: TObject);
> > begin
> >  TextOut(canvas.handle, 200, 200, 'Testline', 8);
> > end;

> > Button 1 displays the new font OK, but button 2 always displays the
> original
> > font, even if it is hit second.
> > With a bit of messing around, it is seems that if the program returns to
> the
> > application message loop, the original font is remapped to the canvas
> device
> > context.

> > I feel I missing something that I should know, but what?

> > Dave

Re:binding HFONTS to the Canvas


"David Reeve" <drscienti...@powerup.com.au> skrev i melding
news:39c8901f@grissom...

Quote
> If I map a logical font to a HFONT called hfNewFont, and test it with
two
> buttons as follows,

> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   SelectObject(canvas.Handle, hfNewFont);
>   TextOut(canvas.handle, 200, 200, 'Testline', 8);
> end;

> procedure TForm1.Button2Click(Sender: TObject);
> begin
>  TextOut(canvas.handle, 200, 200, 'Testline', 8);
> end;

> Button 1 displays the new font OK, but button 2 always displays the
original
> font, even if it is hit second.
> With a bit of messing around, it is seems that if the program returns
to the
> application message loop, the original font is remapped to the canvas
device
> context.

> I feel I missing something that I should know, but what?

I would call what you're doing is a bit "anti-VCL-like", and you will
see some pretty odd sideeffects. The TFont class is nothing ut a wrapper
around a Windows font object, but it actually keeps the data in it's own
fields, it doesn't use Windows' own values. When you set the forn handle
of the Canvas by a SelectObject, Canvas.Font.Handle and Selected HFONT
in Canves.Handle (HDC) isn't the same anymore. At the first occasion
where the TCanvas object needs to get its handles "refreshed", it will
restore the previous font.

What you should rather do, I guess:

  Canvas.Font.Handle:=hfNewFont;

...now I believe it will keep looking the same...;-)
--
Bjoerge Saether
Consultant / Developer
Asker, Norway
bsaether.removet...@online.no (remove the obvious)

Re:binding HFONTS to the Canvas


Quote
Bj?rge S?ther <REMOVE_bsaether@THIS_online.no> wrote in message

news:zZcy5.4935$mq2.81248@news1.online.no...

Quote
> "David Reeve" <drscienti...@powerup.com.au> skrev i melding
> news:39c8901f@grissom...
> > If I map a logical font to a HFONT called hfNewFont, and test it with
> two
> > buttons as follows,

> > procedure TForm1.Button1Click(Sender: TObject);
> > begin
> >   SelectObject(canvas.Handle, hfNewFont);
> >   TextOut(canvas.handle, 200, 200, 'Testline', 8);
> > end;

> > procedure TForm1.Button2Click(Sender: TObject);
> > begin
> >  TextOut(canvas.handle, 200, 200, 'Testline', 8);
> > end;

> > Button 1 displays the new font OK, but button 2 always displays the
> original
> > font, even if it is hit second.
> > With a bit of messing around, it is seems that if the program returns
> to the
> > application message loop, the original font is remapped to the canvas
> device
> > context.

> > I feel I missing something that I should know, but what?

> I would call what you're doing is a bit "anti-VCL-like", and you will
> see some pretty odd sideeffects. The TFont class is nothing ut a wrapper
> around a Windows font object, but it actually keeps the data in it's own
> fields, it doesn't use Windows' own values. When you set the forn handle
> of the Canvas by a SelectObject, Canvas.Font.Handle and Selected HFONT
> in Canves.Handle (HDC) isn't the same anymore. At the first occasion
> where the TCanvas object needs to get its handles "refreshed", it will
> restore the previous font.

> What you should rather do, I guess:

>   Canvas.Font.Handle:=hfNewFont;

> ...now I believe it will keep looking the same...;-)
> --
> Bjoerge Saether
> Consultant / Developer
> Asker, Norway
> bsaether.removet...@online.no (remove the obvious)

Thanks......  thats a much better solution as it keeps the VCL happy. Also,
the VCL frees up the replaced HFONT object for you.

However, I have come across an instability when I'm doing all this font
modifying stuff. Basically, the problem seems to lie with the definition of
Window's LOGFONT versus Delphi's TLogfont structures.

If I do something like,

var
    tempFont: TLogfont;

begin
    GetObject(canvas.font.handle, SizeOf(tempFont), @tempFont);
    with tempFont do
    begin
        lfEscapement := 900;
        lfOrientation := 900;
    end;
    canvas.font.handle := CreateFontIndirect(tempFont);
  end;

The results are unpredictable, and it seems to depend upon what was in the
piece of memory @tempFont. For insatnce, if you fill this block before
calling GetObject like so,
    FillChar(tempFont, SizeOf(tempFont),0)
the results vary according to what you fill it with!

Has anyone come across this?

regards

Dave

Re:binding HFONTS to the Canvas


Quote
David Reeve <drscienti...@powerup.com.au> wrote in message

news:39cbdc8e@grissom...

Quote

> Bj?rge S?ther <REMOVE_bsaether@THIS_online.no> wrote in message
> news:zZcy5.4935$mq2.81248@news1.online.no...
> > "David Reeve" <drscienti...@powerup.com.au> skrev i melding
> > news:39c8901f@grissom...
> > > If I map a logical font to a HFONT called hfNewFont, and test it with
> > two
> > > buttons as follows,

> > > procedure TForm1.Button1Click(Sender: TObject);
> > > begin
> > >   SelectObject(canvas.Handle, hfNewFont);
> > >   TextOut(canvas.handle, 200, 200, 'Testline', 8);
> > > end;

> > > procedure TForm1.Button2Click(Sender: TObject);
> > > begin
> > >  TextOut(canvas.handle, 200, 200, 'Testline', 8);
> > > end;

> > > Button 1 displays the new font OK, but button 2 always displays the
> > original
> > > font, even if it is hit second.
> > > With a bit of messing around, it is seems that if the program returns
> > to the
> > > application message loop, the original font is remapped to the canvas
> > device
> > > context.

> > > I feel I missing something that I should know, but what?

> > I would call what you're doing is a bit "anti-VCL-like", and you will
> > see some pretty odd sideeffects. The TFont class is nothing ut a wrapper
> > around a Windows font object, but it actually keeps the data in it's own
> > fields, it doesn't use Windows' own values. When you set the forn handle
> > of the Canvas by a SelectObject, Canvas.Font.Handle and Selected HFONT
> > in Canves.Handle (HDC) isn't the same anymore. At the first occasion
> > where the TCanvas object needs to get its handles "refreshed", it will
> > restore the previous font.

> > What you should rather do, I guess:

> >   Canvas.Font.Handle:=hfNewFont;

> > ...now I believe it will keep looking the same...;-)
> > --
> > Bjoerge Saether
> > Consultant / Developer
> > Asker, Norway
> > bsaether.removet...@online.no (remove the obvious)

> Thanks......  thats a much better solution as it keeps the VCL happy.
Also,
> the VCL frees up the replaced HFONT object for you.

> However, I have come across an instability when I'm doing all this font
> modifying stuff. Basically, the problem seems to lie with the definition
of
> Window's LOGFONT versus Delphi's TLogfont structures.

> If I do something like,

> var
>     tempFont: TLogfont;

> begin
>     GetObject(canvas.font.handle, SizeOf(tempFont), @tempFont);
>     with tempFont do
>     begin
>         lfEscapement := 900;
>         lfOrientation := 900;
>     end;
>     canvas.font.handle := CreateFontIndirect(tempFont);
>   end;

> The results are unpredictable, and it seems to depend upon what was in the
> piece of memory @tempFont. For insatnce, if you fill this block before
> calling GetObject like so,
>     FillChar(tempFont, SizeOf(tempFont),0)
> the results vary according to what you fill it with!

> Has anyone come across this?

> regards

> Dave

Doing so reading up on the matter (which I should have done first, as
usual), I find the rotation can only be applied to true type fonts. Sure
enough, using true types things go smoothly. But what has this got to do
with GetObject()? Perhaps everything, perhaps not!

regards,

Dave

Re:binding HFONTS to the Canvas


In article <39cbdc8e@grissom>, "David Reeve" <drscienti...@powerup.com.au>
writes:

Quote
>However, I have come across an instability when I'm doing all this font
>modifying stuff. Basically, the problem seems to lie with the definition of
>Window's LOGFONT versus Delphi's TLogfont structures.

>If I do something like,

>var
>    tempFont: TLogfont;

>begin
>    GetObject(canvas.font.handle, SizeOf(tempFont), @tempFont);
>    with tempFont do
>    begin
>        lfEscapement := 900;
>        lfOrientation := 900;
>    end;
>    canvas.font.handle := CreateFontIndirect(tempFont);
>  end;

>The results are unpredictable, and it seems to depend upon what was in the
>piece of memory @tempFont. For insatnce, if you fill this block before
>calling GetObject like so,
>    FillChar(tempFont, SizeOf(tempFont),0)
>the results vary according to what you fill it with!

>Has anyone come across this?

I have a faint recollection that it may be something to do with font caching,
which I believe meant that one must operate at the windows level (ie not change
font i Delphi but with Windows API calls) because Delphi refreshed its cache
from that level (that may be bad memory garbage though <g>). I have had
repeatable results for an italic landscape MS Comic Sans font (from some rather
old code) with :-

function HRotateFont : HFont;
var
  LandFont: TLogFont;   { landscape font for headers}
const
  PointSize : integer = 7;
  PointsPerInch : integer = 72;
begin
  fillchar(LandFont, sizeof(TLogFont), 0); {clear mem}
  with LandFont do begin
    lfHeight := -MulDiv(PointSize,
                        GetDeviceCaps(Printer.Handle, LOGPIXELSY),
                        PointsPerInch);
    lfEscapement := 900;   // 90 deg * 10
    lfOrientation := lfEscapement;  // must be same
    lfWeight := FW_NORMAL;
    lfOutPrecision := OUT_TT_PRECIS;
    lfItalic := byte(true);
    lfFaceName :='Comic Sans MS';
    lfPitchAndFamily := FF_SWISS;
  end;
  Result := CreateFontIndirect(LandFont);
end;

 . . . and to use it . . .

      if PrintRoles then begin  // roles were printed landscape on a label
        if HLandFont = 0 then
          {create rotated font for roles print out}
          HLandFont := HRotateFont();
        {change font orientation, saving previous font}
        HPortFont := SelectObject(Printer.Canvas.Handle, HLandFont);
        PrintStr := ... etc ...
        Printer.Canvas.TextOut(... etc ..., PrintStr);
        {revert font orientation}
        SelectObject(Printer.Canvas.Handle, HPortFont);
      end; {if PrintRoles}

 . . . and later . . .

    if HLandFont > 0 then
       DeleteObject(HLandFont);   // Free the rotated font

I think also I found that if the created landscape font was not immediately
allocated to a canvas, it somehow got "lost". That sounds totally illogical
though <g>.

Alan Lloyd
alangll...@aol.com

Other Threads