標籤:idt sel rar turn 方法 int blank code lfw
高DPI顯示器越來越普及,軟體自然也要適應這個變化,最近實習的時候也遇到了一個關於DPI縮放的問題。因為內部架構的一個控制項有BUG,會導致內容的顯示出問題,後來實在沒辦法改成了用Windows Native API來自己定義字型,但是這一寫就出問題了,本來在內部開發機100%放縮下好好的,一跑到我自己的WIN10,在2K屏放上縮放125%就字型就顯示不正常了(字型變得過大)。
Window Vista以後的系統可以直接來個SetProcessDpiAwareness來控製程序的DPI問題,但是這個函數不是很好用,還是沒有辦法精確控制縮放,而且這個函數只有在Windows 8.1以上的系統才能用(SetProcessDPIAware也行,不過也必須是Windows Vista以上的系統),萬一我們的程式需要在XP上運行呢?這就需要用另外一個辦法了。
其實這個辦法也很簡單,就是用GetDeviceCaps來擷取當前環境控制代碼的DPI就可以了,然後和預設的DPI(96)做運算,獲得我們真正想要的DPI
case WM_PAINT:{ PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd,&ps); auto curDPIX = GetDeviceCaps(hdc, LOGPIXELSX); auto curDPIY = GetDeviceCaps(hdc, LOGPIXELSY); std::wstring str(L"Hello World"); LOGFONT lf; HGDIOBJ hObject; ZeroMemory(&lf, sizeof(LOGFONT)); f.lfCharSet = GB2312_CHARSET; lf.lfWidth = MulDiv(20, 96, curDPIX); lf.lfHeight = MulDiv(55, 96, curDPIY); lf.lfPitchAndFamily = VARIABLE_PITCH; swprintf_s(lf.lfFaceName, _countof(lf.lfFaceName), L"微軟雅黑"); hObject = SelectObject(hdc, CreateFontIndirect(&lf)); TextOut(hdc, 21, 100, str.data(), str.length()); DeleteObject(SelectObject(hdc, hObject)); lf.lfWidth = 20; lf.lfHeight = 55; hObject = SelectObject(hdc, CreateFontIndirect(&lf)); TextOut(hdc, 21, 200, str.data(), str.length()); DeleteObject(SelectObject(hdc, hObject)); EndPaint(hwnd, &ps); return 0;}
這裡示範的是在螢幕上輸出Hello Wolrd,現在假設我們的字型被放大了,但是假設我們其他控制項沒有被放大,那麼字在控制項裡面就會顯示不正常,這個時候就要縮小字的尺寸,要想和100%的時候類似,就需要MulDiv(尺寸, 96, curDPI);一下,字型被縮小了同理
這下我們可以看到,第二行是在120%放大下被放大的高度為55,寬度為22的字型,字型偏大,我們通過上面的方法,把字型縮小回正常的尺寸
掉坑日誌:Windows Native API與DPI縮放