Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dragdrop.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

PCURSOR xxxQueryDropObject (PWND pwnd, LPDROPSTRUCT lpds)
DWORD xxxDragObject (PWND pwndParent, PWND pwndFrom, UINT wFmt, ULONG_PTR dwData, PCURSOR pcur)
BOOL xxxDragDetect (PWND pwnd, POINT pt)
BOOL xxxIsDragging (PWND pwnd, POINT ptScreen, UINT uMsg)


Function Documentation

BOOL xxxDragDetect PWND  pwnd,
POINT  pt
 

Definition at line 338 of file dragdrop.c.

References BOOL, and xxxIsDragging().

Referenced by NtUserDragDetect().

00341 { 00342 return xxxIsDragging(pwnd, pt, WM_LBUTTONUP); 00343 }

DWORD xxxDragObject PWND  pwndParent,
PWND  pwndFrom,
UINT  wFmt,
ULONG_PTR  dwData,
PCURSOR  pcur
 

Definition at line 26 of file dragdrop.c.

References BOOL, CheckLock, DWORD, FALSE, FWINABLE, GETPTI, HW, IsWinEventNotifyDeferredOK, msg, NULL, tagTHREADINFO::pq, PtiCurrent, RevalidateHwnd, tagQ::spcurCurrent, tagQ::spwndCapture, tagWND::spwndParent, SYSCUR, TestwndChild, ThreadLockAlwaysWithPti, ThreadLockPool, ThreadLockWithPti, ThreadUnlock, ThreadUnlockAndFreePool, TIF_ALLOWFOREGROUNDACTIVATE, TRUE, ValidateHwnd, xxxPeekMessage, xxxQueryDropObject(), xxxReleaseCapture(), xxxSendMessage(), xxxSetCapture(), xxxSleepThread(), xxxUpdateWindow(), xxxWindowEvent(), zzzSetCursor(), and zzzShowCursor().

Referenced by NtUserDragObject().

