[User32|Tests] Sync Port Wine Combo Controls.

Need to cross check these changes with WINE ComCtl32 before you PANIC
HACK!!!!

Not in order:
Piotr Caban : Remove unneeded RECT parameter from CBPaintText helper.
              Don't invalidate ComboBox on CB_SETCURSEL message.
Don't invalidate ComboBox on LBN_SELCHANGE and
LBN_SELCANCEL.
              Add more CB_SETCURSEL tests on ComboBox.
              Redraw combo text field even if it's empty.
Let ComboBox edit control handle the redraw even if
CBF_NOREDRAW is set.
Don't do the painting if combobox is not visible in
CBPaintText.

Dmitry Timoshkov : Don't force a combobox repaint on WM_SIZE.

This breaks z-order based painting and causes side effects
for
applications that during the WM_PAINT processing reference
internal
             data associated with a not fully initialized window.
Ref :
2d9e3236ea

Fabian Maurer : Set listbox popup height correctly and add tests.

                Properly set dropdown height.

             Now that user32 and comctl32 combo are separated,
             this won't lead to a regression anymore
             Ref :
3d0be0bad8
             Info by Sebastian Lackner Ref:
f0fc034997

Nikolay Sivov : Remove some misleading TODOs and confusing comments.
This commit is contained in:
James Tabor 2019-09-21 08:47:56 -05:00
parent 432854ee18
commit c57d4d7b9e
2 changed files with 86 additions and 101 deletions

View file

