我正在尝试确定当用户将Windows字体大小从正常字体更改为超大字体时如何检测,通过在Windows XP计算机上执行以下步骤来选择字体大小:

  1. 右键单击桌面,然后选择“属性”。
  2. 单击“外观”选项卡。
  3. 选择字体大小:普通/大字体/超大字体
  4. 我的理解是字体大小更改导致DPI更改,所以这是我到目前为止所尝试的。


    我的目标:

    我想检测 Windows字体大小何时从正常更改为大字体或超大字体,并根据字体大小更改执行某些操作。我假设当Windows字体大小改变时,DPI也会改变(特别是当大小为超大字体时


    到目前为止我尝试过:

    我收到了几条消息,包括:WM_SETTINGCHANGE,WM_NCCALCSIZE,WM_NCPAINT等......但是当字体大小发生变化时,这些消息都不是唯一的,换句话说,当我收到WM_SETTINGSCHANGE消息时我想知道什么改变。

    理论上,当我定义OnSettingChange并且Windows调用它时,lpszSection应该告诉我更改的部分是什么,并且工作正常,但是我通过调用SystemParametersInfo检查给定的部分,然后传入操作SPI_GETNONCLIENTMETRICS,并且我逐步完成调试器,并确保我在返回的NONCLIENTMETRICS中查看任何字体更改的数据,但没有发生。

    即使这不起作用,我仍然可以在设置更改时检查DPI。我真的不在乎其他细节,每次收到WM_SETTINGCHANGE消息时,我都会检查DPI并执行我感兴趣的操作,但我也无法获得系统DPI。 / p>

    我试图通过调用方法GetSystemMetrics来获取DPI,同样也为每个DC:

    Dekstop DC-> GetDeviceCaps LOGPIXELSX / LOGPIXELSY 窗口DC-> GetDeviceCaps LOGPIXELSX / LOGPIXELSY 当前DC-> GetDeviceCaps LOGPIXELSX / LOGPIXELSY

    即使我在图形属性窗口中更改DPI,这些值也不会返回任何不同的值,它们总是显示96.

    有人可以帮我解决这个问题吗?我应该寻找什么?我应该在哪里看?

    afx_msg void CMainFrame::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
    {
        int windowDPI = 0;
        int deviceDPI = 0;
        int systemDPI = 0;
        int desktopDPI = 0;
        int dpi_00_X = 0;
        int dpi_01_X = 0;
        int dpi_02_X = 0;
        int dpi_03_X = 0;
    
        CDC* windowDC = CWnd::GetWindowDC(); // try with window DC
        HDC desktop = ::GetDC(NULL); // try with desktop DC
        CDC* device = CWnd::GetDC(); // try with current DC
        HDC hDC = *device; // try with HDC
        if( windowDC )
        {
            windowDPI = windowDC->GetDeviceCaps(LOGPIXELSY); 
            // always 96 regardless if I change the Font 
            // Size to Extra Large Fonts or keep it at Normal
    
            dpi_00_X = windowDC->GetDeviceCaps(LOGPIXELSX); // 96
        }
    
        if( desktop )
        {
            desktopDPI = ::GetDeviceCaps(desktop, LOGPIXELSY); // 96
            dpi_01_X = ::GetDeviceCaps(desktop, LOGPIXELSX); // 96
        }
    
        if( device )
        {
            deviceDPI = device->GetDeviceCaps(LOGPIXELSY); // 96
            dpi_02_X = device->GetDeviceCaps(LOGPIXELSX); // 96
        }
    
        systemDPI = ::GetDeviceCaps(hDC, LOGPIXELSY); // 96
        dpi_03_X = ::GetDeviceCaps(hDC, LOGPIXELSX); // 96
    
        CWnd::ReleaseDC(device);
        CWnd::ReleaseDC(windowDC);
        ::ReleaseDC(NULL, desktop);
        ::ReleaseDC(NULL, hDC);
    
        CWnd::OnWinSettingChange(uFlags, lpszSection);
    }
    

    DPI始终返回96,但设置更改在我将字体大小更改为超大字体或我将DPI更改为120(从图形属性)时生效。

有帮助吗?

解决方案

[重新阅读后的编辑]我几乎肯定会改为“大字体”。不会导致DPI更改,而是主题设置。您应该可以通过应用“大字体”进行验证。更改然后打开DPI设置所在的高级显示属性,它应该保持在96dpi。


DPI更改应该需要重新启动。也许设置没有传播到GetDeviceCaps可以检索它的地方?

也许尝试更改不需要重新启动的设置(可能是分辨率),然后查看是否可以检测到更改。如果可以,您的答案可能是在重启之后无法检测到DPI更改。

其他提示

当您在桌面DC上调用GetDeviceCaps()时,您是否正在使用可能由MFC缓存的DC,因此包含过时的信息?您是否从OnSettingsChange处理程序内部同步调用GetDeviceCaps()?我可以看到这些东西中的一个或两个可能会让你得到DPI的过时版本。

Raymond Chen 写了这篇文章和他的解决方案看起来像这样(请注意,我添加了::运算符以避免调用API的MFC包装器):

int GetScreenDPI()
{
  HDC hdcScreen = ::GetDC(NULL);
  int iDPI = -1; // assume failure
  if (hdcScreen) {
    iDPI = ::GetDeviceCaps(hdcScreen, LOGPIXELSX);
    ::ReleaseDC(NULL, hdcScreen);
  }
  return iDPI;
}

我有一个预感WM_THEMECHANGED会照顾你。但是,对于改变了什么没有任何暗示。您必须使用OpenThemeData并缓存初始设置,然后在每次收到消息时进行比较。

你可能不需要关心改变了什么,你不能有一个通用的布局例程,通过考虑所有因素并假设从头开始调整你的表单/对话框/什么?

你想解决什么问题?

请参阅 http://msdn.microsoft.com /en-us/library/ms701681(VS.85).aspx ,这里有解释(引用:“如果你不取消dpi缩放,这个调用将返回默认值96 dpi。”)

我不认为当字体大小改变时显示DPI会改变。 Windows可能只是将 WM_PAINT WM_NCPAINT 消息发送到所有打开的窗口,并且它们使用当前(现在很大的)系统字体重绘自己。

在注册表中查看这些值:

Windows XP主题 HKCU \软件\微软\的Windows \ CurrentVersion \ ThemeManager \ SizeName 可能的值:NormalSize,LargeFonts和ExtraLargeFonts 这些值与语言无关

Windows经典主题 HKCU \控制面板\外观\当前 可能的值:Windows Classic,Windows Classic(大),Windows Classic(超大),Windows Standard,Windows Standard(大),Windows Standard(超大) 请注意,这些值语言相关

Windows Vista不支持此功能。如果我们想要更大的字体,只需更改DPI设置即可。在这种情况下,GetDeviceCaps应该可以工作。

希望这有帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top