00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015
PCURSOR xxxQueryDropObject(
PWND pwnd, LPDROPSTRUCT lpds);
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 DWORD xxxDragObject(
00027
PWND pwndParent,
00028
PWND pwndFrom,
00029 UINT wFmt,
00030 ULONG_PTR dwData,
00031
PCURSOR pcur)
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
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
00101
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
00119
00120 lpds->ptDrop =
msg.pt;
00121
00122 pcurT =
xxxQueryDropObject(pwndParent, lpds);
00123
00124
00125
00126
00127
00128
00129
00130
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
00144
00145
00146
if (pwndFrom) {
00147
xxxSendMessage(pwndFrom, WM_DRAGLOOP, (pcurT !=
SYSCUR(NO)),
00148 (LPARAM)lpds);
00149 }
00150
00151
00152
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
00184
00185
if (fDrag)
00186 pcurT =
SYSCUR(NO);
00187
00188
00189
00190
00191
00192
xxxReleaseCapture();
00193
zzzShowCursor(
FALSE);
00194
00195
zzzSetCursor(pcurOld);
00196
00197
00198
00199
00200
if (pcurT !=
SYSCUR(NO)) {
00201
00202
00203
00204
00205 pwndT =
ValidateHwnd(lpds->hwndSink);
00206
if (pwndT !=
NULL) {
00207
00208
ThreadLockAlwaysWithPti(pti, pwndT, &tlpwndT);
00209
00210
00211
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 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 PCURSOR xxxQueryDropObject(
00244
PWND pwnd,
00245 LPDROPSTRUCT lpds)
00246 {
00247
PWND pwndT;
00248
PCURSOR pcurT =
NULL;
00249 POINT pt;
00250
BOOL fNC;
00251
TL tlpwndT;
00252
CheckLock(pwnd);
00253
00254
00255
00256
00257 pt = lpds->ptDrop;
00258
00259
00260
00261
00262
if (!
PtInRect(&pwnd->
rcWindow, pt) ||
TestWF(pwnd,
WFDISABLED))
00263
return NULL;
00264
00265
00266
00267
00268
if (pwnd->
hrgnClip !=
NULL) {
00269
if (!GrePtInRegion(pwnd->
hrgnClip, pt.x, pt.y))
00270
return NULL;
00271 }
00272
00273
00274
00275
00276
00277
if (fNC = (
TestWF(pwnd,
WFMINIMIZED) || !
PtInRect(&pwnd->
rcClient, pt))) {
00278
goto SendQueryDrop;
00279 }
00280
00281
00282
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
00299
00300
00301
00302
00303 SendQueryDrop:
00304
_ScreenToClient(pwnd, &lpds->ptDrop);
00305 lpds->hwndSink =
HWq(pwnd);
00306
00307
00308
00309
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
00320
00321
00322
if (pcurT ==
NULL)
00323 lpds->ptDrop = pt;
00324 }
00325
return pcurT;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 BOOL xxxDragDetect(
00339
PWND pwnd,
00340 POINT pt)
00341 {
00342
return xxxIsDragging(pwnd, pt, WM_LBUTTONUP);
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 BOOL xxxIsDragging(
PWND pwnd, POINT ptScreen, UINT uMsg)
00355 {
00356 RECT rc;
00357 MSG
msg;
00358
BOOL fDragging;
00359
BOOL fCheck;
00360
TL tlpwndDragging;
00361
PTHREADINFO pti =
PtiCurrent();
00362
00363
00364
00365
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
00389
00390
00391
00392
if (!
xxxSleepThread(QS_MOUSE | QS_KEY, 500,
TRUE)) {
00393 fDragging =
TRUE;
00394
goto Cleanup;
00395 }
00396 }
00397
00398
00399
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
00416
00417
xxxCallHook(HCBT_QS, 0, 0, WH_CBT);
00418
break;
00419
00420
case WM_KEYDOWN:
00421
00422
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 }