Working on a program where user can change the fonts of controls.
I need to be able to obtain the same info that is returned by the FONTREQUEST command in order to see their changes.
I have found that using API GetTextMetrics with the TEXTMETRIC structure I can almost get there.
The only thing that is not straightforward is the height.
If I set a font size to 20 I get a number back like 24
A 40 gets me 54.
Also using GETTEXTSIZE 40 will get me a 54.
I suspect that a variation of this might have something to do with the next step but I'm not sure:
-MulDiv(height,GetDeviceCaps(whdc,90 ),72)
Larry
Larry,
Fonts are specified in points, 1 point = 1/72 of an inch.
logical units = -MulDiv(height, GetDeviceCaps(whdc,90 ),72)
or
pixels = -( points * pixels per inch Y) / 72 )
So GetDeviceCaps is returning the pixels per inch in the Y direction of the device. Which is why it works for both printers and CRT's.
That formula is returning the height of the font in logical units (pixels) for a logfont UDT, which is where I am assuming you are getting it from. A little math will get you back to the other direction, given a logical unit size...
lu*72 = height*ppiY
-(lu*72)/ppiY = height
So in the mapping mode used by Emergence windows (MM_TEXT) where 1 pixel = 1 logical unit you can assume that:
points = -((pixels * 72) / GetDeviceCaps(whdc,90 ))
Assuming I solved correctly for height, a bit tired at the moment ;)
Of course an easier way would be to:
Send the control the WM_GETFONT message
Use the GetObject API functionto retrieve the LOGFONT udt from the font handle
and then lf.lfHeight is the pixels.
Paul.
Quote from: Paul Turley on August 14, 2008, 09:47:52 PM
Of course an easier way would be to:
Send the control the WM_GETFONT message
Use the GetObject API functionto retrieve the LOGFONT udt from the font handle
and then lf.lfHeight is the pixels.
I tried that for over 3 hours and never could get it to work.
That's why I was taking this route.
I'll start over with the logfont way.
This is the program I was using with gettextmetrics
declare "gdi32",GetTextColor(hdc:int),int
declare "gdi32",GetTextFaceA(hdc:int,nCount:int,lpFaceName:string),int
declare import, _GetTextMetrics alias GetTextMetricsA(hdc:INT, lpMetrics:TEXTMETRIC),INT
DECLARE "gdi32",GetDeviceCaps(hdc:INT, nIndex:INT),INT
TYPE TEXTMETRIC
DEF tmHeight:INT
DEF tmAscent:INT
DEF tmDescent:INT
DEF tmInternalLeading:INT
DEF tmExternalLeading:INT
DEF tmAveCharWidth:INT
DEF tmMaxCharWidth:INT
DEF tmWeight:INT
DEF tmOverhang:INT
DEF tmDigitizedAspectX:INT
DEF tmDigitizedAspectY:INT
DEF tmFirstChar:CHAR
DEF tmLastChar:CHAR
DEF tmDefaultChar:CHAR
DEF tmBreakChar:CHAR
DEF tmItalic:CHAR
DEF tmUnderlined:CHAR
DEF tmStruckOut:CHAR
DEF tmPitchAndFamily:CHAR
DEF tmCharSet:CHAR
ENDTYPE
TEXTMETRIC yy
openconsole
def w1:window
def fn:string
int h,fh
OPENWINDOW w1,0,0,10,10,@MINBOX,0,"Get Font Testr",&hnd
SETFONT w1, "Terminal", 20, 700, @SFITALIC | 0x00FF0000
print "SETFONT height ",20
h=gethdc(w1)
_GetTextMetrics(h, yy)
print " tmHeight (returned height) " ,yy.tmHeight
fh = ((yy.tmHeight * 72) / GetDeviceCaps(h,90 ))
print "calc font height ",fh
if yy.tmItalic = 0xff then print "Italic"
if yy.tmUnderlined = 0xff then print "Underlined"
if yy.tmStruckOut = 0xff then print "StruckOut"
frontpen w1,rgb(0,0,0)
GetTextFaceA(h,255,fn)
print GetTextColor(h)," ",fn
print
int tWidth, tHeight
GETTEXTSIZE w1, "Tell me", tWidth, tHeight
print "GETTEXTSIZE Height ", tHeight
releasehdc w1,h
waituntil w1=0
closeconsole
end
sub hnd
select @class
case @idclosewindow
closewindow w1
endselect
return
endsubLarry
DECLARE IMPORT,GetObjectA(hObject as UINT,cbSize as INT,pLog as POINTER),INT
DEF lf as LOGFONT
hfont = SendMessage(hControl, WM_GETFONT,0,0)
GetObjectA(hFont,LEN(LOGFONT),lf)
Of course you can also:
hfont = SendMessage(win, WM_GETFONT,0,0, control_id)
Paul.
eureka!
I was only one line away from getting it.
Thanks again Paul
BTW,
Am I correct in assuming that you can't resize rgnbuttons on the fly because of the bitmaps not being resized inside the control?
Larry
Yes you can resize them. If you look at the code I use StretchBlt for the bitmaps if the size of the control is different from the size of the bitmap.
What I did with your rgn demo was changed the INITIAL size of the button and it didn't look correct. (1/2 a button etc)
Anyway, with my get font problem I thougt I had it, but no cigar.
I get a height of 0 with this.
DECLARE IMPORT,GetObjectA(hObject as UINT,cbSize as INT,pLog as POINTER),INT
openconsole
def w1:window
SETID "WM_GETFONT",0x31
uint hfont
DEF lf as LOGFONT
OPENWINDOW w1,0,0,10,10,@MINBOX,0,"Get Font Testr",&hnd
SETFONT w1, "Terminal", 20, 700, @SFITALIC | 0x00FF0000
print "SETFONT height ",20
hfont = SendMessage(w1,@WM_GETFONT,0,0)
print hfont
print GetObjectA(hFont,LEN(LOGFONT),lf)
print "returned height ",lf.lfHeight
waituntil w1=0
closeconsole
end
sub hnd
select @class
case @idclosewindow
closewindow w1
endselect
return
endsub
I know it's something stupid I'm doing wrong but I just can't see it.
Larry
A regular window doesn't respond to WM_GETFONT, because windows don't have fonts only device contexts do. Unless of course you code it to do so. The handle to the windows font is directly accessible from the window UDT.
win.hfont
Which is where I store the font handle. Probably why you are confused because I do associate a font with the window, which is automatically set in the device context when you print, or use GetHDC.
If you are creating a custom control, from a window base, then it is a good idea to respond to WM_GETFONT by returning the primary font used by your control. If you are using a subclassed button control then it already responds to the WM_GETFONT message correctly.
Paul.
And of course the requisite link to the description of WM_GETFONT. Which can return NULL by the way.
http://msdn.microsoft.com/en-us/library/ms632624(VS.85).aspx
This works although there are rounding errors.
set font size to 10 and getfont gives you a 9
others around there don't have error.
DECLARE IMPORT,GetObjectA(hObject as UINT,cbSize as INT,pLog as POINTER),INT
DECLARE "gdi32",GetDeviceCaps(hdc:INT, nIndex:INT),INT
openconsole
def w1:window
SETID "WM_GETFONT",0x31
uint hfont
int fh
DEF lf as LOGFONT
OPENWINDOW w1,0,0,10,10,@MINBOX,0,"Get Font Testr",&hnd
CONTROL w1,@BUTTON,"",20,20,10,20,0x50008000,601
SETFONT w1, "Terminal", 12, 700, @SFITALIC | 0x00FF0000,601
print "SETFONT height ",12
hfont = SendMessage(w1,@WM_GETFONT,0,0,601)
print hfont
print GetObjectA(hFont,LEN(LOGFONT),lf)
print "returned height ",lf.lfHeight
h=gethdc(w1)
fh = -((lf.lfHeight * 72) / GetDeviceCaps(h,90 ))
releasehdc w1,h
print "calc font height ",fh
waituntil w1=0
closeconsole
end
sub hnd
select @class
case @idclosewindow
closewindow w1
endselect
return
endsub
Thanks for bearing with me.
Larry
Thats because "Terminal" is a bitmap font, and not a true type font. It only exists in sizes 5, 6, 9, 12 and 14. Also you can make your calculations a bit more accurate using:
-((lf.lfHeight * 72.0) / GetDeviceCaps(h,90 ))
Othewise it is a pure integer division
Use Courier New, Arial or Lucida Console if you want a monospaced font in any size.
Paul.
Thanks again.
You never cease to amaze me.
Larry
Quote
What I did with your rgn demo was changed the INITIAL size of the button and it didn't look correct. (1/2 a button etc)
It only works if the button doesn't use a region, just the hot tracking and normal bitmaps. Which is really just an oversight on my part, the code I was writing for my contract work needed scalable buttons, but they were not using regions to change the shape of the button...so I only added the stretchblt code in one place.
It's something I'll have to address in the next update.
Paul.