diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c index 631bad0aa9c..ff5ed18878b 100644 --- a/dlls/user32/combo.c +++ b/dlls/user32/combo.c @@ -75,6 +75,9 @@ static UINT CBitHeight, CBitWidth; #define COMBO_EDITBUTTONSPACE() 0 #define EDIT_CONTROL_PADDING() 1 +static void CBCalcPlacement(HEADCOMBO *combo); +static void CBResetPos(HEADCOMBO *combo, BOOL redraw); + /********************************************************************* * combo class descriptor */ @@ -181,6 +184,25 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc ) return 0; } +static INT combo_get_text_height(const HEADCOMBO *combo) +{ + HDC hdc = GetDC(combo->self); + HFONT prev_font = 0; + TEXTMETRICW tm; + + if (combo->hFont) + prev_font = SelectObject(hdc, combo->hFont); + + GetTextMetricsW(hdc, &tm); + + if (prev_font) + SelectObject(hdc, prev_font); + + ReleaseDC(combo->self, hdc); + + return tm.tmHeight + 4; +} + /*********************************************************************** * CBGetTextAreaHeight * @@ -193,35 +215,18 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc ) * This height was determined through experimentation. * CBCalcPlacement will add 2*COMBO_YBORDERSIZE pixels for the border */ -static INT CBGetTextAreaHeight(HEADCOMBO *lphc) +static INT CBGetTextAreaHeight(HEADCOMBO *lphc, BOOL clip_item_height) { - INT iTextItemHeight; + INT item_height, text_height; - if( lphc->editHeight ) /* explicitly set height */ + if (clip_item_height && !CB_OWNERDRAWN(lphc)) { - iTextItemHeight = lphc->editHeight; + text_height = combo_get_text_height(lphc); + if (lphc->item_height < text_height) + lphc->item_height = text_height; } - else - { - TEXTMETRICW tm; - HDC hDC = GetDC(lphc->self); - HFONT hPrevFont = 0; - INT baseUnitY; - if (lphc->hFont) - hPrevFont = SelectObject( hDC, lphc->hFont ); - - GetTextMetricsW(hDC, &tm); - - baseUnitY = tm.tmHeight; - - if( hPrevFont ) - SelectObject( hDC, hPrevFont ); - - ReleaseDC(lphc->self, hDC); - - iTextItemHeight = baseUnitY + 4; - } + item_height = lphc->item_height; /* * Check the ownerdraw case if we haven't asked the parent the size @@ -232,7 +237,7 @@ static INT CBGetTextAreaHeight(HEADCOMBO *lphc) { MEASUREITEMSTRUCT measureItem; RECT clientRect; - INT originalItemHeight = iTextItemHeight; + INT originalItemHeight = item_height; UINT id = (UINT)GetWindowLongPtrW( lphc->self, GWLP_ID ); /* @@ -249,10 +254,10 @@ static INT CBGetTextAreaHeight(HEADCOMBO *lphc) measureItem.CtlID = id; measureItem.itemID = -1; measureItem.itemWidth = clientRect.right; - measureItem.itemHeight = iTextItemHeight - 6; /* ownerdrawn cb is taller */ + measureItem.itemHeight = item_height - 6; /* ownerdrawn cb is taller */ measureItem.itemData = 0; SendMessageW(lphc->owner, WM_MEASUREITEM, id, (LPARAM)&measureItem); - iTextItemHeight = 6 + measureItem.itemHeight; + item_height = 6 + measureItem.itemHeight; /* * Send a second one in the case of a fixed ownerdraw list to calculate the @@ -273,10 +278,10 @@ static INT CBGetTextAreaHeight(HEADCOMBO *lphc) /* * Keep the size for the next time */ - lphc->editHeight = iTextItemHeight; + lphc->item_height = item_height; } - return iTextItemHeight; + return item_height; } /*********************************************************************** @@ -286,13 +291,12 @@ static INT CBGetTextAreaHeight(HEADCOMBO *lphc) * a re-arranging of the contents of the combobox and the recalculation * of the size of the "real" control window. */ -static void CBForceDummyResize( - LPHEADCOMBO lphc) +static void CBForceDummyResize(LPHEADCOMBO lphc) { RECT windowRect; int newComboHeight; - newComboHeight = CBGetTextAreaHeight(lphc) + 2*COMBO_YBORDERSIZE(); + newComboHeight = CBGetTextAreaHeight(lphc, FALSE) + 2*COMBO_YBORDERSIZE(); GetWindowRect(lphc->self, &windowRect); @@ -304,12 +308,17 @@ static void CBForceDummyResize( * this will cancel-out in the processing of the WM_WINDOWPOSCHANGING * message. */ + lphc->wState |= CBF_NORESIZE; SetWindowPos( lphc->self, NULL, 0, 0, windowRect.right - windowRect.left, newComboHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + lphc->wState &= ~CBF_NORESIZE; + + CBCalcPlacement(lphc); + CBResetPos(lphc, FALSE); } /*********************************************************************** @@ -326,7 +335,7 @@ static void CBCalcPlacement(HEADCOMBO *combo) InflateRect(&combo->textRect, -COMBO_XBORDERSIZE(), -COMBO_YBORDERSIZE()); /* Chop off the bottom part to fit with the height of the text area. */ - combo->textRect.bottom = combo->textRect.top + CBGetTextAreaHeight(combo); + combo->textRect.bottom = combo->textRect.top + CBGetTextAreaHeight(combo, FALSE); /* The button starts the same vertical position as the text area. */ combo->buttonRect = combo->textRect; @@ -412,11 +421,9 @@ static LRESULT COMBO_Create( HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG lphc->owner = hwndParent; - /* - * The item height and dropped width are not set when the control - * is created. - */ - lphc->droppedWidth = lphc->editHeight = 0; + lphc->droppedWidth = 0; + + lphc->item_height = combo_get_text_height(lphc); /* * The first time we go through, we want to measure the ownerdraw item @@ -1435,8 +1442,11 @@ static void CBResetPos(HEADCOMBO *combo, BOOL redraw) /*********************************************************************** * COMBO_Size */ -static void COMBO_Size( LPHEADCOMBO lphc ) +static void COMBO_Size( HEADCOMBO *lphc ) { + if (!lphc->hWndLBox || (lphc->wState & CBF_NORESIZE)) + return; + /* * Those controls are always the same height. So we have to make sure * they are not resized to another value. @@ -1449,7 +1459,7 @@ static void COMBO_Size( LPHEADCOMBO lphc ) GetWindowRect(lphc->self, &rc); curComboHeight = rc.bottom - rc.top; curComboWidth = rc.right - rc.left; - newComboHeight = CBGetTextAreaHeight(lphc) + 2*COMBO_YBORDERSIZE(); + newComboHeight = CBGetTextAreaHeight(lphc, TRUE) + 2*COMBO_YBORDERSIZE(); /* * Resizing a combobox has another side effect, it resizes the dropped @@ -1469,9 +1479,13 @@ static void COMBO_Size( LPHEADCOMBO lphc ) /* * Restore original height */ - if( curComboHeight != newComboHeight ) - SetWindowPos(lphc->self, 0, 0, 0, curComboWidth, newComboHeight, - SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW); + if (curComboHeight != newComboHeight) + { + lphc->wState |= CBF_NORESIZE; + SetWindowPos(lphc->self, 0, 0, 0, curComboWidth, newComboHeight, + SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW); + lphc->wState &= ~CBF_NORESIZE; + } } CBCalcPlacement(lphc); @@ -1485,10 +1499,8 @@ static void COMBO_Size( LPHEADCOMBO lphc ) */ static void COMBO_Font( LPHEADCOMBO lphc, HFONT hFont, BOOL bRedraw ) { - /* - * Set the font - */ lphc->hFont = hFont; + lphc->item_height = combo_get_text_height(lphc); /* * Propagate to owned windows. @@ -1524,7 +1536,7 @@ static LRESULT COMBO_SetItemHeight( LPHEADCOMBO lphc, INT index, INT height ) { if( height < 32768 ) { - lphc->editHeight = height + 2; /* Is the 2 for 2*EDIT_CONTROL_PADDING? */ + lphc->item_height = height + 2; /* Is the 2 for 2*EDIT_CONTROL_PADDING? */ /* * Redo the layout of the control. @@ -1781,8 +1793,7 @@ LRESULT ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM lPar return result; } case WM_SIZE: - if( lphc->hWndLBox && - !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc ); + COMBO_Size( lphc ); return TRUE; case WM_SETFONT: COMBO_Font( lphc, (HFONT)wParam, (BOOL)lParam ); @@ -1998,7 +2009,7 @@ LRESULT ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM lPar case CB_GETITEMHEIGHT: if( (INT)wParam >= 0 ) /* listbox item */ return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0); - return CBGetTextAreaHeight(lphc); + return CBGetTextAreaHeight(lphc, FALSE); case CB_RESETCONTENT: SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0); if( (lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc) ) diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index d372bafcefe..0b0f1c28015 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -219,8 +219,8 @@ typedef struct RECT droppedRect; INT droppedIndex; INT fixedOwnerDrawHeight; - INT droppedWidth; /* last two are not used unless set */ - INT editHeight; /* explicitly */ + INT droppedWidth; /* not used unless set explicitly */ + INT item_height; } HEADCOMBO,*LPHEADCOMBO; extern BOOL COMBO_FlipListbox( LPHEADCOMBO, BOOL, BOOL ) DECLSPEC_HIDDEN;