Win32 - 如何在按钮中使用默认按钮字体

4

我正在用C++创建一个小的WinAPI应用程序。我试图使用以下代码在我的表单上创建一个按钮:

HWND hwndButton = CreateWindow(
    TEXT("BUTTON"),   
    TEXT("Click Here"),       
    WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,  // Styles 
    10,         
    10,         
    100,        
    30,        
    hwnd,     
    NULL,       
    (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
    NULL);     

这段代码基于MSDN示例。我的问题是它在按钮上使用了粗体字,就像这样: enter image description here 但我想要使用标准字体,就像这样: enter image description here 我已经在文件顶部加入预处理器指令以启用视觉样式。
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

我该采取哪些步骤来使用标准系统字体?

谢谢。


1
你必须自己设置字体,请参见链接https://dev59.com/OHA85IYBdhLWcg3wF_m0#2942869。 - Barmak Shemirani
好的。谢谢。出于好奇,为什么系统默认不使用全局字体? - Jason Mills
1
我不知道为什么使用那个丑陋的字体作为默认字体,而不是每个人都想要的字体。也许这是为了向后兼容性。 - Barmak Shemirani
顺便提一下,上面的对话框使用了不同的字体。如果目标平台是Vista及以上版本,则可以进入对话框编辑器并使用“Segoe UI”大小为9pt,或在WM_INITDIALOG中管理字体。 - Barmak Shemirani
默认使用哪种字体?如何获取它? - Cody Gray
4个回答

7
GetStockObject 不是获取GUI字体的推荐方法(它不考虑主题,并且可以为按钮、菜单等选择不同的字体)。相反,您应该使用SystemParametersInfo (请参阅GetStockObject备注部分)。

不建议使用此方法获取对话框和窗口使用的当前字体。相反,使用SystemParametersInfo函数,使用SPI_GETNONCLIENTMETRICS参数检索当前字体。 SystemParametersInfo将考虑当前主题,并提供标题、菜单和消息对话框的字体信息。

NONCLIENTMETRICS metrics = {};
metrics.cbSize = sizeof(metrics);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);

HFONT guiFont = CreateFontIndirect(&metrics.lfCaptionFont);

// When you're done with the font, don't forget to call
DeleteObject(guiFont);

2
控件的默认系统字体不存在,最初创建的控件使用“System”字体,这是您在第一张图片中看到的。当按钮作为对话框的一部分创建时,它使用对话框模板中的字体,因此在按钮上使用类似“MS Shell Dlg”的适当大小和WM_SETFONT应该会给您与第二张图片相同的结果。请注意,系统中没有物理的MS Shell Dlg字体,它根据注册表设置映射到特定的字体。
通用控件清单与此无关,行为与comctl32版本6没有改变。

2

默认的GUI字体存储在DEFAULT_GUI_FONT中,可以通过以下方式检索:

GetStockObject(DEFAULT_GUI_FONT);

要设置按钮的字体,您可以使用:

HWND yourButton; // use CreateWindow or anything else to get this
SendMessage(yourButton, WM_SETFONT, (LPARAM)GetStockObject(DEFAULT_GUI_FONT), true);

3
建议使用SystemParametersInfo而不是GetStockObject。 - Mark Ingram

1

一种方便的方法是使用EnumChildWindows函数,而不需要手动调用每个子窗口上的SendMessage,具体实现可以使用以下回调函数 -

  1. Create the callback function EnumChildProc:

     BOOL CALLBACK EnumChildProc(
         HWND hWnd,
         LPARAM lParam
     )
     {
         HFONT hfDefault = *(HFONT *) lParam;
         SendMessageW(hWnd, WM_SETFONT, (WPARAM) hfDefault, MAKELPARAM(TRUE, 0));
         return TRUE;
     }
    
  2. At the start of your (w)WinMain function, add the code:

     NONCLIENTMETRICSW ncm;
     HFONT hfDefault;
    
     ZeroMemory(&ncm, sizeof(NONCLIENTMETRICSW));
     ncm.cbSize = sizeof(NONCLIENTMETRICSW);
    
     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, FALSE);
     hfDefault = CreateFontIndirectW(&ncm.lfMessageFont);
    

    Then, after the ShowWindow call, add this line:

     EnumChildWindows(hWnd, EnumChildProc, (LPARAM)&hfDefault);
    

1
你是一个英雄。 - Vinícius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接