00032 { 00033 MSG msg, msgKey; 00034 DWORD result = 0; 00035 BOOL fDrag = TRUE; 00036 LPDROPSTRUCT lpds; 00037 PWND pwndDragging = NULL; 00038 PWND pwndTop; 00039 PCURSOR pcurOld, pcurT; 00040 PWND pwndT; 00041 TL tlpwndT; 00042 TL tlpwndTop; 00043 TL tlpwndDragging; 00044 TL tlPool; 00045 PTHREADINFO pti = PtiCurrent(); 00046 00047 CheckLock(pwndParent); 00048 CheckLock(pwndFrom); 00049 CheckLock(pcur); 00050 UserAssert(IsWinEventNotifyDeferredOK()); 00051 00052 lpds = (LPDROPSTRUCT)UserAllocPoolWithQuota(2 * sizeof(DROPSTRUCT), TAG_DRAGDROP); 00053 if (lpds == NULL) 00054 return 0; 00055 00056 ThreadLockPool(pti, lpds, &tlPool); 00057 lpds->hwndSource = HW(pwndFrom); 00058 lpds->wFmt = wFmt; 00059 lpds->dwData = dwData; 00060 00061 if (pcur != NULL) { 00062 /* 00063 * No need to DeferWinEventNotify() - pwndFrom is locked 00064 */ 00065 pcurOld = zzzSetCursor(pcur); 00066 } else { 00067 pcurOld = pti->pq->spcurCurrent; 00068 } 00069 00070 if (pwndFrom) { 00071 for (pwndTop = pwndFrom; TestwndChild(pwndTop); 00072 pwndTop = pwndTop->spwndParent) ; 00073 00074 ThreadLockWithPti(pti, pwndTop, &tlpwndTop); 00075 xxxUpdateWindow(pwndTop); 00076 ThreadUnlock(&tlpwndTop); 00077 } 00078 00079 if (FWINABLE()) { 00080 xxxWindowEvent(EVENT_SYSTEM_DRAGDROPSTART, pwndFrom, OBJID_WINDOW, INDEXID_CONTAINER, 0); 00081 } 00082 00083 xxxSetCapture(pwndFrom); 00084 zzzShowCursor(TRUE); 00085 00086 ThreadLockWithPti(pti, pwndDragging, &tlpwndDragging); 00087 00088 while (fDrag && pti->pq->spwndCapture == pwndFrom) { 00089 while (!(xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || 00090 xxxPeekMessage(&msg, NULL, WM_QUEUESYNC, WM_QUEUESYNC, PM_REMOVE) || 00091 xxxPeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))) { 00092 if (!xxxSleepThread(QS_MOUSE | QS_KEY, 0, TRUE)) { 00093 ThreadUnlock(&tlpwndDragging); 00094 ThreadUnlockAndFreePool(pti, &tlPool); 00095 return 0; 00096 } 00097 } 00098 00099 /* 00100 * Be sure to eliminate any extra keydown messages that are 00101 * being queued up by MOUSE message processing. 00102 */ 00103 00104 while (xxxPeekMessage(&msgKey, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) 00105 ; 00106 00107 if ( (pti->pq->spwndCapture != pwndFrom) || 00108 (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) ) 00109 { 00110 if (pcurT = SYSCUR(NO)) 00111 zzzSetCursor(pcurT); 00112 break; 00113 } 00114 00115 RtlCopyMemory(lpds + 1, lpds, sizeof(DROPSTRUCT)); 00116 00117 /* 00118 * in screen coordinates 00119 */ 00120 lpds->ptDrop = msg.pt; 00121 00122 pcurT = xxxQueryDropObject(pwndParent, lpds); 00123 00124 /* 00125 * Returning FALSE to a WM_QUERYDROPOBJECT message means drops 00126 * aren't supported and the 'illegal drop target' cursor should be 00127 * displayed. Returning TRUE means the target is valid and the 00128 * regular drag cursor should be displayed. Also, through a bit 00129 * of polymorphic magic one can return a cursor handle to override 00130 * the normal drag cursor. 00131 */ 00132 if (pcurT == (PCURSOR)FALSE) { 00133 pcurT = SYSCUR(NO); 00134 lpds->hwndSink = NULL; 00135 } else if (pcurT == (PCURSOR)TRUE) { 00136 pcurT = pcur; 00137 } 00138 00139 if (pcurT != NULL) 00140 zzzSetCursor(pcurT); 00141 00142 /* 00143 * send the WM_DRAGLOOP after the above zzzSetCursor() to allow the 00144 * receiver to change the cursor at WM_DRAGLOOP time with a zzzSetCursor() 00145 */ 00146 if (pwndFrom) { 00147 xxxSendMessage(pwndFrom, WM_DRAGLOOP, (pcurT != SYSCUR(NO)), 00148 (LPARAM)lpds); 00149 } 00150 00151 /* 00152 * send these messages internally only 00153 */ 00154 if (pwndDragging != RevalidateHwnd(lpds->hwndSink)) { 00155 if (pwndDragging != NULL) { 00156 xxxSendMessage(pwndDragging, WM_DRAGSELECT, FALSE, 00157 (LPARAM)(lpds + 1)); 00158 } 00159 pwndDragging = RevalidateHwnd(lpds->hwndSink); 00160 ThreadUnlock(&tlpwndDragging); 00161 ThreadLockWithPti(pti, pwndDragging, &tlpwndDragging); 00162 00163 if (pwndDragging != NULL) { 00164 xxxSendMessage(pwndDragging, WM_DRAGSELECT, TRUE, (LPARAM)lpds); 00165 } 00166 } else { 00167 if (pwndDragging != NULL) { 00168 xxxSendMessage(pwndDragging, WM_DRAGMOVE, 0, (LPARAM)lpds); 00169 } 00170 } 00171 00172 switch (msg.message) { 00173 case WM_LBUTTONUP: 00174 case WM_NCLBUTTONUP: 00175 fDrag = FALSE; 00176 break; 00177 } 00178 } 00179 00180 ThreadUnlock(&tlpwndDragging); 00181 00182 /* 00183 * If the capture has been lost (i.e. fDrag == TRUE), don't do the drop. 00184 */ 00185 if (fDrag) 00186 pcurT = SYSCUR(NO); 00187 00188 /* 00189 * before the actual drop, clean up the cursor, as the app may do 00190 * stuff here... 00191 */ 00192 xxxReleaseCapture(); 00193 zzzShowCursor(FALSE); 00194 00195 zzzSetCursor(pcurOld); 00196 00197 /* 00198 * we either got lbuttonup or enter 00199 */ 00200 if (pcurT != SYSCUR(NO)) { 00201 00202 /* 00203 * object allows drop... send drop message 00204 */ 00205 pwndT = ValidateHwnd(lpds->hwndSink); 00206 if (pwndT != NULL) { 00207 00208 ThreadLockAlwaysWithPti(pti, pwndT, &tlpwndT); 00209 00210 /* 00211 * Allow this guy to activate. 00212 */ 00213 GETPTI(pwndT)->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; 00214 TAGMSG1(DBGTAG_FOREGROUND, "xxxDragObject set TIF %#p", GETPTI(pwndT)); 00215 result = (DWORD)xxxSendMessage(pwndT, WM_DROPOBJECT, 00216 (WPARAM)HW(pwndFrom), (LPARAM)lpds); 00217 00218 ThreadUnlock(&tlpwndT); 00219 } 00220 } 00221 00222 if (FWINABLE()) { 00223 xxxWindowEvent(EVENT_SYSTEM_DRAGDROPEND, pwndFrom, OBJID_WINDOW, INDEXID_CONTAINER, 0); 00224 } 00225 00226 ThreadUnlockAndFreePool(pti, &tlPool); 00227 return result; 00228 }

