~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/comctl32/draglist.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Drag List control
  3  *
  4  * Copyright 1999 Eric Kohl
  5  * Copyright 2004 Robert Shearman
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  *
 21  * NOTES
 22  *
 23  * This code was audited for completeness against the documented features
 24  * of Comctl32.dll version 6.0 on Mar. 10, 2004, by Robert Shearman.
 25  * 
 26  * Unless otherwise noted, we believe this code to be complete, as per
 27  * the specification mentioned above.
 28  * If you discover missing features or bugs please note them below.
 29  * 
 30  */
 31 
 32 #include <stdarg.h>
 33 
 34 #include "windef.h"
 35 #include "winbase.h"
 36 #include "wingdi.h"
 37 #include "winuser.h"
 38 #include "winnls.h"
 39 #include "commctrl.h"
 40 #include "comctl32.h"
 41 #include "wine/debug.h"
 42 
 43 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 44 
 45 #define DRAGLIST_SUBCLASSID     0
 46 #define DRAGLIST_SCROLLPERIOD 200
 47 #define DRAGLIST_TIMERID      666
 48 
 49 /* properties relating to IDI_DRAGICON */
 50 #define DRAGICON_HOTSPOT_X 17
 51 #define DRAGICON_HOTSPOT_Y  7
 52 #define DRAGICON_HEIGHT    32
 53 
 54 /* internal Wine specific data for the drag list control */
 55 typedef struct _DRAGLISTDATA
 56 {
 57     /* are we currently in dragging mode? */
 58     BOOL dragging;
 59 
 60     /* cursor to use as determined by DL_DRAGGING notification.
 61      * NOTE: as we use LoadCursor we don't have to use DeleteCursor
 62      * when we are finished with it */
 63     HCURSOR cursor;
 64 
 65     /* optimisation so that we don't have to load the cursor
 66      * all of the time whilst dragging */
 67     LRESULT last_dragging_response;
 68 
 69     /* prevents flicker with drawing drag arrow */
 70     RECT last_drag_icon_rect;
 71 } DRAGLISTDATA;
 72 
 73 UINT uDragListMessage = 0; /* registered window message code */
 74 static DWORD dwLastScrollTime = 0;
 75 static HICON hDragArrow = NULL;
 76 
 77 /***********************************************************************
 78  *              DragList_Notify (internal)
 79  *
 80  * Sends notification messages to the parent control. Note that it
 81  * does not use WM_NOTIFY like the rest of the controls, but a registered
 82  * window message.
 83  */
 84 static LRESULT DragList_Notify(HWND hwndLB, UINT uNotification)
 85 {
 86     DRAGLISTINFO dli;
 87     dli.hWnd = hwndLB;
 88     dli.uNotification = uNotification;
 89     GetCursorPos(&dli.ptCursor);
 90     return SendMessageW(GetParent(hwndLB), uDragListMessage, GetDlgCtrlID(hwndLB), (LPARAM)&dli);
 91 }
 92 
 93 /* cleans up after dragging */
 94 static void DragList_EndDrag(HWND hwnd, DRAGLISTDATA * data)
 95 {
 96     KillTimer(hwnd, DRAGLIST_TIMERID);
 97     ReleaseCapture();
 98     /* clear any drag insert icon present */
 99     InvalidateRect(GetParent(hwnd), &data->last_drag_icon_rect, TRUE);
100     /* clear data for next use */
101     memset(data, 0, sizeof(*data));
102 }
103 
104 /***********************************************************************
105  *              DragList_SubclassWindowProc (internal)
106  *
107  * Handles certain messages to enable dragging for the ListBox and forwards
108  * the rest to the ListBox.
109  */
110 static LRESULT CALLBACK
111 DragList_SubclassWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
112 {
113     DRAGLISTDATA * data = (DRAGLISTDATA*)dwRefData;
114     switch (uMsg)
115     {
116     case WM_LBUTTONDOWN:
117         SetFocus(hwnd);
118         data->dragging = DragList_Notify(hwnd, DL_BEGINDRAG);
119         if (data->dragging)
120         {
121             SetCapture(hwnd);
122             SetTimer(hwnd, DRAGLIST_TIMERID, DRAGLIST_SCROLLPERIOD, NULL);
123         }
124         /* note that we don't absorb this message to let the list box
125          * do its thing (normally selecting an item) */
126         break;
127 
128     case WM_KEYDOWN:
129     case WM_RBUTTONDOWN:
130         /* user cancelled drag by either right clicking or
131          * by pressing the escape key */
132         if ((data->dragging) &&
133             ((uMsg == WM_RBUTTONDOWN) || (wParam == VK_ESCAPE)))
134         {
135             /* clean up and absorb message */
136             DragList_EndDrag(hwnd, data);
137             DragList_Notify(hwnd, DL_CANCELDRAG);
138             return 0;
139         }
140         break;
141 
142     case WM_MOUSEMOVE:
143     case WM_TIMER:
144         if (data->dragging)
145         {
146             LRESULT cursor = DragList_Notify(hwnd, DL_DRAGGING);
147             /* optimisation so that we don't have to load the cursor
148              * all of the time whilst dragging */
149             if (data->last_dragging_response != cursor)
150             {
151                 switch (cursor)
152                 {
153                 case DL_STOPCURSOR:
154                     data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_NO);
155                     SetCursor(data->cursor);
156                     break;
157                 case DL_COPYCURSOR:
158                     data->cursor = LoadCursorW(COMCTL32_hModule, (LPCWSTR)IDC_COPY);
159                     SetCursor(data->cursor);
160                     break;
161                 case DL_MOVECURSOR:
162                     data->cursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
163                     SetCursor(data->cursor);
164                     break;
165                 }
166                 data->last_dragging_response = cursor;
167             }
168             /* don't pass this message on to List Box */
169             return 0;
170         }
171         break;
172 
173     case WM_LBUTTONUP:
174         if (data->dragging)
175         {
176             DragList_EndDrag(hwnd, data);
177             DragList_Notify(hwnd, DL_DROPPED);
178         }
179         break;
180 
181     case WM_GETDLGCODE:
182         /* tell dialog boxes that we want to receive WM_KEYDOWN events
183          * for keys like VK_ESCAPE */
184         if (data->dragging)
185             return DLGC_WANTALLKEYS;
186         break;
187     case WM_NCDESTROY:
188         RemoveWindowSubclass(hwnd, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID);
189         Free(data);
190         break;
191     }
192     return DefSubclassProc(hwnd, uMsg, wParam, lParam);
193 }
194 
195 /***********************************************************************
196  *              MakeDragList (COMCTL32.13)
197  *
198  * Makes a normal ListBox into a DragList by subclassing it.
199  *
200  * RETURNS
201  *      Success: Non-zero
202  *      Failure: Zero
203  */
204 BOOL WINAPI MakeDragList (HWND hwndLB)
205 {
206     DRAGLISTDATA *data = Alloc(sizeof(DRAGLISTDATA));
207 
208     TRACE("(%p)\n", hwndLB);
209 
210     if (!uDragListMessage)
211         uDragListMessage = RegisterWindowMessageW(DRAGLISTMSGSTRINGW);
212 
213     return SetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR)data);
214 }
215 
216 /***********************************************************************
217  *              DrawInsert (COMCTL32.15)
218  *
219  * Draws insert arrow by the side of the ListBox item in the parent window.
220  *
221  * RETURNS
222  *      Nothing.
223  */
224 VOID WINAPI DrawInsert (HWND hwndParent, HWND hwndLB, INT nItem)
225 {
226     RECT rcItem, rcListBox, rcDragIcon;
227     HDC hdc;
228     DRAGLISTDATA * data;
229 
230     TRACE("(%p %p %d)\n", hwndParent, hwndLB, nItem);
231 
232     if (!hDragArrow)
233         hDragArrow = LoadIconW(COMCTL32_hModule, (LPCWSTR)IDI_DRAGARROW);
234 
235     if (LB_ERR == SendMessageW(hwndLB, LB_GETITEMRECT, nItem, (LPARAM)&rcItem))
236         return;
237 
238     if (!GetWindowRect(hwndLB, &rcListBox))
239         return;
240 
241     /* convert item rect to parent co-ordinates */
242     if (!MapWindowPoints(hwndLB, hwndParent, (LPPOINT)&rcItem, 2))
243         return;
244 
245     /* convert list box rect to parent co-ordinates */
246     if (!MapWindowPoints(HWND_DESKTOP, hwndParent, (LPPOINT)&rcListBox, 2))
247         return;
248 
249     rcDragIcon.left = rcListBox.left - DRAGICON_HOTSPOT_X;
250     rcDragIcon.top = rcItem.top - DRAGICON_HOTSPOT_Y;
251     rcDragIcon.right = rcListBox.left;
252     rcDragIcon.bottom = rcDragIcon.top + DRAGICON_HEIGHT;
253 
254     if (!GetWindowSubclass(hwndLB, DragList_SubclassWindowProc, DRAGLIST_SUBCLASSID, (DWORD_PTR*)&data))
255         return;
256 
257     if (nItem < 0)
258         SetRectEmpty(&rcDragIcon);
259 
260     /* prevent flicker by only redrawing when necessary */
261     if (!EqualRect(&rcDragIcon, &data->last_drag_icon_rect))
262     {
263         /* get rid of any previous inserts drawn */
264         RedrawWindow(hwndParent, &data->last_drag_icon_rect, NULL,
265             RDW_INTERNALPAINT | RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
266 
267         CopyRect(&data->last_drag_icon_rect, &rcDragIcon);
268 
269         if (nItem >= 0)
270         {
271             hdc = GetDC(hwndParent);
272 
273             DrawIcon(hdc, rcDragIcon.left, rcDragIcon.top, hDragArrow);
274 
275             ReleaseDC(hwndParent, hdc);
276         }
277     }
278 }
279 
280 /***********************************************************************
281  *              LBItemFromPt (COMCTL32.14)
282  *
283  * Gets the index of the ListBox item under the specified point,
284  * scrolling if bAutoScroll is TRUE and pt is outside of the ListBox.
285  *
286  * RETURNS
287  *      The ListBox item ID if pt is over a list item or -1 otherwise.
288  */
289 INT WINAPI LBItemFromPt (HWND hwndLB, POINT pt, BOOL bAutoScroll)
290 {
291     RECT rcClient;
292     INT nIndex;
293     DWORD dwScrollTime;
294 
295     TRACE("(%p %d x %d %s)\n",
296            hwndLB, pt.x, pt.y, bAutoScroll ? "TRUE" : "FALSE");
297 
298     ScreenToClient (hwndLB, &pt);
299     GetClientRect (hwndLB, &rcClient);
300     nIndex = (INT)SendMessageW (hwndLB, LB_GETTOPINDEX, 0, 0);
301 
302     if (PtInRect (&rcClient, pt))
303     {
304         /* point is inside -- get the item index */
305         while (TRUE)
306         {
307             if (SendMessageW (hwndLB, LB_GETITEMRECT, nIndex, (LPARAM)&rcClient) == LB_ERR)
308                 return -1;
309 
310             if (PtInRect (&rcClient, pt))
311                 return nIndex;
312 
313             nIndex++;
314         }
315     }
316     else
317     {
318         /* point is outside */
319         if (!bAutoScroll)
320             return -1;
321 
322         if ((pt.x > rcClient.right) || (pt.x < rcClient.left))
323             return -1;
324 
325         if (pt.y < 0)
326             nIndex--;
327         else
328             nIndex++;
329 
330         dwScrollTime = GetTickCount ();
331 
332         if ((dwScrollTime - dwLastScrollTime) < DRAGLIST_SCROLLPERIOD)
333             return -1;
334 
335         dwLastScrollTime = dwScrollTime;
336 
337         SendMessageW (hwndLB, LB_SETTOPINDEX, nIndex, 0);
338     }
339 
340     return -1;
341 }
342 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.