來源: http://bbs.csdn.net/topics/370177760
我在win32 + c寫的界面中解決辦法,就是把字體的字號給固定了,這樣做的結果就是,不管dpi是否有改變,界面中控件的文字的字號不變,就不會出現文字換行的情況。
但像菜單文字的字號就變大了,combobox(右三角),checkbox(選擇框)變大一點點,顯的有點不協調。
但至少不影響使用。
下面是判斷當前系統的dpi,然后重置字體的字號。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//高DPI下界面錯亂的解決方法
HWND
hwnd_desktop = GetDesktopWindow();
HDC
hdc = GetWindowDC(hwnd_desktop);
int
dpi = GetDeviceCaps(hdc, LOGPIXELSX);
//printf("hwnd_desktop:%ld, dpi:%d\n", hwnd_desktop, dpi);
ReleaseDC(hwnd_desktop, hdc);
int
dpi_diff = dpi - 96;
//開發平台默認的dpi: 96
if
(dpi_diff > 0)
{
float
zoom = dpi_diff * 1.041666 / 100 + 1;
lgf.lfWidth = lgf.lfWidth / zoom;
lgf.lfHeight = lgf.lfHeight / zoom;
//printf("width:%ld, height:%ld\n", lgf.lfWidth, lgf.lfHeight);
}
|
一般很少或者不開發產品的朋友可能不會發現。你可以在標准96DPI(一般情況下都是)下,新建一個窗體,載入一個小圖片,窗體大小調整為剛好能容納下圖片。生成EXE文件。修改DPI值為120(即125%縮放,XP下桌面-屬性-高級里面找,WIN7>屏幕分辨率->放大或縮小其他項目->中等)。系統會要求注銷,注銷后再進入系統運行EXE程序。馬上會看到惡心的結果:窗體被擴大,而圖片大小依舊,造成多出來的窗體部分空白。丑陋。如果在加上幾個其他空間,丑陋效果更明顯:

【普及個知識:】
屏幕坐標計量單位,分為邏輯和物理坐標(單位),物理坐標為像素點、厘米等;邏輯坐標為緹、DPI等DPI是指單位面積內像素的多少。例如,在96默認DPI下1英寸屏幕有96點像素,如果在120DPI下1英寸有120個像素點。緹是VB6中默認的計量單位,96DPI下15緹等於1像素,120DPI下12緹等於1像素。因此,就造成了不同DPI下窗體控件大小會隨着DPI值增加而放大,原本設計時就比較大的窗體在高DPI下甚至會超出屏幕邊界,還有其他更多問題。
我在 DPI:120下,測試用vb寫的界面,發現會窗口和控件會自動放大尺寸,展示效果沒有受到DPI的影響,估計與使用的邏輯坐標(單位)有關。
【解決思路】
斷斷續續想了很久,經過研究,終於發現導致界面錯亂的所有原理原因和解決辦法。
1.原理原因:界面錯亂的關鍵在於DPI變化后,系統會將程序可視化界面和控件按比例放大。那么使用邏輯坐標(計量單位)就變得不可靠,因為他們都是通過物理單位換算而成,均會受到DPI變化影響,特別是VB6計量單位--緹。完全就是於DPI有着直接的換算關系(96DPI下15緹等於1像素,120DPI下12緹等於1像素)。那么什么單位才可靠呢?答案是--像素、厘米、毫米!鎖住界面大小不讓縮放的最終就是要鎖定三個東西:高度像素值、寬度像素值、控件所位於窗體內的坐標像素值
2.以上這三者被鎖定固定大小,界面就將“穩定”不再受到系統DPI干擾。那么:緹(邏輯單位)--像素(物理單位)--DPI(邏輯單位) 這三者間又是怎么換算的?公式還是:96DPI下15緹等於1像素,120DPI下12緹等於1像素;DPI每增加1,就放大1.041666倍。(1440/DPI值=X,X緹=1像素;1.041666是1.014666666666667的約值,如何計算活動省略,知道即可)
3.不僅僅界面和控件放大了,連字體都給放大了!96DPI下的9磅(默認)字體,同比120DPI下的9磅字體小了很多很多。要固定到96DPI 9磅字體的大小,就要使用到這上面這句“DPI每增加1,就放大1.041666倍”。判斷當前客戶機DPI,減去標准的96,所得值乘以1.041666,所得值為倍數,單位(%)。如120DPI-96=24,24X1.041666%約等於25%,再加上1就是125%。即120DPI比96DPI放大了125%
【總結】
96DPI下獲得窗體、控件高度寬度和坐標(left,top)的緹數。除以15便是其物理單位---像素值。之后到客戶機上,立即獲得其DPI值,獲得值為X,將1440除以X獲得一個值。這時,窗體、控件高度寬度坐標(LEFT,TOP)緹數就應該為:(原緹數/15)*(1440/現DPI值);(解釋:)這樣所得到的就是設計時窗體、控件高寬和所在坐標的物理值(像素),之后再根據客戶機DPI將這個物理值計算成合適的新緹數。
2014-08-11
