私は生の 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);
}