BOOL xxxIsDragging PWND  pwnd,
POINT  ptScreen,
UINT  uMsg
 

Definition at line 354 of file dragdrop.c.

References _GetKeyState(), BOOL, FALSE, InflateRect(), msg, NULL, tagTHREADINFO::pq, PtiCurrent, PtInRect(), tagQ::spwndCapture, SYSMET, ThreadLockWithPti, ThreadUnlock, TRUE, xxxCallHook(), xxxPeekMessage, xxxReleaseCapture(), xxxSetCapture(), and xxxSleepThread().

Referenced by xxxDragDetect(), and xxxSysCommand().

00355 { 00356 RECT rc; 00357 MSG msg; 00358 BOOL fDragging; 00359 BOOL fCheck; 00360 TL tlpwndDragging; 00361 PTHREADINFO pti = PtiCurrent(); 00362 00363 /* 00364 * Check synchronous mouse state, and punt if the mouse isn't down 00365 * according to the queue. 00366 */ 00367 if (!(_GetKeyState((uMsg == WM_LBUTTONUP ? VK_LBUTTON : VK_RBUTTON)) & 0x8000)) 00368 return FALSE; 00369 00370 xxxSetCapture(pwnd); 00371 00372 *(LPPOINT)&rc.left = ptScreen; 00373 *(LPPOINT)&rc.right = ptScreen; 00374 InflateRect(&rc, SYSMET(CXDRAG), SYSMET(CYDRAG)); 00375 00376 fDragging = FALSE; 00377 fCheck = TRUE; 00378 00379 ThreadLockWithPti(pti, pwnd, &tlpwndDragging); 00380 while (fCheck) { 00381 while ( !( 00382 xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST,PM_REMOVE) || 00383 xxxPeekMessage(&msg, NULL, WM_QUEUESYNC, WM_QUEUESYNC,PM_REMOVE) || 00384 xxxPeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST,PM_REMOVE) 00385 ) 00386 && (pti->pq->spwndCapture == pwnd)) { 00387 /* 00388 * If there is no input for half a second (500ms) consider that 00389 * we are dragging. If we don't specify a timeout value, the 00390 * thread may sleep here forever and wouldn't repaint, etc. 00391 */ 00392 if (!xxxSleepThread(QS_MOUSE | QS_KEY, 500, TRUE)) { 00393 fDragging = TRUE; 00394 goto Cleanup; 00395 } 00396 } 00397 00398 /* 00399 * Cancel if the button was released or we no longer have the capture. 00400 */ 00401 if ( pti->pq->spwndCapture != pwnd || msg.message == uMsg) { 00402 fCheck = FALSE; 00403 } else { 00404 switch (msg.message) { 00405 00406 case WM_MOUSEMOVE: 00407 if (!PtInRect(&rc, msg.pt)) { 00408 fDragging = TRUE; 00409 fCheck = FALSE; 00410 } 00411 break; 00412 00413 case WM_QUEUESYNC: 00414 /* 00415 * CBT Hook needs to know 00416 */ 00417 xxxCallHook(HCBT_QS, 0, 0, WH_CBT); 00418 break; 00419 00420 case WM_KEYDOWN: 00421 /* 00422 * <Esc> cancels drag detection 00423 */ 00424 if (msg.wParam == VK_ESCAPE) 00425 fCheck = FALSE; 00426 break; 00427 00428 } 00429 } 00430 } 00431 00432 Cleanup: 00433 if (pti->pq->spwndCapture == pwnd) 00434 xxxReleaseCapture(); 00435 00436 ThreadUnlock(&tlpwndDragging); 00437 return fDragging ; 00438 }

