mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 14:30:57 +00:00
- Sync to Wine: Listbox controls
- Implement NtUserGetListBoxInfo and GetListBoxInfo. Fix header entry. - Add LB_GETLISTBOXINFO to psdk. svn path=/trunk/; revision=29839
This commit is contained in:
parent
243774066b
commit
07c753c912
6 changed files with 149 additions and 64 deletions
|
@ -16,12 +16,26 @@
|
|||
* 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
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
* This code was audited for completeness against the documented features
|
||||
* of Comctl32.dll version 6.0 on Oct. 9, 2004, by Dimitrie O. Paun.
|
||||
*
|
||||
* Unless otherwise noted, we believe this code to be complete, as per
|
||||
* the specification mentioned above.
|
||||
* If you discover missing features, or bugs, please note them below.
|
||||
*
|
||||
* TODO:
|
||||
* - GetListBoxInfo()
|
||||
* - LB_GETLISTBOXINFO
|
||||
* - LBS_NODATA
|
||||
*/
|
||||
|
||||
#include <user32.h>
|
||||
|
||||
#include <wine/debug.h>
|
||||
WINE_DECLARE_DEBUG_CHANNEL(combo);
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(listbox);
|
||||
|
||||
/* Start of hack section -------------------------------- */
|
||||
|
@ -42,14 +56,6 @@ 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
|
||||
|
||||
|
@ -341,10 +347,12 @@ static void LISTBOX_UpdateScroll( LB_DESCR *descr )
|
|||
*
|
||||
* Set the top item of the listbox, scrolling up or down if necessary.
|
||||
*/
|
||||
static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index,
|
||||
BOOL scroll )
|
||||
static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index, BOOL scroll )
|
||||
{
|
||||
INT max = LISTBOX_GetMaxTopIndex( descr );
|
||||
|
||||
TRACE("setting top item %d, scroll %d\n", index, scroll);
|
||||
|
||||
if (index > max) index = max;
|
||||
if (index < 0) index = 0;
|
||||
if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
|
||||
|
@ -520,6 +528,8 @@ static LRESULT LISTBOX_GetItemRect( LB_DESCR *descr, INT index, RECT *rect )
|
|||
rect->right += descr->horz_pos;
|
||||
}
|
||||
|
||||
TRACE("item %d, rect %s\n", index, wine_dbgstr_rect(rect));
|
||||
|
||||
return ((rect->left < descr->width) && (rect->right > 0) &&
|
||||
(rect->top < descr->height) && (rect->bottom > 0));
|
||||
}
|
||||
|
@ -704,8 +714,7 @@ static void LISTBOX_SetRedraw( LB_DESCR *descr, BOOL on )
|
|||
*
|
||||
* Repaint a single item synchronously.
|
||||
*/
|
||||
static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index,
|
||||
UINT action )
|
||||
static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index, UINT action )
|
||||
{
|
||||
HDC hdc;
|
||||
RECT rect;
|
||||
|
@ -735,6 +744,33 @@ static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index,
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LISTBOX_DrawFocusRect
|
||||
*/
|
||||
static void LISTBOX_DrawFocusRect( LB_DESCR *descr, BOOL on )
|
||||
{
|
||||
HDC hdc;
|
||||
RECT rect;
|
||||
HFONT oldFont = 0;
|
||||
|
||||
/* Do not repaint the item if the item is not visible */
|
||||
if (!IsWindowVisible(descr->self)) return;
|
||||
|
||||
if (descr->focus_item == -1) return;
|
||||
if (!descr->caret_on || !descr->in_focus) return;
|
||||
|
||||
if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) != 1) return;
|
||||
if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
|
||||
if (descr->font) oldFont = SelectObject( hdc, descr->font );
|
||||
if (!IsWindowEnabled(descr->self))
|
||||
SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
|
||||
SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
|
||||
LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, on ? FALSE : TRUE );
|
||||
if (oldFont) SelectObject( hdc, oldFont );
|
||||
ReleaseDC( descr->self, hdc );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LISTBOX_InitStorage
|
||||
*/
|
||||
|
@ -767,8 +803,7 @@ static LRESULT LISTBOX_InitStorage( LB_DESCR *descr, INT nb_items )
|
|||
/***********************************************************************
|
||||
* LISTBOX_SetTabStops
|
||||
*/
|
||||
static BOOL LISTBOX_SetTabStops( LB_DESCR *descr, INT count,
|
||||
LPINT tabs, BOOL short_ints )
|
||||
static BOOL LISTBOX_SetTabStops( LB_DESCR *descr, INT count, LPINT tabs, BOOL short_ints )
|
||||
{
|
||||
INT i;
|
||||
|
||||
|
@ -1375,6 +1410,8 @@ static void LISTBOX_MakeItemVisible( LB_DESCR *descr, INT index,
|
|||
{
|
||||
INT top;
|
||||
|
||||
TRACE("current top item %d, index %d, fully %d\n", descr->top_item, index, fully);
|
||||
|
||||
if (index <= descr->top_item) top = index;
|
||||
else if (descr->style & LBS_MULTICOLUMN)
|
||||
{
|
||||
|
@ -1413,16 +1450,17 @@ static LRESULT LISTBOX_SetCaretIndex( LB_DESCR *descr, INT index,
|
|||
{
|
||||
INT oldfocus = descr->focus_item;
|
||||
|
||||
TRACE("old focus %d, index %d\n", oldfocus, index);
|
||||
|
||||
if (descr->style & LBS_NOSEL) return LB_ERR;
|
||||
if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
|
||||
if (index == oldfocus) return LB_OKAY;
|
||||
|
||||
LISTBOX_DrawFocusRect( descr, FALSE );
|
||||
descr->focus_item = index;
|
||||
if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
|
||||
LISTBOX_RepaintItem( descr, oldfocus, ODA_FOCUS );
|
||||
|
||||
LISTBOX_MakeItemVisible( descr, index, fully_visible );
|
||||
if (descr->caret_on && (descr->in_focus))
|
||||
LISTBOX_RepaintItem( descr, index, ODA_FOCUS );
|
||||
LISTBOX_DrawFocusRect( descr, TRUE );
|
||||
|
||||
return LB_OKAY;
|
||||
}
|
||||
|
@ -1476,7 +1514,8 @@ static LRESULT LISTBOX_SelectItemRange( LB_DESCR *descr, INT first,
|
|||
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" );
|
||||
TRACE( "cur_sel=%d index=%d notify=%s\n",
|
||||
descr->selected_item, index, send_notify ? "YES" : "NO" );
|
||||
|
||||
if (descr->style & LBS_NOSEL)
|
||||
{
|
||||
|
@ -1497,8 +1536,8 @@ static LRESULT LISTBOX_SetSelection( LB_DESCR *descr, INT index,
|
|||
if (index == oldsel) return LB_OKAY;
|
||||
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( descr, oldsel, ODA_SELECT );
|
||||
descr->selected_item = index;
|
||||
if (index != -1) LISTBOX_RepaintItem( descr, index, ODA_SELECT );
|
||||
if (send_notify && descr->nb_items) SEND_NOTIFICATION( descr,
|
||||
(index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
|
||||
|
@ -1518,7 +1557,7 @@ static LRESULT LISTBOX_SetSelection( LB_DESCR *descr, INT index,
|
|||
static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index,
|
||||
BOOL fully_visible )
|
||||
{
|
||||
INT oldfocus = descr->focus_item;
|
||||
TRACE("old focus %d, index %d\n", descr->focus_item, index);
|
||||
|
||||
if ((index < 0) || (index >= descr->nb_items))
|
||||
return;
|
||||
|
@ -1531,9 +1570,7 @@ static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index,
|
|||
4. Set the focus to 'index' and repaint the item */
|
||||
|
||||
/* 1. remove the focus and repaint the item */
|
||||
descr->focus_item = -1;
|
||||
if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
|
||||
LISTBOX_RepaintItem( descr, oldfocus, ODA_FOCUS );
|
||||
LISTBOX_DrawFocusRect( descr, FALSE );
|
||||
|
||||
/* 2. then turn off the previous selection */
|
||||
/* 3. repaint the new selected item */
|
||||
|
@ -1558,8 +1595,7 @@ static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index,
|
|||
/* 4. repaint the new item with the focus */
|
||||
descr->focus_item = index;
|
||||
LISTBOX_MakeItemVisible( descr, index, fully_visible );
|
||||
if (descr->caret_on && (descr->in_focus))
|
||||
LISTBOX_RepaintItem( descr, index, ODA_FOCUS );
|
||||
LISTBOX_DrawFocusRect( descr, TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1712,7 +1748,7 @@ static void LISTBOX_DeleteItem( LB_DESCR *descr, INT index )
|
|||
dis.itemData = descr->items[index].data;
|
||||
SendMessageW( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
|
||||
}
|
||||
if (HAS_STRINGS(descr) && descr->items[index].str)
|
||||
if (HAS_STRINGS(descr))
|
||||
HeapFree( GetProcessHeap(), 0, descr->items[index].str );
|
||||
}
|
||||
|
||||
|
@ -2066,7 +2102,10 @@ 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", descr->self, x, y, index );
|
||||
|
||||
TRACE("[%p]: lbuttondown %d,%d item %d, focus item %d\n",
|
||||
descr->self, x, y, index, descr->focus_item);
|
||||
|
||||
if (!descr->caret_on && (descr->in_focus)) return 0;
|
||||
|
||||
if (!descr->in_focus)
|
||||
|
@ -2077,6 +2116,16 @@ static LRESULT LISTBOX_HandleLButtonDown( LB_DESCR *descr,
|
|||
|
||||
if (index == -1) return 0;
|
||||
|
||||
if (!descr->lphc)
|
||||
{
|
||||
if (descr->style & LBS_NOTIFY )
|
||||
SendMessageW( descr->owner, WM_LBTRACKPOINT, index,
|
||||
MAKELPARAM( x, y ) );
|
||||
}
|
||||
|
||||
descr->captured = TRUE;
|
||||
SetCapture( descr->self );
|
||||
|
||||
if (descr->style & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
|
||||
{
|
||||
/* we should perhaps make sure that all items are deselected
|
||||
|
@ -2119,14 +2168,8 @@ static LRESULT LISTBOX_HandleLButtonDown( LB_DESCR *descr,
|
|||
TRUE, (descr->style & LBS_NOTIFY) != 0 );
|
||||
}
|
||||
|
||||
descr->captured = TRUE;
|
||||
SetCapture( descr->self );
|
||||
|
||||
if (!descr->lphc)
|
||||
{
|
||||
if (descr->style & LBS_NOTIFY )
|
||||
SendMessageW( descr->owner, WM_LBTRACKPOINT, index,
|
||||
MAKELPARAM( x, y ) );
|
||||
if (GetWindowLongW( descr->self, GWL_EXSTYLE ) & WS_EX_DRAGDETECT)
|
||||
{
|
||||
POINT pt;
|
||||
|
@ -2147,7 +2190,7 @@ static LRESULT LISTBOX_HandleLButtonDown( LB_DESCR *descr,
|
|||
*
|
||||
* Process LButtonDown message for the ComboListBox
|
||||
*
|
||||
nn * PARAMS
|
||||
* PARAMS
|
||||
* pWnd [I] The windows internal structure
|
||||
* pDescr [I] The ListBox internal structure
|
||||
* wParam [I] Key Flag (WM_LBUTTONDOWN doc for more info)
|
||||
|
@ -2467,7 +2510,6 @@ static LRESULT LISTBOX_HandleKeyDown( LB_DESCR *descr, DWORD key )
|
|||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -2614,8 +2656,8 @@ 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;
|
||||
LPHEADCOMBO lphc = 0;
|
||||
LRESULT ret;
|
||||
|
||||
if (!descr)
|
||||
{
|
||||
|
@ -2625,8 +2667,7 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
|
|||
{
|
||||
CREATESTRUCTW *lpcs = (CREATESTRUCTW *)lParam;
|
||||
if (lpcs->style & LBS_COMBOBOX) lphc = (LPHEADCOMBO)lpcs->lpCreateParams;
|
||||
if (!LISTBOX_Create( hwnd, lphc ))
|
||||
return -1;
|
||||
if (!LISTBOX_Create( hwnd, lphc )) return -1;
|
||||
TRACE("creating wnd=%p descr=%lx\n", hwnd, GetWindowLongPtrW( hwnd, 0 ) );
|
||||
return 0;
|
||||
}
|
||||
|
@ -2638,6 +2679,7 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
|
|||
|
||||
TRACE("[%p]: msg %s wp %08x lp %08lx\n",
|
||||
hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
#ifndef __REACTOS__
|
||||
|
@ -2843,16 +2885,38 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
|
|||
{
|
||||
POINT pt;
|
||||
RECT rect;
|
||||
int index;
|
||||
BOOL hit = TRUE;
|
||||
|
||||
pt.x = LOWORD(lParam);
|
||||
pt.y = HIWORD(lParam);
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = descr->width;
|
||||
rect.bottom = descr->height;
|
||||
/* The hiword of the return value is not a client area
|
||||
hittest as suggested by MSDN, but rather a hittest on
|
||||
the returned listbox item. */
|
||||
|
||||
return MAKELONG( LISTBOX_GetItemFromPoint(descr, pt.x, pt.y),
|
||||
!PtInRect( &rect, pt ) );
|
||||
if(descr->nb_items == 0)
|
||||
return 0x1ffff; /* win9x returns 0x10000, we copy winnt */
|
||||
|
||||
pt.x = (short)LOWORD(lParam);
|
||||
pt.y = (short)HIWORD(lParam);
|
||||
|
||||
SetRect(&rect, 0, 0, descr->width, descr->height);
|
||||
|
||||
if(!PtInRect(&rect, pt))
|
||||
{
|
||||
pt.x = min(pt.x, rect.right - 1);
|
||||
pt.x = max(pt.x, 0);
|
||||
pt.y = min(pt.y, rect.bottom - 1);
|
||||
pt.y = max(pt.y, 0);
|
||||
hit = FALSE;
|
||||
}
|
||||
|
||||
index = LISTBOX_GetItemFromPoint(descr, pt.x, pt.y);
|
||||
|
||||
if(index == -1)
|
||||
{
|
||||
index = descr->nb_items - 1;
|
||||
hit = FALSE;
|
||||
}
|
||||
return MAKELONG(index, hit ? 0 : 1);
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
|
@ -3154,6 +3218,10 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
|
|||
LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
|
||||
return LB_OKAY;
|
||||
|
||||
case LB_GETLISTBOXINFO:
|
||||
FIXME("LB_GETLISTBOXINFO: stub!\n");
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
return LISTBOX_Destroy( descr );
|
||||
|
||||
|
@ -3190,7 +3258,7 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
|
|||
descr->in_focus = TRUE;
|
||||
descr->caret_on = TRUE;
|
||||
if (descr->focus_item != -1)
|
||||
LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
|
||||
LISTBOX_DrawFocusRect( descr, TRUE );
|
||||
SEND_NOTIFICATION( descr, LBN_SETFOCUS );
|
||||
return 0;
|
||||
case WM_KILLFOCUS:
|
||||
|
@ -3325,6 +3393,7 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
|
|||
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;
|
||||
|
@ -3364,12 +3433,11 @@ static LRESULT WINAPI ListBoxWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARA
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* GetListBoxInfo
|
||||
* GetListBoxInfo !REACTOS!
|
||||
*/
|
||||
DWORD STDCALL
|
||||
GetListBoxInfo(HWND hwnd)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
return NtUserGetListBoxInfo(hwnd); // Do it right! Have the message org from kmode!
|
||||
}
|
||||
|
||||
|
|
|
@ -1847,6 +1847,7 @@ extern "C" {
|
|||
#define LB_GETITEMDATA 409
|
||||
#define LB_GETITEMHEIGHT 417
|
||||
#define LB_GETITEMRECT 408
|
||||
#define LB_GETLISTBOXINFO 434
|
||||
#define LB_GETLOCALE 422
|
||||
#define LB_GETSEL 391
|
||||
#define LB_GETSELCOUNT 400
|
||||
|
|
|
@ -1161,7 +1161,7 @@ NtUserGetLayeredWindowAttributes(
|
|||
DWORD
|
||||
NTAPI
|
||||
NtUserGetListBoxInfo(
|
||||
DWORD Unknown0);
|
||||
HWND hWnd);
|
||||
|
||||
typedef struct tagNTUSERGETMESSAGEINFO
|
||||
{
|
||||
|
|
|
@ -125,7 +125,7 @@ User32 -
|
|||
reactos/dll/win32/user32/controls/combo.c # Synced at 20071022
|
||||
reactos/dll/win32/user32/controls/edit.c # Synced at 20071022
|
||||
reactos/dll/win32/user32/controls/icontitle.c # Synced at 20060617
|
||||
reactos/dll/win32/user32/controls/listbox.c # Synced at 20060616
|
||||
reactos/dll/win32/user32/controls/listbox.c # Synced at 20071023
|
||||
reactos/dll/win32/user32/controls/scrollbar.c # Forked
|
||||
reactos/dll/win32/user32/controls/static.c # Synced at 20060908
|
||||
|
||||
|
|
|
@ -334,16 +334,6 @@ NtUserGetImeHotKey(
|
|||
}
|
||||
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserGetListBoxInfo(
|
||||
DWORD Unknown0)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserGetMouseMovePointsEx(
|
||||
|
|
|
@ -2872,6 +2872,32 @@ NtUserGetLastActivePopup(HWND hWnd)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
STDCALL
|
||||
NtUserGetListBoxInfo(
|
||||
HWND hWnd)
|
||||
{
|
||||
PWINDOW_OBJECT Wnd;
|
||||
DECLARE_RETURN(DWORD);
|
||||
|
||||
DPRINT("Enter NtUserGetListBoxInfo\n");
|
||||
UserEnterExclusive();
|
||||
|
||||
if (!(Wnd = UserGetWindowObject(hWnd)))
|
||||
{
|
||||
RETURN( 0 );
|
||||
}
|
||||
|
||||
RETURN( (DWORD) co_IntSendMessage( Wnd->hSelf, LB_GETLISTBOXINFO, 0, 0 ));
|
||||
|
||||
CLEANUP:
|
||||
DPRINT("Leave NtUserGetListBoxInfo, ret=%i\n",_ret_);
|
||||
UserLeave();
|
||||
END_CLEANUP;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NtUserGetParent
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue