Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

904 lines
25 KiB

  1. /****************************************************************************/
  2. /* */
  3. /* WFDIRSRC.C - */
  4. /* */
  5. /* Routines Common to the Directory and Search Windows */
  6. /* */
  7. /****************************************************************************/
  8. #include "winfile.h"
  9. #define DO_DROPFILE 0x454C4946L
  10. #define DO_PRINTFILE 0x544E5250L
  11. #define DO_DROPONDESKTOP 0x504D42L
  12. HWND hwndGlobalSink = NULL;
  13. VOID SelectItem(HWND hwndLB, WPARAM wParam, BOOL bSel);
  14. VOID ShowItemBitmaps(HWND hwndLB, BOOL bShow);
  15. DWORD GetSearchAttribs(HWND hwndLB, WORD wIndex);
  16. HCURSOR
  17. APIENTRY
  18. GetMoveCopyCursor()
  19. {
  20. if (fShowSourceBitmaps)
  21. // copy
  22. return LoadCursor(hAppInstance, MAKEINTRESOURCE(iCurDrag | 1));
  23. else
  24. // move
  25. return LoadCursor(hAppInstance, MAKEINTRESOURCE(iCurDrag & 0xFFFE));
  26. }
  27. DWORD
  28. GetSearchAttribs(
  29. HWND hwndLB,
  30. WORD wIndex
  31. )
  32. {
  33. DWORD dwAttribs;
  34. HANDLE hDTA;
  35. LPDTASEARCH lpschdta;
  36. hDTA = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH);
  37. lpschdta = (LPDTASEARCH)LocalLock(hDTA);
  38. dwAttribs = lpschdta[(INT)SendMessage(hwndLB, LB_GETITEMDATA, wIndex, 0L)].sch_dwAttrs;
  39. LocalUnlock(hDTA);
  40. return dwAttribs;
  41. }
  42. // match a DOS wild card spec against a dos file name
  43. // both strings are ANSI and Upper case
  44. BOOL
  45. MatchFile(
  46. LPSTR szFile,
  47. LPSTR szSpec
  48. )
  49. {
  50. ENTER("MatchFile");
  51. PRINT(BF_PARMTRACE, "IN:szFile=%s", szFile);
  52. PRINT(BF_PARMTRACE, "IN:szSpec=%s", szSpec);
  53. #define IS_DOTEND(ch) ((ch) == '.' || (ch) == 0)
  54. if (!lstrcmp(szSpec, "*") || // "*" matches everything
  55. !lstrcmp(szSpec, szStarDotStar)) // so does "*.*"
  56. return TRUE;
  57. while (*szFile && *szSpec) {
  58. switch (*szSpec) {
  59. case '?':
  60. szFile++;
  61. szSpec++;
  62. break;
  63. case '*':
  64. while (!IS_DOTEND(*szSpec)) // got till a terminator
  65. szSpec = AnsiNext(szSpec);
  66. if (*szSpec == '.')
  67. szSpec++;
  68. while (!IS_DOTEND(*szFile)) // got till a terminator
  69. szFile = AnsiNext(szFile);
  70. if (*szFile == '.')
  71. szFile++;
  72. break;
  73. default:
  74. if (*szSpec == *szFile) {
  75. if (IsDBCSLeadByte(*szSpec)) {
  76. szFile++;
  77. szSpec++;
  78. if (*szFile != *szSpec)
  79. return FALSE;
  80. }
  81. szFile++;
  82. szSpec++;
  83. } else
  84. return FALSE;
  85. }
  86. }
  87. return !*szFile && !*szSpec;
  88. }
  89. VOID
  90. APIENTRY
  91. DSSetSelection(
  92. HWND hwndLB,
  93. BOOL bSelect,
  94. LPSTR szSpec,
  95. BOOL bSearch
  96. )
  97. {
  98. WORD i;
  99. WORD iMac;
  100. HANDLE hMem;
  101. LPMYDTA lpmydta;
  102. CHAR szTemp[MAXPATHLEN];
  103. AnsiUpper(szSpec);
  104. iMac = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
  105. if (bSearch)
  106. hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH);
  107. else
  108. hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTA);
  109. LocalLock(hMem);
  110. for (i = 0; i < iMac; i++) {
  111. if (bSearch) {
  112. SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)szTemp);
  113. StripPath(szTemp);
  114. } else {
  115. SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)&lpmydta);
  116. if (lpmydta->my_dwAttrs & ATTR_PARENT)
  117. continue;
  118. lstrcpy(szTemp, lpmydta->my_cFileName);
  119. }
  120. AnsiUpper(szTemp);
  121. if (MatchFile(szTemp, szSpec))
  122. SendMessage(hwndLB, LB_SETSEL, bSelect, MAKELONG(i, 0));
  123. }
  124. LocalUnlock(hMem);
  125. }
  126. /*--------------------------------------------------------------------------*/
  127. /* */
  128. /* ShowItemBitmaps() - */
  129. /* */
  130. /*--------------------------------------------------------------------------*/
  131. VOID
  132. ShowItemBitmaps(
  133. HWND hwndLB,
  134. BOOL bShow
  135. )
  136. {
  137. INT iSel;
  138. RECT rc;
  139. if (bShow == fShowSourceBitmaps)
  140. return;
  141. fShowSourceBitmaps = bShow;
  142. /* Invalidate the bitmap parts of all visible, selected items. */
  143. iSel = (WORD)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
  144. while (SendMessage(hwndLB, LB_GETITEMRECT, iSel, (LPARAM)&rc) != LB_ERR) {
  145. /* Is this item selected? */
  146. if ((BOOL)SendMessage(hwndLB, LB_GETSEL, iSel, 0L)) {
  147. /* Invalidate the bitmap area. */
  148. rc.right = rc.left + dxFolder + dyBorderx2 + dyBorder;
  149. InvalidateRect(hwndLB, &rc, FALSE);
  150. }
  151. iSel++;
  152. }
  153. UpdateWindow(hwndLB);
  154. }
  155. INT
  156. CharCountToTab(
  157. LPSTR pStr
  158. )
  159. {
  160. LPSTR pTmp = pStr;
  161. while (*pStr && *pStr != '\t') {
  162. pStr = AnsiNext(pStr);
  163. }
  164. return (INT)(pStr-pTmp);
  165. }
  166. // this only deals with opaque text for now
  167. VOID
  168. RightTabbedTextOut(
  169. HDC hdc,
  170. INT x,
  171. INT y,
  172. LPSTR pLine,
  173. WORD *pTabStops,
  174. INT x_offset
  175. )
  176. {
  177. INT len, cch;
  178. INT x_ext;
  179. INT x_initial;
  180. RECT rc;
  181. len = lstrlen(pLine);
  182. // setup opaquing rect (we adjust the right border as we
  183. // output the string)
  184. rc.left = x;
  185. rc.top = y;
  186. rc.bottom = y + dyText; // global max char height
  187. x_initial = x;
  188. cch = CharCountToTab(pLine);
  189. MGetTextExtent(hdc, pLine, cch, &x_ext, NULL);
  190. // first position is left alligned so bias initial x value
  191. x += x_ext;
  192. while (len) {
  193. len -= cch + 1;
  194. rc.right = x;
  195. ExtTextOut(hdc, x - x_ext, y, ETO_OPAQUE, &rc, pLine, cch, NULL);
  196. if (len <= 0)
  197. return;
  198. rc.left = rc.right;
  199. pLine += cch + 1;
  200. cch = CharCountToTab(pLine);
  201. MGetTextExtent(hdc, pLine, cch, &x_ext, NULL);
  202. x = *pTabStops + x_offset;
  203. pTabStops++;
  204. }
  205. }
  206. /*--------------------------------------------------------------------------*/
  207. /* */
  208. /* DrawItem() - */
  209. /* */
  210. /*--------------------------------------------------------------------------*/
  211. VOID
  212. APIENTRY
  213. DrawItem(
  214. LPDRAWITEMSTRUCT lpLBItem,
  215. LPSTR szLine,
  216. DWORD dwAttrib,
  217. BOOL bHasFocus,
  218. WORD *pTabs
  219. )
  220. {
  221. INT x, y;
  222. CHAR ch;
  223. LPSTR psz;
  224. HDC hDC;
  225. BOOL bDrawSelected;
  226. HWND hwndLB;
  227. INT iBitmap;
  228. hwndLB = lpLBItem->hwndItem;
  229. bDrawSelected = (lpLBItem->itemState & ODS_SELECTED);
  230. hDC = lpLBItem->hDC;
  231. if (bHasFocus && bDrawSelected) {
  232. SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  233. SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
  234. }
  235. if (lpLBItem->itemAction == ODA_FOCUS)
  236. goto FocusOnly;
  237. /* Draw the black/white background. */
  238. ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lpLBItem->rcItem, NULL, 0, NULL);
  239. x = lpLBItem->rcItem.left + 1;
  240. y = lpLBItem->rcItem.top + (dyFileName/2);
  241. if (fShowSourceBitmaps || (hwndDragging != hwndLB) || !bDrawSelected) {
  242. if (dwAttrib & ATTR_DIR) {
  243. if (dwAttrib & ATTR_PARENT) {
  244. iBitmap = BM_IND_DIRUP;
  245. szLine = szNULL; // no date/size stuff!
  246. } else
  247. iBitmap = BM_IND_CLOSE;
  248. } else {
  249. // isolate the name so we can see what type of file this is
  250. psz = szLine + CharCountToTab(szLine);
  251. ch = *psz;
  252. *psz = 0;
  253. if (dwAttrib & (ATTR_HIDDEN | ATTR_SYSTEM))
  254. iBitmap = BM_IND_RO;
  255. else if (IsProgramFile(szLine))
  256. iBitmap = BM_IND_APP;
  257. else if (IsDocument(szLine))
  258. iBitmap = BM_IND_DOC;
  259. else
  260. iBitmap = BM_IND_FIL;
  261. *psz = ch; // resore the old character
  262. }
  263. BitBlt(hDC, x + dyBorder, y-(dyFolder/2), dxFolder, dyFolder, hdcMem,
  264. iBitmap * dxFolder, (bHasFocus && bDrawSelected) ? dyFolder : 0, SRCCOPY);
  265. }
  266. x += dxFolder + dyBorderx2;
  267. if ((wTextAttribs & TA_LOWERCASE) && !(dwAttrib & ATTR_LFN))
  268. AnsiLower(szLine);
  269. RightTabbedTextOut(hDC, x, y-(dyText/2), szLine, (WORD *)pTabs, x);
  270. if (lpLBItem->itemState & ODS_FOCUS)
  271. FocusOnly:
  272. DrawFocusRect(hDC, &lpLBItem->rcItem); // toggles focus (XOR)
  273. if (bDrawSelected) {
  274. if (bHasFocus) {
  275. SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  276. SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  277. } else {
  278. HBRUSH hbr;
  279. RECT rc;
  280. if (hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT))) {
  281. rc = lpLBItem->rcItem;
  282. rc.right = rc.left + (INT)SendMessage(hwndLB, LB_GETHORIZONTALEXTENT, 0, 0L);
  283. if (lpLBItem->itemID > 0 &&
  284. (BOOL)SendMessage(hwndLB, LB_GETSEL, lpLBItem->itemID - 1, 0L))
  285. rc.top -= dyBorder;
  286. FrameRect(hDC, &rc, hbr);
  287. DeleteObject(hbr);
  288. }
  289. }
  290. }
  291. }
  292. /*--------------------------------------------------------------------------*/
  293. /* */
  294. /* SelectItem() - */
  295. /* */
  296. /*--------------------------------------------------------------------------*/
  297. VOID
  298. SelectItem(
  299. HWND hwndLB,
  300. WPARAM wParam,
  301. BOOL bSel
  302. )
  303. {
  304. /* Add the current item to the selection. */
  305. SendMessage(hwndLB, LB_SETSEL, bSel, (DWORD)wParam);
  306. /* Give the selected item the focus rect and anchor pt. */
  307. SendMessage(hwndLB, LB_SETCARETINDEX, wParam, 0L);
  308. SendMessage(hwndLB, LB_SETANCHORINDEX, wParam, 0L);
  309. }
  310. //
  311. // void APIENTRY DSDragLoop(register HWND hwndLB, WPARAM wParam, LPDROPSTRUCT lpds, BOOL bSearch)
  312. //
  313. // called by for the directory and search drag loops. this must handle
  314. // detecting all kinds of different destinations.
  315. //
  316. // in:
  317. // hwndLB source listbox (either the dir or the sort)
  318. // wParam same as sent for WM_DRAGLOOP (TRUE if we are on a dropable sink)
  319. // lpds drop struct sent with the message
  320. // bSearch TRUE if we are in the search listbox
  321. //
  322. VOID
  323. APIENTRY
  324. DSDragLoop(
  325. HWND hwndLB,
  326. WPARAM wParam,
  327. LPDROPSTRUCT lpds,
  328. BOOL bSearch
  329. )
  330. {
  331. BOOL bTemp;
  332. BOOL bShowBitmap;
  333. LPMYDTA lpmydta;
  334. HWND hwndMDIChildSink, hwndDir;
  335. // bShowBitmap is used to turn the source bitmaps on or off to distinguish
  336. // between a move and a copy or to indicate that a drop can
  337. // occur (exec and app)
  338. // hack: keep around for drop files!
  339. hwndGlobalSink = lpds->hwndSink;
  340. bShowBitmap = TRUE; // default to copy
  341. if (!wParam)
  342. goto DragLoopCont; // can't drop here
  343. // Is the user holding down the CTRL key (which forces a copy)?
  344. if (GetKeyState(VK_CONTROL) < 0) {
  345. bShowBitmap = TRUE;
  346. goto DragLoopCont;
  347. }
  348. // Is the user holding down the ALT or SHIFT key (which forces a move)?
  349. if (GetKeyState(VK_MENU)<0 || GetKeyState(VK_SHIFT)<0) {
  350. bShowBitmap = FALSE;
  351. goto DragLoopCont;
  352. }
  353. hwndMDIChildSink = GetMDIChildFromDecendant(lpds->hwndSink);
  354. // Are we over the source listbox? (sink and source the same)
  355. if (lpds->hwndSink == hwndLB) {
  356. // Are we over a valid listbox entry?
  357. if (LOWORD(lpds->dwControlData) == 0xFFFF) {
  358. goto DragLoopCont;
  359. } else {
  360. /* Yup, are we over a directory entry? */
  361. if (bSearch) {
  362. bTemp = (GetSearchAttribs(hwndLB, (WORD)(lpds->dwControlData)) & ATTR_DIR) != 0L;
  363. } else {
  364. SendMessage(hwndLB, LB_GETTEXT, (WORD)(lpds->dwControlData), (LPARAM)&lpmydta);
  365. bTemp = lpmydta->my_dwAttrs & ATTR_DIR;
  366. }
  367. if (!bTemp)
  368. goto DragLoopCont;
  369. }
  370. }
  371. /* Now we need to see if we are over an Executable file. If so, we
  372. * need to force the Bitmaps to draw.
  373. */
  374. /* Are we over a directory window? */
  375. if (hwndMDIChildSink)
  376. hwndDir = HasDirWindow(hwndMDIChildSink);
  377. else
  378. hwndDir = NULL;
  379. if (hwndDir && (hwndDir == GetParent(lpds->hwndSink))) {
  380. // Are we over an occupided part of the list box?
  381. if (LOWORD(lpds->dwControlData) != 0xFFFF) {
  382. // Are we over an Executable?
  383. SendMessage(lpds->hwndSink, LB_GETTEXT, (WORD)(lpds->dwControlData), (LPARAM)&lpmydta);
  384. bTemp = IsProgramFile(lpmydta->my_cFileName);
  385. if (bTemp)
  386. goto DragLoopCont;
  387. }
  388. }
  389. // Are we dropping into the same drive (check the source and dest drives)
  390. bShowBitmap = ((INT)SendMessage(GetParent(hwndLB), FS_GETDRIVE, 0, 0L) !=
  391. GetDrive(lpds->hwndSink, lpds->ptDrop));
  392. DragLoopCont:
  393. ShowItemBitmaps(hwndLB, bShowBitmap);
  394. // hack, set the cursor to match the move/copy state
  395. if (wParam)
  396. SetCursor(GetMoveCopyCursor());
  397. }
  398. /*--------------------------------------------------------------------------*/
  399. /* */
  400. /* DSRectItem() - */
  401. /* */
  402. /*--------------------------------------------------------------------------*/
  403. VOID
  404. APIENTRY
  405. DSRectItem(
  406. HWND hwndLB,
  407. INT iItem,
  408. BOOL bFocusOn,
  409. BOOL bSearch
  410. )
  411. {
  412. RECT rc;
  413. RECT rcT;
  414. HDC hDC;
  415. BOOL bSel;
  416. WORD wColor;
  417. HBRUSH hBrush;
  418. LPMYDTA lpmydta;
  419. CHAR szTemp[MAXPATHLEN];
  420. /* Are we over an unused part of the listbox? */
  421. if (iItem == 0xFFFF)
  422. return;
  423. /* Are we over ourselves? (i.e. a selected item in the source listbox) */
  424. bSel = (BOOL)SendMessage(hwndLB, LB_GETSEL, iItem, 0L);
  425. if (bSel && (hwndDragging == hwndLB))
  426. return;
  427. /* We only put rectangles around directories and program items. */
  428. if (bSearch) {
  429. SendMessage(hwndLB, LB_GETTEXT, iItem, (LPARAM)szTemp);
  430. // this is bused, we must test this as attributes
  431. if (!(BOOL)(GetSearchAttribs(hwndLB, (WORD)iItem) & ATTR_DIR) && !IsProgramFile((LPSTR)szTemp))
  432. return;
  433. } else {
  434. SendMessage(hwndLB, LB_GETTEXT, iItem, (LPARAM)&lpmydta);
  435. if (!(lpmydta->my_dwAttrs & ATTR_DIR) &&
  436. !IsProgramFile(lpmydta->my_cFileName)) {
  437. return;
  438. }
  439. }
  440. /* Turn the item's rectangle on or off. */
  441. SendMessage(hwndLB, LB_GETITEMRECT, iItem, (LPARAM)&rc);
  442. GetClientRect(hwndLB,&rcT);
  443. IntersectRect(&rc,&rc,&rcT);
  444. if (bFocusOn) {
  445. hDC = GetDC(hwndLB);
  446. if (bSel) {
  447. wColor = COLOR_WINDOW;
  448. InflateRect(&rc, -1, -1);
  449. } else
  450. wColor = COLOR_WINDOWFRAME;
  451. if (hBrush = CreateSolidBrush(GetSysColor(wColor))) {
  452. FrameRect(hDC, &rc, hBrush);
  453. DeleteObject(hBrush);
  454. }
  455. ReleaseDC(hwndLB, hDC);
  456. } else {
  457. InvalidateRect(hwndLB, &rc, FALSE);
  458. UpdateWindow(hwndLB);
  459. }
  460. }
  461. /*--------------------------------------------------------------------------*/
  462. /* */
  463. /* DropFilesOnApplication() - */
  464. /* */
  465. /*--------------------------------------------------------------------------*/
  466. /* this function will determine whether the application we are currently
  467. * over is a valid drop point and drop the files
  468. */
  469. WORD
  470. DropFilesOnApplication(
  471. LPSTR pszFiles
  472. )
  473. {
  474. POINT pt;
  475. HWND hwnd;
  476. RECT rc;
  477. HANDLE hDrop,hT;
  478. LPSTR lpList;
  479. WORD cbList = 2;
  480. OFSTRUCT ofT;
  481. WORD cbT;
  482. LPDROPFILESTRUCT lpdfs;
  483. CHAR szFile[MAXPATHLEN];
  484. if (!(hwnd = hwndGlobalSink))
  485. return 0;
  486. hwndGlobalSink = NULL;
  487. GetCursorPos(&pt);
  488. cbList = 2 + sizeof (DROPFILESTRUCT);
  489. hDrop = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,cbList);
  490. if (!hDrop)
  491. return 0;
  492. lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop);
  493. GetClientRect(hwnd,&rc);
  494. ScreenToClient(hwnd,&pt);
  495. lpdfs->pt = pt;
  496. lpdfs->fNC = !PtInRect(&rc,pt);
  497. lpdfs->pFiles = sizeof(DROPFILESTRUCT);
  498. GlobalUnlock(hDrop);
  499. while (pszFiles = GetNextFile(pszFiles, szFile, sizeof(szFile))) {
  500. MOpenFile(szFile, &ofT, OF_PARSE);
  501. cbT = (WORD)(lstrlen(ofT.szPathName)+1);
  502. hT = GlobalReAlloc(hDrop,cbList+cbT,GMEM_MOVEABLE|GMEM_ZEROINIT);
  503. if (!hT)
  504. break;
  505. hDrop = hT;
  506. lpList = GlobalLock(hDrop);
  507. OemToCharBuff(ofT.szPathName, lpList+cbList-2, sizeof(ofT.szPathName)/sizeof(ofT.szPathName[0]));
  508. GlobalUnlock(hDrop);
  509. cbList += cbT;
  510. }
  511. PostMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0L);
  512. return 1;
  513. }
  514. /*--------------------------------------------------------------------------*/
  515. /* */
  516. /* DSTrackPoint() - */
  517. /* */
  518. /*--------------------------------------------------------------------------*/
  519. /* Return 0 for normal mouse tracking, 1 for no mouse single-click processing,
  520. * and 2 for no mouse single- or double-click tracking.
  521. */
  522. INT
  523. APIENTRY
  524. DSTrackPoint(
  525. HWND hWnd,
  526. HWND hwndLB,
  527. WPARAM wParam,
  528. LPARAM lParam,
  529. BOOL bSearch
  530. )
  531. {
  532. UINT iSel;
  533. MSG msg;
  534. RECT rc;
  535. WORD wAnchor;
  536. DWORD dwTemp;
  537. LPSTR pch;
  538. BOOL bDir;
  539. BOOL bSelected;
  540. BOOL bSelectOneItem;
  541. BOOL bUnselectIfNoDrag;
  542. CHAR szFileName[MAXPATHLEN+1];
  543. INT iNoYieldCount;
  544. WORD wYieldFlags;
  545. POINT pt;
  546. HANDLE hHackForHDC = NULL; // hDC Express editor relies on this
  547. DRAGOBJECTDATA dodata;
  548. bSelectOneItem = FALSE;
  549. bUnselectIfNoDrag = FALSE;
  550. bSelected = (BOOL)SendMessage(hwndLB, LB_GETSEL, wParam, 0L);
  551. if (GetKeyState(VK_SHIFT) < 0) {
  552. /* What is the state of the Anchor point? */
  553. wAnchor = (WORD)SendMessage(hwndLB, LB_GETANCHORINDEX, 0, 0L);
  554. bSelected = (BOOL)SendMessage(hwndLB, LB_GETSEL, wAnchor, 0L);
  555. /* If Control is up, turn everything off. */
  556. if (!(GetKeyState(VK_CONTROL) < 0))
  557. SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
  558. /* Select everything between the Anchor point and the item. */
  559. SendMessage(hwndLB, LB_SELITEMRANGE, bSelected, MAKELONG(wParam, wAnchor));
  560. /* Give the selected item the focus rect. */
  561. SendMessage(hwndLB, LB_SETCARETINDEX, wParam, 0L);
  562. } else if (GetKeyState(VK_CONTROL) < 0) {
  563. if (bSelected)
  564. bUnselectIfNoDrag = TRUE;
  565. else
  566. SelectItem(hwndLB, wParam, TRUE);
  567. } else {
  568. if (bSelected)
  569. bSelectOneItem = TRUE;
  570. else {
  571. /* Deselect everything. */
  572. SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
  573. /* Select the current item. */
  574. SelectItem(hwndLB, wParam, TRUE);
  575. }
  576. }
  577. if (!bSearch)
  578. UpdateStatus(GetParent(hWnd));
  579. LONG2POINT(lParam, pt);
  580. ClientToScreen(hwndLB, (LPPOINT)&pt);
  581. ScreenToClient(hWnd, (LPPOINT)&pt);
  582. // See if the user moves a certain number of pixels in any direction
  583. SetRect(&rc, pt.x - dxClickRect, pt.y - dyClickRect,
  584. pt.x + dxClickRect, pt.y + dyClickRect);
  585. SetCapture(hWnd);
  586. wYieldFlags = PM_NOYIELD | PM_REMOVE;
  587. iNoYieldCount = 50;
  588. for (;;) {
  589. #if 0
  590. {
  591. CHAR szBuf[80];
  592. wsprintf(szBuf, "Message %4.4X\r\n", msg.message);
  593. OutputDebugString(szBuf);
  594. }
  595. #endif
  596. if (PeekMessage(&msg, NULL, 0, 0, wYieldFlags))
  597. DispatchMessage(&msg);
  598. if (iNoYieldCount <= 0)
  599. wYieldFlags = PM_REMOVE;
  600. else
  601. iNoYieldCount--;
  602. // WM_CANCELMODE messages will unset the capture, in that
  603. // case I want to exit this loop
  604. if (GetCapture() != hWnd) {
  605. msg.message = WM_LBUTTONUP; // don't proceed below
  606. break;
  607. }
  608. if (msg.message == WM_LBUTTONUP)
  609. break;
  610. LONG2POINT(msg.lParam, pt);
  611. if ((msg.message == WM_MOUSEMOVE) && !(PtInRect(&rc, pt)))
  612. break;
  613. }
  614. ReleaseCapture();
  615. /* Did the guy NOT drag anything? */
  616. if (msg.message == WM_LBUTTONUP) {
  617. if (bSelectOneItem) {
  618. /* Deselect everything. */
  619. SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
  620. /* Select the current item. */
  621. SelectItem(hwndLB, wParam, TRUE);
  622. }
  623. if (bUnselectIfNoDrag)
  624. SelectItem(hwndLB, wParam, FALSE);
  625. // notify the appropriate people
  626. SendMessage(hWnd, WM_COMMAND,
  627. GET_WM_COMMAND_MPS(0, hwndLB, LBN_SELCHANGE));
  628. return 1;
  629. }
  630. /* Enter Danger Mouse's BatCave. */
  631. if ((WORD)SendMessage(hwndLB, LB_GETSELCOUNT, 0, 0L) == 1) {
  632. /* There is only one thing selected.
  633. * Figure out which cursor to use.
  634. */
  635. if (bSearch) {
  636. SendMessage(hwndLB, LB_GETTEXT, wParam, (LPARAM)szFileName);
  637. bDir = (BOOL)(GetSearchAttribs(hwndLB, (WORD)wParam) & ATTR_DIR);
  638. } else {
  639. LPMYDTA lpmydta;
  640. SendMessage(hwndLB, LB_GETTEXT, wParam, (LPARAM)&lpmydta);
  641. lstrcpy(szFileName, lpmydta->my_cFileName);
  642. bDir = lpmydta->my_dwAttrs & ATTR_DIR;
  643. // avoid dragging the parrent dir
  644. if (lpmydta->my_dwAttrs & ATTR_PARENT) {
  645. return 1;
  646. }
  647. }
  648. if (bDir) {
  649. iSel = DOF_DIRECTORY;
  650. } else if (IsProgramFile(szFileName)) {
  651. iSel = DOF_EXECUTABLE;
  652. goto HDC_HACK_FROM_HELL;
  653. } else if (IsDocument(szFileName)) {
  654. iSel = DOF_DOCUMENT;
  655. HDC_HACK_FROM_HELL:
  656. hHackForHDC = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(OFSTRUCT));
  657. if (hHackForHDC) {
  658. LPOFSTRUCT lpof;
  659. lpof = (LPOFSTRUCT)GlobalLock(hHackForHDC);
  660. QualifyPath(szFileName);
  661. lstrcpy(lpof->szPathName, szFileName);
  662. GlobalUnlock(hHackForHDC);
  663. }
  664. } else
  665. iSel = DOF_DOCUMENT;
  666. iCurDrag = SINGLECOPYCURSOR;
  667. } else {
  668. /* Multiple files are selected. */
  669. iSel = DOF_MULTIPLE;
  670. iCurDrag = MULTCOPYCURSOR;
  671. }
  672. /* Get the list of selected things. */
  673. pch = (LPSTR)SendMessage(hWnd, FS_GETSELECTION, FALSE, 0L);
  674. /* Wiggle things around. */
  675. hwndDragging = hwndLB;
  676. dodata.pch = pch;
  677. dodata.hMemGlobal = hHackForHDC;
  678. dwTemp = DragObject(GetDesktopWindow(),hWnd,(UINT)iSel,(DWORD)(ULONG_PTR)&dodata,GetMoveCopyCursor());
  679. if (hHackForHDC)
  680. GlobalFree(hHackForHDC);
  681. SetWindowDirectory();
  682. if (dwTemp == DO_PRINTFILE) {
  683. // print these
  684. hdlgProgress = NULL;
  685. WFPrint(pch);
  686. } else if (dwTemp == DO_DROPFILE) {
  687. // try and drop them on an application
  688. DropFilesOnApplication(pch);
  689. }
  690. LocalFree((HANDLE)pch);
  691. if (IsWindow(hWnd))
  692. ShowItemBitmaps(hwndLB, TRUE);
  693. hwndDragging = NULL;
  694. if (!bSearch && IsWindow(hWnd))
  695. UpdateStatus(GetParent(hWnd));
  696. return 2;
  697. }