Source code of Windows XP (NT5)
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.

929 lines
24 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // wfdrives.c
  4. //
  5. // window procs and other stuff for the drive bar
  6. //
  7. //---------------------------------------------------------------------------
  8. #define PUBLIC // avoid collision with shell.h
  9. #include "winfile.h"
  10. #include "treectl.h"
  11. #include "lfn.h"
  12. #include "wfcopy.h"
  13. #include "winnet.h"
  14. #include <winnetp.h>
  15. VOID InvalidateDrive(HWND hwnd, INT nDrive);
  16. VOID RectDrive(HWND hWnd, INT nDrive, BOOL bFocusOn);
  17. VOID GetDriveRect(HWND hWnd, INT nDrive, PRECT prc);
  18. INT DriveFromPoint(HWND hWnd, POINT pt);
  19. VOID DrawDrive(HDC hdc, INT x, INT y, INT nDrive, BOOL bCurrent, BOOL bFocus);
  20. INT KeyToItem(HWND hWnd, WORD nDriveLetter);
  21. VOID GetVolShareString(WORD wDrive, LPSTR szStr);
  22. VOID SetVolumeString(HWND hWnd, INT nDrive);
  23. VOID APIENTRY CheckEscapes(LPSTR);
  24. // create a new split tree window for the given drive
  25. // and inherit all the properties of the current window
  26. // the current directory is set to the DOS current directory
  27. // for this drive. note, this can be somewhat random given
  28. // that windows does not keep this info for each app (it is
  29. // global to the system)
  30. //
  31. // in:
  32. // iDrive the driver number to create the window for
  33. // hwndSrc the window to take all the properties from
  34. //
  35. VOID
  36. APIENTRY
  37. NewTree(
  38. INT iDrive,
  39. HWND hwndSrc
  40. )
  41. {
  42. HWND hwnd, hwndTree, hwndDir;
  43. CHAR szDir[MAXPATHLEN * 2];
  44. INT dxSplit;
  45. ENTER("NewTree");
  46. PRINT(BF_PARMTRACE, "iDrive=%d", IntToPtr(iDrive));
  47. // make sure the floppy/net drive is still valid
  48. if (!CheckDrive(hwndSrc, iDrive))
  49. return;
  50. if (hwndSrc == hwndSearch)
  51. dxSplit = -1;
  52. else {
  53. hwndTree = HasTreeWindow(hwndSrc);
  54. hwndDir = HasDirWindow(hwndSrc);
  55. if (hwndTree && hwndDir)
  56. dxSplit = GetWindowLong(hwndSrc, GWL_SPLIT);
  57. else if (hwndDir)
  58. dxSplit = 0;
  59. else
  60. dxSplit = 10000;
  61. }
  62. // take all the attributes from the current window
  63. // (except the filespec, we may want to change this)
  64. wNewSort = (WORD)GetWindowLong(hwndSrc, GWL_SORT);
  65. wNewView = (WORD)GetWindowLong(hwndSrc, GWL_VIEW);
  66. dwNewAttribs = (DWORD)GetWindowLong(hwndSrc, GWL_ATTRIBS);
  67. GetSelectedDirectory((WORD)(iDrive + 1), szDir);
  68. AddBackslash(szDir);
  69. SendMessage(hwndSrc, FS_GETFILESPEC, MAXPATHLEN, (LPARAM)szDir+lstrlen(szDir));
  70. hwnd = CreateTreeWindow(szDir, dxSplit);
  71. if (hwnd && (hwndTree = HasTreeWindow(hwnd)))
  72. SendMessage(hwndTree, TC_SETDRIVE, MAKEWORD(FALSE, 0), 0L);
  73. LEAVE("NewTree");
  74. }
  75. VOID
  76. SetVolumeString(
  77. HWND hWnd,
  78. INT nDrive
  79. )
  80. {
  81. LPSTR pVol;
  82. CHAR szVolShare[128];
  83. // clean up any old label
  84. if (pVol = (LPSTR)GetWindowLongPtr(hWnd, GWLP_LPSTRVOLUME)) {
  85. LocalFree((HANDLE)pVol);
  86. }
  87. GetVolShareString((WORD)nDrive, szVolShare);
  88. if (pVol = (LPSTR)LocalAlloc(LPTR, lstrlen(szVolShare)+1))
  89. lstrcpy(pVol, szVolShare);
  90. SetWindowLongPtr(hWnd, GWLP_LPSTRVOLUME, (LONG_PTR)pVol);
  91. }
  92. VOID
  93. GetVolShareString(
  94. WORD wDrive,
  95. LPSTR szStr
  96. )
  97. {
  98. CHAR szVolShare[128];
  99. GetVolShare(wDrive, szVolShare);
  100. wsprintf(szStr, "%c: %s", wDrive + 'A', (LPSTR)szVolShare);
  101. }
  102. DWORD
  103. APIENTRY
  104. GetVolShareExtent(
  105. HWND hwndDrives
  106. )
  107. {
  108. HDC hdc;
  109. CHAR szVolShare[128];
  110. HFONT hOld;
  111. INT i;
  112. lstrcpy(szVolShare, (LPSTR)GetWindowLongPtr(hwndDrives, GWLP_LPSTRVOLUME));
  113. hdc = GetDC(hwndDrives);
  114. hOld = SelectObject(hdc, hFont);
  115. MGetTextExtent(hdc, szVolShare, lstrlen(szVolShare), &i, NULL);
  116. if (hOld)
  117. SelectObject(hdc, hOld);
  118. ReleaseDC(hwndDrives, hdc);
  119. return ((DWORD)i);
  120. }
  121. VOID
  122. GetDriveRect(
  123. HWND hWnd,
  124. INT nDrive,
  125. PRECT prc
  126. )
  127. {
  128. RECT rc;
  129. INT nDrivesPerRow;
  130. GetClientRect(hWnd, &rc);
  131. if (!dxDrive) // avoid div by zero
  132. dxDrive++;
  133. nDrivesPerRow = rc.right / dxDrive;
  134. if (!nDrivesPerRow) // avoid div by zero
  135. nDrivesPerRow++;
  136. prc->top = dyDrive * (nDrive / nDrivesPerRow);
  137. prc->bottom = prc->top + dyDrive;
  138. prc->left = dxDrive * (nDrive % nDrivesPerRow);
  139. prc->right = prc->left + dxDrive;
  140. }
  141. INT
  142. DriveFromPoint(
  143. HWND hWnd,
  144. POINT pt
  145. )
  146. {
  147. RECT rc, rcDrive;
  148. INT x, y, nDrive;
  149. GetClientRect(hWnd, &rc);
  150. x = 0;
  151. y = 0;
  152. nDrive = 0;
  153. for (nDrive = 0; nDrive < cDrives; nDrive++) {
  154. rcDrive.left = x;
  155. rcDrive.right = x + dxDrive;
  156. rcDrive.top = y;
  157. rcDrive.bottom = y + dyDrive;
  158. InflateRect(&rcDrive, -dyBorder, -dyBorder);
  159. if (PtInRect(&rcDrive, pt))
  160. return nDrive;
  161. x += dxDrive;
  162. if (x + dxDrive > rc.right) {
  163. x = 0;
  164. y += dyDrive;
  165. }
  166. }
  167. return -1; // no hit
  168. }
  169. VOID
  170. InvalidateDrive(
  171. HWND hwnd,
  172. INT nDrive
  173. )
  174. {
  175. RECT rc;
  176. GetDriveRect(hwnd, nDrive, &rc);
  177. InvalidateRect(hwnd, &rc, TRUE);
  178. }
  179. //
  180. // void RectDrive(HWND hWnd, int nDrive, BOOL bDraw)
  181. //
  182. // draw the hilight rect around the drive to indicate that it is
  183. // the target of a drop action.
  184. //
  185. // in:
  186. // hWnd Drives window
  187. // nDrive the drive to draw the rect around
  188. // bDraw if TRUE, draw a rect around this drive
  189. // FALSE, erase the rect (draw the default rect)
  190. //
  191. VOID
  192. RectDrive(
  193. HWND hWnd,
  194. INT nDrive,
  195. BOOL bDraw
  196. )
  197. {
  198. RECT rc, rcDrive;
  199. HBRUSH hBrush;
  200. HDC hdc;
  201. GetDriveRect(hWnd, nDrive, &rc);
  202. rcDrive = rc;
  203. InflateRect(&rc, -dyBorder, -dyBorder);
  204. if (bDraw) {
  205. hdc = GetDC(hWnd);
  206. hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT));
  207. if (hBrush) {
  208. FrameRect(hdc, &rc, hBrush);
  209. DeleteObject(hBrush);
  210. }
  211. ReleaseDC(hWnd, hdc);
  212. } else {
  213. InvalidateRect(hWnd, &rcDrive, TRUE);
  214. UpdateWindow(hWnd);
  215. }
  216. }
  217. //
  218. // void DrawDrive(HDC hdc, int x, int y, int nDrive, BOOL bCurrent, BOOL bFocus)
  219. //
  220. // paint the drive icons in the standard state, given the
  221. // drive with the focus and the current selection
  222. //
  223. // in:
  224. // hdc dc to draw to
  225. // x, y position to start (dxDrive, dyDrive are the extents)
  226. // nDrive the drive to paint
  227. // bCurrent draw as the current drive (pushed in)
  228. // bFocus draw with the focus
  229. //
  230. VOID
  231. DrawDrive(
  232. HDC hdc,
  233. INT x,
  234. INT y,
  235. INT nDrive,
  236. BOOL bCurrent,
  237. BOOL bFocus
  238. )
  239. {
  240. RECT rc;
  241. CHAR szTemp[2];
  242. DWORD rgb;
  243. rc.left = x;
  244. rc.right = x + dxDrive;
  245. rc.top = y;
  246. rc.bottom = y + dyDrive;
  247. rgb = GetSysColor(COLOR_BTNTEXT);
  248. if (bCurrent) {
  249. HBRUSH hbr;
  250. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  251. if (hbr) {
  252. if (bFocus) {
  253. rgb = GetSysColor(COLOR_HIGHLIGHTTEXT);
  254. FillRect(hdc, &rc, hbr);
  255. } else {
  256. InflateRect(&rc, -dyBorder, -dyBorder);
  257. FrameRect(hdc, &rc, hbr);
  258. }
  259. DeleteObject(hbr);
  260. }
  261. }
  262. if (bFocus)
  263. DrawFocusRect(hdc, &rc);
  264. szTemp[0] = (CHAR)(chFirstDrive + rgiDrive[nDrive]);
  265. SetBkMode(hdc, TRANSPARENT);
  266. rgb = SetTextColor(hdc, rgb);
  267. TextOut(hdc, x + dxDriveBitmap+(dyBorder*6), y + (dyDrive - dyText) / 2, szTemp, 1);
  268. SetTextColor(hdc, rgb);
  269. BitBlt(hdc, x + 4*dyBorder, y + (dyDrive - dyDriveBitmap) / 2, dxDriveBitmap, dyDriveBitmap,
  270. hdcMem, rgiDrivesOffset[nDrive], 2 * dyFolder, SRCCOPY);
  271. }
  272. // check net/floppy drives for validity, sets the net drive bitmap
  273. // when the thing is not available
  274. //
  275. // note: IsTheDiskReallyThere() has the side effect of setting the
  276. // current drive to the new disk if it is successful
  277. BOOL
  278. CheckDrive(
  279. HWND hwnd,
  280. INT nDrive
  281. )
  282. {
  283. UINT err;
  284. CHAR szDrive[5];
  285. int iDriveInd;
  286. return TRUE;
  287. }
  288. VOID
  289. DrivesDropObject(
  290. HWND hWnd,
  291. LPDROPSTRUCT lpds
  292. )
  293. {
  294. INT nDrive;
  295. CHAR szPath[MAXPATHLEN * 2];
  296. PSTR pFrom;
  297. BOOL bIconic;
  298. bIconic = IsIconic(GetParent(hWnd));
  299. if (bIconic) {
  300. UseCurDir:
  301. SendMessage(GetParent(hWnd), FS_GETDIRECTORY, sizeof(szPath), (LPARAM)szPath);
  302. } else {
  303. nDrive = DriveFromPoint(hWnd, lpds->ptDrop);
  304. if (nDrive < 0)
  305. goto UseCurDir;
  306. // this searches windows in the zorder then asks dos
  307. // if nothing is found...
  308. GetSelectedDirectory((WORD)(rgiDrive[nDrive] + 1), szPath);
  309. }
  310. AddBackslash(szPath); // add spec part
  311. lstrcat(szPath, szStarDotStar);
  312. pFrom = (PSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch);
  313. CheckEscapes(szPath);
  314. DMMoveCopyHelper(pFrom, szPath, fShowSourceBitmaps);
  315. if (!bIconic)
  316. RectDrive(hWnd, nDrive, FALSE);
  317. }
  318. VOID
  319. DrivesPaint(
  320. HWND hWnd,
  321. INT nDriveFocus,
  322. INT nDriveCurrent
  323. )
  324. {
  325. RECT rc;
  326. INT nDrive;
  327. CHAR szPath[MAXPATHLEN * 2];
  328. HDC hdc;
  329. PAINTSTRUCT ps;
  330. DWORD dw;
  331. WORD dxAfterDrives;
  332. INT x, y;
  333. HANDLE hOld;
  334. INT cDriveRows, cDrivesPerRow;
  335. GetClientRect(hWnd, &rc);
  336. if (!rc.right)
  337. return;
  338. hdc = BeginPaint(hWnd, &ps);
  339. hOld = SelectObject(hdc, hFont);
  340. cDrivesPerRow = rc.right / dxDrive;
  341. if (!cDrivesPerRow)
  342. cDrivesPerRow++;
  343. cDriveRows = ((cDrives-1) / cDrivesPerRow) + 1;
  344. x = 0;
  345. y = 0;
  346. for (nDrive = 0; nDrive < cDrives; nDrive++) {
  347. if (GetFocus() != hWnd)
  348. nDriveFocus = -1;
  349. DrawDrive(hdc, x, y, nDrive, nDriveCurrent == nDrive, nDriveFocus == nDrive);
  350. x += dxDrive;
  351. if (x + dxDrive > rc.right) {
  352. x = 0;
  353. y += dyDrive;
  354. }
  355. }
  356. // now figure out where to put that stupid volume string
  357. lstrcpy(szPath, (PSTR)GetWindowLongPtr(hWnd, GWLP_LPSTRVOLUME));
  358. MGetTextExtent(hdc, szPath, lstrlen(szPath), (INT *)&dw, NULL);
  359. dxAfterDrives = (WORD)(rc.right - x);
  360. // does it fit after the drives in the last row?
  361. if (dxAfterDrives < LOWORD(dw)) {
  362. x = dxText; // no, flush left
  363. y = rc.bottom - dyText - dyBorderx2;
  364. } else {
  365. x += (dxAfterDrives - LOWORD(dw)) / 2; // yes, centered
  366. y = rc.bottom - (dyDrive + dyText) / 2;
  367. }
  368. SetBkMode(hdc, TRANSPARENT);
  369. TextOut(hdc, x, y, szPath, lstrlen(szPath));
  370. if (hOld)
  371. SelectObject(hdc, hOld);
  372. EndPaint(hWnd, &ps);
  373. }
  374. // set the current window to a new drive
  375. //
  376. //
  377. VOID
  378. DrivesSetDrive(
  379. HWND hWnd,
  380. INT iDriveInd,
  381. INT nDriveCurrent
  382. )
  383. {
  384. CHAR szPath[MAXPATHLEN * 2];
  385. HWND hwndTree;
  386. HWND hwndDir;
  387. InvalidateRect(hWnd, NULL, TRUE);
  388. // save the current directory on this drive for later so
  389. // we don't have to hit the drive to get the current directory
  390. // and other apps won't change this out from under us
  391. GetSelectedDirectory(0, szPath);
  392. SaveDirectory(szPath);
  393. // this also sets the current drive if successful
  394. if (!CheckDrive(hWnd, rgiDrive[iDriveInd]))
  395. return;
  396. // cause current tree read to abort if already in progress
  397. hwndTree = HasTreeWindow(GetParent(hWnd));
  398. if (hwndTree && GetWindowLong(hwndTree, GWL_READLEVEL)) {
  399. // bounce any clicks on a drive that is currently being read
  400. if (iDriveInd != nDriveCurrent)
  401. bCancelTree = TRUE;
  402. return;
  403. }
  404. // do again after in case a dialog cause the drive bar
  405. // to repaint
  406. InvalidateRect(hWnd, NULL, TRUE);
  407. // get this from our cache if possible
  408. GetSelectedDirectory((WORD)(rgiDrive[iDriveInd] + 1), szPath);
  409. // set the drives window parameters and repaint
  410. SetWindowLong(hWnd, GWL_CURDRIVEIND, iDriveInd);
  411. SetWindowLong(hWnd, GWL_CURDRIVEFOCUS, iDriveInd);
  412. SetVolumeString(hWnd, rgiDrive[iDriveInd]);
  413. // this is set in TC_SETDRIVE as well but the FS_CHANGEDISPLAY
  414. // likes to have this set before for the UpdateStatus() call
  415. SetWindowLong(GetParent(hWnd), GWL_TYPE, rgiDrive[iDriveInd]);
  416. // reset the dir first to allow tree to steal data
  417. // if szPath is not valid the TC_SETDRIVE will reinit
  418. // the files half (if there is no tree we are dicked)
  419. if (hwndDir = HasDirWindow(GetParent(hWnd))) {
  420. AddBackslash(szPath);
  421. SendMessage(hwndDir, FS_GETFILESPEC, MAXFILENAMELEN, (LPARAM)szPath + lstrlen(szPath));
  422. SendMessage(hwndDir, FS_CHANGEDISPLAY, CD_PATH_FORCE, (LPARAM)szPath);
  423. StripFilespec(szPath);
  424. }
  425. // do this before TC_SETDRIVE incase the tree read
  426. // is aborted and lFreeSpace gets set to -2L
  427. lFreeSpace = -1L; // force status info refresh
  428. // tell the tree control to do it's thing
  429. if (hwndTree)
  430. SendMessage(hwndTree, TC_SETDRIVE, MAKEWORD(GetKeyState(VK_SHIFT) < 0, 0), (LPARAM)(szPath));
  431. else { // at least resize things
  432. RECT rc;
  433. GetClientRect(GetParent(hWnd), &rc);
  434. ResizeWindows(GetParent(hWnd),(WORD)(rc.right+1),(WORD)(rc.bottom+1));
  435. }
  436. UpdateStatus(GetParent(hWnd));
  437. }
  438. /*--------------------------------------------------------------------------*/
  439. /* */
  440. /* DrivesWndProc() - */
  441. /* */
  442. /*--------------------------------------------------------------------------*/
  443. INT_PTR
  444. APIENTRY
  445. DrivesWndProc(
  446. HWND hWnd,
  447. UINT wMsg,
  448. WPARAM wParam,
  449. LPARAM lParam
  450. )
  451. {
  452. INT nDrive, nDriveCurrent, nDriveFocus;
  453. RECT rc;
  454. static INT nDriveDoubleClick = -1;
  455. static INT nDriveDragging = -1;
  456. nDriveCurrent = GetWindowLong(hWnd, GWL_CURDRIVEIND);
  457. nDriveFocus = GetWindowLong(hWnd, GWL_CURDRIVEFOCUS);
  458. switch (wMsg) {
  459. case WM_CREATE:
  460. TRACE(BF_WM_CREATE, "DrivesWndProc - WM_CREATE");
  461. {
  462. INT i;
  463. // Find the current drive, set the drive bitmaps
  464. nDrive = GetWindowLong(GetParent(hWnd), GWL_TYPE);
  465. SetVolumeString(hWnd, nDrive);
  466. for (i=0; i < cDrives; i++) {
  467. if (rgiDrive[i] == nDrive) {
  468. SetWindowLong(hWnd, GWL_CURDRIVEIND, i);
  469. SetWindowLong(hWnd, GWL_CURDRIVEFOCUS, i);
  470. }
  471. }
  472. break;
  473. }
  474. case WM_DESTROY:
  475. MSG("DrivesWndProc", "WM_DESTROY");
  476. LocalFree((HANDLE)GetWindowLongPtr(hWnd, GWLP_LPSTRVOLUME));
  477. break;
  478. case WM_VKEYTOITEM:
  479. KeyToItem(hWnd, (WORD)wParam);
  480. return -2L;
  481. break;
  482. case WM_KEYDOWN:
  483. MSG("DrivesWndProc", "WM_KEYDOWN");
  484. switch (wParam) {
  485. case VK_ESCAPE:
  486. bCancelTree = TRUE;
  487. break;
  488. case VK_F6: // like excel
  489. case VK_TAB:
  490. {
  491. HWND hwndTree, hwndDir;
  492. BOOL bDir;
  493. DWORD dwTemp;
  494. GetTreeWindows(GetParent(hWnd), &hwndTree, &hwndDir, NULL);
  495. // Check to see if we can change to the directory window
  496. bDir = hwndDir ? TRUE : FALSE;
  497. if (bDir) {
  498. HWND hwndLB; /* Local scope ONLY */
  499. hwndLB = GetDlgItem (hwndDir,IDCW_LISTBOX);
  500. if (hwndLB) {
  501. SendMessage (hwndLB,LB_GETTEXT,0,(LPARAM) &dwTemp);
  502. bDir = dwTemp ? TRUE : FALSE;
  503. }
  504. }
  505. if (GetKeyState(VK_SHIFT) < 0) {
  506. if (bDir)
  507. SetFocus (hwndDir);
  508. else
  509. SetFocus (hwndTree ? hwndTree : hWnd);
  510. } else
  511. SetFocus (hwndTree ? hwndTree :
  512. (bDir ? hwndDir : hWnd));
  513. break;
  514. }
  515. case VK_RETURN: // same as double click
  516. NewTree(rgiDrive[nDriveFocus], GetParent(hWnd));
  517. break;
  518. case VK_SPACE: // same as single click
  519. SendMessage(hWnd, FS_SETDRIVE, nDriveFocus, 0L);
  520. break;
  521. case VK_LEFT:
  522. nDrive = max(nDriveFocus-1, 0);
  523. break;
  524. case VK_RIGHT:
  525. nDrive = min(nDriveFocus+1, cDrives-1);
  526. break;
  527. }
  528. if ((wParam == VK_LEFT) || (wParam == VK_RIGHT)) {
  529. SetWindowLong(hWnd, GWL_CURDRIVEFOCUS, nDrive);
  530. GetDriveRect(hWnd, nDriveFocus, &rc);
  531. InvalidateRect(hWnd, &rc, TRUE);
  532. GetDriveRect(hWnd, nDrive, &rc);
  533. InvalidateRect(hWnd, &rc, TRUE);
  534. } else if ((wParam >= 'A') && (wParam <= 'Z'))
  535. KeyToItem(hWnd, (WORD)wParam);
  536. break;
  537. case FS_GETDRIVE:
  538. MSG("DrivesWndProc", "FS_GETDRIVE");
  539. {
  540. POINT pt;
  541. MPOINT2POINT(MAKEMPOINT(lParam), pt);
  542. nDrive = DriveFromPoint(hWnd, pt);
  543. if (nDrive < 0)
  544. nDrive = nDriveCurrent;
  545. return rgiDrive[nDrive] + 'A';
  546. }
  547. case WM_DRAGMOVE:
  548. MSG("DrivesWndProc", "WM_DRAGSELECT/WM_DRAGMOVE");
  549. #define lpds ((LPDROPSTRUCT)lParam)
  550. nDrive = DriveFromPoint(hWnd, lpds->ptDrop);
  551. #if 0
  552. {
  553. char buf[100];
  554. wsprintf(buf, "WM_DRAGSELECT nDrive=%d nDriveDragging=%d\r\n", nDrive, nDriveDragging);
  555. OutputDebugString(buf);
  556. }
  557. #endif
  558. // turn off?
  559. if ((nDrive != nDriveDragging) && (nDriveDragging >= 0)) {
  560. RectDrive(hWnd, nDriveDragging, FALSE);
  561. nDriveDragging = -1;
  562. }
  563. // turn on?
  564. if ((nDrive >= 0) && (nDrive != nDriveDragging)) {
  565. RectDrive(hWnd, nDrive, TRUE);
  566. nDriveDragging = nDrive;
  567. }
  568. break;
  569. case WM_DRAGSELECT:
  570. #define lpds ((LPDROPSTRUCT)lParam)
  571. #if 0
  572. {
  573. char buf[100];
  574. wsprintf(buf, "WM_DRAGSELECT wParam=%d\r\n", wParam);
  575. OutputDebugString(buf);
  576. }
  577. #endif
  578. if (wParam) {
  579. // entered, turn it on
  580. nDriveDragging = DriveFromPoint(hWnd, lpds->ptDrop);
  581. if (nDriveDragging >= 0)
  582. RectDrive(hWnd, nDriveDragging, TRUE);
  583. } else {
  584. // leaving, turn it off
  585. if (nDriveDragging >= 0)
  586. RectDrive(hWnd, nDriveDragging, FALSE);
  587. }
  588. break;
  589. case WM_QUERYDROPOBJECT:
  590. MSG("DrivesWndProc", "WM_QUERYDROPOBJECT");
  591. /* Validate the format. */
  592. #define lpds ((LPDROPSTRUCT)lParam)
  593. // if (DriveFromPoint(hWnd, lpds->ptDrop) < 0)
  594. // return FALSE;
  595. switch (lpds->wFmt) {
  596. case DOF_EXECUTABLE:
  597. case DOF_DIRECTORY:
  598. case DOF_MULTIPLE:
  599. case DOF_DOCUMENT:
  600. return (INT_PTR)GetMoveCopyCursor();
  601. default:
  602. return FALSE;
  603. }
  604. break;
  605. case WM_DROPOBJECT:
  606. MSG("DrivesWndProc", "WM_DROPOBJECT");
  607. DrivesDropObject(hWnd, (LPDROPSTRUCT)lParam);
  608. return TRUE;
  609. case WM_SETFOCUS:
  610. MSG("DrivesWndProc", "WM_SETFOCUS");
  611. SetWindowLongPtr(GetParent(hWnd), GWLP_LASTFOCUS, (LPARAM)hWnd);
  612. // fall through
  613. case WM_KILLFOCUS:
  614. MSG("DrivesWndProc", "WM_KILLFOCUS");
  615. GetDriveRect(hWnd, nDriveFocus, &rc);
  616. InvalidateRect(hWnd, &rc, TRUE);
  617. break;
  618. case WM_PAINT:
  619. DrivesPaint(hWnd, nDriveFocus, nDriveCurrent);
  620. break;
  621. case WM_MDIACTIVATE:
  622. /* we're not an MDI child, but the real MDI child proc
  623. is sending us this so we can handle the following problem.
  624. nDriveDoubleClick is static, and is shared by all the child window
  625. drivewindow instances. If the user rapidly clicks two child window
  626. drivewindows, then we can mistakenly interpret the second click
  627. as a double click in the first window.
  628. */
  629. if (!wParam && (nDriveDoubleClick != -1))
  630. /* terminate wait for doubleclick, make it a single click */
  631. SendMessage(hWnd,WM_TIMER,1,0L);
  632. break;
  633. case WM_TIMER:
  634. MSG("DrivesWndProc", "WM_TIMER");
  635. KillTimer(hWnd, wParam);
  636. if (nDriveDoubleClick > -1)
  637. SendMessage(hWnd, FS_SETDRIVE, nDriveDoubleClick, 0L); // single click action
  638. nDriveDoubleClick = -1; // default
  639. break;
  640. case WM_LBUTTONDOWN:
  641. MSG("DrivesWndProc", "WM_LBUTTONDOWN");
  642. {
  643. POINT pt;
  644. MPOINT2POINT(MAKEMPOINT(lParam), pt);
  645. nDrive = DriveFromPoint(hWnd, pt);
  646. if (nDrive < 0)
  647. /* clicked outside of drive box */
  648. {
  649. if (nDriveDoubleClick == -2)
  650. /* legit doubleclick outside */
  651. {
  652. nDriveDoubleClick = -1; // default value
  653. KillTimer(hWnd, 1);
  654. PostMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_DRIVESMORE, 0, 0));
  655. } else /* first click outside */ {
  656. if (nDriveDoubleClick != -1) // fast click on drivebox then outside drivebox
  657. /* igonre first click, user is a spaz */
  658. KillTimer(hWnd, 1);
  659. nDriveDoubleClick = -2; // see WM_TIMER
  660. SetTimer(hWnd, 1, GetDoubleClickTime(), NULL);
  661. }
  662. } else {
  663. if (nDriveDoubleClick == nDrive)
  664. /* double click in drivebox */
  665. {
  666. nDriveDoubleClick = -1; // default
  667. KillTimer(hWnd, 1);
  668. InvalidateRect(hWnd, NULL, TRUE); // erase the rect from the click
  669. NewTree(rgiDrive[nDrive], GetParent(hWnd)); // double click action
  670. } else if (nDriveDoubleClick == -2) // fast click outside drive then in drivebox
  671. /* do nothing, user is a spaz */
  672. {
  673. KillTimer(hWnd, 1);
  674. nDriveDoubleClick = -1;
  675. } else { // legit first click in drivebox
  676. nDriveDoubleClick = nDrive;
  677. SetTimer(hWnd, 1, GetDoubleClickTime(), NULL);
  678. }
  679. }
  680. }
  681. break;
  682. case FS_SETDRIVE:
  683. MSG("DrivesWndProc", "FS_SETDRIVE");
  684. // wParam the drive index to set
  685. // lParam not used
  686. DrivesSetDrive(hWnd, (WORD)wParam, nDriveCurrent);
  687. break;
  688. default:
  689. DEFMSG("DrivesWndProc", (WORD)wMsg);
  690. return DefWindowProc(hWnd, wMsg, wParam, lParam);
  691. }
  692. return 0L;
  693. }
  694. /* Returns nDrive if found, else -1 */
  695. INT
  696. KeyToItem(
  697. HWND hWnd,
  698. WORD nDriveLetter
  699. )
  700. {
  701. INT nDrive;
  702. if (nDriveLetter > 'Z')
  703. nDriveLetter -= 'a';
  704. else
  705. nDriveLetter -= 'A';
  706. for (nDrive = 0; nDrive < cDrives; nDrive++) {
  707. if (rgiDrive[nDrive] == (int)nDriveLetter) {
  708. SendMessage(hWnd, FS_SETDRIVE, nDrive, 0L);
  709. return nDrive;
  710. }
  711. }
  712. return -1;
  713. }