我正在尝试确定当用户将Windows字体大小从正常字体更改为超大字体时如何检测,通过在Windows XP计算机上执行以下步骤来选择字体大小:
我的理解是字体大小更改导致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(从图形属性)时生效。
答案 0 :(得分:4)
[重新阅读后编辑]我几乎肯定更改为“大字体”不会导致DPI更改,而是主题设置。您应该能够通过应用“大字体”更改进行验证,然后打开DPI设置所在的高级显示属性,它应该保持在96dpi。
<小时/> DPI更改应该需要重新启动。也许设置没有传播到GetDeviceCaps可以检索它的地方?
也许尝试更改不需要重新启动的设置(可能是分辨率),然后查看是否可以检测到更改。如果可以,您的答案可能是在重启之后无法检测到DPI更改。
答案 1 :(得分:2)
当您在桌面DC上调用GetDeviceCaps()时,您是否正在使用可能由MFC缓存的DC,因此包含过时的信息?您是否从OnSettingsChange处理程序内部同步调用GetDeviceCaps()?我可以看到这些东西中的一个或两个可能会让你得到DPI的过时版本。
Raymond Chen wrote about this和他的解决方案看起来像这样(请注意我添加了::运算符以避免调用API的MFC包装器):
int GetScreenDPI()
{
HDC hdcScreen = ::GetDC(NULL);
int iDPI = -1; // assume failure
if (hdcScreen) {
iDPI = ::GetDeviceCaps(hdcScreen, LOGPIXELSX);
::ReleaseDC(NULL, hdcScreen);
}
return iDPI;
}
答案 2 :(得分:2)
我有一个预感WM_THEMECHANGED会照顾你。但是,对于改变了什么没有任何暗示。您必须使用OpenThemeData并缓存初始设置,然后在每次收到消息时进行比较。
你可能不需要关心改变了什么,你不能有一个通用的布局例程,通过考虑所有因素并假设从头开始调整你的表单/对话框/什么?
你想解决什么问题?
答案 3 :(得分:1)
请参阅http://msdn.microsoft.com/en-us/library/ms701681(VS.85).aspx,此处对此进行了解释(引用:“如果不取消dpi缩放,则此调用将返回默认值96 dpi。”)
答案 4 :(得分:0)
我不认为当字体大小改变时显示DPI会改变。 Windows可能只是向所有打开的窗口发送WM_PAINT
和WM_NCPAINT
消息,并且他们使用当前(现在很大的)系统字体重绘自己。
答案 5 :(得分:0)
在注册表中查看这些值:
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应该可以工作。
希望这有帮助。