什么时候向 win32 中主窗口的静态控件子控件发送 WM_SETFONT 消息的正确时间?

问题描述 投票:0回答:1

我正在尝试找出“正确”的方法来设置作为主窗口子窗口的静态文本框的字体。 经过大量谷歌搜索后,我发现许多结果基本上解释了以下内容:

使用 CreateFont 创建字体对象
  1. 将 WM_SETFONT 消息发送到控件,引用字体句柄。
  2. 当不再需要字体对象时销毁它。
  3. 在我找到的所有可能的解释中,我缺少的是“何时”发送消息。 我是否在处理其他适当的消息时在 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; }

在我找到的所有可能的解释中,我缺少的是“何时”发送消息。  我是否在处理其他适当的消息时在 WinProc 中发送它?
winapi sendmessage windows-messages
1个回答
0
投票
您可以在创建后随时将其发送到
static

控件。

至少[一篇 MSDN 文章][1] 讨论了在处理
WM_INITDIALOG

消息时设置字体,但这不是一个对话框。 这只是一个带有静态子文本框的主窗口。


由于您没有创建对话框,因此您可以处理
WM_CREATE


我所做的是在进入消息循环之前发送
WM_SETFONT

消息。 让我惊讶的是,它有效!


是的,因为您在创建
static

控件后发送了它。


我的惊讶来自于我的理解,
SendMessage

在消息被处理之前不会返回(即“直到窗口过程处理了消息。”-[DOCS][2])。 那么,代码到底是如何进入消息循环的呢?


事实并非如此。 根据同一文档:

如果指定的窗口是由调用线程创建的,则立即将窗口过程作为子例程调用。

换句话说,

SendMessage()

将在您的示例中直接调用静态控件自己的WndProc。这就是为什么它不需要经过消息循环。

[在 WM_INITDIALOG 或 WM_CREATE 上] 不起作用。我添加了以下片段:

case WM_INITDIALOG: case WM_CREATE: SendMessage ( hStaticBox, WM_SETFONT, (WPARAM) hFont, TRUE ); break;

到我的 

switch
中的

WinProc

语句,并在消息循环之前注释掉对
SendMessage
的调用。这不起作用 - 静态文本框的字体没有更新。

那是因为 
WM_CREATE
是在您创建静态控件之前
发送到您的 
WndProc

,因为

WM_CREATE

 是由 
CreateWindowEx()
 本身发送的。
您应该拥有 WndProc
 句柄 
WM_CREATE
 并从那里创建所有子控件,而不是直接在 
WinMain()

中。然后您也可以在

WM_SETFONT

 内部发送 
WM_CREATE
,例如:
...

int WINAPI WinMain( HINSTANCE hMainInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nShowCmd )
{
    ...    

    hMainWind = CreateWindowEx(...);

    // get rid of all the subsequent creates here...
    
    ShowWindow(hMainWind, nShowCmd);
    UpdateWindow(hMainWind);
    
    ...

    return Msg.wParam;
}
    
static LRESULT CALLBACK MainWinProc(  HWND hWind, UINT Message, WPARAM wParam,
                                      LPARAM lParam )
{
    switch(Message) /* handle the message */
    {
        case WM_CREATE:
            hStartButton = CreateWindow(..., hWind, ...);
            hStopButton = CreateWindow(..., hWind, ...);
            hStaticBox = CreateWindow(..., hWind, ...);
    
            hFont = CreateFont(...);
            SendMessage(hStaticBox, WM_SETFONT, (WPARAM) hFont, TRUE);
            break;

        case WM_DESTROY:
            DeleteObject(hFont);
            PostQuitMessage(0); /* sends a WM_QUIT to the message queue */
            break;
    
        ...
    }

    ...
}
	
© www.soinside.com 2019 - 2024. All rights reserved.