Skip to content

Instantly share code, notes, and snippets.

@ysc3839
Created March 2, 2019 14:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ysc3839/b818c2d97c8e7cae398474df9bf29eb0 to your computer and use it in GitHub Desktop.
Save ysc3839/b818c2d97c8e7cae398474df9bf29eb0 to your computer and use it in GitHub Desktop.
#pragma once
// DLGTEMPLATEEX structure
// https://docs.microsoft.com/en-us/windows/desktop/dlgbox/dlgtemplateex
const uint8_t* SkipIDorString(const uint8_t* p)
{
if (*reinterpret_cast<const uint16_t*>(p) == 0xFFFF)
return p + sizeof(uint16_t) * 2;
while (*reinterpret_cast<const uint16_t*>(p))
p += sizeof(uint16_t);
return p += sizeof(uint16_t);
}
const uint8_t* SkipString(const uint8_t* p)
{
while (*reinterpret_cast<const uint16_t*>(p))
p += sizeof(uint16_t);
return p += sizeof(uint16_t);
}
WORD MapFontHeightToPointSize(LONG height)
{
if (height < 0)
{
HDC hdc = GetDC(nullptr);
if (hdc)
{
auto dpi = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(0, hdc);
return MulDiv(-height, 72, dpi);
}
}
return static_cast<WORD>(height);
}
INT_PTR DialogBoxIndirectParamFixFontWithSize(HINSTANCE hInstance, LPCDLGTEMPLATEW hDialogTemplate, size_t templateSize, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
{
auto dlgVerAndSignature = reinterpret_cast<const WORD*>(hDialogTemplate);
// is an extended dialog box and version is 1
if (dlgVerAndSignature[1] == 0xFFFF && *dlgVerAndSignature == 1)
{
auto dlgTemplate = reinterpret_cast<const uint8_t*>(hDialogTemplate);
dlgTemplate += sizeof(WORD); // dlgVer
dlgTemplate += sizeof(WORD); // signature
dlgTemplate += sizeof(DWORD); // helpID
dlgTemplate += sizeof(DWORD); // exStyle
dlgTemplate += sizeof(DWORD); // style
dlgTemplate += sizeof(WORD); // cDlgItems
dlgTemplate += sizeof(short); // x
dlgTemplate += sizeof(short); // y
dlgTemplate += sizeof(short); // cx
dlgTemplate += sizeof(short); // cy
dlgTemplate = SkipIDorString(dlgTemplate); // menu
dlgTemplate = SkipIDorString(dlgTemplate); // windowClass
dlgTemplate = SkipString(dlgTemplate); // title
NONCLIENTMETRICSW ncm = { sizeof(ncm) };
if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
{
size_t fontSize = (wcslen(ncm.lfMessageFont.lfFaceName) + 1) * sizeof(wchar_t);
size_t origTemplateSize = dlgTemplate - reinterpret_cast<const uint8_t*>(hDialogTemplate);
size_t newTemplateSize = origTemplateSize;
newTemplateSize += sizeof(WORD); // pointsize
newTemplateSize += sizeof(WORD); // weight
newTemplateSize += sizeof(BYTE); // italic
newTemplateSize += sizeof(BYTE); // charset
newTemplateSize += fontSize; // typeface
dlgTemplate += sizeof(WORD); // pointsize
dlgTemplate += sizeof(WORD); // weight
dlgTemplate += sizeof(BYTE); // italic
dlgTemplate += sizeof(BYTE); // charset
dlgTemplate = SkipString(dlgTemplate); // typeface
size_t remainSize = templateSize - (dlgTemplate - reinterpret_cast<const uint8_t*>(hDialogTemplate));
newTemplateSize += remainSize;
auto newTemplate = new uint8_t[newTemplateSize];
memcpy(newTemplate, hDialogTemplate, origTemplateSize);
auto newTemplateFont = newTemplate + origTemplateSize;
*reinterpret_cast<WORD*>(newTemplateFont) = static_cast<WORD>(MapFontHeightToPointSize(ncm.lfMessageFont.lfHeight)); // pointsize
newTemplateFont += sizeof(WORD);
*reinterpret_cast<WORD*>(newTemplateFont) = static_cast<WORD>(ncm.lfMessageFont.lfWeight); // weight
newTemplateFont += sizeof(WORD);
*reinterpret_cast<BYTE*>(newTemplateFont) = ncm.lfMessageFont.lfItalic; // italic
newTemplateFont += sizeof(BYTE);
*reinterpret_cast<BYTE*>(newTemplateFont) = ncm.lfMessageFont.lfCharSet; // charset
newTemplateFont += sizeof(BYTE);
memcpy(newTemplateFont, ncm.lfMessageFont.lfFaceName, fontSize);
newTemplateFont += fontSize;
memcpy(newTemplateFont, dlgTemplate, remainSize);
auto ret = DialogBoxIndirectParamW(hInstance, reinterpret_cast<LPCDLGTEMPLATEW>(newTemplate), hWndParent, lpDialogFunc, dwInitParam);
delete[] newTemplate;
return ret;
}
}
return DialogBoxIndirectParamW(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam);
}
INT_PTR DialogBoxParamFixFont(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
{
auto hResInfo = FindResourceW(hInstance, lpTemplateName, RT_DIALOG);
if (hResInfo)
{
auto hDialogTemplate = reinterpret_cast<LPCDLGTEMPLATEW>(LoadResource(hInstance, hResInfo));
if (hDialogTemplate)
{
auto size = SizeofResource(hInstance, hResInfo);
return DialogBoxIndirectParamFixFontWithSize(hInstance, hDialogTemplate, size, hWndParent, lpDialogFunc, dwInitParam);
}
}
return -1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment