The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: zemtex on July 23, 2011, 09:45:51 PM

Title: Set font of window using code, not resource files
Post by: zemtex on July 23, 2011, 09:45:51 PM
Do I have to use CreateFont and WM_SETFONT to set a default font on my window and all controls within it?

Can't I load a preset font that is commonly used in windows or do I have to run through the rather large CreateFont function?
Title: Re: Set font of window using code, not resource files
Post by: Gunner on July 23, 2011, 10:16:39 PM
You have to set the font for each control and window otherwise windows will use the default system font...

Easy way to do it... create a callback like so:
SetControlFonts proc hWin:DWORD, lParam:DWORD
invoke SendMessage, hWin, WM_SETFONT, HANDLE TO YOUR FONT HERE, FALSE

mov eax, TRUE
ret
SetControlFonts endp


next, in each WM_CREATE AFTER all the controls have been created, call
; ##### set all fonts
invoke EnumChildWindows, hWin, addr SetControlFonts, NULL


now if you want underline, bold, diff size, you will have to set those controls after your call to enumchildwindows
Title: Re: Set font of window using code, not resource files
Post by: zemtex on July 23, 2011, 10:32:15 PM
Thanks. EnumChildWindow is a useful function  :U but as far as I know WM_SETFONT sets font for all controls in the dialog automatically, I don't think it is neccesary to use EnumChildWindow

(I am merely reading ms docs, I haven't actually checked if it is so, but I appreciate your help, you are probably right, I merely speculate here based on an inconsistent ms documentation  :U
I should proibably just trust your words and go for it, but I have a habit of always reading documentation before I try to do something, even with samples)
Title: Re: Set font of window using code, not resource files
Post by: dedndave on August 28, 2011, 12:46:03 AM
that's a nice little trick, Rob....
....now that i understand why it's so useful   :P

:U

i passed hFont to the EnumChildProc as lParam   :bg

SetControlFonts PROTO :HWND,:LPARAM
;
;

;WM_INITDIALOG

        mov     eax,sizeof NONCLIENTMETRICS
        mov     ncm.cbSize,eax
        INVOKE  SystemParametersInfo,SPI_GETNONCLIENTMETRICS,eax,addr ncm,NULL
        INVOKE  CreateFontIndirect,addr ncm.lfMessageFont
        mov     hDlgFont,eax
        INVOKE  EnumChildWindows,hWnd,SetControlFonts,eax
;
;
;********************************************************************

        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

SetControlFonts PROC hWnd:HWND,lParam:LPARAM

        push    TRUE
        INVOKE  SendMessage,[esp+20],WM_SETFONT,[esp+16],0
        pop     eax
        ret     8

SetControlFonts ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

;********************************************************************
Title: Re: Set font of window using code, not resource files
Post by: dedndave on August 28, 2011, 01:17:23 AM
in fact, i may pass a pointer to the stack frame and use it to set font, text, control sizes - the whole ball of wax - lol
Title: Re: Set font of window using code, not resource files
Post by: Gunner on August 28, 2011, 01:35:59 AM
Yeah, I can see many uses for it.  Makes it real easy to use the whole ball of wax!  :toothy
Title: Re: Set font of window using code, not resource files
Post by: dedndave on August 28, 2011, 01:48:33 AM
i have another little problem
i would like to store a stack frame pointer from the creating routine for access in DlgProc
i am thinking of creating one or two "dummy" controls to store the address   :bg
i can use some of the ID bits and some of the style bits
i am trying to avoid using any global variables

it may not be necessary - we'll see how it goes
Title: Re: Set font of window using code, not resource files
Post by: qWord on August 28, 2011, 01:52:13 AM
Quote from: dedndave on August 28, 2011, 01:48:33 AMi am trying to avoid using any global variables
use the class and window extra memory (WNDCLASSEX.cbClsExtra/cbWndExtra)
Title: Re: Set font of window using code, not resource files
Post by: Gunner on August 28, 2011, 01:56:35 AM
Why use "dummy" controls?  You don't have to create un-needed controls.  Every control has "extra" memory - GWL_USERDATA  Just pick some controls to store the addresses and use SetWindowLong

invoke SetWindowLong, CONTROL_HANDLE, GWL_USERDATA, ADDRESS_HERE

then just use GetWindowLong to get that stored address.  Simple storage for addresses/pointers  :bg
Title: Re: Set font of window using code, not resource files
Post by: dedndave on August 28, 2011, 02:03:14 AM
ahhhhhh
thanks guys   :U

i wasn't liking the other method - it sounded really hoakie - lol
it hadn't dawned on me to use the extra memory of the dialog box - DOH !!!
Title: Re: Set font of window using code, not resource files
Post by: Tedd on August 28, 2011, 01:47:09 PM
Quote from: zemtex on July 23, 2011, 09:45:51 PM
Can't I load a preset font that is commonly used in windows or do I have to run through the rather large CreateFont function?

invoke GetStockObject, DEFAULT_GUI_FONT
mov hFont,eax

Title: Re: Set font of window using code, not resource files
Post by: baltoro on August 29, 2011, 09:01:11 PM
ZEMTEX,   
If you can get a copy of Charles Petzold's, Programming Windows, Fifth Edition, 1998 (http://www.charlespetzold.com/pw5/index.html), you will find it describes almost every aspect of Windows programming, clearly and comprehensively. It's written for C and C++ programmers, and, it comes with a CD that has numerous examples of windows programs,...both the source code and the compiled programs. If you have a version of Visual Studio, you can load the source files directly and compile immediately.
...It's,...like,...cooler than Dave,...almost,... :eek
Title: Re: Set font of window using code, not resource files
Post by: raleeper on September 01, 2011, 10:59:31 AM
I'm probably missing something basic, but can't you just have a single LOGFONT structure and a single code block or procedure:

    invoke    CreateFontIndirect,logfont
    invoke    SelectObject, hdc, eax
    mov       [hfont], eax


and when you want change fonts, just write the new values into the structure and call or use the code?

I assume the handle remains valid after the structure used to create it is changed or destroyed.

Thanks, Robert

Title: Re: Set font of window using code, not resource files
Post by: Tedd on September 01, 2011, 11:36:57 AM
Yes, once you have the font handle, the logfont structure is no longer needed - so you can reuse it as you wish.
If you're changing fonts, remember to delete the previous font first :wink
Title: Re: Set font of window using code, not resource files
Post by: raleeper on September 01, 2011, 12:27:52 PM
Quote from: Tedd on September 01, 2011, 11:36:57 AM
Yes, once you have the font handle, the logfont structure is no longer needed - so you can reuse it as you wish.
If you're changing fonts, remember to delete the previous font first :wink

What happens if you don't delete it, but just select another into the device context, then perhaps a character later, select the first back in (using its handle, which you've saved)?

Another question:

Can you create all the fonts in winmain and save the handles globally, so you don't have to recreate them in the windows procedure?
Title: Re: Set font of window using code, not resource files
Post by: ToutEnMasm on September 01, 2011, 12:30:47 PM
There is  windows common dialog box who show you the list of fonts existing in your system.
Choose one and the dialog return you a structure with which you can recreate the font.
Coudn't be more simple.
here is  sample:
Quote
   CreeFont PROC
         Local  retour:DWORD
         Local  logfont:LOGFONT

   mov logfont.lfHeight,-19
   mov logfont.lfWidth,0
   mov logfont.lfEscapement,0
   mov logfont.lfOrientation,0
   mov logfont.lfWeight,400
   mov logfont.lfItalic,0
   mov logfont.lfUnderline,0
   mov logfont.lfStrikeOut,0
   mov logfont.lfCharSet,0
   mov logfont.lfOutPrecision,3
   mov logfont.lfClipPrecision,2
   mov logfont.lfQuality,1   ;0 DEFAULT_QUALITY ,1 DRAFT_QUALITY,2 PROOF_QUALITY
   mov logfont.lfPitchAndFamily,34
   jmp overtext
   NamedFont db "Segoe UI",0      ;LOGFONT
   overtext:
   invoke lstrcpy,addr logfont.lfFaceName,addr NamedFont
   INVOKE     CreateFontIndirect, addr logfont      ;Modifie    logfont:LOGFONT
   mov     retour, eax   ;retourne Hfonte

   ;invoke SendMessage,Hcontrole,WM_SETFONT,Hfonte,FALSE
   FindeCreeFont:
   mov eax,retour
   ret
CreeFont endp

Title: Re: Set font of window using code, not resource files
Post by: raleeper on September 01, 2011, 01:45:37 PM
Quote from: ToutEnMasm on September 01, 2011, 12:30:47 PM
There is  windows common dialog box who show you the list of fonts existing in your system.
Choose one and the dialog return you a structure with which you can recreate the font.
Coudn't be more simple.
here is  sample:
Quote
   CreeFont PROC
         Local  retour:DWORD
         Local  logfont:LOGFONT

   mov logfont.lfHeight,-19
   mov logfont.lfWidth,0
   mov logfont.lfEscapement,0
   mov logfont.lfOrientation,0
   mov logfont.lfWeight,400
   mov logfont.lfItalic,0
   mov logfont.lfUnderline,0
   mov logfont.lfStrikeOut,0
   mov logfont.lfCharSet,0
   mov logfont.lfOutPrecision,3
   mov logfont.lfClipPrecision,2
   mov logfont.lfQuality,1   ;0 DEFAULT_QUALITY ,1 DRAFT_QUALITY,2 PROOF_QUALITY
   mov logfont.lfPitchAndFamily,34
   jmp overtext
   NamedFont db "Segoe UI",0      ;LOGFONT
   overtext:
   invoke lstrcpy,addr logfont.lfFaceName,addr NamedFont
   INVOKE     CreateFontIndirect, addr logfont      ;Modifie    logfont:LOGFONT
   mov     retour, eax   ;retourne Hfonte

   ;invoke SendMessage,Hcontrole,WM_SETFONT,Hfonte,FALSE
   FindeCreeFont:
   mov eax,retour
   ret
