![](/img/trans.png)
[英]Windows/C++: detect when focus has changed between windows (globally)
[英]Can't detect when Windows Font Size has changed C++ MFC
我試圖確定如何檢測用戶何時將 Windows 字體大小從普通字體更改為超大字體,通過在 Windows XP 計算機上執行以下步驟來選擇字體大小:
我的理解是字體大小的變化會導致 DPI 的變化,所以這是我迄今為止嘗試過的。
我想檢測Windows 字體大小何時從普通字體變為大字體或超大字體,並根據字體大小的變化采取一些措施。 我假設當 Windows 字體大小改變時,DPI 也會改變(特別是當大小為 Extra Large Fonts 時
我收到了幾條消息,包括:WM_SETTINGCHANGE、WM_NCCALCSIZE、WM_NCPAINT 等……但是這些消息都不是字體大小更改時所特有的,換句話說,當我收到 WM_SETTINGSCANGE 消息時,我想知道發生了什么變化。
理論上,當我定義 OnSettingChange 並且 Windows 調用它時,lpszSection 應該告訴我更改部分是什么,並且工作正常,但是然后我通過調用 SystemParametersInfo 檢查給定部分並傳入操作 SPI_GETNONCLIENTMETRICS,然后我逐步完成調試器,我確保我在返回的 NONCLIENTMETRICS 中查看任何字體更改的數據,但沒有發生任何更改。
即使這不起作用,當設置更改時,我仍然應該能夠檢查 DPI。 我真的不會關心其他細節,每次收到 WM_SETTINGCHANGE 消息時,我只會檢查 DPI 並執行我有興趣執行的操作,但我也無法獲得系統 DPI。
我試圖通過調用 GetSystemMetrics 方法來獲取 DPI,也適用於每個 DC:
桌面 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 更改。
當您在桌面 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。”)
查看注冊表中的這些值:
Windows XP 主題 HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager\\SizeName 可能的值:NormalSize、LargeFonts 和 ExtraLargeFonts 這些值與語言無關。
Windows 經典主題 HKCU\\控制面板\\外觀\\當前 可能的值:Windows 經典、Windows 經典(大)、Windows 經典(特大)、Windows 標准、Windows 標准(大)、Windows 標准(特大) 請注意,這些值是語言依賴。
Windows Vista 不支持此功能。 如果我們想要更大的字體,只需更改 DPI 設置。 在這種情況下,GetDeviceCaps 應該可以工作。
希望這可以幫助。
我認為當字體大小改變時,顯示 DPI 不會改變。 Windows 可能只是將WM_PAINT
和WM_NCPAINT
消息發送到所有打開的窗口,並且它們正在使用當前(現在很大)的系統字體重新繪制自己。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.