Draw background of the empty selected item in empty lists.

Don't draw a focus rect if we dont have the focus.
Don't select items on key up/down in multi-select lists.
Handle LBS_NOSEL correctly, fix remaining todo_wine tests.
This commit is contained in:
Jon Griffiths 2004-10-05 22:31:00 +00:00 committed by Alexandre Julliard
parent f3a56591ec
commit 7a9e800566
2 changed files with 63 additions and 40 deletions

View File

@ -106,7 +106,8 @@ typedef struct
#define IS_MULTISELECT(descr) \ #define IS_MULTISELECT(descr) \
((descr)->style & LBS_MULTIPLESEL || ((descr)->style & LBS_EXTENDEDSEL)) ((descr)->style & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && \
!((descr)->style & LBS_NOSEL))
#define SEND_NOTIFICATION(hwnd,descr,code) \ #define SEND_NOTIFICATION(hwnd,descr,code) \
(SendMessageW( (descr)->owner, WM_COMMAND, \ (SendMessageW( (descr)->owner, WM_COMMAND, \
@ -968,7 +969,9 @@ static LRESULT LISTBOX_GetSelCount( LB_DESCR *descr )
INT i, count; INT i, count;
LB_ITEMDATA *item = descr->items; LB_ITEMDATA *item = descr->items;
if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR; if (!(descr->style & LBS_MULTIPLESEL) ||
(descr->style & LBS_NOSEL))
return LB_ERR;
for (i = count = 0; i < descr->nb_items; i++, item++) for (i = count = 0; i < descr->nb_items; i++, item++)
if (item->selected) count++; if (item->selected) count++;
return count; return count;
@ -1038,6 +1041,8 @@ static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
{ {
/* Special case for empty listbox: paint focus rect */ /* Special case for empty listbox: paint focus rect */
rect.bottom = rect.top + descr->item_height; rect.bottom = rect.top + descr->item_height;
ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
&rect, NULL, 0, NULL );
LISTBOX_PaintItem( hwnd, descr, hdc, &rect, descr->focus_item, LISTBOX_PaintItem( hwnd, descr, hdc, &rect, descr->focus_item,
ODA_FOCUS, FALSE ); ODA_FOCUS, FALSE );
rect.top = rect.bottom; rect.top = rect.bottom;
@ -1091,7 +1096,8 @@ static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
} }
/* Paint the focus item now */ /* Paint the focus item now */
if (focusRect.top != focusRect.bottom && descr->caret_on) if (focusRect.top != focusRect.bottom &&
descr->caret_on && descr->in_focus)
LISTBOX_PaintItem( hwnd, descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE ); LISTBOX_PaintItem( hwnd, descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
if (!IS_OWNERDRAW(descr)) if (!IS_OWNERDRAW(descr))
@ -1404,7 +1410,11 @@ static LRESULT LISTBOX_SetSelection( HWND hwnd, LB_DESCR *descr, INT index,
{ {
TRACE( "index=%d notify=%s\n", index, send_notify ? "YES" : "NO" ); TRACE( "index=%d notify=%s\n", index, send_notify ? "YES" : "NO" );
if (descr->style & LBS_NOSEL) return LB_ERR; if (descr->style & LBS_NOSEL)
{
descr->selected_item = index;
return LB_ERR;
}
if ((index < -1) || (index >= descr->nb_items)) return LB_ERR; if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
if (descr->style & LBS_MULTIPLESEL) if (descr->style & LBS_MULTIPLESEL)
{ {
@ -1507,7 +1517,7 @@ static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
item = HeapReAlloc( GetProcessHeap(), 0, descr->items, item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
max_items * sizeof(LB_ITEMDATA) ); max_items * sizeof(LB_ITEMDATA) );
else else
item = HeapAlloc( GetProcessHeap(), 0, item = HeapAlloc( GetProcessHeap(), 0,
max_items * sizeof(LB_ITEMDATA) ); max_items * sizeof(LB_ITEMDATA) );
if (!item) if (!item)
{ {
@ -1566,8 +1576,8 @@ static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
{ {
if (index <= descr->selected_item) if (index <= descr->selected_item)
{ {
descr->selected_item++; descr->selected_item++;
descr->focus_item = oldfocus; /* focus not changed */ descr->focus_item = oldfocus; /* focus not changed */
} }
} }
return LB_OKAY; return LB_OKAY;
@ -1996,7 +2006,7 @@ static LRESULT LISTBOX_HandleLButtonDown( HWND hwnd, LB_DESCR *descr,
if (index == -1) return 0; if (index == -1) return 0;
if (descr->style & LBS_EXTENDEDSEL) if (descr->style & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
{ {
/* we should perhaps make sure that all items are deselected /* we should perhaps make sure that all items are deselected
FIXME: needed for !LBS_EXTENDEDSEL, too ? FIXME: needed for !LBS_EXTENDEDSEL, too ?
@ -2012,15 +2022,25 @@ static LRESULT LISTBOX_HandleLButtonDown( HWND hwnd, LB_DESCR *descr,
!descr->items[index].selected, !descr->items[index].selected,
(descr->style & LBS_NOTIFY) != 0); (descr->style & LBS_NOTIFY) != 0);
} }
else LISTBOX_MoveCaret( hwnd, descr, index, FALSE ); else
} {
else LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
{
LISTBOX_MoveCaret( hwnd, descr, index, FALSE ); if (descr->style & LBS_MULTIPLESEL)
LISTBOX_SetSelection( hwnd, descr, index, {
LISTBOX_SetSelection( hwnd, descr, index,
(!(descr->style & LBS_MULTIPLESEL) || (!(descr->style & LBS_MULTIPLESEL) ||
!descr->items[index].selected), !descr->items[index].selected),
(descr->style & LBS_NOTIFY) != 0 ); (descr->style & LBS_NOTIFY) != 0 );
}
}
}
else
{
descr->anchor_item = index;
LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
LISTBOX_SetSelection( hwnd, descr, index,
TRUE, (descr->style & LBS_NOTIFY) != 0 );
} }
descr->captured = TRUE; descr->captured = TRUE;
@ -2278,7 +2298,7 @@ static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam
INT caret = -1; INT caret = -1;
BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */ BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item)) if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
bForceSelection = FALSE; /* only for single select list */ bForceSelection = FALSE; /* only for single select list */
if (descr->style & LBS_WANTKEYBOARDINPUT) if (descr->style & LBS_WANTKEYBOARDINPUT)
{ {
@ -2358,18 +2378,23 @@ static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam
caret = descr->focus_item; caret = descr->focus_item;
if (caret >= 0) if (caret >= 0)
{ {
if ((descr->style & LBS_EXTENDEDSEL) && if (((descr->style & LBS_EXTENDEDSEL) &&
!(GetKeyState( VK_SHIFT ) & 0x8000)) !(GetKeyState( VK_SHIFT ) & 0x8000)) ||
!IS_MULTISELECT(descr))
descr->anchor_item = caret; descr->anchor_item = caret;
LISTBOX_MoveCaret( hwnd, descr, caret, TRUE ); LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
if (descr->style & LBS_MULTIPLESEL)
descr->selected_item = caret;
else
LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
if (descr->style & LBS_NOTIFY) if (descr->style & LBS_NOTIFY)
{ {
if( descr->lphc ) if( descr->lphc )
{ {
/* make sure that combo parent doesn't hide us */ /* make sure that combo parent doesn't hide us */
descr->lphc->wState |= CBF_NOROLLUP; descr->lphc->wState |= CBF_NOROLLUP;
} }
if (descr->nb_items) SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE ); if (descr->nb_items) SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
} }
} }
@ -2655,15 +2680,13 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
case LB_GETCURSEL16: case LB_GETCURSEL16:
case LB_GETCURSEL: case LB_GETCURSEL:
if (descr->nb_items==0) if (descr->nb_items == 0)
return LB_ERR; return LB_ERR;
if (!IS_MULTISELECT(descr)) if (!IS_MULTISELECT(descr))
return descr->selected_item; return descr->selected_item;
/* else */ if (descr->selected_item != -1)
if (descr->selected_item!=-1) return descr->selected_item;
return descr->selected_item; return descr->focus_item;
/* else */
return descr->focus_item;
/* otherwise, if the user tries to move the selection with the */ /* otherwise, if the user tries to move the selection with the */
/* arrow keys, we will give the application something to choke on */ /* arrow keys, we will give the application something to choke on */
case LB_GETTOPINDEX16: case LB_GETTOPINDEX16:
@ -2884,7 +2907,7 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
/* according to Win16 docs, DDL_DRIVES should make DDL_EXCLUSIVE /* according to Win16 docs, DDL_DRIVES should make DDL_EXCLUSIVE
* be set automatically (this is different in Win32) */ * be set automatically (this is different in Win32) */
if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE; if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
lParam = (LPARAM)MapSL(lParam); lParam = (LPARAM)MapSL(lParam);
/* fall through */ /* fall through */
case LB_DIR: case LB_DIR:
{ {

View File

@ -143,24 +143,24 @@ START_TEST(listbox)
/* {add_style} */ /* {add_style} */
{{0}, {{0},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,1,0,0}, { 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,1,0,0}}; { 2, 2, 2, LB_ERR}, {0,0,0,0}};
/* {selected, anchor, caret, selcount}{TODO fields} */ /* {selected, anchor, caret, selcount}{TODO fields} */
const struct listbox_test SS_NS = const struct listbox_test SS_NS =
{{LBS_NOSEL}, {{LBS_NOSEL},
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0}, {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {1,1,0,0}, { 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {1,1,1,0}}; { 2, 2, 2, LB_ERR}, {0,0,0,0}};
const struct listbox_test MS = const struct listbox_test MS =
{{LBS_MULTIPLESEL}, {{LBS_MULTIPLESEL},
{ 0, LB_ERR, 0, 0}, {0,0,0,0}, { 0, LB_ERR, 0, 0}, {0,0,0,0},
{ 1, 1, 1, 1}, {0,1,0,0}, { 1, 1, 1, 1}, {0,0,0,0},
{ 2, 1, 2, 1}, {0,1,0,1}}; { 2, 1, 2, 1}, {0,0,0,0}};
const struct listbox_test MS_NS = const struct listbox_test MS_NS =
{{LBS_MULTIPLESEL | LBS_NOSEL}, {{LBS_MULTIPLESEL | LBS_NOSEL},
{LB_ERR, LB_ERR, 0, LB_ERR}, {1,0,0,1}, {LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
{ 1, 1, 1, LB_ERR}, {0,1,0,1}, { 1, 1, 1, LB_ERR}, {0,0,0,0},
{ 2, 2, 2, LB_ERR}, {0,1,0,1}}; { 2, 2, 2, LB_ERR}, {0,0,0,0}};
trace (" Testing single selection...\n"); trace (" Testing single selection...\n");
check (SS); check (SS);