0

我在这里玩原始的 Windows API。我试图在 WM_INITDIALOG 消息期间将字体传递给对话框,然后在该对话框中创建新的子窗口时继续使用该字体。但我不想继续传递我创建的 HFONT,我想在需要时从对话框窗口中检索它。

因此,当我进入我的 WM_INITDIALOG 处理程序时,我会创建字体,然后使用 SendMessage(WM_SETFONT) 将其发送到对话框。然后,每当我想创建一个新的子窗口时,我认为我需要做的就是使用 SendMessage(WM_GETFONT) 检索对话框字体。但是我从对话框收到的句柄不是我创建的句柄,所以当我使用新的句柄设置新的控制字体时,我得到错误的字体也就不足为奇了。

我只在应用程序终止时销毁字体句柄。但我敢打赌,无效的句柄不是问题,否则在下面的示例中,我显式传递字体句柄的控件将不会显示正确的句柄。

有任何想法吗?

#include <Windows.h>
#include <CommCtrl.h>

static INT_PTR CALLBACK DialogProc(
    _In_  HWND   hwndDlg,
    _In_  UINT   uMsg,
    _In_  WPARAM wParam,
    _In_  LPARAM lParam)
{
    static HFONT hFont = NULL;

    switch(uMsg)
    {
        case WM_CLOSE:
            ::EndDialog(hwndDlg, 0);
            ::DeleteObject(hFont);
            return TRUE;

        case WM_INITDIALOG:
        {
            // create our font
            hFont = ::CreateFontW(
                36,
                0,
                0,
                0,
                FW_NORMAL,
                0,
                0,
                0,
                DEFAULT_CHARSET,
                OUT_DEFAULT_PRECIS,
                CLIP_DEFAULT_PRECIS,
                CLEARTYPE_QUALITY,
                VARIABLE_PITCH,
                L"Tahoma");

            // set that font as the dialog font
            ::SendMessageW(hwndDlg, WM_SETFONT, (WPARAM)hFont, TRUE);

            // retrieve the dialog font
            HFONT hFontDialog = (HFONT)::SendMessageW(hwndDlg, WM_GETFONT, 0, 0);

            // create two child windows
            HWND hwndStatic1 = ::CreateWindowExW(0, WC_STATIC, L"hFont",       WS_VISIBLE | WS_CHILD, 0,  0, 100, 30, hwndDlg, NULL, 0, 0);
            HWND hwndStatic2 = ::CreateWindowExW(0, WC_STATIC, L"hFontDialog", WS_VISIBLE | WS_CHILD, 0, 50, 100, 20, hwndDlg, NULL, 0, 0);

            // set their fonts, using the one we created for the first one and
            // the one from the dialog for the second one
            ::SendMessageW(hwndStatic1, WM_SETFONT, (WPARAM)hFont,      TRUE);
            ::SendMessageW(hwndStatic2, WM_SETFONT, (WPARAM)hFontDialog, TRUE);            

            return FALSE;
        }
    }

    return FALSE;
}       


#include <PshPack2.h>
struct DialogTemplate
{               
    DLGTEMPLATE Base; 
    WORD Menu;
    WORD Class;         
    WCHAR Title[1];
};
#include <PopPack.h>


int WINAPI wWinMain(
    __in HINSTANCE     hInstance,
    __in_opt HINSTANCE hPrevInstance,
    __in LPWSTR        lpCmdLine,
    __in int           nShowCmd)
{
    DialogTemplate dt = {0};
    dt.Base.style = DS_CENTER | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU;
    dt.Base.cx    = 200;
    dt.Base.cy    = 200;    

    return ::DialogBoxIndirectParamW(
        ::GetModuleHandle(NULL),
        (DLGTEMPLATE*)&dt, // holy hack, Batman! I hope this is OK...
        NULL,
        DialogProc,
        (LPARAM)0); 
}
4

1 回答 1

2

对话框不响应WM_SETFONT. 对话框具有在其模板中定义的字体,如果DS_SETFONT设置了样式,它将在创建时将其传播到其所有子控件。您返回的字体WM_GETFONT是最初基于模板创建的字体。

如果要在创建对话框后更改控制字体,则需要WM_SETFONT单独向它们发送消息。

我关于为什么会这样的理论:对话框布局基于字体大小(“对话框单位”是字体高度和平均字体宽度的一小部分)。因此,对话框需要在创建时知道其字体,以便调整控件的大小和布局。从对话框的角度来看,之后更改字体可能需要调整大小/重新布局,这不是对话框管理器中已实现的功能。

于 2013-08-09T21:22:41.617 回答