我从对话框中获取的HFONT不是我发送的那个

时间:2013-08-09 21:17:55

标签: c winapi

我在这里玩原始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); 
}

1 个答案:

答案 0 :(得分:1)

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

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

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