Listbox: implement LBS_COMBOBOX
Dimitrie O. Paun
dpaun at rogers.com
Thu Oct 14 09:19:09 CDT 2004
Thanks to Dmitry for the LBS_COMBOBOX value.
ChangeLog
Implement LBS_COMBOBOX, and make use of it.
Better separation between the Listbox and Combobox.
Have a single set of wndprocs, just like Windows.
Index: include/winuser.h
===================================================================
RCS file: /var/cvs/wine/include/winuser.h,v
retrieving revision 1.190
diff -u -r1.190 winuser.h
--- include/winuser.h 8 Oct 2004 20:50:06 -0000 1.190
+++ include/winuser.h 14 Oct 2004 13:34:09 -0000
@@ -2151,6 +2151,7 @@
#define LBS_DISABLENOSCROLL 0x1000
#define LBS_NODATA 0x2000
#define LBS_NOSEL 0x4000
+#define LBS_COMBOBOX 0x8000
#define LBS_STANDARD (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
/* Listbox messages */
Index: dlls/user/controls.h
===================================================================
RCS file: /var/cvs/wine/dlls/user/controls.h,v
retrieving revision 1.18
diff -u -r1.18 controls.h
--- dlls/user/controls.h 20 Sep 2004 21:45:45 -0000 1.18
+++ dlls/user/controls.h 14 Oct 2004 12:35:21 -0000
@@ -113,9 +113,6 @@
INT editHeight; /* explicitly */
} HEADCOMBO,*LPHEADCOMBO;
-/* Note, that CBS_DROPDOWNLIST style is actually (CBS_SIMPLE | CBS_DROPDOWN) */
-#define CB_GETTYPE( lphc ) ((lphc)->dwStyle & (CBS_DROPDOWNLIST))
-
extern BOOL COMBO_FlipListbox( LPHEADCOMBO, BOOL, BOOL );
/* Dialog info structure */
Index: dlls/user/combo.c
===================================================================
RCS file: /var/cvs/wine/dlls/user/combo.c,v
retrieving revision 1.3
diff -u -r1.3 combo.c
--- dlls/user/combo.c 6 Oct 2004 00:05:07 -0000 1.3
+++ dlls/user/combo.c 14 Oct 2004 14:04:22 -0000
@@ -70,6 +70,7 @@
#define CB_OWNERDRAWN( lphc ) ((lphc)->dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
#define CB_HASSTRINGS( lphc ) ((lphc)->dwStyle & CBS_HASSTRINGS)
#define CB_HWND( lphc ) ((lphc)->self)
+#define CB_GETTYPE( lphc ) ((lphc)->dwStyle & (CBS_DROPDOWNLIST))
#define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
@@ -566,7 +567,7 @@
/* create listbox popup */
- lbeStyle = (LBS_NOTIFY | WS_BORDER | WS_CLIPSIBLINGS | WS_CHILD) |
+ lbeStyle = (LBS_NOTIFY | LBS_COMBOBOX | WS_BORDER | WS_CLIPSIBLINGS | WS_CHILD) |
(style & (WS_VSCROLL | CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE));
if( lphc->dwStyle & CBS_SORT )
Index: dlls/user/listbox.c
===================================================================
RCS file: /var/cvs/wine/dlls/user/listbox.c,v
retrieving revision 1.3
diff -u -r1.3 listbox.c
--- dlls/user/listbox.c 11 Oct 2004 19:51:16 -0000 1.3
+++ dlls/user/listbox.c 14 Oct 2004 14:09:48 -0000
@@ -29,9 +29,7 @@
* TODO:
* - GetListBoxInfo()
* - LB_GETLISTBOXINFO
- * - LBS_COMBOBOX
* - LBS_NODATA
- * - LBS_STANDARD
* - LB_SETLOCALE: some FIXMEs remain
* - LBS_USETABSTOPS: some FIXMEs remain
*/
@@ -56,7 +54,6 @@
#include "win.h"
WINE_DEFAULT_DEBUG_CHANNEL(listbox);
-WINE_DECLARE_DEBUG_CHANNEL(combo);
/* Items array granularity */
#define LB_ARRAY_GRANULARITY 16
@@ -137,8 +134,6 @@
static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
-static LRESULT WINAPI ComboLBWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
-static LRESULT WINAPI ComboLBWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
static LRESULT WINAPI ListBoxWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
static LRESULT WINAPI ListBoxWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
@@ -166,8 +161,8 @@
{
"ComboLBox", /* name */
CS_DBLCLKS | CS_SAVEBITS, /* style */
- ComboLBWndProcA, /* procA */
- ComboLBWndProcW, /* procW */
+ ListBoxWndProcA, /* procA */
+ ListBoxWndProcW, /* procW */
sizeof(LB_DESCR *), /* extra */
IDC_ARROW, /* cursor */
0 /* brush */
@@ -2494,7 +2489,7 @@
if( lphc )
{
- TRACE_(combo)("[%p]: resetting owner %p -> %p\n", hwnd, descr->owner, lphc->self );
+ TRACE("[%p]: resetting owner %p -> %p\n", hwnd, descr->owner, lphc->self );
descr->owner = lphc->self;
}
@@ -2553,23 +2548,29 @@
{
LRESULT ret;
LB_DESCR *descr;
+ LPHEADCOMBO lphc = 0;
+
+ if (!IsWindow(hwnd)) return 0;
- if (!(descr = (LB_DESCR *)GetWindowLongA( hwnd, 0 )))
+ if (!(descr = (LB_DESCR *)GetWindowLongW( hwnd, 0 )))
{
if (msg == WM_CREATE)
{
- if (!LISTBOX_Create( hwnd, NULL ))
- return -1;
- TRACE("creating wnd=%p descr=%lx\n", hwnd, GetWindowLongA( hwnd, 0 ) );
+ CREATESTRUCTW *lpcs = (CREATESTRUCTW *)lParam;
+ if (lpcs->style & LBS_COMBOBOX) lphc = (LPHEADCOMBO)lpcs->lpCreateParams;
+ if (!LISTBOX_Create( hwnd, lphc )) return -1;
+ TRACE("creating wnd=%p descr=%lx\n", hwnd, GetWindowLongW( hwnd, 0 ) );
return 0;
}
/* Ignore all other messages before we get a WM_CREATE */
return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
DefWindowProcA( hwnd, msg, wParam, lParam );
}
+ if (descr->style & LBS_COMBOBOX) lphc = descr->lphc;
TRACE("[%p]: msg %s wp %08x lp %08lx\n",
hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
+
switch(msg)
{
case LB_RESETCONTENT16:
@@ -2864,7 +2865,9 @@
case LB_SETCURSEL:
if (IS_MULTISELECT(descr)) return LB_ERR;
LISTBOX_SetCaretIndex( hwnd, descr, wParam, TRUE );
- return LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
+ ret = LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
+ if (lphc && ret != LB_ERR) ret = descr->selected_item;
+ return ret;
case LB_GETSELCOUNT16:
case LB_GETSELCOUNT:
@@ -3028,21 +3031,88 @@
return DefWindowProcW( hwnd, msg, wParam, lParam );
return LISTBOX_HandleMouseWheel( hwnd, descr, wParam );
case WM_LBUTTONDOWN:
+ if (lphc)
+ return LISTBOX_HandleLButtonDownCombo(hwnd, descr, msg, wParam,
+ (INT16)LOWORD(lParam),
+ (INT16)HIWORD(lParam) );
return LISTBOX_HandleLButtonDown( hwnd, descr, wParam,
(INT16)LOWORD(lParam),
(INT16)HIWORD(lParam) );
case WM_LBUTTONDBLCLK:
+ if (lphc)
+ return LISTBOX_HandleLButtonDownCombo(hwnd, descr, msg, wParam,
+ (INT16)LOWORD(lParam),
+ (INT16)HIWORD(lParam) );
if (descr->style & LBS_NOTIFY)
SEND_NOTIFICATION( hwnd, descr, LBN_DBLCLK );
return 0;
case WM_MOUSEMOVE:
- if (GetCapture() == hwnd)
+ if ( lphc && ((lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE) )
+ {
+ BOOL captured = descr->captured;
+ POINT mousePos;
+ RECT clientRect;
+
+ mousePos.x = (INT16)LOWORD(lParam);
+ mousePos.y = (INT16)HIWORD(lParam);
+
+ /*
+ * If we are in a dropdown combobox, we simulate that
+ * the mouse is captured to show the tracking of the item.
+ */
+ if (GetClientRect(hwnd, &clientRect) && PtInRect( &clientRect, mousePos ))
+ descr->captured = TRUE;
+
+ LISTBOX_HandleMouseMove( hwnd, descr, mousePos.x, mousePos.y);
+
+ descr->captured = captured;
+ }
+ else if (GetCapture() == hwnd)
+ {
LISTBOX_HandleMouseMove( hwnd, descr, (INT16)LOWORD(lParam),
(INT16)HIWORD(lParam) );
+ }
return 0;
case WM_LBUTTONUP:
+ if (lphc)
+ {
+ POINT mousePos;
+ RECT clientRect;
+
+ /*
+ * If the mouse button "up" is not in the listbox,
+ * we make sure there is no selection by re-selecting the
+ * item that was selected when the listbox was made visible.
+ */
+ mousePos.x = (INT16)LOWORD(lParam);
+ mousePos.y = (INT16)HIWORD(lParam);
+
+ GetClientRect(hwnd, &clientRect);
+
+ /*
+ * When the user clicks outside the combobox and the focus
+ * is lost, the owning combobox will send a fake buttonup with
+ * 0xFFFFFFF as the mouse location, we must also revert the
+ * selection to the original selection.
+ */
+ if ( (lParam == (LPARAM)-1) || (!PtInRect( &clientRect, mousePos )) )
+ LISTBOX_MoveCaret( hwnd, descr, lphc->droppedIndex, FALSE );
+ }
return LISTBOX_HandleLButtonUp( hwnd, descr );
case WM_KEYDOWN:
+ if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
+ {
+ /* for some reason Windows makes it possible to
+ * show/hide ComboLBox by sending it WM_KEYDOWNs */
+
+ if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
+ ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
+ && (wParam == VK_DOWN || wParam == VK_UP)) )
+ {
+ COMBO_FlipListbox( lphc, FALSE, FALSE );
+ return 0;
+ }
+ }
return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
case WM_CHAR:
{
@@ -3075,30 +3145,34 @@
}
return 1;
case WM_DROPFILES:
- if( !descr->lphc )
- return unicode ? SendMessageW( descr->owner, msg, wParam, lParam ) :
- SendMessageA( descr->owner, msg, wParam, lParam );
+ if( lphc ) return 0;
+ return unicode ? SendMessageW( descr->owner, msg, wParam, lParam ) :
+ SendMessageA( descr->owner, msg, wParam, lParam );
+
+ case WM_NCDESTROY:
+ if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
+ lphc->hWndLBox = 0;
break;
+ case WM_NCACTIVATE:
+ if (lphc) return 0;
+ break;
+
default:
if ((msg >= WM_USER) && (msg < 0xc000))
WARN("[%p]: unknown msg %04x wp %08x lp %08lx\n",
hwnd, msg, wParam, lParam );
- return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
- DefWindowProcA( hwnd, msg, wParam, lParam );
}
- return 0;
+
+ return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
+ DefWindowProcA( hwnd, msg, wParam, lParam );
}
/***********************************************************************
* ListBoxWndProcA
- *
- * This is just a wrapper for the real wndproc, it only does window locking
- * and unlocking.
*/
static LRESULT WINAPI ListBoxWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
- if (!IsWindow(hwnd)) return 0;
return ListBoxWndProc_common( hwnd, msg, wParam, lParam, FALSE );
}
@@ -3107,171 +3181,5 @@
*/
static LRESULT WINAPI ListBoxWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
- if (!IsWindow(hwnd)) return 0;
return ListBoxWndProc_common( hwnd, msg, wParam, lParam, TRUE );
}
-
-/***********************************************************************
- * ComboLBWndProc_common
- *
- * The real combo listbox wndproc
- */
-static LRESULT WINAPI ComboLBWndProc_common( HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam, BOOL unicode )
-{
- LRESULT lRet = 0;
- LB_DESCR *descr;
- LPHEADCOMBO lphc;
-
- if (!(descr = (LB_DESCR *)GetWindowLongA( hwnd, 0 )))
- {
- if (msg == WM_CREATE)
- {
- CREATESTRUCTA *lpcs = (CREATESTRUCTA *)lParam;
- TRACE_(combo)("\tpassed parent handle = %p\n",lpcs->lpCreateParams);
- lphc = (LPHEADCOMBO)(lpcs->lpCreateParams);
- return LISTBOX_Create( hwnd, lphc );
- }
- /* Ignore all other messages before we get a WM_CREATE */
- return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
- DefWindowProcA( hwnd, msg, wParam, lParam );
- }
-
- TRACE_(combo)("[%p]: msg %s wp %08x lp %08lx\n",
- hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
-
- if ((lphc = descr->lphc) != NULL)
- {
- switch( msg )
- {
- case WM_MOUSEMOVE:
- if ( (CB_GETTYPE(lphc) != CBS_SIMPLE) )
- {
- POINT mousePos;
- BOOL captured;
- RECT clientRect;
-
- mousePos.x = (INT16)LOWORD(lParam);
- mousePos.y = (INT16)HIWORD(lParam);
-
- /*
- * If we are in a dropdown combobox, we simulate that
- * the mouse is captured to show the tracking of the item.
- */
- GetClientRect(hwnd, &clientRect);
-
- if (PtInRect( &clientRect, mousePos ))
- {
- captured = descr->captured;
- descr->captured = TRUE;
-
- LISTBOX_HandleMouseMove( hwnd, descr,
- mousePos.x, mousePos.y);
-
- descr->captured = captured;
-
- }
- else
- {
- LISTBOX_HandleMouseMove( hwnd, descr,
- mousePos.x, mousePos.y);
- }
-
- return 0;
-
- }
- break;
-
- case WM_LBUTTONUP:
- {
- POINT mousePos;
- RECT clientRect;
-
- /*
- * If the mouse button "up" is not in the listbox,
- * we make sure there is no selection by re-selecting the
- * item that was selected when the listbox was made visible.
- */
- mousePos.x = (INT16)LOWORD(lParam);
- mousePos.y = (INT16)HIWORD(lParam);
-
- GetClientRect(hwnd, &clientRect);
-
- /*
- * When the user clicks outside the combobox and the focus
- * is lost, the owning combobox will send a fake buttonup with
- * 0xFFFFFFF as the mouse location, we must also revert the
- * selection to the original selection.
- */
- if ( (lParam == (LPARAM)-1) ||
- (!PtInRect( &clientRect, mousePos )) )
- {
- LISTBOX_MoveCaret( hwnd, descr, lphc->droppedIndex, FALSE );
- }
- }
- return LISTBOX_HandleLButtonUp( hwnd, descr );
- case WM_LBUTTONDBLCLK:
- case WM_LBUTTONDOWN:
- return LISTBOX_HandleLButtonDownCombo(hwnd, descr, msg, wParam,
- (INT16)LOWORD(lParam),
- (INT16)HIWORD(lParam) );
- case WM_NCACTIVATE:
- return FALSE;
- case WM_KEYDOWN:
- if( CB_GETTYPE(lphc) != CBS_SIMPLE )
- {
- /* for some reason(?) Windows makes it possible to
- * show/hide ComboLBox by sending it WM_KEYDOWNs */
-
- if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
- ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
- && (wParam == VK_DOWN || wParam == VK_UP)) )
- {
- COMBO_FlipListbox( lphc, FALSE, FALSE );
- return 0;
- }
- }
- return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
-
- case LB_SETCURSEL16:
- case LB_SETCURSEL:
- lRet = unicode ? ListBoxWndProcW( hwnd, msg, wParam, lParam ) :
- ListBoxWndProcA( hwnd, msg, wParam, lParam );
- lRet =(lRet == LB_ERR) ? lRet : descr->selected_item;
- return lRet;
- case WM_NCDESTROY:
- if( CB_GETTYPE(lphc) != CBS_SIMPLE )
- lphc->hWndLBox = 0;
- break;
- }
- }
-
- /* default handling: call listbox wnd proc */
- lRet = unicode ? ListBoxWndProcW( hwnd, msg, wParam, lParam ) :
- ListBoxWndProcA( hwnd, msg, wParam, lParam );
-
- TRACE_(combo)("\t default on msg [%04x]\n", (UINT16)msg );
-
- return lRet;
-}
-
-/***********************************************************************
- * ComboLBWndProcA
- *
- * NOTE: in Windows, winproc address of the ComboLBox is the same
- * as that of the Listbox.
- */
-LRESULT WINAPI ComboLBWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
- if (!IsWindow(hwnd)) return 0;
- return ComboLBWndProc_common( hwnd, msg, wParam, lParam, FALSE );
-}
-
-/***********************************************************************
- * ComboLBWndProcW
- */
-LRESULT WINAPI ComboLBWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
- if (!IsWindow(hwnd)) return 0;
- return ComboLBWndProc_common( hwnd, msg, wParam, lParam, TRUE );
-}
More information about the wine-patches
mailing list