CreeFont endp


What is that windows common dialog box, and what are Hcontrole and Hfonte?

Would that be

EnumFontFamiliesEx hdc,logfont,fenproc,0,0

with logfont.lfCharSet = DEFAULT_CHARSET, and fenproc the callback?

Thanks, Robert
Title: Re: Set font of window using code, not resource files
Post by: Gunner on September 01, 2011, 02:22:17 PM
If you are going to create a few variations of the same font... Normal, bold, bigger, smaller, then all you have to do is zero out the logfont struc, fill in the info, create the font, save the handle, next font JUST change what needs to be changed create font save handle repeat for each variation. 
Title: Re: Set font of window using code, not resource files
Post by: dedndave on September 01, 2011, 02:41:56 PM
the EnumFontFamiliesEx function looks at only 3 members of the LOGFONT structure
lfCharSet, lfPitchAndFamily, lfFaceName

if you set them all to 0, it looks through all the fonts (at least, all the fonts with a default char-set)
each font is enumerated only once
i.e., Arial will only show up once, even though there are bold, italic, underlined, etc versions of it

if you set one or more members to some non-zero value, it enumerates only matching fonts

as it happens, i was playing with this function the other day (see attachment)
i called EnumFontFamiliesEx with all members set to 0
in the callback proc for that, i coded another call to EnumFontFamiliesEx
this time, i copied the lfFaceName from the LOGFONT passed to me by the function into another LOGFONT structure
then, i set the lfCharSet and lfPitchAndFamily to 0
the second call enumerates the font family

if you are looking for a font that the user has selected through "appearances" settings, use
        LOCAL   ncm:NONCLIENTMETRICS

        mov     eax,sizeof NONCLIENTMETRICS
        mov     ncm.cbSize,eax
        INVOKE  SystemParametersInfo,SPI_GETNONCLIENTMETRICS,eax,addr ncm,NULL


the NONCLIENTMETRICS structure has 5 LOGFONT members that you can use to create user-selected fonts
lfCaptionFont , lfSMCaptionFont, lfMenuFont, lfStatusFont,  lfMessageFont

then use CreateFontIndirect to create the appropriate font for what you are displaying
        INVOKE  CreateFontIndirect,addr ncm.lfMessageFont
        mov     hFont,eax          ;store the font handle

that makes it simple - you don't have to copy names or worry about whether or not the font exists
also, if the user has poor eyesight or has selected a special font for some other reason, you get what he/she wants
when you are done using the font, call DeleteObject to delete it

i am still learning about this stuff - lol
i think it may be a good idea to check the language to see if it will display English text
if not, get the user-selected size and use Tahoma   :P

if you want to see what Rob is talking about, MichaelW wrote a simple example...
http://www.masm32.com/board/index.php?topic=3835.msg28602#msg28602
Title: Re: Set font of window using code, not resource files
Post by: ToutEnMasm on September 01, 2011, 03:17:31 PM
Quote
What is that windows common dialog box, and what are Hcontrole and Hfonte?

For the dialog box it is this one

Quote
   ;-----------------------------------------------------------------
   INVOKE     ChooseFont, addr cf   ; Invoke common ChooseFont dialog
   ;------------------------------------------------------------------

The line you refer with Hcontrole is in comment .To use the created handle of font (Hfonte) you need to send  message to the control.
You have just to copy the line comment,uncomment it and replace the Hcontrol by your own handle of control or window.


Title: Re: Set font of window using code, not resource files
Post by: ToutEnMasm on September 01, 2011, 03:27:19 PM
I have  made a tool who generate this proc.
You can find it here:
/http://www.masm32.com/board/index.php?topic=8542.0 (http://www.masm32.com/board/index.php?topic=8542.0)
you can find it here \sdkrc7\examples\cherche.exe
USAGE:
put some text in it nd select it.
Used this menus:             "Autre recherches"--->"cherche fonte"
Title: Re: Set font of window using code, not resource files
Post by: raleeper on September 01, 2011, 04:32:30 PM
Quote from: ToutEnMasm on September 01, 2011, 03:17:31 PM
Quote
What is that windows common dialog box, and what are Hcontrole and Hfonte?

For the dialog box it is this one

Quote
   ;-----------------------------------------------------------------
   INVOKE     ChooseFont, addr cf   ; Invoke common ChooseFont dialog
   ;------------------------------------------------------------------

The line you refer with Hcontrole is in comment .To use the created handle of font (Hfonte) you need to send  message to the control.
You have just to copy the line comment,uncomment it and replace the Hcontrol by your own handle of control or window.




Thank you, ToutEnMasm.  I see.  This will be very useful.  I've just started playing with ChooseFont and so far I don't see a way to select a character set, but I set it up hurriedly, so I probably made a mistake.  Anyway, this is great.
I haven't looked at the tool in your next post, but I expect it to be very useful also.

Thank you again.