2017-10-11 100 views
2

我有一個包含兩個組合框,一個所有者繪製和一個非所有者繪製的對話框。所有者繪製組合框的垂直大小大於非所有者繪製組合框的大小

這是他們是如何在rc文件中定義:

COMBOBOX  IDC_COMBO2,149,49,77,73, 
       CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_SORT | VS_VSCROLL 
COMBOBOX  IDC_COMBO3,237,49,48,30, 
       CBS_DROPDOWNLIST CBS_SORT | WS_VSCROLL 

他們完全一樣的高度rc文件,但老闆畫之一(一個在左側)稍高於非所有者繪製的一個:

enter image description here

+0

您需要指定[CBS_NOINTEGRALHEIGHT](https://msdn.microsoft.com/en-us/library/windows/desktop/bb775796.aspx)組合框樣式,理想情況下適用於這兩種樣式。高度差異可能是由於標準組合框使用不同的所有者的默認值來繪製一個。這是猜測,但。 – IInspectable

+0

@IInspectable CBS_NOINTEGRALHEIGHT是無關的,我試過但它沒有改變任何東西。我想這隻適用於下拉列表框。 –

回答

4

首先,資源中的給定高度是下降狀態下組合框的高度。

此行爲是由 設計的。我相信組合框項目高度的大小由 確定分配給控件的字體的字體高度。 對於所有者繪製組合框,系統不知道,因此它向您發送一個默認大小爲組合框(可能爲 ,取決於系統字體而不是gui字體)初始化的WM_MEASUREITEM。

所以,你需要處理WM_MEASUREITEM在父對話框......

像這樣的東西可能會幫助(對編譯器不能驗證碼):

void CMyDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
{ 
    CClientDC dc(this); 
    CFont* pFont = GetFont(); 
    CFont* pFontPrev = NULL; 

    if (pFont != NULL) 
    pFontPrev = dc.SelectObject(pFont); 

    int iborder = ::GetSystemMetrics(SM_CYBORDER); 
    CSize sz = dc.GetTextExtent(_T("0")); 
    lpMeasureItemStruct->itemHeight = sz.cy + 2*iborder; 

    if (pFont != NULL) 
    dc.SelectObject(pFontPrev); 

    __super::OnMeasureItem(nIDCtl, lpMeasureItemStruct); 
} 
+0

非常好,你救了我的一天!我只是放棄了那段代碼,它按預期工作。 –

+0

還有助於使用[__super](https://msdn.microsoft.com/en-us/library/94dw1w7x.aspx)。我不知道那件事。 – acraig5075

+0

請記住,__super僅在MS編譯器中可用。 – xMRi

3

組合框是最可怕的控制在處理大小和佈局時使用Windows。因爲它也支持「簡單」樣式,並且單獨的編輯和列表框控件始終可見,所以它不使用標準窗口邊框/邊框樣式,而是在需要時繪製其邊框。

創建控件時指定的高度實際上是在下降狀態下使用的大小。它在運行時根據其字體強制編輯控件的大小。因爲如此多的人錯誤地認爲主題化的ComCtl32 v6實現可以確保下拉的大小是合理的,即使你最初給它一個小的尺寸。

要匹配系統,您需要嘗試在WM_MEASUREITEM中計算所需的大小,但默認控件的確切佈局當然沒有記錄。這可能是字體的高度+ SM_C * EDGE的系統度量值大小,可能還有一些填充。

如果您只需要文本旁邊的圖標,則可以使用ComboBoxEx控件。