View Full Version : How do you set the font for use with TextOut onto a surface?
Gadget
19-01-2003, 07:22 PM
I am writting text to a DirectX surface and can't seem to change the font...
Any ideas?
Alimonster
19-01-2003, 08:04 PM
If you're using some_surface.GetDC/TextOut/some_surface.ReleaseDC then you can use the stanard GDI functions. In this case, you want to fill out a TLogFont structure. There are a lot of options here for the font name, size, style, and so on -- too many to explain, so have a look at the LOGFONT structure in win32.hlp for more info (as a side note: you can rotate text using the lfOrientation and lfEscapement fields, which is a nice bonus). You then create the font from the LogFont structure using CreateFontIndirect, which returns a HFONT to your new GDI object. You select the object into the DC, draw your text, and select old font back. Something like this [untested]:
[background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]var
FontDesc: TLogFont;
OldFont: HFONT;
NewFont: HFONT;
DC: HDC;
TheText: String;
begin
TheText := 'blah blah blah';
your_surface.GetDC(DC);
with FontDesc do
begin
lfHeight := 12;
lfWidth := 0;
lfEscapement := 0;
lfOrientation := 0;
// and so on for all the rest of the fields!
//...
end;
// create a new font based on the description above
NewFont := CreateFontIndirect(FontDesc);
// use the new font - we select it into the DC and grab the
// the return value, which is the old font
OldFont := SelectObject(DC, NewFont);
SetBKMode(DC, TRANSPARENT);
TextOut(DC, x, y, PChar(TheText), Length(TheText));
// restore the old font
SelectObject(DC, OldFont);
DeleteObject(NewFont);
your_surface.ReleaseDC(DC);
end;
(Consider adding try..finally blocks above if appropriate, of course.)
The above code demonstrates why the GDI sucks ass ;). If you're already using the VCL then you could probably create and use a TCanvas, making your life simpler. Dunno if it'll work like this, but try it anyway:
[background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]var
Canv: TCanvas;
DC: HDC;
begni
Canv := TCanvas.Create;
your_surface.GetDC(DC);
Canv.Handle := DC;
// now use the canvas as normal!
Canv.Font.Name := 'Verdana';
Canv.Font.Size := 12;
Canv.TextOut(10, 20, 'roxx');
your_surface.ReleaseDC(DC);
Canv.Free;
end;
The above is untested and is only useful if you want to use the VCL (which you may or may not, due to the size increase).
Gadget
19-01-2003, 08:36 PM
If you're using some_surface.GetDC/TextOut/some_surface.ReleaseDC then you can use the stanard GDI functions. In this case, you want to fill out a TLogFont structure. There are a lot of options here for the font name, size, style, and so on -- too many to explain, so have a look at the LOGFONT structure in win32.hlp for more info (as a side note: you can rotate text using the lfOrientation and lfEscapement fields, which is a nice bonus). You then create the font from the LogFont structure using CreateFontIndirect, which returns a HFONT to your new GDI object. You select the object into the DC, draw your text, and select old font back. Something like this [untested]:
[background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]var
FontDesc: TLogFont;
OldFont: HFONT;
NewFont: HFONT;
DC: HDC;
TheText: String;
begin
TheText := 'blah blah blah';
your_surface.GetDC(DC);
with FontDesc do
begin
lfHeight := 12;
lfWidth := 0;
lfEscapement := 0;
lfOrientation := 0;
// and so on for all the rest of the fields!
//...
end;
// create a new font based on the description above
NewFont := CreateFontIndirect(FontDesc);
// use the new font - we select it into the DC and grab the
// the return value, which is the old font
OldFont := SelectObject(DC, NewFont);
SetBKMode(DC, TRANSPARENT);
TextOut(DC, x, y, PChar(TheText), Length(TheText));
// restore the old font
SelectObject(DC, OldFont);
DeleteObject(NewFont);
your_surface.ReleaseDC(DC);
end;
(Consider adding try..finally blocks above if appropriate, of course.)
The above code demonstrates why the GDI sucks ass ;). If you're already using the VCL then you could probably create and use a TCanvas, making your life simpler. Dunno if it'll work like this, but try it anyway:
[background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]var
Canv: TCanvas;
DC: HDC;
begni
Canv := TCanvas.Create;
your_surface.GetDC(DC);
Canv.Handle := DC;
// now use the canvas as normal!
Canv.Font.Name := 'Verdana';
Canv.Font.Size := 12;
Canv.TextOut(10, 20, 'roxx');
your_surface.ReleaseDC(DC);
Canv.Free;
end;
The above is untested and is only useful if you want to use the VCL (which you may or may not, due to the size increase).
Thanks for that ;) Worked a treat! I have now pretty much coded a dx replacement for that TRichEdit I was using. Just need to work out how to calculate the width of the text in bytes so I know when to wrap to the next line...
Alimonster
19-01-2003, 08:43 PM
The function TCanvas.TextWidth uses the API function "GetTextExtentPoint32" behind the scenes - it ought to do the trick.
I would use DrawTextEx. You can pass a TRect to it and it will wrap the lines for you.
Gadget
20-01-2003, 01:59 PM
I would use DrawTextEx. You can pass a TRect to it and it will wrap the lines for you.
Thanks a lot guys :)
Will probably have to use DrawTextEx as the component doesn't have a Canvas.
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.