Estou tentando descobrir a maneira correta de definir a fonte de uma caixa de texto estática que é filha de uma janela principal. Depois de muito pesquisar no Google, encontro muitos resultados que explicam essencialmente o seguinte:
- Crie um objeto de fonte usando CreateFont
- Envie a mensagem WM_SETFONT para o controle, referenciando o identificador da fonte.
- Destrua o objeto fonte quando ele não for mais necessário.
O que me falta em todas as explicações possíveis que encontrei é quando enviar a mensagem. Devo enviá-lo no WinProc enquanto manipulo alguma outra mensagem apropriada? Não consigo encontrar uma boa explicação para isso.
Pelo menos um artigo do MSDN discute a configuração da fonte ao lidar com uma WM_INITDIALOG
mensagem, mas isso não é uma caixa de diálogo. Esta é apenas uma janela principal com uma caixa de texto secundária estática.
O que fiz foi enviar a WM_SETFONT
mensagem antes de entrar no loop de mensagens. Surpreendentemente para mim, funciona! Minha surpresa surge do meu entendimento de que SendMessage
não retorna até que a mensagem seja tratada (ou seja, "até que o procedimento de janela tenha processado a mensagem." - DOCS ). Então, como diabos o código chega ao loop de mensagens?
Aqui está meu código:
#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;
}
Você pode enviá-lo para o
static
controle a qualquer momento após criá-lo.Como você não está criando uma caixa de diálogo, você pode manipular
WM_CREATE
.Sim, porque você enviou depois de criar o
static
controle.Isso não acontece. De acordo com o mesmo documento que você citou:
Em outras palavras,
SendMessage()
chamará o próprio WndProc do controle estático diretamente no seu exemplo. É por isso que não precisa passar pelo loop de mensagens.Isso porque
WM_CREATE
foi enviado para vocêWndProc
antes de você criar ostatic
controle, poisWM_CREATE
é enviado porCreateWindowEx()
si só. Se você tivesse depurado seu código, você teria visto issohStaticBox
ehFont
ainda estavaNULL
no momento em que enviouWM_SETFONT
e, portanto,SendMessage()
teria retornado uma falha devido a ter recebido um arquivo inválidoHWND
.Você deve ter seu
MainWinProc
identificadorWM_CREATE
e criar todos os seus controles filhos a partir daí, eles não pertencemWinMain()
diretamente. Você também pode enviarWM_SETFONT
dentro deWM_CREATE
, por exemplo: