I am tring to figure out the correct way to set the font of a static text box which is a child of a main window. After much googling, I find many results that explain essentially the following:
- Create a font object using CreateFont
- Send the WM_SETFONT message to the control, referencing the font handle.
- Destroy the font object when it is no longer needed.
What’s missing to me in every possible explanation I’ve found is when to send the message. Do I send it in the WinProc while handling some other appropriate message? I can’t find a good explanation for this.
A few MSDN articles discuss setting the font while handling a WM_INITDIALOG message but this isn’t a dialog. This is just a main window with a static child text box.
What I’ve done is send the WM_SETFONT message just before entering the message loop. Surprisingly to me, it works! My surprise arises from my understanding that SendMessage doesn’t return until the message has been handled (i.e. “until the window procedure has processed the message.” – DOCS). So, how the heck does the code even get to the message loop?
Here’s my code:
#include <windows.h>
#include <windowsx.h>
HWND hMainWind;
HWND hStartButton;
HWND hStopButton;
HWND hStaticBox;
static HFONT hFont;
static LRESULT CALLBACK MainWinProc(HWND, UINT, WPARAM, LPARAM);
#define START_BUTTON 1001
#define STOP_BUTTON 1002
int WINAPI WinMain( HINSTANCE hMainInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd )
{
MSG Msg = {0};
WNDCLASSEX MainWinClass;
MainWinClass.cbSize = sizeof(WNDCLASSEX);
MainWinClass.style = CS_VREDRAW|CS_HREDRAW;
MainWinClass.lpfnWndProc = MainWinProc;
MainWinClass.cbClsExtra = 0;
MainWinClass.cbWndExtra = 0;
MainWinClass.hInstance = hMainInstance;
MainWinClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
MainWinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
MainWinClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
MainWinClass.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
MainWinClass.lpszMenuName = NULL; /*No menu*/
MainWinClass.lpszClassName = "TwoButtons"; /* class name to register*/
if( !RegisterClassEx( &MainWinClass ) )
{
MessageBox( NULL, "Window Failed to Register!", "ERROR",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hMainWind = CreateWindowEx
(
WS_EX_LEFT,
MainWinClass.lpszClassName,
"TwoButtons",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, /*Default x pos*/
CW_USEDEFAULT, /*Default y pos*/
640, /*Width*/
480, /*Height*/
HWND_DESKTOP,
NULL,
hMainInstance,
NULL
);
hStartButton = CreateWindow
(
"BUTTON",
"START",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
270, /*x pos*/
200, /*y pos*/
100,
50,
hMainWind,
(HMENU)START_BUTTON,
hMainInstance,
NULL
);
hStopButton = CreateWindow
(
"BUTTON",
"STOP",
WS_TABSTOP | WS_VISIBLE | WS_DISABLED | WS_CHILD | BS_PUSHBUTTON,
270,
300,
100,
50,
hMainWind,
(HMENU)STOP_BUTTON,
hMainInstance,
NULL
);
/*create a static text box*/
hStaticBox = CreateWindow
(
"STATIC", /* lpClassName */
"Box", /* lpWindowName */
WS_BORDER|WS_CHILD|WS_VISIBLE, /* dwStyle */
270, /* x */
100, /* y */
100, /* nWidth */
50, /* nHeight */
hMainWind, /* hWndParent */
NULL, /* hMenu */
hMainInstance, /* hInstance */
(LPVOID)1 /* lpParam */
);
hFont = CreateFont
(
24, /* cHeight */
0, /* cWidth use default*/
0, /* cEscapement */
0, /* cOrientation */
FW_NORMAL, /* cWeight */
FALSE, /* bItalic */
FALSE, /* bUnderline */
FALSE, /* bStrikeOut */
DEFAULT_CHARSET, /* iCharSet */
OUT_DEFAULT_PRECIS, /* iOutPrecision */
CLIP_DEFAULT_PRECIS, /* iClipPrecision */
DEFAULT_QUALITY, /* iQuality */
DEFAULT_PITCH, /* iPitchAndFamily */
"Arial" /* pszFacename */
);
/* Make the main window visible on the screen */
ShowWindow(hMainWind, nShowCmd);
UpdateWindow(hMainWind);
/*Set up the font for the static text box*/
SendMessage ( hStaticBox, WM_SETFONT, (WPARAM) hFont, TRUE );
/* Run the message loop. It will run until GetMessage() returns 0 */
while( GetMessage( &Msg, NULL, 0, 0 ) )
{
/* Translate virtual-key messages into character messages */
TranslateMessage( &Msg );
/* Send message to MainWinProc */
DispatchMessage( &Msg );
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return Msg.wParam;
}
/* This function is called by DispatchMessage() */
static LRESULT CALLBACK MainWinProc( HWND hWind, UINT Message, WPARAM wParam,
LPARAM lParam )
{
switch(Message) /* handle the message */
{
case WM_DESTROY:
DeleteObject(hFont);
PostQuitMessage(0); /* sends a WM_QUIT to the message queue */
break;
case WM_COMMAND:
if( HIWORD( wParam ) == BN_CLICKED ) /*A button was clicked*/
{
switch ( LOWORD(wParam) ) /*Which button?*/
{
case START_BUTTON:
Button_Enable( hStartButton, FALSE );
Button_Enable( hStopButton, TRUE );
SetWindowText( hStaticBox, "START" );
break;
case STOP_BUTTON:
Button_Enable( hStartButton, TRUE );
Button_Enable( hStopButton, FALSE );
SetWindowText( hStaticBox, "STOP" );
break;
}
}
default: /* Pass on messages not handled here */
return DefWindowProc (hWind, Message, wParam, lParam);
}
return 0;
}