Several focus and selection problems in listboxes.

This commit is contained in:
Gerard Patel 1999-07-25 13:03:17 +00:00 committed by Alexandre Julliard
parent 278d0586dc
commit c9a6d50c20
1 changed files with 76 additions and 28 deletions

View File

@ -16,6 +16,7 @@
#include "combo.h"
#include "debugtools.h"
#include "tweak.h"
#include "winversion.h"
DEFAULT_DEBUG_CHANNEL(listbox)
DECLARE_DEBUG_CHANNEL(combo)
@ -80,10 +81,16 @@ typedef struct
#define HAS_STRINGS(descr) \
(!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
#define IS_MULTISELECT(descr) \
((descr)->style & LBS_MULTIPLESEL || ((descr)->style & LBS_EXTENDEDSEL))
#define SEND_NOTIFICATION(wnd,descr,code) \
(SendMessageA( (descr)->owner, WM_COMMAND, \
MAKEWPARAM((((descr)->lphc)?ID_CB_LISTBOX:(wnd)->wIDmenu), (code) ), (wnd)->hwndSelf ))
#define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
/* Current timer status */
typedef enum
{
@ -1250,7 +1257,7 @@ static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT index,
descr->selected_item = index;
if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT);
if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT );
if (send_notify) SEND_NOTIFICATION( wnd, descr,
if (send_notify && descr->nb_items) SEND_NOTIFICATION( wnd, descr,
(index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
else
if( descr->lphc ) /* set selection change flag for parent combo */
@ -1297,6 +1304,7 @@ static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT index,
{
LB_ITEMDATA *item;
INT max_items;
INT oldfocus = descr->focus_item;
if (index == -1) index = descr->nb_items;
else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
@ -1351,17 +1359,23 @@ static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT index,
LISTBOX_InvalidateItems( wnd, descr, index );
/* Move selection and focused item */
if (index <= descr->selected_item) descr->selected_item++;
if (index <= descr->focus_item)
{
descr->focus_item++;
LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
}
/* If listbox was empty, set focus to the first item */
if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
if (descr->nb_items == 1)
LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
/* single select don't change selection index in win31 */
else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
{
descr->selected_item++;
LISTBOX_SetSelection( wnd, descr, descr->selected_item-1, TRUE, FALSE );
}
else
{
if (index <= descr->selected_item)
{
descr->selected_item++;
descr->focus_item = oldfocus; /* focus not changed */
}
}
return LB_OKAY;
}
@ -1378,6 +1392,7 @@ static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT index,
if (HAS_STRINGS(descr))
{
if (!str) str="";
if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
{
SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
@ -1461,19 +1476,31 @@ static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT index )
max_items * sizeof(LB_ITEMDATA) );
if (item) descr->items = item;
}
/* Repaint the items */
LISTBOX_UpdateScroll( wnd, descr );
LISTBOX_InvalidateItems( wnd, descr, index );
/* if we removed the scrollbar, reset the top of the list
(correct for owner-drawn ???) */
if (descr->nb_items == descr->page_size)
LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
/* Move selection and focused item */
if (index <= descr->selected_item) descr->selected_item--;
if (index <= descr->focus_item)
if (!IS_MULTISELECT(descr))
{
descr->focus_item--;
LISTBOX_MoveCaret( wnd, descr, descr->focus_item, FALSE );
if (index == descr->selected_item)
descr->selected_item = -1;
else if (index < descr->selected_item)
{
descr->selected_item--;
if (ISWIN31) /* win 31 do not change the selected item number */
LISTBOX_SetSelection( wnd, descr, descr->selected_item + 1, TRUE, FALSE);
}
}
LISTBOX_InvalidateItems( wnd, descr, index );
if (descr->focus_item >= descr->nb_items)
{
descr->focus_item = descr->nb_items - 1;
if (descr->focus_item < 0) descr->focus_item = 0;
}
return LB_OKAY;
}
@ -1793,7 +1820,7 @@ static LRESULT LISTBOX_HandleLButtonUp( WND *wnd, LB_DESCR *descr )
{
descr->captured = FALSE;
if (GetCapture() == wnd->hwndSelf) ReleaseCapture();
if (descr->style & LBS_NOTIFY)
if ((descr->style & LBS_NOTIFY) && descr->nb_items)
SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
}
return 0;
@ -1910,6 +1937,10 @@ static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr,
static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
{
INT caret = -1;
BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
bForceSelection = FALSE; /* only for single select list */
if (descr->style & LBS_WANTKEYBOARDINPUT)
{
caret = SendMessageA( descr->owner, WM_VKEYTOITEM,
@ -1922,6 +1953,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
case VK_LEFT:
if (descr->style & LBS_MULTICOLUMN)
{
bForceSelection = FALSE;
if (descr->focus_item >= descr->page_size)
caret = descr->focus_item - descr->page_size;
break;
@ -1934,6 +1966,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
case VK_RIGHT:
if (descr->style & LBS_MULTICOLUMN)
{
bForceSelection = FALSE;
if (descr->focus_item + descr->page_size < descr->nb_items)
caret = descr->focus_item + descr->page_size;
break;
@ -1943,6 +1976,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
caret = descr->focus_item + 1;
if (caret >= descr->nb_items) caret = descr->nb_items - 1;
break;
case VK_PRIOR:
if (descr->style & LBS_MULTICOLUMN)
{
@ -1977,19 +2011,19 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
!descr->items[descr->focus_item].selected,
(descr->style & LBS_NOTIFY) != 0 );
}
else if (descr->selected_item == -1)
{
LISTBOX_SetSelection( wnd, descr, descr->focus_item, TRUE,
(descr->style & LBS_NOTIFY) != 0 );
}
break;
default:
bForceSelection = FALSE;
}
if (bForceSelection) /* focused item is used instead of key */
caret = descr->focus_item;
if (caret >= 0)
{
if ((descr->style & LBS_EXTENDEDSEL) &&
!(GetKeyState( VK_SHIFT ) & 0x8000))
descr->anchor_item = caret;
LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
LISTBOX_SetSelection( wnd, descr, caret, TRUE, FALSE);
if (descr->style & LBS_NOTIFY)
{
if( descr->lphc && CB_GETTYPE(descr->lphc) != CBS_SIMPLE )
@ -1997,7 +2031,7 @@ static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr, WPARAM wParam )
/* make sure that combo parent doesn't hide us */
descr->lphc->wState |= CBF_NOROLLUP;
}
SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
if (descr->nb_items) SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
}
}
return 0;
@ -2027,8 +2061,10 @@ static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr,
caret = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE);
if (caret != -1)
{
if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
LISTBOX_SetSelection( wnd, descr, caret, TRUE, FALSE);
LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
if (descr->style & LBS_NOTIFY)
if ((descr->style & LBS_NOTIFY) && descr->nb_items)
SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
}
return 0;
@ -2187,7 +2223,10 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
case LB_DELETESTRING16:
case LB_DELETESTRING:
return LISTBOX_RemoveItem( wnd, descr, wParam );
if (LISTBOX_RemoveItem( wnd, descr, wParam) != LB_ERR)
return descr->nb_items;
else
return LB_ERR;
case LB_GETITEMDATA16:
case LB_GETITEMDATA:
@ -2224,6 +2263,8 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
case LB_GETCURSEL:
if (descr->nb_items==0)
return LB_ERR;
if (!IS_MULTISELECT(descr))
return descr->selected_item;
/* else */
if (descr->selected_item!=-1)
return descr->selected_item;
@ -2263,7 +2304,13 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
case LB_SETCARETINDEX16:
case LB_SETCARETINDEX:
return LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam );
if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
if (LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam ) == LB_ERR)
return LB_ERR;
else if (ISWIN31)
return wParam;
else
return LB_OKAY;
case LB_GETCARETINDEX16:
case LB_GETCARETINDEX:
@ -2334,6 +2381,7 @@ static inline LRESULT WINAPI ListBoxWndProc_locked( WND* wnd, UINT msg,
wParam = (INT)(INT16)wParam;
/* fall through */
case LB_SETCURSEL:
if (IS_MULTISELECT(descr)) return LB_ERR;
LISTBOX_SetCaretIndex( wnd, descr, wParam, TRUE );
return LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE );