user1593842
user1593842

Reputation: 357

HFONT I am getting from my dialog box is not the one I sent

I am playing with the raw Windows API here. I am trying to pass a font to a dialog during the WM_INITDIALOG message and then keep using that font whenever a new child window is created inside that dialog. But I do not want to keep passing that HFONT I created, I want to retrieve it from the dialog window instead, whenever I need it.

So when I enter my WM_INITDIALOG handler, I create the font and then send it to the dialog using SendMessage(WM_SETFONT). Then, whenever I wanted to create a new child window, I thought that all I needed to do was to retrieve the dialog font, using SendMessage(WM_GETFONT). But the handle I receive from the dialog is not the one I created, so it is no surprise that when I use that new handle to set the new control font I get the wrong font.

I am only destroying the font handle when the application terminates. But I bet that an invalid handle is not the problem otherwise, in the example below, the control where I explicit pass my font handle would not be displaying the correct one.

Any ideas?

#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); 
}

Upvotes: 0

Views: 713

Answers (1)

Jonathan Potter
Jonathan Potter

Reputation: 37192

Dialogs don't respond to WM_SETFONT. A dialog has a font that is defined in its template, and if the DS_SETFONT style is set it will propogate that to all its child controls on creation. The font you get back from WM_GETFONT is the one created initially based on the template.

If you want to change control fonts after the dialog has been created you need to send them WM_SETFONT messages individually.

My theory as to why this is the case: dialog layout is based on the font size ("dialog units" are a fraction of the font height and average font width). Therefore, the dialog needs to know its font upon creation, in order to resize and layout the controls. Changing the font afterwards, from the dialog's point of view, would potentially require a resize/re-layout and this is not functionality that has been implemented in the dialog manager.

Upvotes: 2

Related Questions