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 に答える