@ -291,7 +291,7 @@ static void test_WM_LBUTTONDOWN(void)
hCombo = CreateWindowA("ComboBox", "Combo", WS_VISIBLE|WS_CHILD|CBS_DROPDOWN, hCombo = CreateWindowA("ComboBox", "Combo", WS_VISIBLE|WS_CHILD|CBS_DROPDOWN,
0, 0, 200, 150, hMainWnd, (HMENU)COMBO_ID, NULL, 0); 0, 0, 200, 150, hMainWnd, (HMENU)COMBO_ID, NULL, 0);
for (i = 0; i < sizeof(choices)/sizeof(UINT); i++){ for (i = 0; i < ARRAY_SIZE(choices); i++){
sprintf(buffer, stringFormat, choices[i]); sprintf(buffer, stringFormat, choices[i]);
result = SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)buffer); result = SendMessageA(hCombo, CB_ADDSTRING, 0, (LPARAM)buffer);
ok(result == i, ok(result == i,
@ -688,28 +688,28 @@ static void test_listbox_size(DWORD style)
int height_combo; int height_combo;
BOOL todo; BOOL todo;
} info_height[] = { } info_height[] = {
{2, 24, TRUE}, {2, 24, FALSE},
{2, 41, TRUE}, {2, 41, TRUE},
{2, 42, TRUE}, {2, 42, FALSE},
{2, 50, TRUE}, {2, 50, FALSE},
{2, 60}, {2, 60},
{2, 80}, {2, 80},
{2, 89}, {2, 89},
{2, 90}, {2, 90},
{2, 100}, {2, 100},
{10, 24, TRUE}, {10, 24, FALSE},
{10, 41, TRUE}, {10, 41, TRUE},
{10, 42, TRUE}, {10, 42, FALSE},
{10, 50, TRUE}, {10, 50, FALSE},
{10, 60, TRUE}, {10, 60, FALSE},
{10, 80, TRUE}, {10, 80, FALSE},
{10, 89, TRUE}, {10, 89, TRUE},
{10, 90, TRUE}, {10, 90, FALSE},
{10, 100, TRUE}, {10, 100, FALSE},
}; };
for(test = 0; test < sizeof(info_height) / sizeof(info_height[0]); test++) for(test = 0; test < ARRAY_SIZE(info_height); test++)
{ {
const struct list_size_info *info_test = &info_height[test]; const struct list_size_info *info_test = &info_height[test];
int height_item; /* Height of a list item */ int height_item; /* Height of a list item */

View file

@ -17,18 +17,7 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
* *
* NOTES
*
* This code was audited for completeness against the documented features
* of Comctl32.dll version 6.0 on Oct. 4, 2004, by Dimitrie O. Paun.
*
* Unless otherwise noted, we believe this code to be complete, as per
* the specification mentioned above.
* If you discover missing features, or bugs, please note them below.
*
* TODO: * TODO:
* - ComboBox_[GS]etMinVisible()
* - CB_GETMINVISIBLE, CB_SETMINVISIBLE
* - CB_SETTOPINDEX * - CB_SETTOPINDEX
*/ */
@ -651,6 +640,58 @@ static void CBPaintButton( LPHEADCOMBO lphc, HDC hdc, RECT rectButton)
DrawFrameControl(hdc, &rectButton, DFC_SCROLL, buttonState); DrawFrameControl(hdc, &rectButton, DFC_SCROLL, buttonState);
} }
/***********************************************************************
* COMBO_PrepareColors
*
* This method will sent the appropriate WM_CTLCOLOR message to
* prepare and setup the colors for the combo's DC.
*
* It also returns the brush to use for the background.
*/
static HBRUSH COMBO_PrepareColors(
LPHEADCOMBO lphc,
HDC hDC)
{
HBRUSH hBkgBrush;
/*
* Get the background brush for this control.
*/
if (CB_DISABLED(lphc))
{
#ifdef __REACTOS__
hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLORSTATIC);
#else
hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLORSTATIC,
(WPARAM)hDC, (LPARAM)lphc->self );
#endif
/*
* We have to change the text color since WM_CTLCOLORSTATIC will
* set it to the "enabled" color. This is the same behavior as the
* edit control
*/
SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT));
}
else
{
/* FIXME: In which cases WM_CTLCOLORLISTBOX should be sent? */
#ifdef __REACTOS__
hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLOREDIT);
#else
hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLOREDIT,
(WPARAM)hDC, (LPARAM)lphc->self );
#endif
}
/*
* Catch errors.
*/
if( !hBkgBrush )
hBkgBrush = GetSysColorBrush(COLOR_WINDOW);
return hBkgBrush;
}
/*********************************************************************** /***********************************************************************
* CBPaintText * CBPaintText
* *
@ -658,14 +699,12 @@ static void CBPaintButton( LPHEADCOMBO lphc, HDC hdc, RECT rectButton)
*/ */
static void CBPaintText( static void CBPaintText(
LPHEADCOMBO lphc, LPHEADCOMBO lphc,
HDC hdc, HDC hdc_paint)
RECT rectEdit)
{ {
RECT rectEdit = lphc->textRect;
INT id, size = 0; INT id, size = 0;
LPWSTR pText = NULL; LPWSTR pText = NULL;
if( lphc->wState & CBF_NOREDRAW ) return;
TRACE("\n"); TRACE("\n");
/* follow Windows combobox that sends a bunch of text /* follow Windows combobox that sends a bunch of text
@ -683,27 +722,31 @@ static void CBPaintText(
pText[size] = '\0'; /* just in case */ pText[size] = '\0'; /* just in case */
} else return; } else return;
} }
else
if( !CB_OWNERDRAWN(lphc) )
return;
if( lphc->wState & CBF_EDIT ) if( lphc->wState & CBF_EDIT )
{ {
static const WCHAR empty_stringW[] = { 0 }; static const WCHAR empty_stringW[] = { 0 };
if( CB_HASSTRINGS(lphc) ) SetWindowTextW( lphc->hWndEdit, pText ? pText : empty_stringW ); if( CB_HASSTRINGS(lphc) ) SetWindowTextW( lphc->hWndEdit, pText ? pText : empty_stringW );
if( lphc->wState & CBF_FOCUSED ) if( lphc->wState & CBF_FOCUSED )
SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1)); SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, MAXLONG);
} }
else /* paint text field ourselves */ else if(!(lphc->wState & CBF_NOREDRAW) && IsWindowVisible( lphc->self ))
{ {
/* paint text field ourselves */
HDC hdc = hdc_paint ? hdc_paint : GetDC(lphc->self);
UINT itemState = ODS_COMBOBOXEDIT; UINT itemState = ODS_COMBOBOXEDIT;
HFONT hPrevFont = (lphc->hFont) ? SelectObject(hdc, lphc->hFont) : 0; HFONT hPrevFont = (lphc->hFont) ? SelectObject(hdc, lphc->hFont) : 0;
HBRUSH hPrevBrush, hBkgBrush;
/* /*
* Give ourselves some space. * Give ourselves some space.
*/ */
InflateRect( &rectEdit, -1, -1 ); InflateRect( &rectEdit, -1, -1 );
hBkgBrush = COMBO_PrepareColors( lphc, hdc );
hPrevBrush = SelectObject( hdc, hBkgBrush );
FillRect( hdc, &rectEdit, hBkgBrush );
if( CB_OWNERDRAWN(lphc) ) if( CB_OWNERDRAWN(lphc) )
{ {
DRAWITEMSTRUCT dis; DRAWITEMSTRUCT dis;
@ -769,6 +812,12 @@ static void CBPaintText(
if( hPrevFont ) if( hPrevFont )
SelectObject(hdc, hPrevFont ); SelectObject(hdc, hPrevFont );
if( hPrevBrush )
SelectObject( hdc, hPrevBrush );
if( !hdc_paint )
ReleaseDC( lphc->self, hdc );
} }
#ifdef __REACTOS__ #ifdef __REACTOS__
if (pText) if (pText)
@ -801,59 +850,6 @@ static void CBPaintBorder(
DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_RECT); DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_RECT);
} }
/***********************************************************************
* COMBO_PrepareColors
*
* This method will sent the appropriate WM_CTLCOLOR message to
* prepare and setup the colors for the combo's DC.
*
* It also returns the brush to use for the background.
*/
static HBRUSH COMBO_PrepareColors(
LPHEADCOMBO lphc,
HDC hDC)
{
HBRUSH hBkgBrush;
/*
* Get the background brush for this control.
*/
if (CB_DISABLED(lphc))
{
#ifdef __REACTOS__
hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLORSTATIC);
#else
hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLORSTATIC,
(WPARAM)hDC, (LPARAM)lphc->self );
#endif
/*
* We have to change the text color since WM_CTLCOLORSTATIC will
* set it to the "enabled" color. This is the same behavior as the
* edit control
*/
SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT));
}
else
{
/* FIXME: In which cases WM_CTLCOLORLISTBOX should be sent? */
#ifdef __REACTOS__
hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLOREDIT);
#else
hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLOREDIT,
(WPARAM)hDC, (LPARAM)lphc->self );
#endif
}
/*
* Catch errors.
*/
if( !hBkgBrush )
hBkgBrush = GetSysColorBrush(COLOR_WINDOW);
return hBkgBrush;
}
/*********************************************************************** /***********************************************************************
* COMBO_Paint * COMBO_Paint
*/ */
@ -902,7 +898,7 @@ static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC)
} }
if( !(lphc->wState & CBF_EDIT) ) if( !(lphc->wState & CBF_EDIT) )
CBPaintText( lphc, hDC, lphc->textRect); CBPaintText( lphc, hDC );
if( hPrevBrush ) if( hPrevBrush )
SelectObject( hDC, hPrevBrush ); SelectObject( hDC, hPrevBrush );
@ -1055,14 +1051,6 @@ static void CBDropDown( LPHEADCOMBO lphc )
if (nHeight < nDroppedHeight - COMBO_YBORDERSIZE()) if (nHeight < nDroppedHeight - COMBO_YBORDERSIZE())
nDroppedHeight = nHeight + COMBO_YBORDERSIZE(); nDroppedHeight = nHeight + COMBO_YBORDERSIZE();
if (nDroppedHeight < nHeight)
{
if (nItems < 5)
nDroppedHeight = (nItems+1)*nIHeight;
else if (nDroppedHeight < 6*nIHeight)
nDroppedHeight = 6*nIHeight;
}
} }
r.left = rect.left; r.left = rect.left;
@ -1580,7 +1568,7 @@ static void COMBO_Size( LPHEADCOMBO lphc )
&lphc->buttonRect, &lphc->buttonRect,
&lphc->droppedRect); &lphc->droppedRect);
CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, TRUE ); CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, FALSE );
} }
@ -2203,10 +2191,7 @@ LRESULT WINAPI ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPAR
SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0); SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0);
/* no LBN_SELCHANGE in this case, update manually */ /* no LBN_SELCHANGE in this case, update manually */
if( lphc->wState & CBF_EDIT ) CBPaintText( lphc, NULL );
CBUpdateEdit( lphc, (INT)wParam );
else
InvalidateRect(lphc->self, &lphc->textRect, TRUE);
lphc->wState &= ~CBF_SELCHANGE; lphc->wState &= ~CBF_SELCHANGE;
return lParam; return lParam;
case CB_GETLBTEXT: case CB_GETLBTEXT: