mirror of
https://github.com/reactos/wine.git
synced 2025-03-03 02:05:48 +00:00
- Implement the drag list control.
- Fix tabs in LBItemFromPt.
This commit is contained in:
parent
6174bccfb1
commit
dd72963949
@ -9,6 +9,7 @@ idb_std_large.bmp
|
||||
idb_std_small.bmp
|
||||
idb_view_large.bmp
|
||||
idb_view_small.bmp
|
||||
idc_copy.cur
|
||||
idc_divider.cur
|
||||
idc_divideropen.cur
|
||||
idi_dragarrow.ico
|
||||
|
@ -46,6 +46,7 @@ RC_BINARIES = \
|
||||
idb_std_small.bmp \
|
||||
idb_view_large.bmp \
|
||||
idb_view_small.bmp \
|
||||
idc_copy.cur \
|
||||
idc_divider.cur \
|
||||
idc_divideropen.cur \
|
||||
idi_dragarrow.ico \
|
||||
|
@ -102,8 +102,9 @@ extern HBRUSH COMCTL32_hPattern55AABrush;
|
||||
#define IDC_DIVIDEROPEN 107
|
||||
|
||||
|
||||
/* DragList icon */
|
||||
#define IDI_DRAGARROW 150
|
||||
/* DragList resources */
|
||||
#define IDI_DRAGARROW 501
|
||||
#define IDC_COPY 502
|
||||
|
||||
|
||||
/* HOTKEY internal strings */
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Drag List control
|
||||
*
|
||||
* Copyright 1999 Eric Kohl
|
||||
* Copyright 2004 Robert Shearman
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -17,12 +18,6 @@
|
||||
* 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 is just a dummy control. An author is needed! Any volunteers?
|
||||
* Eric <ekohl@abo.rhein-zeitung.de>
|
||||
*
|
||||
* TODO:
|
||||
* - Everything.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
@ -32,13 +27,175 @@
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "winnls.h"
|
||||
#include "winnt.h"
|
||||
#include "commctrl.h"
|
||||
#include "comctl32.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
|
||||
|
||||
#ifndef TEXT
|
||||
# define TEXT(string) string
|
||||
#endif
|
||||
|
||||
#define DRAGLIST_SUBCLASSID 0
|
||||
#define DRAGLIST_SCROLLPERIOD 200
|
||||
#define DRAGLIST_TIMERID 666
|
||||
|
||||
/* properties relating to IDI_DRAGICON */
|
||||
#define DRAGICON_HOTSPOT_X 17
|
||||
#define DRAGICON_HOTSPOT_Y 7
|
||||
#define DRAGICON_HEIGHT 32
|
||||
|
||||
/* internal Wine specific data for the drag list control */
|
||||
typedef struct _DRAGLISTDATA
|
||||
{
|
||||
/* are we currently in dragging mode? */
|
||||
BOOL dragging;
|
||||
|
||||
/* cursor to use as determined by DL_DRAGGING notification.
|
||||
* NOTE: as we use LoadCursor we don't have to use DeleteCursor
|
||||
* when we are finished with it */
|
||||
HCURSOR cursor;
|
||||
|
||||
/* optimisation so that we don't have to load the cursor
|
||||
* all of the time whilst dragging */
|
||||
LRESULT last_dragging_response;
|
||||
/* prevents flicker with drawing drag arrow */
|
||||
RECT last_drag_icon_rect;
|
||||
} DRAGLISTDATA;
|
||||
|
||||
static UINT uDragListMessage = 0; /* registered window message code */
|
||||
static DWORD dwLastScrollTime = 0;
|
||||
static HICON hDragArrow = NULL;
|
||||
|
||||
/***********************************************************************
|
||||
* DragList_Notify (internal)
|
||||
*
|
||||
* Sends notification messages to the parent control. Note that it
|
||||
* does not use WM_NOTIFY like the rest of the controls, but a registered
|
||||
* window message.
|
||||
*/
|
||||
static LRESULT DragList_Notify(HWND hwndLB, UINT uNotification)
|
||||
{
|
||||
DRAGLISTINFO dli;
|
||||
dli.hWnd = hwndLB;
|
||||
dli.uNotification = uNotification;
|
||||
GetCursorPos(&dli.ptCursor);
|
||||
return SendMessageW(GetParent(hwndLB), uDragListMessage, GetDlgCtrlID(hwndLB), (LPARAM)&dli);
|
||||
}
|
||||
|
||||
/* cleans up after dragging */
|
||||
static inline void DragList_EndDrag(HWND hwnd, DRAGLISTDATA * data)
|
||||
{
|
||||
KillTimer(hwnd, DRAGLIST_TIMERID);
|
||||
ReleaseCapture();
|
||||
data->dragging = FALSE;
|
||||
/* clear any drag insert icon present */
|
||||
InvalidateRect(GetParent(hwnd), &data->last_drag_icon_rect, TRUE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DragList_SubclassWindowProc (internal)
|
||||
*
|
||||
* Handles certain messages to enable dragging for the ListBox and forwards
|
||||
* the rest to the ListBox.
|
||||
*/
|
||||
static LRESULT CALLBACK
|
||||
DragList_SubclassWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
|
||||
{
|
||||
DRAGLISTDATA * data = (DRAGLISTDATA*)dwRefData;
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
SetFocus(hwnd);
|
||||
data->cursor = NULL;
|
||||
SetRectEmpty(&data->last_drag_icon_rect);
|
||||
data->dragging = DragList_Notify(hwnd, DL_BEGINDRAG);
|
||||
if (data->dragging)
|
||||
{
|
||||
SetCapture(hwnd);
|
||||
SetTimer(hwnd, DRAGLIST_TIMERID, DRAGLIST_SCROLLPERIOD, NULL);
|
||||
}
|
||||
/* note that we don't absorb this message to let the list box
|
||||
* do its thing (normally selecting an item) */
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
/* user cancelled drag by either right clicking or
|
||||
* by pressing the escape key */
|
||||
if ((data->dragging) &&
|
||||
((uMsg == WM_RBUTTONDOWN) || (wParam == VK_ESCAPE)))
|
||||
{
|
||||
/* clean up and absorb message */
|
||||
DragList_EndDrag(hwnd, data);
|
||||
DragList_Notify(hwnd, DL_CANCELDRAG);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_TIMER:
|
||||
if (data->dragging)
|
||||
{
|
||||
LRESULT cursor = DragList_Notify(hwnd, DL_DRAGGING);
|
||||
/* optimisation so that we don't have to load the cursor
|
||||
* all of the time whilst dragging */
|
||||
if (data->last_dragging_response != cursor)
|
||||
{
|
||||
switch (cursor)
|
||||
{
|
||||
case DL_STOPCURSOR:
|
||||
data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_NO);
|
||||
SetCursor(data->cursor);
|
||||
break;
|
||||
case DL_COPYCURSOR:
|
||||
data->cursor = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_COPY);
|
||||
SetCursor(data->cursor);
|
||||
break;
|
||||
case DL_MOVECURSOR:
|
||||
data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
|
||||
SetCursor(data->cursor);
|
||||
break;
|
||||
}
|
||||
data->last_dragging_response = cursor;
|
||||
}
|
||||
/* don't pass this message on to List Box */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
if (data->dragging)
|
||||
{
|
||||
DragList_EndDrag(hwnd, data);
|
||||
DragList_Notify(hwnd, DL_DROPPED);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
/* if app has told us to set a cursor then do so */
|
||||
if (data->dragging && data->cursor)
|
||||
{
|
||||
SetCursor(data->cursor);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GETDLGCODE:
|
||||
/* tell dialog boxes that we want to receive WM_KEYDOWN events
|
||||
* for keys like VK_ESCAPE */
|
||||
if (data->dragging)
|
||||
return DLGC_WANTALLKEYS;
|
||||
break;
|
||||
case WM_NCDESTROY:
|
||||
RemoveWindowSubclass(hwnd, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID);
|
||||
Free(data);
|
||||
break;
|
||||
}
|
||||
return DefSubclassProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MakeDragList (COMCTL32.13)
|
||||
@ -51,10 +208,14 @@ static DWORD dwLastScrollTime = 0;
|
||||
*/
|
||||
BOOL WINAPI MakeDragList (HWND hwndLB)
|
||||
{
|
||||
FIXME("(%p)\n", hwndLB);
|
||||
DRAGLISTDATA * data = Alloc(sizeof(DRAGLISTDATA));
|
||||
|
||||
TRACE("(%p)\n", hwndLB);
|
||||
|
||||
return FALSE;
|
||||
if (!uDragListMessage)
|
||||
uDragListMessage = RegisterWindowMessageA(DRAGLISTMSGSTRING);
|
||||
|
||||
return SetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR)data);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@ -67,9 +228,54 @@ BOOL WINAPI MakeDragList (HWND hwndLB)
|
||||
*/
|
||||
VOID WINAPI DrawInsert (HWND hwndParent, HWND hwndLB, INT nItem)
|
||||
{
|
||||
FIXME("(%p %p %d)\n", hwndParent, hwndLB, nItem);
|
||||
RECT rcItem, rcListBox, rcDragIcon;
|
||||
HDC hdc;
|
||||
DRAGLISTDATA * data;
|
||||
|
||||
TRACE("(%p %p %d)\n", hwndParent, hwndLB, nItem);
|
||||
|
||||
if (!hDragArrow)
|
||||
hDragArrow = LoadIconW(COMCTL32_hModule, (LPCWSTR)IDI_DRAGARROW);
|
||||
|
||||
if (LB_ERR == SendMessageW(hwndLB, LB_GETITEMRECT, nItem, (LPARAM)&rcItem))
|
||||
return;
|
||||
|
||||
if (!GetWindowRect(hwndLB, &rcListBox))
|
||||
return;
|
||||
|
||||
/* convert item rect to parent co-ordinates */
|
||||
if (!MapWindowPoints(hwndLB, hwndParent, (LPPOINT)&rcItem, 2))
|
||||
return;
|
||||
|
||||
/* convert list box rect to parent co-ordinates */
|
||||
if (!MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rcListBox, 2))
|
||||
return;
|
||||
|
||||
rcDragIcon.left = rcListBox.left - DRAGICON_HOTSPOT_X;
|
||||
rcDragIcon.top = rcItem.top - DRAGICON_HOTSPOT_Y;
|
||||
rcDragIcon.right = rcListBox.left;
|
||||
rcDragIcon.bottom = rcDragIcon.top + DRAGICON_HEIGHT;
|
||||
|
||||
if (!GetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR*)&data))
|
||||
return;
|
||||
|
||||
/* prevent flicker by only redrawing when necessary */
|
||||
if (!EqualRect(&rcDragIcon, &data->last_drag_icon_rect))
|
||||
{
|
||||
/* get rid of any previous inserts drawn */
|
||||
RedrawWindow(hwndParent, &data->last_drag_icon_rect, NULL,
|
||||
RDW_INTERNALPAINT | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
|
||||
|
||||
if (nItem >= 0)
|
||||
{
|
||||
hdc = GetDC(hwndParent);
|
||||
|
||||
DrawIcon(hdc, rcDragIcon.left, rcDragIcon.top, hDragArrow);
|
||||
|
||||
ReleaseDC(hwndParent, hdc);
|
||||
}
|
||||
}
|
||||
CopyRect(&data->last_drag_icon_rect, &rcDragIcon);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@ -87,8 +293,8 @@ INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll)
|
||||
INT nIndex;
|
||||
DWORD dwScrollTime;
|
||||
|
||||
FIXME("(%p %ld x %ld %s)\n",
|
||||
hwndLB, pt.x, pt.y, bAutoScroll ? "TRUE" : "FALSE");
|
||||
TRACE("(%p %ld x %ld %s)\n",
|
||||
hwndLB, pt.x, pt.y, bAutoScroll ? "TRUE" : "FALSE");
|
||||
|
||||
ScreenToClient (hwndLB, &pt);
|
||||
GetClientRect (hwndLB, &rcClient);
|
||||
@ -96,51 +302,41 @@ INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll)
|
||||
|
||||
if (PtInRect (&rcClient, pt))
|
||||
{
|
||||
/* point is inside -- get the item index */
|
||||
while (TRUE)
|
||||
{
|
||||
if (SendMessageA (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR)
|
||||
return -1;
|
||||
/* point is inside -- get the item index */
|
||||
while (TRUE)
|
||||
{
|
||||
if (SendMessageA (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR)
|
||||
return -1;
|
||||
|
||||
if (PtInRect (&rcClient, pt))
|
||||
return nIndex;
|
||||
if (PtInRect (&rcClient, pt))
|
||||
return nIndex;
|
||||
|
||||
nIndex++;
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* point is outside */
|
||||
if (!bAutoScroll)
|
||||
return -1;
|
||||
/* point is outside */
|
||||
if (!bAutoScroll)
|
||||
return -1;
|
||||
|
||||
if ((pt.x > rcClient.right) || (pt.x < rcClient.left))
|
||||
return -1;
|
||||
if ((pt.x > rcClient.right) || (pt.x < rcClient.left))
|
||||
return -1;
|
||||
|
||||
if (pt.y < 0)
|
||||
nIndex--;
|
||||
else
|
||||
nIndex++;
|
||||
if (pt.y < 0)
|
||||
nIndex--;
|
||||
else
|
||||
nIndex++;
|
||||
|
||||
dwScrollTime = GetTickCount ();
|
||||
dwScrollTime = GetTickCount ();
|
||||
|
||||
if ((dwScrollTime - dwLastScrollTime) < 200)
|
||||
return -1;
|
||||
if ((dwScrollTime - dwLastScrollTime) < DRAGLIST_SCROLLPERIOD)
|
||||
return -1;
|
||||
|
||||
dwLastScrollTime = dwScrollTime;
|
||||
dwLastScrollTime = dwScrollTime;
|
||||
|
||||
SendMessageA (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0);
|
||||
SendMessageA (hwndLB, LB_SETTOPINDEX, (WPARAM)nIndex, 0);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static LRESULT CALLBACK
|
||||
DRAGLIST_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
@ -971,6 +971,33 @@ IDB_HIST_LARGE BITMAP LOADONCALL DISCARDABLE idb_hist_large.bmp
|
||||
} */
|
||||
|
||||
|
||||
/* BINRES idc_copy.cur */
|
||||
IDC_COPY CURSOR LOADONCALL DISCARDABLE idc_copy.cur
|
||||
/* {
|
||||
'00 00 02 00 01 00 20 20 00 00 00 00 00 00 30 01'
|
||||
'00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00'
|
||||
'00 00 01 00 01 00 00 00 00 00 00 01 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
|
||||
'00 00 00 00 00 00 00 00 00 00 00 C0 00 00 00 C0'
|
||||
'00 00 01 80 00 00 01 80 00 00 03 00 00 00 43 00'
|
||||
'00 00 66 00 00 00 76 00 00 00 7E 00 00 00 7F C0'
|
||||
'00 00 7F 80 00 00 7F 00 00 00 7E 00 00 00 7C 00'
|
||||
'00 00 78 00 00 00 70 00 00 00 60 00 00 00 40 00'
|
||||
'00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF'
|
||||
'FF FF FF FF FF FF FF FD FF FF FF FD FF FF FF F0'
|
||||
'7F FF FF FD FF FF FF 3D FF FF FE 1F FF FF FE 1F'
|
||||
'FF FF FC 3F FF FF 7C 3F FF FF 38 7F FF FF 18 7F'
|
||||
'FF FF 00 FF FF FF 00 FF FF FF 00 0F FF FF 00 1F'
|
||||
'FF FF 00 3F FF FF 00 7F FF FF 00 FF FF FF 01 FF'
|
||||
'FF FF 03 FF FF FF 07 FF FF FF 0F FF FF FF 1F FF'
|
||||
'FF FF 3F FF FF FF'
|
||||
} */
|
||||
|
||||
|
||||
/* BINRES idc_divider.cur */
|
||||
IDC_DIVIDER CURSOR LOADONCALL DISCARDABLE idc_divider.cur
|
||||
/* {
|
||||
|
Loading…
x
Reference in New Issue
Block a user