1. 程式人生 > >VC DLU和PIXEL的單位轉換(轉)

VC DLU和PIXEL的單位轉換(轉)

本來以為做完BUTTON效果後就OVER了,結果今天傍晚時候遇到一個很惱火的問題。在VC / eVC / VS中畫的對話方塊、按鈕等控制元件時,在IDE右下角顯示的 XX * XX單位是DLU (Dialog Unit), 這是根據你設定的對話方塊字型大小而改變的。這種做法無可厚非。如果把字型改大了,那麼DIALOG和BUTTON自然也被“撐”大了,比較靈活。但是我往上疊加的圖片是按畫素(PIXEL)來算的。最後實現出來,有兩個方法。按照國際慣例,當然是先講笨的方法,MSDN上的作風也是如此。

(1)方法一:我查了下DLU和PIXEL之間的換算關係,有個講得比較全的網頁是http://support.microsoft.com/default.aspx?scid=kb;en-us;145994

 (How to caculate dialog box units based on the current font in Visual C++) 按照文中的Method Two簡單測試了一下

1 BOOL CALLBACK DialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
2 
{
3 switch
(uMsg)
4 
     {
5 case
 WM_INITDIALOG:
6 
         {
7              RECT rc={0,0,4,8
};
8 
9              MapDialogRect(hDlg, 
&
rc );
10              printf("baseUnitX = %ld\n"
, rc.right);
11              printf("baseUnitY = %ld\n"
, rc.bottom);
12 
13 //DLU_Weight = pixel_weight * 4 / baseunitX;
14 //DLU_Height = pixel_height * 8 / baseunitY;
15 16 return TRUE;
17 
         }
18 
     }
19 
20 return FALSE;
21 }


對於我DIALOG中設定的Courier New 10pt字型,
第一步

:從程式碼中得到baseUnitX = 7, baseUnitY = 16,
第二步:套用公式
weight_DLU = weight_pixel * 4 / baseUnitX
height_DLU = height_pixel * 8 / baseUnitY
比如我想建立一個320*240 PIXEL的對話方塊,那麼
weight_DLU = 320 * 4 / 7 = 182.86, 取整為183
height_DLU = 240 * 8 / 16 = 120
第三步:到VC裡去拖動對話方塊的邊界,畫出183*120的對話方塊,那麼程式碼執行起來後,通過GetClientRect查一下,的確是得到320*240 pixel的對話方塊了。

但是這種方法有一個致命的缺點。比如我要畫一個60*70的按鈕,按照上面的baseUnitX和baseUnitY折算後應該為34.28 * 35,但是我畫34*35 DLU時,執行得到59*70 PIXEL視窗;畫35*35 DLU時,執行得到61*70 PIXEL視窗,無法恰到好處,這導致了往上疊加60*70 pixel的圖片時,按鈕邊緣會出現不連續的黑點。所以這段文字只能當作DLU和PIXEL的換算關係來玩了,沒有任何實際應用價值。

(2) 方法二:正確的方法
其實也很簡單。晚飯後突然想到的,用SetWindowPos強制設定window的長寬和左上角座標。我在WM_DRAWITEM訊息的處理中簡單試了一下:
SetWindowPos(lpDIS->hwndItem, NULL, 10, 10, 60, 70, SWP_NOZORDER);
設定前是59*70的按鈕,設定後就是60*70了,並且疊加圖片沒有任何問題。OK,整個基於GWES的UI方案至此成型了。後面貌似沒有什麼大的技術障礙了。

至此,我沒有發現GWES方案上還有什麼路障了,可以拍板使用這套方案了,和只用GDI寫UI相比,軟體研發的工作量大概降低了30%左右。當然事情還沒有就這樣結束,這套方案對我這專案組的意義是很深遠的。請看下篇:程式碼中的一小步,專案進度管理上的一大步