PCURSOR xxxQueryDropObject PWND  pwnd,
LPDROPSTRUCT  lpds
 

Definition at line 243 of file dragdrop.c.

References _ChildWindowFromPointEx(), _ClientToScreen(), _ScreenToClient(), BOOL, CheckLock, FALSE, HMValidateHandle(), tagWND::hrgnClip, HWq, NULL, PtInRect(), tagWND::rcClient, tagWND::rcWindow, TestWF, ThreadLock, ThreadUnlock, TRUE, TYPE_CURSOR, WFDISABLED, WFMINIMIZED, and xxxSendMessageTimeout().

Referenced by xxxDragObject().

00246 { 00247 PWND pwndT; 00248 PCURSOR pcurT = NULL; 00249 POINT pt; 00250 BOOL fNC; 00251 TL tlpwndT; 00252 CheckLock(pwnd); 00253 00254 /* 00255 * pt is in screen coordinates 00256 */ 00257 pt = lpds->ptDrop; 00258 00259 /* 00260 * reject points outside this window or if the window is disabled 00261 */ 00262 if (!PtInRect(&pwnd->rcWindow, pt) || TestWF(pwnd, WFDISABLED)) 00263 return NULL; 00264 00265 /* 00266 * Check to see if in window region (if it has one) 00267 */ 00268 if (pwnd->hrgnClip != NULL) { 00269 if (!GrePtInRegion(pwnd->hrgnClip, pt.x, pt.y)) 00270 return NULL; 00271 } 00272 00273 /* 00274 * are we dropping in the nonclient area of the window or on an iconic 00275 * window? 00276 */ 00277 if (fNC = (TestWF(pwnd, WFMINIMIZED) || !PtInRect(&pwnd->rcClient, pt))) { 00278 goto SendQueryDrop; 00279 } 00280 00281 /* 00282 * dropping in client area 00283 */ 00284 _ScreenToClient(pwnd, &pt); 00285 pwndT = _ChildWindowFromPointEx(pwnd, pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE); 00286 _ClientToScreen(pwnd, &pt); 00287 00288 pcurT = NULL; 00289 if (pwndT && pwndT != pwnd) { 00290 ThreadLock(pwndT, &tlpwndT); 00291 pcurT = xxxQueryDropObject(pwndT, lpds); 00292 ThreadUnlock(&tlpwndT); 00293 } 00294 00295 if (pcurT == NULL) { 00296 00297 /* 00298 * there are no children who are in the right place or who want 00299 * drops... convert the point into client coordinates of the 00300 * current window. Because of the recursion, this is already 00301 * done if a child window grabbed the drop. 00302 */ 00303 SendQueryDrop: 00304 _ScreenToClient(pwnd, &lpds->ptDrop); 00305 lpds->hwndSink = HWq(pwnd); 00306 00307 /* 00308 * To avoid hanging dropper (sender) app we do a SendMessageTimeout to 00309 * the droppee (receiver) 00310 */ 00311 if ((PCURSOR)xxxSendMessageTimeout(pwnd, WM_QUERYDROPOBJECT, fNC, 00312 (LPARAM)lpds, SMTO_ABORTIFHUNG, 3*1000, (PLONG_PTR)&pcurT) == FALSE) 00313 pcurT = (PCURSOR)FALSE; 00314 00315 if (pcurT != (PCURSOR)FALSE && pcurT != (PCURSOR)TRUE) 00316 pcurT = HMValidateHandle((HCURSOR)pcurT, TYPE_CURSOR); 00317 00318 /* 00319 * restore drop point to screen coordinates if this window won't 00320 * take drops 00321 */ 00322 if (pcurT == NULL) 00323 lpds->ptDrop = pt; 00324 } 00325 return pcurT; 00326 }


Generated on Sat May 15 19:43:29 2004 for test by doxygen 1.3.7