我正在尝试找出设置主窗口子窗口静态文本框字体的正确方法。经过大量谷歌搜索,我发现许多结果基本上解释了以下内容:
- 使用 CreateFont 创建字体对象
- 向控件发送 WM_SETFONT 消息,引用字体句柄。
- 当不再需要字体对象时,将其销毁。
在我找到的所有可能的解释中,我都不知道何时发送消息。我是否在处理其他适当消息的同时在 WinProc 中发送它?我找不到对此的良好解释。
至少有一篇 MSDN 文章讨论了在处理消息时设置字体WM_INITDIALOG
,但这不是对话框。这只是一个带有静态子文本框的主窗口。
我所做的就是WM_SETFONT
在进入消息循环之前发送消息。令我惊讶的是,它起作用了!我之所以感到惊讶,是因为我的理解是,SendMessage
直到消息被处理后它才会返回(即“直到窗口过程处理完消息。” - DOCS)。那么,代码到底是如何进入消息循环的呢?
这是我的代码:
#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;
}
static
创建后您可以随时将其发送给控件。由于您没有创建对话框,因此您可以
WM_CREATE
自行处理。是的,因为您是在创建
static
控件之后发送的。事实并非如此。根据您引用的同一篇文档:
换句话说,
SendMessage()
在您的示例中将直接调用静态控件自己的 WndProc。这就是为什么它不需要经过消息循环。这是因为 是在你创建控件之前
WM_CREATE
发送给你的,就像是自己发送的一样。如果你调试了代码,你会看到并且在你发送 时仍然,因此会因为给出无效的 而返回失败。WndProc
static
WM_CREATE
CreateWindowEx()
hStaticBox
hFont
NULL
WM_SETFONT
SendMessage()
HWND
您应该拥有自己的
MainWinProc
句柄WM_CREATE
并从那里创建所有子控件,它们不直接属于其中WinMain()
。然后您也可以发送WM_SETFONT
其中的内容WM_CREATE
,例如: