-/* $Id: listbox.c,v 1.14 2003/12/14 19:36:15 sedwards Exp $
+/*
+ * Listbox controls
*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS User32
- * PURPOSE: ListBox controls
- * FILE: lib/user32/controls/listbox.c
- * PROGRAMER: Andrew Greenwood
- * REVISION HISTORY: 2003/08/17 Created
- * NOTES: Adapted from Wine
+ * Copyright 1996 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <user32.h>
#define NDEBUG
-#include <string.h>
-#include <stdlib.h>
-//#include <stdio.h>
-#include "windows.h"
-#include "controls.h"
-#include "user32/regcontrol.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
-
-/* Unimplemented yet:
- * - LBS_USETABSTOPS
- * - Locale handling
- *
- * Probably needs improvement:
- * - LBS_NOSEL
- */
+#include <debug.h>
/* Start of hack section -------------------------------- */
#define WS_EX_DRAGDETECT 0x00000002L
#define WM_BEGINDRAG 0x022C
+UINT STDCALL SetSystemTimer(HWND,UINT_PTR,UINT,TIMERPROC);
+BOOL STDCALL KillSystemTimer(HWND,UINT_PTR);
+
/* End of hack section -------------------------------- */
+/* Unimplemented yet:
+ * - LBS_USETABSTOPS
+ * - Locale handling
+ *
+ * Probably needs improvement:
+ * - LBS_NOSEL
+ */
+
/* Items array granularity */
#define LB_ARRAY_GRANULARITY 16
/* Listbox structure */
typedef struct
{
+ HWND self; /* Our own window handle */
HWND owner; /* Owner window to send notifications to */
UINT style; /* Window style */
INT width; /* Window width */
INT horz_pos; /* Horizontal position */
INT nb_tabs; /* Number of tabs in array */
INT *tabs; /* Array of tabs */
+ INT avg_char_width; /* Average width of characters */
BOOL caret_on; /* Is caret on? */
BOOL captured; /* Is mouse captured? */
BOOL in_focus;
#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(descr,code) \
(SendMessageW( (descr)->owner, WM_COMMAND, \
- MAKEWPARAM( GetWindowLongA((hwnd),GWL_ID), (code)), (LPARAM)(hwnd) ))
+ MAKEWPARAM( GetWindowLongPtrW((descr->self),GWLP_ID), (code)), (LPARAM)(descr->self) ))
#define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
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 );
*/
const struct builtin_class_descr LISTBOX_builtin_class =
{
+#ifdef __REACTOS__
L"ListBox", /* name */
- CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/, /* style */
+ CS_DBLCLKS /*| CS_PARENTDC*/, /* style */
(WNDPROC)ListBoxWndProcW, /* procW */
(WNDPROC)ListBoxWndProcA, /* procA */
sizeof(LB_DESCR *), /* extra */
(LPCWSTR) IDC_ARROW, /* cursor */
0 /* brush */
+#else
+ "ListBox", /* name */
+ CS_DBLCLKS /*| CS_PARENTDC*/, /* style */
+ ListBoxWndProcA, /* procA */
+ ListBoxWndProcW, /* procW */
+ sizeof(LB_DESCR *), /* extra */
+ IDC_ARROW, /* cursor */
+ 0 /* brush */
+#endif
};
*/
const struct builtin_class_descr COMBOLBOX_builtin_class =
{
+#ifdef __REACTOS__
L"ComboLBox", /* name */
- CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS, /* style */
- (WNDPROC)ComboLBWndProcW, /* procW */
- (WNDPROC)ComboLBWndProcA, /* procA */
+ CS_DBLCLKS | CS_SAVEBITS, /* style */
+ (WNDPROC)ListBoxWndProcW, /* procW */
+ (WNDPROC)ListBoxWndProcA, /* procA */
sizeof(LB_DESCR *), /* extra */
(LPCWSTR) IDC_ARROW, /* cursor */
0 /* brush */
+#else
+ "ComboLBox", /* name */
+ CS_DBLCLKS | CS_SAVEBITS, /* style */
+ ListBoxWndProcA, /* procA */
+ ListBoxWndProcW, /* procW */
+ sizeof(LB_DESCR *), /* extra */
+ IDC_ARROW, /* cursor */
+ 0 /* brush */
+#endif
};
-#if 0
+#ifndef __REACTOS__
+/* check whether app is a Win 3.1 app */
+inline static BOOL is_old_app( HWND hwnd )
+{
+ return (GetExpWinVer16( GetWindowLongA(hwnd,GWL_HINSTANCE) ) & 0xFF00 ) == 0x0300;
+}
+#endif
+
+
/***********************************************************************
* LISTBOX_Dump
*/
for (i = 0, item = descr->items; i < descr->nb_items; i++, item++)
{
TRACE( "%4d: %-40s %d %08lx %3d\n",
- i,
- debugstr_w(item->str),
- item->selected,
- item->data,
- item->height );
+ i, debugstr_w(item->str), item->selected, item->data, item->height );
}
}
-#endif
+
/***********************************************************************
* LISTBOX_GetCurrentPageSize
* Update the scrollbars. Should be called whenever the content
* of the listbox changes.
*/
-static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_UpdateScroll( LB_DESCR *descr )
{
SCROLLINFO info;
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
if (descr->style & WS_HSCROLL)
- SetScrollInfo( hwnd, SB_HORZ, &info, TRUE );
+ SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
info.nMax = 0;
info.fMask = SIF_RANGE;
if (descr->style & WS_VSCROLL)
- SetScrollInfo( hwnd, SB_VERT, &info, TRUE );
+ SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
}
else
{
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
if (descr->style & WS_VSCROLL)
- SetScrollInfo( hwnd, SB_VERT, &info, TRUE );
+ SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
if (descr->horz_extent)
{
if (descr->style & LBS_DISABLENOSCROLL)
info.fMask |= SIF_DISABLENOSCROLL;
if (descr->style & WS_HSCROLL)
- SetScrollInfo( hwnd, SB_HORZ, &info, TRUE );
+ SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
}
}
}
*
* Set the top item of the listbox, scrolling up or down if necessary.
*/
-static LRESULT LISTBOX_SetTopItem( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index,
BOOL scroll )
{
INT max = LISTBOX_GetMaxTopIndex( descr );
{
INT diff = (descr->top_item - index) / descr->page_size * descr->column_width;
if (scroll && (abs(diff) < descr->width))
- ScrollWindowEx( hwnd, diff, 0, NULL, NULL, 0, NULL,
+ ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
else
diff = (descr->top_item - index) * descr->item_height;
if (abs(diff) < descr->height)
- ScrollWindowEx( hwnd, 0, diff, NULL, NULL, 0, NULL,
+ ScrollWindowEx( descr->self, 0, diff, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
else
scroll = FALSE;
}
- if (!scroll) InvalidateRect( hwnd, NULL, TRUE );
+ if (!scroll) InvalidateRect( descr->self, NULL, TRUE );
descr->top_item = index;
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdateScroll( descr );
return LB_OKAY;
}
* Update the page size. Should be called when the size of
* the client area or the item height changes.
*/
-static void LISTBOX_UpdatePage( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_UpdatePage( LB_DESCR *descr )
{
INT page_size;
if (page_size == descr->page_size) return;
descr->page_size = page_size;
if (descr->style & LBS_MULTICOLUMN)
- InvalidateRect( hwnd, NULL, TRUE );
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item, FALSE );
+ InvalidateRect( descr->self, NULL, TRUE );
+ LISTBOX_SetTopItem( descr, descr->top_item, FALSE );
}
* Update the size of the listbox. Should be called when the size of
* the client area changes.
*/
-static void LISTBOX_UpdateSize( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_UpdateSize( LB_DESCR *descr )
{
RECT rect;
- GetClientRect( hwnd, &rect );
+ GetClientRect( descr->self, &rect );
descr->width = rect.right - rect.left;
descr->height = rect.bottom - rect.top;
if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE))
INT remaining;
RECT rect;
- GetWindowRect( hwnd, &rect );
+ GetWindowRect( descr->self, &rect );
if(descr->item_height != 0)
remaining = descr->height % descr->item_height;
else
remaining = 0;
if ((descr->height > descr->item_height) && remaining)
{
+#ifndef __REACTOS__
if (is_old_app(hwnd))
{ /* give a margin for error to 16 bits programs - if we need
less than the height of the nonclient area, round to the
if ((descr->item_height - remaining) <= ncheight)
remaining = remaining - descr->item_height;
}
+#endif
TRACE("[%p]: changing height %d -> %d\n",
- hwnd, descr->height, descr->height - remaining );
- SetWindowPos( hwnd, 0, 0, 0, rect.right - rect.left,
+ descr->self, descr->height, descr->height - remaining );
+ SetWindowPos( descr->self, 0, 0, 0, rect.right - rect.left,
rect.bottom - rect.top - remaining,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
return;
}
}
- TRACE("[%p]: new size = %d,%d\n", hwnd, descr->width, descr->height );
- LISTBOX_UpdatePage( hwnd, descr );
- LISTBOX_UpdateScroll( hwnd, descr );
+ TRACE("[%p]: new size = %d,%d\n", descr->self, descr->width, descr->height );
+ LISTBOX_UpdatePage( descr );
+ LISTBOX_UpdateScroll( descr );
/* Invalidate the focused item so it will be repainted correctly */
if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
{
- InvalidateRect( hwnd, &rect, FALSE );
+ InvalidateRect( descr->self, &rect, FALSE );
}
}
static LRESULT LISTBOX_GetItemRect( LB_DESCR *descr, INT index, RECT *rect )
{
/* Index <= 0 is legal even on empty listboxes */
- if (index && (index >= descr->nb_items)) return -1;
+ if (index && (index >= descr->nb_items))
+ {
+ memset(rect, 0, sizeof(*rect));
+ SetLastError(ERROR_INVALID_INDEX);
+ return LB_ERR;
+ }
SetRect( rect, 0, 0, descr->width, descr->height );
if (descr->style & LBS_MULTICOLUMN)
{
*
* Paint an item.
*/
-static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
+static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc,
const RECT *rect, INT index, UINT action, BOOL ignoreFocus )
{
LB_ITEMDATA *item = NULL;
DRAWITEMSTRUCT dis;
RECT r;
HRGN hrgn;
- UINT id = GetWindowLongA( hwnd, GWL_ID );
if (!item)
{
if (action == ODA_FOCUS)
DrawFocusRect( hdc, rect );
else
-// FIXME("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
+ FIXME("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
return;
}
drawing the item, *and* restore the previous region
after they are done, so a region has better to exist
else everything ends clipped */
- GetClientRect(hwnd, &r);
+ GetClientRect(descr->self, &r);
hrgn = CreateRectRgnIndirect(&r);
SelectClipRgn( hdc, hrgn);
DeleteObject( hrgn );
dis.CtlType = ODT_LISTBOX;
- dis.CtlID = id;
- dis.hwndItem = hwnd;
+ dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID );
+ dis.hwndItem = descr->self;
dis.itemAction = action;
dis.hDC = hdc;
dis.itemID = index;
if (!ignoreFocus && (descr->focus_item == index) &&
(descr->caret_on) &&
(descr->in_focus)) dis.itemState |= ODS_FOCUS;
- if (!IsWindowEnabled(hwnd)) dis.itemState |= ODS_DISABLED;
+ if (!IsWindowEnabled(descr->self)) dis.itemState |= ODS_DISABLED;
dis.itemData = item ? item->data : 0;
dis.rcItem = *rect;
TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%ld,%ld-%ld,%ld\n",
- hwnd, index, item ? debugstr_w(item->str) : "", action,
+ descr->self, index, item ? debugstr_w(item->str) : "", action,
dis.itemState, rect->left, rect->top, rect->right, rect->bottom );
- SendMessageW(descr->owner, WM_DRAWITEM, id, (LPARAM)&dis);
+ SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
}
else
{
}
TRACE("[%p]: painting %d (%s) action=%02x rect=%ld,%ld-%ld,%ld\n",
- hwnd, index, item ? debugstr_w(item->str) : "", action,
+ descr->self, index, item ? debugstr_w(item->str) : "", action,
rect->left, rect->top, rect->right, rect->bottom );
if (!item)
ExtTextOutW( hdc, rect->left + 1, rect->top,
*
* Change the redraw flag.
*/
-static void LISTBOX_SetRedraw( HWND hwnd, LB_DESCR *descr, BOOL on )
+static void LISTBOX_SetRedraw( LB_DESCR *descr, BOOL on )
{
if (on)
{
descr->style &= ~LBS_NOREDRAW;
if (descr->style & LBS_DISPLAYCHANGED)
{ /* page was changed while setredraw false, refresh automatically */
- InvalidateRect(hwnd, NULL, TRUE);
+ InvalidateRect(descr->self, NULL, TRUE);
if ((descr->top_item + descr->page_size) > descr->nb_items)
{ /* reset top of page if less than number of items/page */
descr->top_item = descr->nb_items - descr->page_size;
}
descr->style &= ~LBS_DISPLAYCHANGED;
}
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdateScroll( descr );
}
else descr->style |= LBS_NOREDRAW;
}
*
* Repaint a single item synchronously.
*/
-static void LISTBOX_RepaintItem( HWND hwnd, LB_DESCR *descr, INT index,
+static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index,
UINT action )
{
HDC hdc;
HBRUSH hbrush, oldBrush = 0;
/* Do not repaint the item if the item is not visible */
- if (!IsWindowVisible(hwnd)) return;
+ if (!IsWindowVisible(descr->self)) return;
if (descr->style & LBS_NOREDRAW)
{
descr->style |= LBS_DISPLAYCHANGED;
return;
}
if (LISTBOX_GetItemRect( descr, index, &rect ) != 1) return;
- if (!(hdc = GetDCEx( hwnd, 0, DCX_CACHE ))) return;
+ if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
if (descr->font) oldFont = SelectObject( hdc, descr->font );
hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
- (WPARAM)hdc, (LPARAM)hwnd );
+ (WPARAM)hdc, (LPARAM)descr->self );
if (hbrush) oldBrush = SelectObject( hdc, hbrush );
- if (!IsWindowEnabled(hwnd))
+ if (!IsWindowEnabled(descr->self))
SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
- LISTBOX_PaintItem( hwnd, descr, hdc, &rect, index, action, FALSE );
+ LISTBOX_PaintItem( descr, hdc, &rect, index, action, FALSE );
if (oldFont) SelectObject( hdc, oldFont );
if (oldBrush) SelectObject( hdc, oldBrush );
- ReleaseDC( hwnd, hdc );
+ ReleaseDC( descr->self, hdc );
}
/***********************************************************************
* LISTBOX_InitStorage
*/
-static LRESULT LISTBOX_InitStorage( HWND hwnd, LB_DESCR *descr, INT nb_items )
+static LRESULT LISTBOX_InitStorage( LB_DESCR *descr, INT nb_items )
{
LB_ITEMDATA *item;
nb_items += LB_ARRAY_GRANULARITY - 1;
nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
- if (descr->items)
+ if (descr->items) {
nb_items += HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
- if (!(item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
- nb_items * sizeof(LB_ITEMDATA) )))
+ item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
+ nb_items * sizeof(LB_ITEMDATA));
+ }
+ else {
+ item = HeapAlloc( GetProcessHeap(), 0,
+ nb_items * sizeof(LB_ITEMDATA));
+ }
+
+ if (!item)
{
- SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
+ SEND_NOTIFICATION( descr, LBN_ERRSPACE );
return LB_ERRSPACE;
}
descr->items = item;
/***********************************************************************
* LISTBOX_SetTabStops
*/
-static BOOL LISTBOX_SetTabStops( HWND hwnd, LB_DESCR *descr, INT count,
+static BOOL LISTBOX_SetTabStops( LB_DESCR *descr, INT count,
LPINT tabs, BOOL short_ints )
{
- if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
- if (descr->tabs) HeapFree( GetProcessHeap(), 0, descr->tabs );
+ INT i;
+
+ if (!(descr->style & LBS_USETABSTOPS))
+ {
+ SetLastError(ERROR_LB_WITHOUT_TABSTOPS);
+ return FALSE;
+ }
+
+ HeapFree( GetProcessHeap(), 0, descr->tabs );
if (!(descr->nb_tabs = count))
{
descr->tabs = NULL;
return TRUE;
}
- /* FIXME: count = 1 */
- if (!(descr->tabs = (INT *)HeapAlloc( GetProcessHeap(), 0,
- descr->nb_tabs * sizeof(INT) )))
+ if (!(descr->tabs = HeapAlloc( GetProcessHeap(), 0,
+ descr->nb_tabs * sizeof(INT) )))
return FALSE;
+#ifndef __REACTOS__
if (short_ints)
{
INT i;
if (TRACE_ON(listbox)) TRACE("\n");
}
else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
- /* FIXME: repaint the window? */
+#else
+ memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
+#endif
+
+ /* convert into "dialog units"*/
+ for (i = 0; i < descr->nb_tabs; i++)
+ descr->tabs[i] = MulDiv(descr->tabs[i], descr->avg_char_width, 4);
+
return TRUE;
}
/***********************************************************************
* LISTBOX_GetText
*/
-static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPARAM lParam, BOOL unicode )
+static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPWSTR buffer, BOOL unicode )
{
- if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ if ((index < 0) || (index >= descr->nb_items))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ return LB_ERR;
+ }
if (HAS_STRINGS(descr))
{
- if (!lParam)
- return strlenW(descr->items[index].str);
+ if (!buffer)
+ {
+ DWORD len = strlenW(descr->items[index].str);
+ if( unicode )
+ return len;
+ return WideCharToMultiByte( CP_ACP, 0, descr->items[index].str, len,
+ NULL, 0, NULL, NULL );
+ }
TRACE("index %d (0x%04x) %s\n", index, index, debugstr_w(descr->items[index].str));
if(unicode)
{
- LPWSTR buffer = (LPWSTR)lParam;
strcpyW( buffer, descr->items[index].str );
return strlenW(buffer);
}
else
{
- LPSTR buffer = (LPSTR)lParam;
- return WideCharToMultiByte(CP_ACP, 0, descr->items[index].str, -1, buffer, 0x7FFFFFFF, NULL, NULL) - 1;
+ return WideCharToMultiByte(CP_ACP, 0, descr->items[index].str, -1, (LPSTR)buffer, 0x7FFFFFFF, NULL, NULL) - 1;
}
} else {
- if (lParam)
- *((LPDWORD)lParam)=*(LPDWORD)(&descr->items[index].data);
+ if (buffer)
+ *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
return sizeof(DWORD);
}
}
+static inline INT LISTBOX_lstrcmpiW( LCID lcid, LPCWSTR str1, LPCWSTR str2 )
+{
+ INT ret = CompareStringW( lcid, NORM_IGNORECASE, str1, -1, str2, -1 );
+ if (ret == CSTR_LESS_THAN)
+ return -1;
+ if (ret == CSTR_EQUAL)
+ return 0;
+ if (ret == CSTR_GREATER_THAN)
+ return 1;
+ return -1;
+}
/***********************************************************************
* LISTBOX_FindStringPos
* Find the nearest string located before a given string in sort order.
* If 'exact' is TRUE, return an error if we don't get an exact match.
*/
-static INT LISTBOX_FindStringPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str,
- BOOL exact )
+static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
{
INT index, min, max, res = -1;
{
index = (min + max) / 2;
if (HAS_STRINGS(descr))
- res = lstrcmpiW( str, descr->items[index].str);
+ res = LISTBOX_lstrcmpiW( descr->locale, str, descr->items[index].str);
else
{
COMPAREITEMSTRUCT cis;
- UINT id = GetWindowLongA( hwnd, GWL_ID );
+ UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
cis.CtlType = ODT_LISTBOX;
cis.CtlID = id;
- cis.hwndItem = hwnd;
+ cis.hwndItem = descr->self;
/* note that some application (MetaStock) expects the second item
* to be in the listbox */
cis.itemID1 = -1;
return exact ? -1 : max;
}
-
/***********************************************************************
* LISTBOX_FindFileStrPos
*
* Find the nearest string located before a given string in directory
* sort order (i.e. first files, then directories, then drives).
*/
-static INT LISTBOX_FindFileStrPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str )
+static INT LISTBOX_FindFileStrPos( LB_DESCR *descr, LPCWSTR str )
{
INT min, max, res = -1;
if (!HAS_STRINGS(descr))
- return LISTBOX_FindStringPos( hwnd, descr, str, FALSE );
+ return LISTBOX_FindStringPos( descr, str, FALSE );
min = 0;
max = descr->nb_items;
while (min != max)
else /* directory */
{
if (str[1] == '-') res = 1;
- else res = lstrcmpiW( str, p );
+ else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
}
}
else /* filename */
{
if (*str == '[') res = 1;
- else res = lstrcmpiW( str, p );
+ else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
}
if (!res) return index;
if (res < 0) max = index;
*
* Find the item beginning with a given string.
*/
-static INT LISTBOX_FindString( HWND hwnd, LB_DESCR *descr, INT start,
- LPCWSTR str, BOOL exact )
+static INT LISTBOX_FindString( LB_DESCR *descr, INT start, LPCWSTR str, BOOL exact )
{
INT i;
LB_ITEMDATA *item;
if (exact)
{
for (i = start + 1; i < descr->nb_items; i++, item++)
- if (!lstrcmpiW( str, item->str )) return i;
+ if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
for (i = 0, item = descr->items; i <= start; i++, item++)
- if (!lstrcmpiW( str, item->str )) return i;
+ if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
}
else
{
{
if (exact && (descr->style & LBS_SORT))
/* If sorted, use a WM_COMPAREITEM binary search */
- return LISTBOX_FindStringPos( hwnd, descr, str, TRUE );
+ return LISTBOX_FindStringPos( descr, str, TRUE );
/* Otherwise use a linear search */
for (i = start + 1; i < descr->nb_items; i++, item++)
- if (item->data == (DWORD)str) return i;
+ if (item->data == (ULONG_PTR)str) return i;
for (i = 0, item = descr->items; i <= start; i++, item++)
- if (item->data == (DWORD)str) return i;
+ if (item->data == (ULONG_PTR)str) return i;
}
return LB_ERR;
}
INT i, count;
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++)
if (item->selected) count++;
return count;
}
+
+#ifndef __REACTOS__
+/***********************************************************************
+ * LISTBOX_GetSelItems16
+ */
+static LRESULT LISTBOX_GetSelItems16( LB_DESCR *descr, INT16 max, LPINT16 array )
+{
+ INT i, count;
+ LB_ITEMDATA *item = descr->items;
+
+ if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+ for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+ if (item->selected) array[count++] = (INT16)i;
+ return count;
+}
+#endif
+
+
/***********************************************************************
* LISTBOX_GetSelItems
*/
-static LRESULT LISTBOX_GetSelItems( LB_DESCR *descr, INT maxcount, LPINT array )
+static LRESULT LISTBOX_GetSelItems( LB_DESCR *descr, INT max, LPINT array )
{
INT i, count;
LB_ITEMDATA *item = descr->items;
if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
- for (i = count = 0; (i < descr->nb_items) && (count < maxcount); i++, item++)
+ for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
if (item->selected) array[count++] = i;
return count;
}
/***********************************************************************
* LISTBOX_Paint
*/
-static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
+static LRESULT LISTBOX_Paint( LB_DESCR *descr, HDC hdc )
{
INT i, col_pos = descr->page_size - 1;
RECT rect;
if (descr->font) oldFont = SelectObject( hdc, descr->font );
hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
- (WPARAM)hdc, (LPARAM)hwnd );
+ (WPARAM)hdc, (LPARAM)descr->self );
if (hbrush) oldBrush = SelectObject( hdc, hbrush );
- if (!IsWindowEnabled(hwnd)) SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+ if (!IsWindowEnabled(descr->self)) SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
(descr->in_focus))
{
/* Special case for empty listbox: paint focus rect */
rect.bottom = rect.top + descr->item_height;
- LISTBOX_PaintItem( hwnd, descr, hdc, &rect, descr->focus_item,
+ ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+ &rect, NULL, 0, NULL );
+ LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item,
ODA_FOCUS, FALSE );
rect.top = rect.bottom;
}
focusRect.top = rect.top;
focusRect.bottom = rect.bottom;
}
- LISTBOX_PaintItem( hwnd, descr, hdc, &rect, i, ODA_DRAWENTIRE, TRUE );
+ LISTBOX_PaintItem( descr, hdc, &rect, i, ODA_DRAWENTIRE, TRUE );
rect.top = rect.bottom;
if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
}
/* Paint the focus item now */
- if (focusRect.top != focusRect.bottom && descr->caret_on)
- LISTBOX_PaintItem( hwnd, descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
+ if (focusRect.top != focusRect.bottom &&
+ descr->caret_on && descr->in_focus)
+ LISTBOX_PaintItem( descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
if (!IS_OWNERDRAW(descr))
{
* Invalidate all items from a given item. If the specified item is not
* visible, nothing happens.
*/
-static void LISTBOX_InvalidateItems( HWND hwnd, LB_DESCR *descr, INT index )
+static void LISTBOX_InvalidateItems( LB_DESCR *descr, INT index )
{
RECT rect;
return;
}
rect.bottom = descr->height;
- InvalidateRect( hwnd, &rect, TRUE );
+ InvalidateRect( descr->self, &rect, TRUE );
if (descr->style & LBS_MULTICOLUMN)
{
/* Repaint the other columns */
rect.left = rect.right;
rect.right = descr->width;
rect.top = 0;
- InvalidateRect( hwnd, &rect, TRUE );
+ InvalidateRect( descr->self, &rect, TRUE );
}
}
}
+static void LISTBOX_InvalidateItemRect( LB_DESCR *descr, INT index )
+{
+ RECT rect;
+
+ if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
+ InvalidateRect( descr->self, &rect, TRUE );
+}
/***********************************************************************
* LISTBOX_GetItemHeight
{
if (descr->style & LBS_OWNERDRAWVARIABLE)
{
- if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ if ((index < 0) || (index >= descr->nb_items))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ return LB_ERR;
+ }
return descr->items[index].height;
}
else return descr->item_height;
/***********************************************************************
* LISTBOX_SetItemHeight
*/
-static LRESULT LISTBOX_SetItemHeight( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetItemHeight( LB_DESCR *descr, INT index,
INT height, BOOL repaint )
{
if (!height) height = 1;
if (descr->style & LBS_OWNERDRAWVARIABLE)
{
- if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
- TRACE("[%p]: item %d height = %d\n", hwnd, index, height );
+ if ((index < 0) || (index >= descr->nb_items))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ return LB_ERR;
+ }
+ TRACE("[%p]: item %d height = %d\n", descr->self, index, height );
descr->items[index].height = height;
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdateScroll( descr );
if (repaint)
- LISTBOX_InvalidateItems( hwnd, descr, index );
+ LISTBOX_InvalidateItems( descr, index );
}
else if (height != descr->item_height)
{
- TRACE("[%p]: new height = %d\n", hwnd, height );
+ TRACE("[%p]: new height = %d\n", descr->self, height );
descr->item_height = height;
- LISTBOX_UpdatePage( hwnd, descr );
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdatePage( descr );
+ LISTBOX_UpdateScroll( descr );
if (repaint)
- InvalidateRect( hwnd, 0, TRUE );
+ InvalidateRect( descr->self, 0, TRUE );
}
return LB_OKAY;
}
/***********************************************************************
* LISTBOX_SetHorizontalPos
*/
-static void LISTBOX_SetHorizontalPos( HWND hwnd, LB_DESCR *descr, INT pos )
+static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos )
{
INT diff;
pos = descr->horz_extent - descr->width;
if (pos < 0) pos = 0;
if (!(diff = descr->horz_pos - pos)) return;
- TRACE("[%p]: new horz pos = %d\n", hwnd, pos );
+ TRACE("[%p]: new horz pos = %d\n", descr->self, pos );
descr->horz_pos = pos;
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdateScroll( descr );
if (abs(diff) < descr->width)
- ScrollWindowEx( hwnd, diff, 0, NULL, NULL, 0, NULL,
+ {
+ RECT rect;
+ /* Invalidate the focused item so it will be repainted correctly */
+ if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
+ InvalidateRect( descr->self, &rect, TRUE );
+ ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
+ }
else
- InvalidateRect( hwnd, NULL, TRUE );
+ InvalidateRect( descr->self, NULL, TRUE );
}
/***********************************************************************
* LISTBOX_SetHorizontalExtent
*/
-static LRESULT LISTBOX_SetHorizontalExtent( HWND hwnd, LB_DESCR *descr,
+static LRESULT LISTBOX_SetHorizontalExtent( LB_DESCR *descr,
INT extent )
{
if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
return LB_OKAY;
if (extent <= 0) extent = 1;
if (extent == descr->horz_extent) return LB_OKAY;
- TRACE("[%p]: new horz extent = %d\n", hwnd, extent );
+ TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
descr->horz_extent = extent;
if (descr->horz_pos > extent - descr->width)
- LISTBOX_SetHorizontalPos( hwnd, descr, extent - descr->width );
+ LISTBOX_SetHorizontalPos( descr, extent - descr->width );
else
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdateScroll( descr );
return LB_OKAY;
}
/***********************************************************************
* LISTBOX_SetColumnWidth
*/
-static LRESULT LISTBOX_SetColumnWidth( HWND hwnd, LB_DESCR *descr, INT width)
+static LRESULT LISTBOX_SetColumnWidth( LB_DESCR *descr, INT width)
{
if (width == descr->column_width) return LB_OKAY;
- TRACE("[%p]: new column width = %d\n", hwnd, width );
+ TRACE("[%p]: new column width = %d\n", descr->self, width );
descr->column_width = width;
- LISTBOX_UpdatePage( hwnd, descr );
+ LISTBOX_UpdatePage( descr );
return LB_OKAY;
}
*
* Returns the item height.
*/
-static INT LISTBOX_SetFont( HWND hwnd, LB_DESCR *descr, HFONT font )
+static INT LISTBOX_SetFont( LB_DESCR *descr, HFONT font )
{
HDC hdc;
HFONT oldFont = 0;
- TEXTMETRICW tm;
+ const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ SIZE sz;
descr->font = font;
- if (!(hdc = GetDCEx( hwnd, 0, DCX_CACHE )))
+ if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE )))
{
ERR("unable to get DC.\n" );
return 16;
}
if (font) oldFont = SelectObject( hdc, font );
- GetTextMetricsW( hdc, &tm );
+ GetTextExtentPointA( hdc, alphabet, 52, &sz);
if (oldFont) SelectObject( hdc, oldFont );
- ReleaseDC( hwnd, hdc );
+ ReleaseDC( descr->self, hdc );
+
+ descr->avg_char_width = (sz.cx / 26 + 1) / 2;
if (!IS_OWNERDRAW(descr))
- LISTBOX_SetItemHeight( hwnd, descr, 0, tm.tmHeight, FALSE );
- return tm.tmHeight ;
+ LISTBOX_SetItemHeight( descr, 0, sz.cy, FALSE );
+ return sz.cy;
}
*
* Make sure that a given item is partially or fully visible.
*/
-static void LISTBOX_MakeItemVisible( HWND hwnd, LB_DESCR *descr, INT index,
+static void LISTBOX_MakeItemVisible( LB_DESCR *descr, INT index,
BOOL fully )
{
INT top;
(descr->height > (descr->page_size * descr->item_height))) return;
top = index - descr->page_size + 1;
}
- LISTBOX_SetTopItem( hwnd, descr, top, TRUE );
+ LISTBOX_SetTopItem( descr, top, TRUE );
}
/***********************************************************************
* index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
*
*/
-static LRESULT LISTBOX_SetCaretIndex( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetCaretIndex( LB_DESCR *descr, INT index,
BOOL fully_visible )
{
INT oldfocus = descr->focus_item;
if (index == oldfocus) return LB_OKAY;
descr->focus_item = index;
if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
- LISTBOX_RepaintItem( hwnd, descr, oldfocus, ODA_FOCUS );
+ LISTBOX_RepaintItem( descr, oldfocus, ODA_FOCUS );
- LISTBOX_MakeItemVisible( hwnd, descr, index, fully_visible );
+ LISTBOX_MakeItemVisible( descr, index, fully_visible );
if (descr->caret_on && (descr->in_focus))
- LISTBOX_RepaintItem( hwnd, descr, index, ODA_FOCUS );
+ LISTBOX_RepaintItem( descr, index, ODA_FOCUS );
return LB_OKAY;
}
*
* Select a range of items. Should only be used on a MULTIPLESEL listbox.
*/
-static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
+static LRESULT LISTBOX_SelectItemRange( LB_DESCR *descr, INT first,
INT last, BOOL on )
{
INT i;
if (last == -1) last = descr->nb_items - 1;
if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
- /* selected_item reflects last selected/unselected item on multiple sel */
- descr->selected_item = last;
if (on) /* Turn selection on */
{
{
if (descr->items[i].selected) continue;
descr->items[i].selected = TRUE;
- LISTBOX_RepaintItem( hwnd, descr, i, ODA_SELECT );
+ LISTBOX_InvalidateItemRect(descr, i);
}
- LISTBOX_SetCaretIndex( hwnd, descr, last, TRUE );
}
else /* Turn selection off */
{
{
if (!descr->items[i].selected) continue;
descr->items[i].selected = FALSE;
- LISTBOX_RepaintItem( hwnd, descr, i, ODA_SELECT );
+ LISTBOX_InvalidateItemRect(descr, i);
}
}
return LB_OKAY;
/***********************************************************************
* LISTBOX_SetSelection
*/
-static LRESULT LISTBOX_SetSelection( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetSelection( LB_DESCR *descr, INT index,
BOOL on, BOOL send_notify )
{
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 (descr->style & LBS_MULTIPLESEL)
{
if (index == -1) /* Select all items */
- return LISTBOX_SelectItemRange( hwnd, descr, 0, -1, on );
+ return LISTBOX_SelectItemRange( descr, 0, -1, on );
else /* Only one item */
- return LISTBOX_SelectItemRange( hwnd, descr, index, index, on );
+ return LISTBOX_SelectItemRange( descr, index, index, on );
}
else
{
if (oldsel != -1) descr->items[oldsel].selected = FALSE;
if (index != -1) descr->items[index].selected = TRUE;
descr->selected_item = index;
- if (oldsel != -1) LISTBOX_RepaintItem( hwnd, descr, oldsel, ODA_SELECT );
- if (index != -1) LISTBOX_RepaintItem( hwnd, descr, index, ODA_SELECT );
- if (send_notify && descr->nb_items) SEND_NOTIFICATION( hwnd, descr,
+ if (oldsel != -1) LISTBOX_RepaintItem( descr, oldsel, ODA_SELECT );
+ if (index != -1) LISTBOX_RepaintItem( descr, index, ODA_SELECT );
+ if (send_notify && descr->nb_items) SEND_NOTIFICATION( descr,
(index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
else
if( descr->lphc ) /* set selection change flag for parent combo */
*
* Change the caret position and extend the selection to the new caret.
*/
-static void LISTBOX_MoveCaret( HWND hwnd, LB_DESCR *descr, INT index,
+static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index,
BOOL fully_visible )
{
INT oldfocus = descr->focus_item;
/* 1. remove the focus and repaint the item */
descr->focus_item = -1;
if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
- LISTBOX_RepaintItem( hwnd, descr, oldfocus, ODA_FOCUS );
+ LISTBOX_RepaintItem( descr, oldfocus, ODA_FOCUS );
/* 2. then turn off the previous selection */
/* 3. repaint the new selected item */
INT first = min( index, descr->anchor_item );
INT last = max( index, descr->anchor_item );
if (first > 0)
- LISTBOX_SelectItemRange( hwnd, descr, 0, first - 1, FALSE );
- LISTBOX_SelectItemRange( hwnd, descr, last + 1, -1, FALSE );
- LISTBOX_SelectItemRange( hwnd, descr, first, last, TRUE );
+ LISTBOX_SelectItemRange( descr, 0, first - 1, FALSE );
+ LISTBOX_SelectItemRange( descr, last + 1, -1, FALSE );
+ LISTBOX_SelectItemRange( descr, first, last, TRUE );
}
}
else if (!(descr->style & LBS_MULTIPLESEL))
{
/* Set selection to new caret item */
- LISTBOX_SetSelection( hwnd, descr, index, TRUE, FALSE );
+ LISTBOX_SetSelection( descr, index, TRUE, FALSE );
}
/* 4. repaint the new item with the focus */
descr->focus_item = index;
- LISTBOX_MakeItemVisible( hwnd, descr, index, fully_visible );
+ LISTBOX_MakeItemVisible( descr, index, fully_visible );
if (descr->caret_on && (descr->in_focus))
- LISTBOX_RepaintItem( hwnd, descr, index, ODA_FOCUS );
+ LISTBOX_RepaintItem( descr, index, ODA_FOCUS );
}
/***********************************************************************
* LISTBOX_InsertItem
*/
-static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index,
LPWSTR str, DWORD data )
{
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;
-
- if (!descr->items)
- max_items = 0;
- else
- max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
-
+ if (index == -1) index = descr->nb_items;
+ else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
+ if (!descr->items) max_items = 0;
+ else max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
if (descr->nb_items == max_items)
{
/* We need to grow the array */
max_items += LB_ARRAY_GRANULARITY;
-
- /* In WINE it seems to be possible to use HeapReAlloc for allocating new blocks
- of memory. This doesn't work in Windows */
-
- if (descr->items&&!(item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
- max_items * sizeof(LB_ITEMDATA) )))
- {
- SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
- return LB_ERRSPACE;
- }
- else if((!descr->items)&&!(item = HeapAlloc( GetProcessHeap(), 0,
- max_items * sizeof(LB_ITEMDATA) )))
+ if (descr->items)
+ item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
+ max_items * sizeof(LB_ITEMDATA) );
+ else
+ item = HeapAlloc( GetProcessHeap(), 0,
+ max_items * sizeof(LB_ITEMDATA) );
+ if (!item)
{
- SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
+ SEND_NOTIFICATION( descr, LBN_ERRSPACE );
return LB_ERRSPACE;
}
-
descr->items = item;
}
if (descr->style & LBS_OWNERDRAWVARIABLE)
{
MEASUREITEMSTRUCT mis;
- UINT id = GetWindowLongA( hwnd, GWL_ID );
+ UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
mis.CtlType = ODT_LISTBOX;
mis.CtlID = id;
SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
item->height = mis.itemHeight ? mis.itemHeight : 1;
TRACE("[%p]: measure item %d (%s) = %d\n",
- hwnd, index, str ? debugstr_w(str) : "", item->height );
+ descr->self, index, str ? debugstr_w(str) : "", item->height );
}
/* Repaint the items */
- LISTBOX_UpdateScroll( hwnd, descr );
- LISTBOX_InvalidateItems( hwnd, descr, index );
+ LISTBOX_UpdateScroll( descr );
+ LISTBOX_InvalidateItems( descr, index );
/* Move selection and focused item */
/* If listbox was empty, set focus to the first item */
if (descr->nb_items == 1)
- LISTBOX_SetCaretIndex( hwnd, descr, 0, FALSE );
+ LISTBOX_SetCaretIndex( descr, 0, FALSE );
/* single select don't change selection index in win31 */
else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
{
descr->selected_item++;
- LISTBOX_SetSelection( hwnd, descr, descr->selected_item-1, TRUE, FALSE );
+ LISTBOX_SetSelection( descr, descr->selected_item-1, TRUE, FALSE );
}
else
{
/***********************************************************************
* LISTBOX_InsertString
*/
-static LRESULT LISTBOX_InsertString( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_InsertString( LB_DESCR *descr, INT index,
LPCWSTR str )
{
LPWSTR new_str = NULL;
if (!str) str = empty_stringW;
if (!(new_str = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR) )))
{
- SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
+ SEND_NOTIFICATION( descr, LBN_ERRSPACE );
return LB_ERRSPACE;
}
strcpyW(new_str, str);
else data = (DWORD)str;
if (index == -1) index = descr->nb_items;
- if ((ret = LISTBOX_InsertItem( hwnd, descr, index, new_str, data )) != 0)
+ if ((ret = LISTBOX_InsertItem( descr, index, new_str, data )) != 0)
{
- if (new_str) HeapFree( GetProcessHeap(), 0, new_str );
+ HeapFree( GetProcessHeap(), 0, new_str );
return ret;
}
TRACE("[%p]: added item %d %s\n",
- hwnd, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
+ descr->self, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
return index;
}
*
* Delete the content of an item. 'index' must be a valid index.
*/
-static void LISTBOX_DeleteItem( HWND hwnd, LB_DESCR *descr, INT index )
+static void LISTBOX_DeleteItem( LB_DESCR *descr, INT index )
{
/* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
* while Win95 sends it for all items with user data.
if (IS_OWNERDRAW(descr) || descr->items[index].data)
{
DELETEITEMSTRUCT dis;
- UINT id = GetWindowLongA( hwnd, GWL_ID );
+ UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
dis.CtlType = ODT_LISTBOX;
dis.CtlID = id;
dis.itemID = index;
- dis.hwndItem = hwnd;
+ dis.hwndItem = descr->self;
dis.itemData = descr->items[index].data;
SendMessageW( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
}
*
* Remove an item from the listbox and delete its content.
*/
-static LRESULT LISTBOX_RemoveItem( HWND hwnd, LB_DESCR *descr, INT index )
+static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index )
{
LB_ITEMDATA *item;
INT max_items;
- if ((index == -1) && (descr->nb_items > 0)) index = descr->nb_items - 1;
- else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+ if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
/* We need to invalidate the original rect instead of the updated one. */
- LISTBOX_InvalidateItems( hwnd, descr, index );
+ LISTBOX_InvalidateItems( descr, index );
- LISTBOX_DeleteItem( hwnd, descr, index );
+ LISTBOX_DeleteItem( descr, index );
/* Remove the item */
}
/* Repaint the items */
- LISTBOX_UpdateScroll( hwnd, descr );
+ LISTBOX_UpdateScroll( descr );
/* if we removed the scrollbar, reset the top of the list
(correct for owner-drawn ???) */
if (descr->nb_items == descr->page_size)
- LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
+ LISTBOX_SetTopItem( descr, 0, TRUE );
/* Move selection and focused item */
if (!IS_MULTISELECT(descr))
{
descr->selected_item--;
if (ISWIN31) /* win 31 do not change the selected item number */
- LISTBOX_SetSelection( hwnd, descr, descr->selected_item + 1, TRUE, FALSE);
+ LISTBOX_SetSelection( descr, descr->selected_item + 1, TRUE, FALSE);
}
}
/***********************************************************************
* LISTBOX_ResetContent
*/
-static void LISTBOX_ResetContent( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_ResetContent( LB_DESCR *descr )
{
INT i;
- for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( hwnd, descr, i );
- if (descr->items) HeapFree( GetProcessHeap(), 0, descr->items );
+ for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( descr, i );
+ HeapFree( GetProcessHeap(), 0, descr->items );
descr->nb_items = 0;
descr->top_item = 0;
descr->selected_item = -1;
/***********************************************************************
* LISTBOX_SetCount
*/
-static LRESULT LISTBOX_SetCount( HWND hwnd, LB_DESCR *descr, INT count )
+static LRESULT LISTBOX_SetCount( LB_DESCR *descr, INT count )
{
LRESULT ret;
- if (HAS_STRINGS(descr)) return LB_ERR;
+ if (HAS_STRINGS(descr))
+ {
+ SetLastError(ERROR_SETCOUNT_ON_BAD_LB);
+ return LB_ERR;
+ }
+
/* FIXME: this is far from optimal... */
if (count > descr->nb_items)
{
while (count > descr->nb_items)
- if ((ret = LISTBOX_InsertString( hwnd, descr, -1, 0 )) < 0)
+ if ((ret = LISTBOX_InsertString( descr, -1, 0 )) < 0)
return ret;
}
else if (count < descr->nb_items)
{
while (count < descr->nb_items)
- if ((ret = LISTBOX_RemoveItem( hwnd, descr, -1 )) < 0)
+ if ((ret = LISTBOX_RemoveItem( descr, -1 )) < 0)
return ret;
}
return LB_OKAY;
/***********************************************************************
* LISTBOX_Directory
*/
-static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
+static LRESULT LISTBOX_Directory( LB_DESCR *descr, UINT attrib,
LPCWSTR filespec, BOOL long_names )
{
HANDLE handle;
static const WCHAR bracketW[] = { ']',0 };
static const WCHAR dotW[] = { '.',0 };
if (!(attrib & DDL_DIRECTORY) ||
- !strcmpW( entry.cAlternateFileName, dotW )) continue;
+ !strcmpW( entry.cFileName, dotW )) continue;
buffer[0] = '[';
- if (long_names) strcpyW( buffer + 1, entry.cFileName );
- else strcpyW( buffer + 1, entry.cAlternateFileName );
+ if (!long_names && entry.cAlternateFileName[0])
+ strcpyW( buffer + 1, entry.cAlternateFileName );
+ else
+ strcpyW( buffer + 1, entry.cFileName );
strcatW(buffer, bracketW);
}
else /* not a directory */
((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
continue;
#undef ATTRIBS
- if (long_names) strcpyW( buffer, entry.cFileName );
- else strcpyW( buffer, entry.cAlternateFileName );
+ if (!long_names && entry.cAlternateFileName[0])
+ strcpyW( buffer, entry.cAlternateFileName );
+ else
+ strcpyW( buffer, entry.cFileName );
}
if (!long_names) CharLowerW( buffer );
- pos = LISTBOX_FindFileStrPos( hwnd, descr, buffer );
- if ((ret = LISTBOX_InsertString( hwnd, descr, pos, buffer )) < 0)
+ pos = LISTBOX_FindFileStrPos( descr, buffer );
+ if ((ret = LISTBOX_InsertString( descr, pos, buffer )) < 0)
break;
} while (FindNextFileW( handle, &entry ));
FindClose( handle );
for (drive = 0; drive < 26; drive++, buffer[2]++, root[0]++)
{
if (GetDriveTypeW(root) <= DRIVE_NO_ROOT_DIR) continue;
- if ((ret = LISTBOX_InsertString( hwnd, descr, -1, buffer )) < 0)
+ if ((ret = LISTBOX_InsertString( descr, -1, buffer )) < 0)
break;
}
}
/***********************************************************************
* LISTBOX_HandleVScroll
*/
-static LRESULT LISTBOX_HandleVScroll( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleVScroll( LB_DESCR *descr, WORD scrollReq, WORD pos )
{
SCROLLINFO info;
if (descr->style & LBS_MULTICOLUMN) return 0;
- switch(LOWORD(wParam))
+ switch(scrollReq)
{
case SB_LINEUP:
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item - 1, TRUE );
+ LISTBOX_SetTopItem( descr, descr->top_item - 1, TRUE );
break;
case SB_LINEDOWN:
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item + 1, TRUE );
+ LISTBOX_SetTopItem( descr, descr->top_item + 1, TRUE );
break;
case SB_PAGEUP:
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item -
+ LISTBOX_SetTopItem( descr, descr->top_item -
LISTBOX_GetCurrentPageSize( descr ), TRUE );
break;
case SB_PAGEDOWN:
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item +
+ LISTBOX_SetTopItem( descr, descr->top_item +
LISTBOX_GetCurrentPageSize( descr ), TRUE );
break;
case SB_THUMBPOSITION:
- LISTBOX_SetTopItem( hwnd, descr, HIWORD(wParam), TRUE );
+ LISTBOX_SetTopItem( descr, pos, TRUE );
break;
case SB_THUMBTRACK:
info.cbSize = sizeof(info);
info.fMask = SIF_TRACKPOS;
- GetScrollInfo( hwnd, SB_VERT, &info );
- LISTBOX_SetTopItem( hwnd, descr, info.nTrackPos, TRUE );
+ GetScrollInfo( descr->self, SB_VERT, &info );
+ LISTBOX_SetTopItem( descr, info.nTrackPos, TRUE );
break;
case SB_TOP:
- LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
+ LISTBOX_SetTopItem( descr, 0, TRUE );
break;
case SB_BOTTOM:
- LISTBOX_SetTopItem( hwnd, descr, descr->nb_items, TRUE );
+ LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
break;
}
return 0;
/***********************************************************************
* LISTBOX_HandleHScroll
*/
-static LRESULT LISTBOX_HandleHScroll( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleHScroll( LB_DESCR *descr, WORD scrollReq, WORD pos )
{
SCROLLINFO info;
INT page;
if (descr->style & LBS_MULTICOLUMN)
{
- switch(LOWORD(wParam))
+ switch(scrollReq)
{
case SB_LINELEFT:
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item-descr->page_size,
+ LISTBOX_SetTopItem( descr, descr->top_item-descr->page_size,
TRUE );
break;
case SB_LINERIGHT:
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item+descr->page_size,
+ LISTBOX_SetTopItem( descr, descr->top_item+descr->page_size,
TRUE );
break;
case SB_PAGELEFT:
page = descr->width / descr->column_width;
if (page < 1) page = 1;
- LISTBOX_SetTopItem( hwnd, descr,
+ LISTBOX_SetTopItem( descr,
descr->top_item - page * descr->page_size, TRUE );
break;
case SB_PAGERIGHT:
page = descr->width / descr->column_width;
if (page < 1) page = 1;
- LISTBOX_SetTopItem( hwnd, descr,
+ LISTBOX_SetTopItem( descr,
descr->top_item + page * descr->page_size, TRUE );
break;
case SB_THUMBPOSITION:
- LISTBOX_SetTopItem( hwnd, descr, HIWORD(wParam)*descr->page_size,
+ LISTBOX_SetTopItem( descr, pos*descr->page_size,
TRUE );
break;
case SB_THUMBTRACK:
info.cbSize = sizeof(info);
info.fMask = SIF_TRACKPOS;
- GetScrollInfo( hwnd, SB_VERT, &info );
- LISTBOX_SetTopItem( hwnd, descr, info.nTrackPos*descr->page_size,
+ GetScrollInfo( descr->self, SB_VERT, &info );
+ LISTBOX_SetTopItem( descr, info.nTrackPos*descr->page_size,
TRUE );
break;
case SB_LEFT:
- LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
+ LISTBOX_SetTopItem( descr, 0, TRUE );
break;
case SB_RIGHT:
- LISTBOX_SetTopItem( hwnd, descr, descr->nb_items, TRUE );
+ LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
break;
}
}
else if (descr->horz_extent)
{
- switch(LOWORD(wParam))
+ switch(scrollReq)
{
case SB_LINELEFT:
- LISTBOX_SetHorizontalPos( hwnd, descr, descr->horz_pos - 1 );
+ LISTBOX_SetHorizontalPos( descr, descr->horz_pos - 1 );
break;
case SB_LINERIGHT:
- LISTBOX_SetHorizontalPos( hwnd, descr, descr->horz_pos + 1 );
+ LISTBOX_SetHorizontalPos( descr, descr->horz_pos + 1 );
break;
case SB_PAGELEFT:
- LISTBOX_SetHorizontalPos( hwnd, descr,
+ LISTBOX_SetHorizontalPos( descr,
descr->horz_pos - descr->width );
break;
case SB_PAGERIGHT:
- LISTBOX_SetHorizontalPos( hwnd, descr,
+ LISTBOX_SetHorizontalPos( descr,
descr->horz_pos + descr->width );
break;
case SB_THUMBPOSITION:
- LISTBOX_SetHorizontalPos( hwnd, descr, HIWORD(wParam) );
+ LISTBOX_SetHorizontalPos( descr, pos );
break;
case SB_THUMBTRACK:
info.cbSize = sizeof(info);
info.fMask = SIF_TRACKPOS;
- GetScrollInfo( hwnd, SB_HORZ, &info );
- LISTBOX_SetHorizontalPos( hwnd, descr, info.nTrackPos );
+ GetScrollInfo( descr->self, SB_HORZ, &info );
+ LISTBOX_SetHorizontalPos( descr, info.nTrackPos );
break;
case SB_LEFT:
- LISTBOX_SetHorizontalPos( hwnd, descr, 0 );
+ LISTBOX_SetHorizontalPos( descr, 0 );
break;
case SB_RIGHT:
- LISTBOX_SetHorizontalPos( hwnd, descr,
+ LISTBOX_SetHorizontalPos( descr,
descr->horz_extent - descr->width );
break;
}
return 0;
}
-static LRESULT LISTBOX_HandleMouseWheel(HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta )
{
short gcWheelDelta = 0;
UINT pulScrollLines = 3;
-
-#if 0
+
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
-#endif
- gcWheelDelta -= (short) HIWORD(wParam);
+ gcWheelDelta -= delta;
if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
{
int cLineScroll = (int) min((UINT) descr->page_size, pulScrollLines);
cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
- LISTBOX_SetTopItem( hwnd, descr, descr->top_item + cLineScroll, TRUE );
+ LISTBOX_SetTopItem( descr, descr->top_item + cLineScroll, TRUE );
}
return 0;
}
/***********************************************************************
* LISTBOX_HandleLButtonDown
*/
-static LRESULT LISTBOX_HandleLButtonDown( HWND hwnd, LB_DESCR *descr,
- WPARAM wParam, INT x, INT y )
+static LRESULT LISTBOX_HandleLButtonDown( LB_DESCR *descr,
+ DWORD keys, INT x, INT y )
{
INT index = LISTBOX_GetItemFromPoint( descr, x, y );
- TRACE("[%p]: lbuttondown %d,%d item %d\n", hwnd, x, y, index );
+ TRACE("[%p]: lbuttondown %d,%d item %d\n", descr->self, x, y, index );
if (!descr->caret_on && (descr->in_focus)) return 0;
if (!descr->in_focus)
{
- if( !descr->lphc ) SetFocus( hwnd );
+ if( !descr->lphc ) SetFocus( descr->self );
else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit : descr->lphc->self );
}
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
FIXME: needed for !LBS_EXTENDEDSEL, too ?
- if (!(wParam & (MK_SHIFT|MK_CONTROL)))
- LISTBOX_SetSelection( hwnd, descr, -1, FALSE, FALSE);
+ if (!(keys & (MK_SHIFT|MK_CONTROL)))
+ LISTBOX_SetSelection( descr, -1, FALSE, FALSE);
*/
- if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
- if (wParam & MK_CONTROL)
+ if (!(keys & MK_SHIFT)) descr->anchor_item = index;
+ if (keys & MK_CONTROL)
{
- LISTBOX_SetCaretIndex( hwnd, descr, index, FALSE );
- LISTBOX_SetSelection( hwnd, descr, index,
+ LISTBOX_SetCaretIndex( descr, index, FALSE );
+ LISTBOX_SetSelection( descr, index,
!descr->items[index].selected,
(descr->style & LBS_NOTIFY) != 0);
}
- else LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
+ else
+ {
+ LISTBOX_MoveCaret( descr, index, FALSE );
+
+ if (descr->style & LBS_EXTENDEDSEL)
+ {
+ LISTBOX_SetSelection( descr, index,
+ descr->items[index].selected,
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
+ else
+ {
+ LISTBOX_SetSelection( descr, index,
+ !descr->items[index].selected,
+ (descr->style & LBS_NOTIFY) != 0 );
+ }
+ }
}
else
{
- LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
- LISTBOX_SetSelection( hwnd, descr, index,
- (!(descr->style & LBS_MULTIPLESEL) ||
- !descr->items[index].selected),
- (descr->style & LBS_NOTIFY) != 0 );
+ descr->anchor_item = index;
+ LISTBOX_MoveCaret( descr, index, FALSE );
+ LISTBOX_SetSelection( descr, index,
+ TRUE, (descr->style & LBS_NOTIFY) != 0 );
}
descr->captured = TRUE;
- SetCapture( hwnd );
+ SetCapture( descr->self );
if (!descr->lphc)
{
if (descr->style & LBS_NOTIFY )
SendMessageW( descr->owner, WM_LBTRACKPOINT, index,
MAKELPARAM( x, y ) );
- if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_DRAGDETECT)
+ if (GetWindowLongW( descr->self, GWL_EXSTYLE ) & WS_EX_DRAGDETECT)
{
POINT pt;
pt.x = x;
pt.y = y;
- if (DragDetect( hwnd, pt ))
+ if (DragDetect( descr->self, pt ))
SendMessageW( descr->owner, WM_BEGINDRAG, 0, 0 );
}
}
* This function is only to be used when a ListBox is a ComboListBox
*/
-static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
- UINT msg, WPARAM wParam, INT x, INT y)
+static LRESULT LISTBOX_HandleLButtonDownCombo( LB_DESCR *pDescr,
+ UINT msg, DWORD keys, INT x, INT y)
{
RECT clientRect, screenRect;
POINT mousePos;
mousePos.x = x;
mousePos.y = y;
- GetClientRect(hwnd, &clientRect);
+ GetClientRect(pDescr->self, &clientRect);
if(PtInRect(&clientRect, mousePos))
{
if (msg == WM_LBUTTONDOWN)
{
pDescr->lphc->droppedIndex = pDescr->nb_items ? pDescr->selected_item : -1;
- return LISTBOX_HandleLButtonDown( hwnd, pDescr, wParam, x, y);
+ return LISTBOX_HandleLButtonDown( pDescr, keys, x, y);
}
else if (pDescr->style & LBS_NOTIFY)
- SEND_NOTIFICATION( hwnd, pDescr, LBN_DBLCLK );
- return 0;
+ SEND_NOTIFICATION( pDescr, LBN_DBLCLK );
}
else
{
screenMousePos = mousePos;
hWndOldCapture = GetCapture();
ReleaseCapture();
- GetWindowRect(hwnd, &screenRect);
- ClientToScreen(hwnd, &screenMousePos);
+ GetWindowRect(pDescr->self, &screenRect);
+ ClientToScreen(pDescr->self, &screenMousePos);
if(!PtInRect(&screenRect, screenMousePos))
{
- LISTBOX_SetCaretIndex( hwnd, pDescr, pDescr->lphc->droppedIndex, FALSE );
- LISTBOX_SetSelection( hwnd, pDescr, pDescr->lphc->droppedIndex, FALSE, FALSE );
-#if 0
+ LISTBOX_SetCaretIndex( pDescr, pDescr->lphc->droppedIndex, FALSE );
+ LISTBOX_SetSelection( pDescr, pDescr->lphc->droppedIndex, FALSE, FALSE );
COMBO_FlipListbox( pDescr->lphc, FALSE, FALSE );
-#endif
- return 0;
}
else
{
/* Check to see the NC is a scrollbar */
INT nHitTestType=0;
- LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+ LONG style = GetWindowLongW( pDescr->self, GWL_STYLE );
/* Check Vertical scroll bar */
if (style & WS_VSCROLL)
{
+
clientRect.right += GetSystemMetrics(SM_CXVSCROLL);
if (PtInRect( &clientRect, mousePos ))
- {
nHitTestType = HTVSCROLL;
- }
}
/* Check horizontal scroll bar */
if (style & WS_HSCROLL)
{
clientRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
if (PtInRect( &clientRect, mousePos ))
- {
nHitTestType = HTHSCROLL;
- }
}
/* Windows sends this message when a scrollbar is clicked
*/
if(nHitTestType != 0)
{
- SendMessageW(hwnd, WM_NCLBUTTONDOWN, nHitTestType,
+ SendMessageW(pDescr->self, WM_NCLBUTTONDOWN, nHitTestType,
MAKELONG(screenMousePos.x, screenMousePos.y));
}
/* Resume the Capture after scrolling is complete
*/
if(hWndOldCapture != 0)
- {
SetCapture(hWndOldCapture);
- }
}
}
return 0;
/***********************************************************************
* LISTBOX_HandleLButtonUp
*/
-static LRESULT LISTBOX_HandleLButtonUp( HWND hwnd, LB_DESCR *descr )
+static LRESULT LISTBOX_HandleLButtonUp( LB_DESCR *descr )
{
if (LISTBOX_Timer != LB_TIMER_NONE)
- KillSystemTimer( hwnd, LB_TIMER_ID );
+ KillSystemTimer( descr->self, LB_TIMER_ID );
LISTBOX_Timer = LB_TIMER_NONE;
if (descr->captured)
{
descr->captured = FALSE;
- if (GetCapture() == hwnd) ReleaseCapture();
+ if (GetCapture() == descr->self) ReleaseCapture();
if ((descr->style & LBS_NOTIFY) && descr->nb_items)
- SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
+ SEND_NOTIFICATION( descr, LBN_SELCHANGE );
}
return 0;
}
* Handle scrolling upon a timer event.
* Return TRUE if scrolling should continue.
*/
-static LRESULT LISTBOX_HandleTimer( HWND hwnd, LB_DESCR *descr,
+static LRESULT LISTBOX_HandleTimer( LB_DESCR *descr,
INT index, TIMER_DIRECTION dir )
{
switch(dir)
break;
}
if (index == descr->focus_item) return FALSE;
- LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
+ LISTBOX_MoveCaret( descr, index, FALSE );
return TRUE;
}
*
* WM_SYSTIMER handler.
*/
-static LRESULT LISTBOX_HandleSystemTimer( HWND hwnd, LB_DESCR *descr )
+static LRESULT LISTBOX_HandleSystemTimer( LB_DESCR *descr )
{
- if (!LISTBOX_HandleTimer( hwnd, descr, descr->focus_item, LISTBOX_Timer ))
+ if (!LISTBOX_HandleTimer( descr, descr->focus_item, LISTBOX_Timer ))
{
- KillSystemTimer( hwnd, LB_TIMER_ID );
+ KillSystemTimer( descr->self, LB_TIMER_ID );
LISTBOX_Timer = LB_TIMER_NONE;
}
return 0;
*
* WM_MOUSEMOVE handler.
*/
-static void LISTBOX_HandleMouseMove( HWND hwnd, LB_DESCR *descr,
+static void LISTBOX_HandleMouseMove( LB_DESCR *descr,
INT x, INT y )
{
INT index;
index = LISTBOX_GetItemFromPoint( descr, x, y );
if (index == -1) index = descr->focus_item;
- if (!LISTBOX_HandleTimer( hwnd, descr, index, dir )) dir = LB_TIMER_NONE;
+ if (!LISTBOX_HandleTimer( descr, index, dir )) dir = LB_TIMER_NONE;
/* Start/stop the system timer */
if (dir != LB_TIMER_NONE)
- SetSystemTimer( hwnd, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
+ SetSystemTimer( descr->self, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
else if (LISTBOX_Timer != LB_TIMER_NONE)
- KillSystemTimer( hwnd, LB_TIMER_ID );
+ KillSystemTimer( descr->self, LB_TIMER_ID );
LISTBOX_Timer = dir;
}
/***********************************************************************
* LISTBOX_HandleKeyDown
*/
-static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleKeyDown( LB_DESCR *descr, DWORD key )
{
INT caret = -1;
BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
if (descr->style & LBS_WANTKEYBOARDINPUT)
{
caret = SendMessageW( descr->owner, WM_VKEYTOITEM,
- MAKEWPARAM(LOWORD(wParam), descr->focus_item),
- (LPARAM)hwnd );
+ MAKEWPARAM(LOWORD(key), descr->focus_item),
+ (LPARAM)descr->self );
if (caret == -2) return 0;
}
- if (caret == -1) switch(wParam)
+ if (caret == -1) switch(key)
{
case VK_LEFT:
if (descr->style & LBS_MULTICOLUMN)
if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
else if (descr->style & LBS_MULTIPLESEL)
{
- LISTBOX_SetSelection( hwnd, descr, descr->focus_item,
+ LISTBOX_SetSelection( descr, descr->focus_item,
!descr->items[descr->focus_item].selected,
(descr->style & LBS_NOTIFY) != 0 );
}
caret = descr->focus_item;
if (caret >= 0)
{
- if ((descr->style & LBS_EXTENDEDSEL) &&
- !(GetKeyState( VK_SHIFT ) & 0x8000))
+ if (((descr->style & LBS_EXTENDEDSEL) &&
+ !(GetKeyState( VK_SHIFT ) & 0x8000)) ||
+ !IS_MULTISELECT(descr))
descr->anchor_item = caret;
- LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
- LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
+ LISTBOX_MoveCaret( descr, caret, TRUE );
+
+ if (descr->style & LBS_MULTIPLESEL)
+ descr->selected_item = caret;
+ else
+ LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
if (descr->style & LBS_NOTIFY)
{
- if( descr->lphc )
+ if( descr->lphc )
{
- /* make sure that combo parent doesn't hide us */
- descr->lphc->wState |= CBF_NOROLLUP;
- }
- if (descr->nb_items) SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
+ /* make sure that combo parent doesn't hide us */
+ descr->lphc->wState |= CBF_NOROLLUP;
+ }
+ if (descr->nb_items) SEND_NOTIFICATION( descr, LBN_SELCHANGE );
}
}
return 0;
+
}
/***********************************************************************
* LISTBOX_HandleChar
*/
-static LRESULT LISTBOX_HandleChar( HWND hwnd, LB_DESCR *descr, WCHAR charW )
+static LRESULT LISTBOX_HandleChar( LB_DESCR *descr, WCHAR charW )
{
INT caret = -1;
WCHAR str[2];
{
caret = SendMessageW( descr->owner, WM_CHARTOITEM,
MAKEWPARAM(charW, descr->focus_item),
- (LPARAM)hwnd );
+ (LPARAM)descr->self );
if (caret == -2) return 0;
}
if (caret == -1)
- caret = LISTBOX_FindString( hwnd, descr, descr->focus_item, str, FALSE);
+ caret = LISTBOX_FindString( descr, descr->focus_item, str, FALSE);
if (caret != -1)
{
if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
- LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
- LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
+ LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
+ LISTBOX_MoveCaret( descr, caret, TRUE );
if ((descr->style & LBS_NOTIFY) && descr->nb_items)
- SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
+ SEND_NOTIFICATION( descr, LBN_SELCHANGE );
}
return 0;
}
return FALSE;
GetClientRect( hwnd, &rect );
- descr->owner = GetParent( hwnd );
- descr->style = GetWindowLongA( hwnd, GWL_STYLE );
+ descr->self = hwnd;
+ descr->owner = GetParent( descr->self );
+ descr->style = GetWindowLongA( descr->self, GWL_STYLE );
descr->width = rect.right - rect.left;
descr->height = rect.bottom - rect.top;
descr->items = NULL;
descr->in_focus = FALSE;
descr->captured = FALSE;
descr->font = 0;
- descr->locale = 0; /* FIXME */
+ descr->locale = GetUserDefaultLCID();
descr->lphc = lphc;
+#ifndef __REACTOS__
if (is_old_app(hwnd) && ( descr->style & ( WS_VSCROLL | WS_HSCROLL ) ) )
{
/* Win95 document "List Box Differences" from MSDN:
*/
descr->style |= WS_VSCROLL | WS_HSCROLL;
}
+#endif
if( lphc )
{
descr->owner = lphc->self;
}
- SetWindowLongA( hwnd, 0, (LONG)descr );
+ SetWindowLongPtrW( descr->self, 0, (LONG_PTR)descr );
/* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
*/
if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
- descr->item_height = LISTBOX_SetFont( hwnd, descr, 0 );
+ descr->item_height = LISTBOX_SetFont( descr, 0 );
if (descr->style & LBS_OWNERDRAWFIXED)
{
}
else
{
- UINT id = GetWindowLongA( hwnd, GWL_ID );
+ UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
mis.CtlType = ODT_LISTBOX;
mis.CtlID = id;
mis.itemID = -1;
/***********************************************************************
* LISTBOX_Destroy
*/
-static BOOL LISTBOX_Destroy( HWND hwnd, LB_DESCR *descr )
+static BOOL LISTBOX_Destroy( LB_DESCR *descr )
{
- LISTBOX_ResetContent( hwnd, descr );
- SetWindowLongA( hwnd, 0, 0 );
+ LISTBOX_ResetContent( descr );
+ SetWindowLongPtrW( descr->self, 0, 0 );
HeapFree( GetProcessHeap(), 0, descr );
return TRUE;
}
static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam, BOOL unicode )
{
+ LB_DESCR *descr = (LB_DESCR *)GetWindowLongPtrW( hwnd, 0 );
LRESULT ret;
- LB_DESCR *descr;
+ LPHEADCOMBO lphc = 0;
- if (!(descr = (LB_DESCR *)GetWindowLongA( hwnd, 0 )))
+ if (!descr)
{
+ if (!IsWindow(hwnd)) return 0;
+
if (msg == WM_CREATE)
{
- if (!LISTBOX_Create( hwnd, NULL ))
+ 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, GetWindowLongA( hwnd, 0 ) );
+ TRACE("creating wnd=%p descr=%lx\n", hwnd, GetWindowLongPtrW( 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;
-#if 0
- TRACE("[%p]: msg %s wp %08x lp %08lx\n",
- hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
-#endif
-
+ //TRACE("[%p]: msg %s wp %08x lp %08lx\n",
+ // hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
switch(msg)
{
+#ifndef __REACTOS__
+ case LB_RESETCONTENT16:
+#endif
case LB_RESETCONTENT:
- LISTBOX_ResetContent( hwnd, descr );
- LISTBOX_UpdateScroll( hwnd, descr );
- InvalidateRect( hwnd, NULL, TRUE );
+ LISTBOX_ResetContent( descr );
+ LISTBOX_UpdateScroll( descr );
+ InvalidateRect( descr->self, NULL, TRUE );
return 0;
+#ifndef __REACTOS__
+ case LB_ADDSTRING16:
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_ADDSTRING:
{
INT ret;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- wParam = LISTBOX_FindStringPos( hwnd, descr, textW, FALSE );
- ret = LISTBOX_InsertString( hwnd, descr, wParam, textW );
+ wParam = LISTBOX_FindStringPos( descr, textW, FALSE );
+ ret = LISTBOX_InsertString( descr, wParam, textW );
if (!unicode && HAS_STRINGS(descr))
HeapFree(GetProcessHeap(), 0, textW);
return ret;
}
+#ifndef __REACTOS__
+ case LB_INSERTSTRING16:
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+ wParam = (INT)(INT16)wParam;
+ /* fall through */
+#endif
case LB_INSERTSTRING:
{
INT ret;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- ret = LISTBOX_InsertString( hwnd, descr, wParam, textW );
+ ret = LISTBOX_InsertString( descr, wParam, textW );
if(!unicode && HAS_STRINGS(descr))
HeapFree(GetProcessHeap(), 0, textW);
return ret;
}
+#ifndef __REACTOS__
+ case LB_ADDFILE16:
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_ADDFILE:
{
INT ret;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- wParam = LISTBOX_FindFileStrPos( hwnd, descr, textW );
- ret = LISTBOX_InsertString( hwnd, descr, wParam, textW );
+ wParam = LISTBOX_FindFileStrPos( descr, textW );
+ ret = LISTBOX_InsertString( descr, wParam, textW );
if(!unicode && HAS_STRINGS(descr))
HeapFree(GetProcessHeap(), 0, textW);
return ret;
}
+#ifndef __REACTOS__
+ case LB_DELETESTRING16:
+#endif
case LB_DELETESTRING:
- if (LISTBOX_RemoveItem( hwnd, descr, wParam) != LB_ERR)
+ if (LISTBOX_RemoveItem( descr, wParam) != LB_ERR)
return descr->nb_items;
else
+ {
+ SetLastError(ERROR_INVALID_INDEX);
return LB_ERR;
+ }
+#ifndef __REACTOS__
+ case LB_GETITEMDATA16:
+#endif
case LB_GETITEMDATA:
if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
return LB_ERR;
+ }
return descr->items[wParam].data;
+#ifndef __REACTOS__
+ case LB_SETITEMDATA16:
+#endif
case LB_SETITEMDATA:
if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
return LB_ERR;
+ }
descr->items[wParam].data = (DWORD)lParam;
return LB_OKAY;
+#ifndef __REACTOS__
+ case LB_GETCOUNT16:
+#endif
case LB_GETCOUNT:
return descr->nb_items;
+#ifndef __REACTOS__
+ case LB_GETTEXT16:
+ lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_GETTEXT:
- return LISTBOX_GetText( descr, wParam, lParam, unicode );
+ return LISTBOX_GetText( descr, wParam, (LPWSTR)lParam, unicode );
+#ifndef __REACTOS__
+ case LB_GETTEXTLEN16:
+ /* fall through */
+#endif
case LB_GETTEXTLEN:
if ((INT)wParam >= descr->nb_items || (INT)wParam < 0)
+ {
+ SetLastError(ERROR_INVALID_INDEX);
return LB_ERR;
+ }
if (!HAS_STRINGS(descr)) return sizeof(DWORD);
if (unicode) return strlenW( descr->items[wParam].str );
return WideCharToMultiByte( CP_ACP, 0, descr->items[wParam].str,
strlenW(descr->items[wParam].str), NULL, 0, NULL, NULL );
+#ifndef __REACTOS__
+ case LB_GETCURSEL16:
+#endif
case LB_GETCURSEL:
if (descr->nb_items==0)
return LB_ERR;
return descr->focus_item;
/* otherwise, if the user tries to move the selection with the */
/* arrow keys, we will give the application something to choke on */
+#ifndef __REACTOS__
+ case LB_GETTOPINDEX16:
+#endif
case LB_GETTOPINDEX:
return descr->top_item;
+#ifndef __REACTOS__
+ case LB_GETITEMHEIGHT16:
+#endif
case LB_GETITEMHEIGHT:
return LISTBOX_GetItemHeight( descr, wParam );
+#ifndef __REACTOS__
+ case LB_SETITEMHEIGHT16:
+ lParam = LOWORD(lParam);
+ /* fall through */
+#endif
case LB_SETITEMHEIGHT:
- return LISTBOX_SetItemHeight( hwnd, descr, wParam, lParam, TRUE );
+ return LISTBOX_SetItemHeight( descr, wParam, lParam, TRUE );
case LB_ITEMFROMPOINT:
{
!PtInRect( &rect, pt ) );
}
+#ifndef __REACTOS__
+ case LB_SETCARETINDEX16:
+#endif
case LB_SETCARETINDEX:
if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
- if (LISTBOX_SetCaretIndex( hwnd, descr, wParam, !lParam ) == LB_ERR)
+ if (LISTBOX_SetCaretIndex( descr, wParam, !lParam ) == LB_ERR)
return LB_ERR;
else if (ISWIN31)
return wParam;
else
return LB_OKAY;
+#ifndef __REACTOS__
+ case LB_GETCARETINDEX16:
+#endif
case LB_GETCARETINDEX:
return descr->focus_item;
+#ifndef __REACTOS__
+ case LB_SETTOPINDEX16:
+#endif
case LB_SETTOPINDEX:
- return LISTBOX_SetTopItem( hwnd, descr, wParam, TRUE );
+ return LISTBOX_SetTopItem( descr, wParam, TRUE );
+#ifndef __REACTOS__
+ case LB_SETCOLUMNWIDTH16:
+#endif
case LB_SETCOLUMNWIDTH:
- return LISTBOX_SetColumnWidth( hwnd, descr, wParam );
+ return LISTBOX_SetColumnWidth( descr, wParam );
+
+#ifndef __REACTOS__
+ case LB_GETITEMRECT16:
+ {
+ RECT rect;
+ ret = LISTBOX_GetItemRect( descr, (INT16)wParam, &rect );
+ CONV_RECT32TO16( &rect, MapSL(lParam) );
+ }
+ return ret;
+#endif
case LB_GETITEMRECT:
return LISTBOX_GetItemRect( descr, wParam, (RECT *)lParam );
+#ifndef __REACTOS__
+ case LB_FINDSTRING16:
+ wParam = (INT)(INT16)wParam;
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_FINDSTRING:
{
INT ret;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- ret = LISTBOX_FindString( hwnd, descr, wParam, textW, FALSE );
+ ret = LISTBOX_FindString( descr, wParam, textW, FALSE );
if(!unicode && HAS_STRINGS(descr))
HeapFree(GetProcessHeap(), 0, textW);
return ret;
}
+#ifndef __REACTOS__
+ case LB_FINDSTRINGEXACT16:
+ wParam = (INT)(INT16)wParam;
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_FINDSTRINGEXACT:
{
INT ret;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- ret = LISTBOX_FindString( hwnd, descr, wParam, textW, TRUE );
+ ret = LISTBOX_FindString( descr, wParam, textW, TRUE );
if(!unicode && HAS_STRINGS(descr))
HeapFree(GetProcessHeap(), 0, textW);
return ret;
}
+#ifndef __REACTOS__
+ case LB_SELECTSTRING16:
+ wParam = (INT)(INT16)wParam;
+ if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_SELECTSTRING:
{
INT index;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- index = LISTBOX_FindString( hwnd, descr, wParam, textW, FALSE );
+ index = LISTBOX_FindString( descr, wParam, textW, FALSE );
if(!unicode && HAS_STRINGS(descr))
HeapFree(GetProcessHeap(), 0, textW);
if (index != LB_ERR)
{
- LISTBOX_SetCaretIndex( hwnd, descr, index, TRUE );
- LISTBOX_SetSelection( hwnd, descr, index, TRUE, FALSE );
+ LISTBOX_MoveCaret( descr, index, TRUE );
+ LISTBOX_SetSelection( descr, index, TRUE, FALSE );
}
return index;
}
+#ifndef __REACTOS__
+ case LB_GETSEL16:
+ wParam = (INT)(INT16)wParam;
+ /* fall through */
+#endif
case LB_GETSEL:
if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
return LB_ERR;
return descr->items[wParam].selected;
+#ifndef __REACTOS__
+ case LB_SETSEL16:
+ lParam = (INT)(INT16)lParam;
+ /* fall through */
+#endif
case LB_SETSEL:
- return LISTBOX_SetSelection( hwnd, descr, lParam, wParam, FALSE );
+ return LISTBOX_SetSelection( descr, lParam, wParam, FALSE );
+#ifndef __REACTOS__
+ case LB_SETCURSEL16:
+ wParam = (INT)(INT16)wParam;
+ /* fall through */
+#endif
case LB_SETCURSEL:
if (IS_MULTISELECT(descr)) return LB_ERR;
- LISTBOX_SetCaretIndex( hwnd, descr, wParam, TRUE );
- return LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
+ LISTBOX_SetCaretIndex( descr, wParam, TRUE );
+ ret = LISTBOX_SetSelection( descr, wParam, TRUE, FALSE );
+ if (lphc && ret != LB_ERR) ret = descr->selected_item;
+ return ret;
+#ifndef __REACTOS__
+ case LB_GETSELCOUNT16:
+#endif
case LB_GETSELCOUNT:
return LISTBOX_GetSelCount( descr );
+#ifndef __REACTOS__
+ case LB_GETSELITEMS16:
+ return LISTBOX_GetSelItems16( descr, wParam, (LPINT16)MapSL(lParam) );
+#endif
+
case LB_GETSELITEMS:
return LISTBOX_GetSelItems( descr, wParam, (LPINT)lParam );
+#ifndef __REACTOS__
+ case LB_SELITEMRANGE16:
+#endif
case LB_SELITEMRANGE:
if (LOWORD(lParam) <= HIWORD(lParam))
- return LISTBOX_SelectItemRange( hwnd, descr, LOWORD(lParam),
+ return LISTBOX_SelectItemRange( descr, LOWORD(lParam),
HIWORD(lParam), wParam );
else
- return LISTBOX_SelectItemRange( hwnd, descr, HIWORD(lParam),
+ return LISTBOX_SelectItemRange( descr, HIWORD(lParam),
LOWORD(lParam), wParam );
+#ifndef __REACTOS__
+ case LB_SELITEMRANGEEX16:
+#endif
case LB_SELITEMRANGEEX:
if ((INT)lParam >= (INT)wParam)
- return LISTBOX_SelectItemRange( hwnd, descr, wParam, lParam, TRUE );
+ return LISTBOX_SelectItemRange( descr, wParam, lParam, TRUE );
else
- return LISTBOX_SelectItemRange( hwnd, descr, lParam, wParam, FALSE);
+ return LISTBOX_SelectItemRange( descr, lParam, wParam, FALSE);
+#ifndef __REACTOS__
+ case LB_GETHORIZONTALEXTENT16:
+#endif
case LB_GETHORIZONTALEXTENT:
return descr->horz_extent;
+#ifndef __REACTOS__
+ case LB_SETHORIZONTALEXTENT16:
+#endif
case LB_SETHORIZONTALEXTENT:
- return LISTBOX_SetHorizontalExtent( hwnd, descr, wParam );
+ return LISTBOX_SetHorizontalExtent( descr, wParam );
+#ifndef __REACTOS__
+ case LB_GETANCHORINDEX16:
+#endif
case LB_GETANCHORINDEX:
return descr->anchor_item;
+#ifndef __REACTOS__
+ case LB_SETANCHORINDEX16:
+ wParam = (INT)(INT16)wParam;
+ /* fall through */
+#endif
case LB_SETANCHORINDEX:
if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
return LB_ERR;
+ }
descr->anchor_item = (INT)wParam;
return LB_OKAY;
+#ifndef __REACTOS__
+ case LB_DIR16:
+ /* according to Win16 docs, DDL_DRIVES should make DDL_EXCLUSIVE
+ * be set automatically (this is different in Win32) */
+ if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
+ lParam = (LPARAM)MapSL(lParam);
+ /* fall through */
+#endif
case LB_DIR:
{
INT ret;
if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
}
- ret = LISTBOX_Directory( hwnd, descr, wParam, textW, msg == LB_DIR );
+ ret = LISTBOX_Directory( descr, wParam, textW, msg == LB_DIR );
if(!unicode)
HeapFree(GetProcessHeap(), 0, textW);
return ret;
return descr->locale;
case LB_SETLOCALE:
- descr->locale = (LCID)wParam; /* FIXME: should check for valid lcid */
- return LB_OKAY;
+ {
+ LCID ret;
+ if (!IsValidLocale((LCID)wParam, LCID_INSTALLED))
+ return LB_ERR;
+ ret = descr->locale;
+ descr->locale = (LCID)wParam;
+ return ret;
+ }
case LB_INITSTORAGE:
- return LISTBOX_InitStorage( hwnd, descr, wParam );
+ return LISTBOX_InitStorage( descr, wParam );
case LB_SETCOUNT:
- return LISTBOX_SetCount( hwnd, descr, (INT)wParam );
+ return LISTBOX_SetCount( descr, (INT)wParam );
+
+#ifndef __REACTOS__
+ case LB_SETTABSTOPS16:
+ return LISTBOX_SetTabStops( descr, (INT)(INT16)wParam, MapSL(lParam), TRUE );
+#endif
case LB_SETTABSTOPS:
- return LISTBOX_SetTabStops( hwnd, descr, wParam, (LPINT)lParam, FALSE );
+ return LISTBOX_SetTabStops( descr, wParam, (LPINT)lParam, FALSE );
+#ifndef __REACTOS__
+ case LB_CARETON16:
+#endif
case LB_CARETON:
if (descr->caret_on)
return LB_OKAY;
descr->caret_on = TRUE;
if ((descr->focus_item != -1) && (descr->in_focus))
- LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
+ LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
return LB_OKAY;
+#ifndef __REACTOS__
+ case LB_CARETOFF16:
+#endif
case LB_CARETOFF:
if (!descr->caret_on)
return LB_OKAY;
descr->caret_on = FALSE;
if ((descr->focus_item != -1) && (descr->in_focus))
- LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
+ LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
return LB_OKAY;
case WM_DESTROY:
- return LISTBOX_Destroy( hwnd, descr );
+ return LISTBOX_Destroy( descr );
case WM_ENABLE:
InvalidateRect( hwnd, NULL, TRUE );
return 0;
case WM_SETREDRAW:
- LISTBOX_SetRedraw( hwnd, descr, wParam != 0 );
+ LISTBOX_SetRedraw( descr, wParam != 0 );
return 0;
case WM_GETDLGCODE:
{
PAINTSTRUCT ps;
HDC hdc = ( wParam ) ? ((HDC)wParam) : BeginPaint( hwnd, &ps );
- ret = LISTBOX_Paint( hwnd, descr, hdc );
+ ret = LISTBOX_Paint( descr, hdc );
if( !wParam ) EndPaint( hwnd, &ps );
}
return ret;
case WM_SIZE:
- LISTBOX_UpdateSize( hwnd, descr );
+ LISTBOX_UpdateSize( descr );
return 0;
case WM_GETFONT:
return (LRESULT)descr->font;
case WM_SETFONT:
- LISTBOX_SetFont( hwnd, descr, (HFONT)wParam );
+ LISTBOX_SetFont( descr, (HFONT)wParam );
if (lParam) InvalidateRect( hwnd, 0, TRUE );
return 0;
case WM_SETFOCUS:
descr->in_focus = TRUE;
descr->caret_on = TRUE;
if (descr->focus_item != -1)
- LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
- SEND_NOTIFICATION( hwnd, descr, LBN_SETFOCUS );
+ LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
+ SEND_NOTIFICATION( descr, LBN_SETFOCUS );
return 0;
case WM_KILLFOCUS:
descr->in_focus = FALSE;
if ((descr->focus_item != -1) && descr->caret_on)
- LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
- SEND_NOTIFICATION( hwnd, descr, LBN_KILLFOCUS );
+ LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
+ SEND_NOTIFICATION( descr, LBN_KILLFOCUS );
return 0;
case WM_HSCROLL:
- return LISTBOX_HandleHScroll( hwnd, descr, wParam );
+ return LISTBOX_HandleHScroll( descr, LOWORD(wParam), HIWORD(wParam) );
case WM_VSCROLL:
- return LISTBOX_HandleVScroll( hwnd, descr, wParam );
+ return LISTBOX_HandleVScroll( descr, LOWORD(wParam), HIWORD(wParam) );
case WM_MOUSEWHEEL:
if (wParam & (MK_SHIFT | MK_CONTROL))
return DefWindowProcW( hwnd, msg, wParam, lParam );
- return LISTBOX_HandleMouseWheel( hwnd, descr, wParam );
+ return LISTBOX_HandleMouseWheel( descr, (SHORT)HIWORD(wParam) );
case WM_LBUTTONDOWN:
- return LISTBOX_HandleLButtonDown( hwnd, descr, wParam,
+ if (lphc)
+ return LISTBOX_HandleLButtonDownCombo(descr, msg, wParam,
+ (INT16)LOWORD(lParam),
+ (INT16)HIWORD(lParam) );
+ return LISTBOX_HandleLButtonDown(descr, wParam,
(INT16)LOWORD(lParam),
(INT16)HIWORD(lParam) );
case WM_LBUTTONDBLCLK:
+ if (lphc)
+ return LISTBOX_HandleLButtonDownCombo(descr, msg, wParam,
+ (INT16)LOWORD(lParam),
+ (INT16)HIWORD(lParam) );
if (descr->style & LBS_NOTIFY)
- SEND_NOTIFICATION( hwnd, descr, LBN_DBLCLK );
+ SEND_NOTIFICATION( descr, LBN_DBLCLK );
return 0;
case WM_MOUSEMOVE:
- if (GetCapture() == hwnd)
- LISTBOX_HandleMouseMove( hwnd, descr, (INT16)LOWORD(lParam),
+ 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(descr->self, &clientRect) && PtInRect( &clientRect, mousePos ))
+ descr->captured = TRUE;
+
+ LISTBOX_HandleMouseMove( descr, mousePos.x, mousePos.y);
+
+ descr->captured = captured;
+ }
+ else if (GetCapture() == descr->self)
+ {
+ LISTBOX_HandleMouseMove( descr, (INT16)LOWORD(lParam),
(INT16)HIWORD(lParam) );
+ }
return 0;
case WM_LBUTTONUP:
- return LISTBOX_HandleLButtonUp( hwnd, descr );
+ 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( descr, lphc->droppedIndex, FALSE );
+ }
+ return LISTBOX_HandleLButtonUp( descr );
case WM_KEYDOWN:
- return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
+ 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( descr, wParam );
case WM_CHAR:
{
WCHAR charW;
CHAR charA = (CHAR)wParam;
MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
}
- return LISTBOX_HandleChar( hwnd, descr, charW );
+ return LISTBOX_HandleChar( descr, charW );
}
case WM_SYSTIMER:
- return LISTBOX_HandleSystemTimer( hwnd, descr );
+ return LISTBOX_HandleSystemTimer( descr );
case WM_ERASEBKGND:
if ((IS_OWNERDRAW(descr)) && !(descr->style & LBS_DISPLAYCHANGED))
{
RECT rect;
HBRUSH hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
- wParam, (LPARAM)hwnd );
+ wParam, (LPARAM)descr->self );
TRACE("hbrush = %p\n", hbrush);
if(!hbrush)
hbrush = GetSysColorBrush(COLOR_WINDOW);
if(hbrush)
{
- GetClientRect(hwnd, &rect);
+ GetClientRect(descr->self, &rect);
FillRect((HDC)wParam, &rect, hbrush);
}
}
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:
- return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
- DefWindowProcA( hwnd, msg, wParam, lParam );
+ if ((msg >= WM_USER) && (msg < 0xc000))
+ WARN("[%p]: unknown msg %04x wp %08x lp %08lx\n",
+ 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 );
}
*/
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
+ * GetListBoxInfo
*/
-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 );
- }
-
-#if 0
- TRACE_(combo)("[%p]: msg %s wp %08x lp %08lx\n",
- hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
-#endif
-
- 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;
-
- }
- /* else we are in Win3.1 look, go with the default behavior. */
- 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)) )
- {
-#if 0
- COMBO_FlipListbox( lphc, FALSE, FALSE );
-#endif
- return 0;
- }
- }
- return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
-
- 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 );
-}
-
-
DWORD STDCALL
GetListBoxInfo(HWND hwnd)
{
UNIMPLEMENTED;
return 0;
}
+