//--------------------------------------------------------------------------- // // wfdrives.c // // window procs and other stuff for the drive bar // //--------------------------------------------------------------------------- #define PUBLIC // avoid collision with shell.h #include "winfile.h" #include "treectl.h" #include "lfn.h" #include "wfcopy.h" #include "winnet.h" #include VOID NEAR PASCAL InvalidateDrive(HWND hwnd, INT nDrive); VOID NEAR PASCAL RectDrive(HWND hWnd, INT nDrive, BOOL bFocusOn); VOID NEAR PASCAL GetDriveRect(HWND hWnd, INT nDrive, PRECT prc); INT NEAR PASCAL DriveFromPoint(HWND hWnd, POINT pt); VOID NEAR PASCAL DrawDrive(HDC hdc, INT x, INT y, INT nDrive, BOOL bCurrent, BOOL bFocus); INT NEAR PASCAL KeyToItem(HWND hWnd, WORD nDriveLetter); VOID NEAR PASCAL GetVolShareString(WORD wDrive, LPSTR szStr); VOID NEAR PASCAL SetVolumeString(HWND hWnd, INT nDrive); VOID APIENTRY CheckEscapes(LPSTR); // create a new split tree window for the given drive // and inherit all the properties of the current window // the current directory is set to the DOS current directory // for this drive. note, this can be somewhat random given // that windows does not keep this info for each app (it is // global to the system) // // in: // iDrive the driver number to create the window for // hwndSrc the window to take all the properties from // VOID APIENTRY NewTree( INT iDrive, HWND hwndSrc) { HWND hwnd, hwndTree, hwndDir; CHAR szDir[MAXPATHLEN * 2]; INT dxSplit; ENTER("NewTree"); PRINT(BF_PARMTRACE, "iDrive=%d", iDrive); // make sure the floppy/net drive is still valid if (!CheckDrive(hwndSrc, iDrive)) return; if (hwndSrc == hwndSearch) dxSplit = -1; else { hwndTree = HasTreeWindow(hwndSrc); hwndDir = HasDirWindow(hwndSrc); if (hwndTree && hwndDir) dxSplit = GetWindowLong(hwndSrc, GWL_SPLIT); else if (hwndDir) dxSplit = 0; else dxSplit = 10000; } // take all the attributes from the current window // (except the filespec, we may want to change this) wNewSort = (WORD)GetWindowLong(hwndSrc, GWL_SORT); wNewView = (WORD)GetWindowLong(hwndSrc, GWL_VIEW); dwNewAttribs = (DWORD)GetWindowLong(hwndSrc, GWL_ATTRIBS); GetSelectedDirectory((WORD)(iDrive + 1), szDir); AddBackslash(szDir); SendMessage(hwndSrc, FS_GETFILESPEC, MAXPATHLEN, (LONG)(LPSTR)szDir+lstrlen(szDir)); hwnd = CreateTreeWindow(szDir, dxSplit); if (hwnd && (hwndTree = HasTreeWindow(hwnd))) SendMessage(hwndTree, TC_SETDRIVE, MAKEWORD(FALSE, 0), 0L); LEAVE("NewTree"); } VOID NEAR PASCAL SetVolumeString(HWND hWnd, INT nDrive) { LPSTR pVol; CHAR szVolShare[128]; // clean up any old label if (pVol = (LPSTR)GetWindowLong(hWnd, GWL_LPSTRVOLUME)) { LocalFree((HANDLE)pVol); } GetVolShareString((WORD)nDrive, szVolShare); if (pVol = (LPSTR)LocalAlloc(LPTR, lstrlen(szVolShare)+1)) lstrcpy(pVol, szVolShare); SetWindowLong(hWnd, GWL_LPSTRVOLUME, (LONG)pVol); } VOID NEAR PASCAL GetVolShareString(WORD wDrive, LPSTR szStr) { CHAR szVolShare[128]; GetVolShare(wDrive, szVolShare); wsprintf(szStr, "%c: %s", wDrive + 'A', (LPSTR)szVolShare); } DWORD APIENTRY GetVolShareExtent(HWND hwndDrives) { HDC hdc; CHAR szVolShare[128]; HFONT hOld; INT i; lstrcpy(szVolShare, (LPSTR)GetWindowLong(hwndDrives, GWL_LPSTRVOLUME)); hdc = GetDC(hwndDrives); hOld = SelectObject(hdc, hFont); MGetTextExtent(hdc, szVolShare, lstrlen(szVolShare), &i, NULL); if (hOld) SelectObject(hdc, hOld); ReleaseDC(hwndDrives, hdc); return ((DWORD)i); } VOID NEAR PASCAL GetDriveRect(HWND hWnd, INT nDrive, PRECT prc) { RECT rc; INT nDrivesPerRow; GetClientRect(hWnd, &rc); if (!dxDrive) // avoid div by zero dxDrive++; nDrivesPerRow = rc.right / dxDrive; if (!nDrivesPerRow) // avoid div by zero nDrivesPerRow++; prc->top = dyDrive * (nDrive / nDrivesPerRow); prc->bottom = prc->top + dyDrive; prc->left = dxDrive * (nDrive % nDrivesPerRow); prc->right = prc->left + dxDrive; } INT NEAR PASCAL DriveFromPoint(HWND hWnd, POINT pt) { RECT rc, rcDrive; INT x, y, nDrive; GetClientRect(hWnd, &rc); x = 0; y = 0; nDrive = 0; for (nDrive = 0; nDrive < cDrives; nDrive++) { rcDrive.left = x; rcDrive.right = x + dxDrive; rcDrive.top = y; rcDrive.bottom = y + dyDrive; InflateRect(&rcDrive, -dyBorder, -dyBorder); if (PtInRect(&rcDrive, pt)) return nDrive; x += dxDrive; if (x + dxDrive > rc.right) { x = 0; y += dyDrive; } } return -1; // no hit } VOID NEAR PASCAL InvalidateDrive(HWND hwnd, INT nDrive) { RECT rc; GetDriveRect(hwnd, nDrive, &rc); InvalidateRect(hwnd, &rc, TRUE); } // // void NEAR PASCAL RectDrive(HWND hWnd, int nDrive, BOOL bDraw) // // draw the hilight rect around the drive to indicate that it is // the target of a drop action. // // in: // hWnd Drives window // nDrive the drive to draw the rect around // bDraw if TRUE, draw a rect around this drive // FALSE, erase the rect (draw the default rect) // VOID NEAR PASCAL RectDrive(HWND hWnd, INT nDrive, BOOL bDraw) { RECT rc, rcDrive; HBRUSH hBrush; HDC hdc; GetDriveRect(hWnd, nDrive, &rc); rcDrive = rc; InflateRect(&rc, -dyBorder, -dyBorder); if (bDraw) { hdc = GetDC(hWnd); hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOWTEXT)); FrameRect(hdc, &rc, hBrush); DeleteObject(hBrush); ReleaseDC(hWnd, hdc); } else { InvalidateRect(hWnd, &rcDrive, TRUE); UpdateWindow(hWnd); } } // // void NEAR PASCAL DrawDrive(HDC hdc, int x, int y, int nDrive, BOOL bCurrent, BOOL bFocus) // // paint the drive icons in the standard state, given the // drive with the focus and the current selection // // in: // hdc dc to draw to // x, y position to start (dxDrive, dyDrive are the extents) // nDrive the drive to paint // bCurrent draw as the current drive (pushed in) // bFocus draw with the focus // VOID NEAR PASCAL DrawDrive(HDC hdc, INT x, INT y, INT nDrive, BOOL bCurrent, BOOL bFocus) { RECT rc; CHAR szTemp[2]; DWORD rgb; rc.left = x; rc.right = x + dxDrive; rc.top = y; rc.bottom = y + dyDrive; rgb = GetSysColor(COLOR_BTNTEXT); if (bCurrent) { HBRUSH hbr; hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); if (bFocus) { rgb = GetSysColor(COLOR_HIGHLIGHTTEXT); FillRect(hdc, &rc, hbr); } else { InflateRect(&rc, -dyBorder, -dyBorder); FrameRect(hdc, &rc, hbr); } DeleteObject(hbr); } if (bFocus) DrawFocusRect(hdc, &rc); szTemp[0] = (CHAR)(chFirstDrive + rgiDrive[nDrive]); SetBkMode(hdc, TRANSPARENT); rgb = SetTextColor(hdc, rgb); TextOut(hdc, x + dxDriveBitmap+(dyBorder*6), y + (dyDrive - dyText) / 2, szTemp, 1); SetTextColor(hdc, rgb); BitBlt(hdc, x + 4*dyBorder, y + (dyDrive - dyDriveBitmap) / 2, dxDriveBitmap, dyDriveBitmap, hdcMem, rgiDrivesOffset[nDrive], 2 * dyFolder, SRCCOPY); } // check net/floppy drives for validity, sets the net drive bitmap // when the thing is not available // // note: IsTheDiskReallyThere() has the side effect of setting the // current drive to the new disk if it is successful BOOL FAR PASCAL CheckDrive(HWND hwnd, INT nDrive) { UINT err; CHAR szDrive[5]; int iDriveInd; #if 0 szDrive[0] = (CHAR)('A' + nDrive); szDrive[1] = ':'; szDrive[2] = 0; // find index for this drive iDriveInd = 0; while ((iDriveInd < cDrives) && (rgiDrive[iDriveInd] != nDrive)) iDriveInd++; switch (IsNetDrive((WORD)nDrive)) { case 2: err = WNetRestoreConnection(hwnd, szDrive); if (err != WN_SUCCESS) { if (!(err == WN_CANCEL || err == WN_CONTINUE)) { WNetErrorText(err, szMessage, sizeof(szMessage)); LoadString(hAppInstance, IDS_COPYERROR + FUNC_SETDRIVE, szTitle, sizeof(szTitle)); MessageBox(hwnd, szMessage, szTitle, MB_OK | MB_ICONEXCLAMATION); } rgiDrivesOffset[iDriveInd] = dxDriveBitmap * 5; InvalidateDrive(hwnd, iDriveInd); return FALSE; } // fall through... case 1: rgiDrivesOffset[iDriveInd] = dxDriveBitmap * 4; InvalidateDrive(hwnd, iDriveInd); break; default: return IsTheDiskReallyThere(hwnd, szDrive, FUNC_SETDRIVE); } #endif return TRUE; } VOID NEAR PASCAL DrivesDropObject(HWND hWnd, LPDROPSTRUCT lpds) { INT nDrive; CHAR szPath[MAXPATHLEN * 2]; PSTR pFrom; BOOL bIconic; bIconic = IsIconic(GetParent(hWnd)); if (bIconic) { UseCurDir: SendMessage(GetParent(hWnd), FS_GETDIRECTORY, sizeof(szPath), (LONG)(LPSTR)szPath); } else { nDrive = DriveFromPoint(hWnd, lpds->ptDrop); if (nDrive < 0) goto UseCurDir; // this searches windows in the zorder then asks dos // if nothing is found... GetSelectedDirectory((WORD)(rgiDrive[nDrive] + 1), szPath); } AddBackslash(szPath); // add spec part lstrcat(szPath, szStarDotStar); pFrom = (PSTR)(((LPDRAGOBJECTDATA)(lpds->dwData))->pch); CheckEscapes(szPath); DMMoveCopyHelper(pFrom, szPath, fShowSourceBitmaps); if (!bIconic) RectDrive(hWnd, nDrive, FALSE); } VOID NEAR PASCAL DrivesPaint(HWND hWnd, INT nDriveFocus, INT nDriveCurrent) { RECT rc; INT nDrive; CHAR szPath[MAXPATHLEN * 2]; HDC hdc; PAINTSTRUCT ps; DWORD dw; WORD dxAfterDrives; INT x, y; HANDLE hOld; INT cDriveRows, cDrivesPerRow; GetClientRect(hWnd, &rc); if (!rc.right) return; hdc = BeginPaint(hWnd, &ps); hOld = SelectObject(hdc, hFont); cDrivesPerRow = rc.right / dxDrive; if (!cDrivesPerRow) cDrivesPerRow++; cDriveRows = ((cDrives-1) / cDrivesPerRow) + 1; x = 0; y = 0; for (nDrive = 0; nDrive < cDrives; nDrive++) { if (GetFocus() != hWnd) nDriveFocus = -1; DrawDrive(hdc, x, y, nDrive, nDriveCurrent == nDrive, nDriveFocus == nDrive); x += dxDrive; if (x + dxDrive > rc.right) { x = 0; y += dyDrive; } } // now figure out where to put that stupid volume string lstrcpy(szPath, (PSTR)GetWindowLong(hWnd, GWL_LPSTRVOLUME)); MGetTextExtent(hdc, szPath, lstrlen(szPath), (INT *)&dw, NULL); dxAfterDrives = (WORD)(rc.right - x); // does it fit after the drives in the last row? if (dxAfterDrives < LOWORD(dw)) { x = dxText; // no, flush left y = rc.bottom - dyText - dyBorderx2; } else { x += (dxAfterDrives - LOWORD(dw)) / 2; // yes, centered y = rc.bottom - (dyDrive + dyText) / 2; } SetBkMode(hdc, TRANSPARENT); TextOut(hdc, x, y, szPath, lstrlen(szPath)); if (hOld) SelectObject(hdc, hOld); EndPaint(hWnd, &ps); } // set the current window to a new drive // // VOID NEAR PASCAL DrivesSetDrive(HWND hWnd, INT iDriveInd, INT nDriveCurrent) { CHAR szPath[MAXPATHLEN * 2]; HWND hwndTree; HWND hwndDir; InvalidateRect(hWnd, NULL, TRUE); // save the current directory on this drive for later so // we don't have to hit the drive to get the current directory // and other apps won't change this out from under us GetSelectedDirectory(0, szPath); SaveDirectory(szPath); // this also sets the current drive if successful if (!CheckDrive(hWnd, rgiDrive[iDriveInd])) return; // cause current tree read to abort if already in progress hwndTree = HasTreeWindow(GetParent(hWnd)); if (hwndTree && GetWindowLong(hwndTree, GWL_READLEVEL)) { // bounce any clicks on a drive that is currently being read if (iDriveInd != nDriveCurrent) bCancelTree = TRUE; return; } // do again after in case a dialog cause the drive bar // to repaint InvalidateRect(hWnd, NULL, TRUE); // get this from our cache if possible GetSelectedDirectory((WORD)(rgiDrive[iDriveInd] + 1), szPath); // set the drives window parameters and repaint SetWindowLong(hWnd, GWL_CURDRIVEIND, iDriveInd); SetWindowLong(hWnd, GWL_CURDRIVEFOCUS, iDriveInd); SetVolumeString(hWnd, rgiDrive[iDriveInd]); // this is set in TC_SETDRIVE as well but the FS_CHANGEDISPLAY // likes to have this set before for the UpdateStatus() call SetWindowLong(GetParent(hWnd), GWL_TYPE, rgiDrive[iDriveInd]); // reset the dir first to allow tree to steal data // if szPath is not valid the TC_SETDRIVE will reinit // the files half (if there is no tree we are dicked) if (hwndDir = HasDirWindow(GetParent(hWnd))) { AddBackslash(szPath); SendMessage(hwndDir, FS_GETFILESPEC, MAXFILENAMELEN, (LONG)(LPSTR)szPath + lstrlen(szPath)); SendMessage(hwndDir, FS_CHANGEDISPLAY, CD_PATH_FORCE, (LONG)(LPSTR)szPath); StripFilespec(szPath); } // do this before TC_SETDRIVE incase the tree read // is aborted and lFreeSpace gets set to -2L lFreeSpace = -1L; // force status info refresh // tell the tree control to do it's thing if (hwndTree) SendMessage(hwndTree, TC_SETDRIVE, MAKEWORD(GetKeyState(VK_SHIFT) < 0, 0), (LONG)(szPath)); else // at least resize things { RECT rc; GetClientRect(GetParent(hWnd), &rc); ResizeWindows(GetParent(hWnd),(WORD)(rc.right+1),(WORD)(rc.bottom+1)); } UpdateStatus(GetParent(hWnd)); } /*--------------------------------------------------------------------------*/ /* */ /* DrivesWndProc() - */ /* */ /*--------------------------------------------------------------------------*/ LONG APIENTRY DrivesWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LONG lParam) { INT nDrive, nDriveCurrent, nDriveFocus; RECT rc; static INT nDriveDoubleClick = -1; static INT nDriveDragging = -1; nDriveCurrent = GetWindowLong(hWnd, GWL_CURDRIVEIND); nDriveFocus = GetWindowLong(hWnd, GWL_CURDRIVEFOCUS); switch (wMsg) { case WM_CREATE: TRACE(BF_WM_CREATE, "DrivesWndProc - WM_CREATE"); { INT i; // Find the current drive, set the drive bitmaps nDrive = GetWindowLong(GetParent(hWnd), GWL_TYPE); SetVolumeString(hWnd, nDrive); for (i=0; i < cDrives; i++) { if (rgiDrive[i] == nDrive) { SetWindowLong(hWnd, GWL_CURDRIVEIND, i); SetWindowLong(hWnd, GWL_CURDRIVEFOCUS, i); } } break; } case WM_DESTROY: MSG("DrivesWndProc", "WM_DESTROY"); LocalFree((HANDLE)GetWindowLong(hWnd, GWL_LPSTRVOLUME)); break; case WM_VKEYTOITEM: KeyToItem(hWnd, (WORD)wParam); return -2L; break; case WM_KEYDOWN: MSG("DrivesWndProc", "WM_KEYDOWN"); switch (wParam) { case VK_ESCAPE: bCancelTree = TRUE; break; case VK_F6: // like excel case VK_TAB: { HWND hwndTree, hwndDir; BOOL bDir; DWORD dwTemp; GetTreeWindows(GetParent(hWnd), &hwndTree, &hwndDir, NULL); // Check to see if we can change to the directory window bDir = (BOOL) hwndDir; if (bDir) { HWND hwndLB; /* Local scope ONLY */ hwndLB = GetDlgItem (hwndDir,IDCW_LISTBOX); if (hwndLB) { SendMessage (hwndLB,LB_GETTEXT,0,(LONG)(LPSTR) &dwTemp); bDir = (BOOL) dwTemp; } } if (GetKeyState(VK_SHIFT) < 0) { if (bDir) SetFocus (hwndDir); else SetFocus (hwndTree ? hwndTree : hWnd); } else SetFocus (hwndTree ? hwndTree : (bDir ? hwndDir : hWnd)); break; } case VK_RETURN: // same as double click NewTree(rgiDrive[nDriveFocus], GetParent(hWnd)); break; case VK_SPACE: // same as single click SendMessage(hWnd, FS_SETDRIVE, nDriveFocus, 0L); break; case VK_LEFT: nDrive = max(nDriveFocus-1, 0); break; case VK_RIGHT: nDrive = min(nDriveFocus+1, cDrives-1); break; } if ((wParam == VK_LEFT) || (wParam == VK_RIGHT)) { SetWindowLong(hWnd, GWL_CURDRIVEFOCUS, nDrive); GetDriveRect(hWnd, nDriveFocus, &rc); InvalidateRect(hWnd, &rc, TRUE); GetDriveRect(hWnd, nDrive, &rc); InvalidateRect(hWnd, &rc, TRUE); } else if ((wParam >= 'A') && (wParam <= 'Z')) KeyToItem(hWnd, (WORD)wParam); break; case FS_GETDRIVE: MSG("DrivesWndProc", "FS_GETDRIVE"); { POINT pt; MPOINT2POINT(MAKEMPOINT(lParam), pt); nDrive = DriveFromPoint(hWnd, pt); if (nDrive < 0) nDrive = nDriveCurrent; return rgiDrive[nDrive] + 'A'; } case WM_DRAGMOVE: MSG("DrivesWndProc", "WM_DRAGSELECT/WM_DRAGMOVE"); #define lpds ((LPDROPSTRUCT)lParam) nDrive = DriveFromPoint(hWnd, lpds->ptDrop); #if 0 { char buf[100]; wsprintf(buf, "WM_DRAGSELECT nDrive=%d nDriveDragging=%d\r\n", nDrive, nDriveDragging); OutputDebugString(buf); } #endif // turn off? if ((nDrive != nDriveDragging) && (nDriveDragging >= 0)) { RectDrive(hWnd, nDriveDragging, FALSE); nDriveDragging = -1; } // turn on? if ((nDrive >= 0) && (nDrive != nDriveDragging)) { RectDrive(hWnd, nDrive, TRUE); nDriveDragging = nDrive; } break; case WM_DRAGSELECT: #define lpds ((LPDROPSTRUCT)lParam) #if 0 { char buf[100]; wsprintf(buf, "WM_DRAGSELECT wParam=%d\r\n", wParam); OutputDebugString(buf); } #endif if (wParam) { // entered, turn it on nDriveDragging = DriveFromPoint(hWnd, lpds->ptDrop); if (nDriveDragging >= 0) RectDrive(hWnd, nDriveDragging, TRUE); } else { // leaving, turn it off if (nDriveDragging >= 0) RectDrive(hWnd, nDriveDragging, FALSE); } break; case WM_QUERYDROPOBJECT: MSG("DrivesWndProc", "WM_QUERYDROPOBJECT"); /* Validate the format. */ #define lpds ((LPDROPSTRUCT)lParam) // if (DriveFromPoint(hWnd, lpds->ptDrop) < 0) // return FALSE; switch (lpds->wFmt) { case DOF_EXECUTABLE: case DOF_DIRECTORY: case DOF_MULTIPLE: case DOF_DOCUMENT: return (LONG)GetMoveCopyCursor(); default: return FALSE; } break; case WM_DROPOBJECT: MSG("DrivesWndProc", "WM_DROPOBJECT"); DrivesDropObject(hWnd, (LPDROPSTRUCT)lParam); return TRUE; case WM_SETFOCUS: MSG("DrivesWndProc", "WM_SETFOCUS"); SetWindowLong(GetParent(hWnd), GWL_LASTFOCUS, (LONG)hWnd); // fall through case WM_KILLFOCUS: MSG("DrivesWndProc", "WM_KILLFOCUS"); GetDriveRect(hWnd, nDriveFocus, &rc); InvalidateRect(hWnd, &rc, TRUE); break; case WM_PAINT: DrivesPaint(hWnd, nDriveFocus, nDriveCurrent); break; case WM_MDIACTIVATE: /* we're not an MDI child, but the real MDI child proc is sending us this so we can handle the following problem. nDriveDoubleClick is static, and is shared by all the child window drivewindow instances. If the user rapidly clicks two child window drivewindows, then we can mistakenly interpret the second click as a double click in the first window. */ if (!wParam && (nDriveDoubleClick != -1)) /* terminate wait for doubleclick, make it a single click */ SendMessage(hWnd,WM_TIMER,1,0L); break; case WM_TIMER: MSG("DrivesWndProc", "WM_TIMER"); KillTimer(hWnd, wParam); if (nDriveDoubleClick > -1) SendMessage(hWnd, FS_SETDRIVE, nDriveDoubleClick, 0L); // single click action nDriveDoubleClick = -1; // default break; case WM_LBUTTONDOWN: MSG("DrivesWndProc", "WM_LBUTTONDOWN"); { POINT pt; MPOINT2POINT(MAKEMPOINT(lParam), pt); nDrive = DriveFromPoint(hWnd, pt); if (nDrive < 0) /* clicked outside of drive box */ { if (nDriveDoubleClick == -2) /* legit doubleclick outside */ { nDriveDoubleClick = -1; // default value KillTimer(hWnd, 1); PostMessage(hwndFrame, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_DRIVESMORE, 0, 0)); } else /* first click outside */ { if (nDriveDoubleClick != -1) // fast click on drivebox then outside drivebox /* igonre first click, user is a spaz */ KillTimer(hWnd, 1); nDriveDoubleClick = -2; // see WM_TIMER SetTimer(hWnd, 1, GetDoubleClickTime(), NULL); } } else { if (nDriveDoubleClick == nDrive) /* double click in drivebox */ { nDriveDoubleClick = -1; // default KillTimer(hWnd, 1); InvalidateRect(hWnd, NULL, TRUE); // erase the rect from the click NewTree(rgiDrive[nDrive], GetParent(hWnd)); // double click action } else if (nDriveDoubleClick == -2) // fast click outside drive then in drivebox /* do nothing, user is a spaz */ { KillTimer(hWnd, 1); nDriveDoubleClick = -1; } else // legit first click in drivebox { nDriveDoubleClick = nDrive; SetTimer(hWnd, 1, GetDoubleClickTime(), NULL); } } } break; case FS_SETDRIVE: MSG("DrivesWndProc", "FS_SETDRIVE"); // wParam the drive index to set // lParam not used DrivesSetDrive(hWnd, (WORD)wParam, nDriveCurrent); break; default: DEFMSG("DrivesWndProc", (WORD)wMsg); return DefWindowProc(hWnd, wMsg, wParam, lParam); } return 0L; } /* Returns nDrive if found, else -1 */ INT NEAR PASCAL KeyToItem(HWND hWnd, WORD nDriveLetter) { INT nDrive; if (nDriveLetter > 'Z') nDriveLetter -= 'a'; else nDriveLetter -= 'A'; for (nDrive = 0; nDrive < cDrives; nDrive++) { if (rgiDrive[nDrive] == (int)nDriveLetter) { SendMessage(hWnd, FS_SETDRIVE, nDrive, 0L); return nDrive; } } return -1; }