905 lines
24 KiB
C
905 lines
24 KiB
C
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* WFDIRSRC.C - */
|
||
|
/* */
|
||
|
/* Routines Common to the Directory and Search Windows */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
#include "winfile.h"
|
||
|
|
||
|
#define DO_DROPFILE 0x454C4946L
|
||
|
#define DO_PRINTFILE 0x544E5250L
|
||
|
#define DO_DROPONDESKTOP 0x504D42L
|
||
|
|
||
|
HWND hwndGlobalSink = NULL;
|
||
|
|
||
|
VOID SelectItem(HWND hwndLB, WPARAM wParam, BOOL bSel);
|
||
|
VOID ShowItemBitmaps(HWND hwndLB, BOOL bShow);
|
||
|
DWORD GetSearchAttribs(HWND hwndLB, WORD wIndex);
|
||
|
|
||
|
HCURSOR
|
||
|
APIENTRY
|
||
|
GetMoveCopyCursor()
|
||
|
{
|
||
|
if (fShowSourceBitmaps)
|
||
|
// copy
|
||
|
return LoadCursor(hAppInstance, MAKEINTRESOURCE(iCurDrag | 1));
|
||
|
else
|
||
|
// move
|
||
|
return LoadCursor(hAppInstance, MAKEINTRESOURCE(iCurDrag & 0xFFFE));
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetSearchAttribs(
|
||
|
HWND hwndLB,
|
||
|
WORD wIndex
|
||
|
)
|
||
|
{
|
||
|
DWORD dwAttribs;
|
||
|
HANDLE hDTA;
|
||
|
LPDTASEARCH lpschdta;
|
||
|
|
||
|
hDTA = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH);
|
||
|
lpschdta = (LPDTASEARCH)LocalLock(hDTA);
|
||
|
dwAttribs = lpschdta[(INT)SendMessage(hwndLB, LB_GETITEMDATA, wIndex, 0L)].sch_dwAttrs;
|
||
|
LocalUnlock(hDTA);
|
||
|
|
||
|
return dwAttribs;
|
||
|
}
|
||
|
|
||
|
|
||
|
// match a DOS wild card spec against a dos file name
|
||
|
// both strings are ANSI and Upper case
|
||
|
|
||
|
BOOL
|
||
|
MatchFile(
|
||
|
LPSTR szFile,
|
||
|
LPSTR szSpec
|
||
|
)
|
||
|
{
|
||
|
ENTER("MatchFile");
|
||
|
PRINT(BF_PARMTRACE, "IN:szFile=%s", szFile);
|
||
|
PRINT(BF_PARMTRACE, "IN:szSpec=%s", szSpec);
|
||
|
|
||
|
#define IS_DOTEND(ch) ((ch) == '.' || (ch) == 0)
|
||
|
|
||
|
if (!lstrcmp(szSpec, "*") || // "*" matches everything
|
||
|
!lstrcmp(szSpec, szStarDotStar)) // so does "*.*"
|
||
|
return TRUE;
|
||
|
|
||
|
while (*szFile && *szSpec) {
|
||
|
|
||
|
switch (*szSpec) {
|
||
|
case '?':
|
||
|
szFile++;
|
||
|
szSpec++;
|
||
|
break;
|
||
|
|
||
|
case '*':
|
||
|
|
||
|
while (!IS_DOTEND(*szSpec)) // got till a terminator
|
||
|
szSpec = AnsiNext(szSpec);
|
||
|
|
||
|
if (*szSpec == '.')
|
||
|
szSpec++;
|
||
|
|
||
|
while (!IS_DOTEND(*szFile)) // got till a terminator
|
||
|
szFile = AnsiNext(szFile);
|
||
|
|
||
|
if (*szFile == '.')
|
||
|
szFile++;
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (*szSpec == *szFile) {
|
||
|
if (IsDBCSLeadByte(*szSpec)) {
|
||
|
szFile++;
|
||
|
szSpec++;
|
||
|
if (*szFile != *szSpec)
|
||
|
return FALSE;
|
||
|
}
|
||
|
szFile++;
|
||
|
szSpec++;
|
||
|
} else
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
return !*szFile && !*szSpec;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
APIENTRY
|
||
|
DSSetSelection(
|
||
|
HWND hwndLB,
|
||
|
BOOL bSelect,
|
||
|
LPSTR szSpec,
|
||
|
BOOL bSearch
|
||
|
)
|
||
|
{
|
||
|
WORD i;
|
||
|
WORD iMac;
|
||
|
HANDLE hMem;
|
||
|
LPMYDTA lpmydta;
|
||
|
CHAR szTemp[MAXPATHLEN];
|
||
|
|
||
|
AnsiUpper(szSpec);
|
||
|
|
||
|
iMac = (WORD)SendMessage(hwndLB, LB_GETCOUNT, 0, 0L);
|
||
|
|
||
|
if (bSearch)
|
||
|
hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTASEARCH);
|
||
|
else
|
||
|
hMem = (HANDLE)GetWindowLongPtr(GetParent(hwndLB), GWLP_HDTA);
|
||
|
|
||
|
LocalLock(hMem);
|
||
|
|
||
|
for (i = 0; i < iMac; i++) {
|
||
|
|
||
|
if (bSearch) {
|
||
|
SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)szTemp);
|
||
|
StripPath(szTemp);
|
||
|
} else {
|
||
|
|
||
|
SendMessage(hwndLB, LB_GETTEXT, i, (LPARAM)&lpmydta);
|
||
|
|
||
|
if (lpmydta->my_dwAttrs & ATTR_PARENT)
|
||
|
continue;
|
||
|
|
||
|
lstrcpy(szTemp, lpmydta->my_cFileName);
|
||
|
}
|
||
|
|
||
|
AnsiUpper(szTemp);
|
||
|
|
||
|
if (MatchFile(szTemp, szSpec))
|
||
|
SendMessage(hwndLB, LB_SETSEL, bSelect, MAKELONG(i, 0));
|
||
|
}
|
||
|
|
||
|
LocalUnlock(hMem);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* ShowItemBitmaps() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
VOID
|
||
|
ShowItemBitmaps(
|
||
|
HWND hwndLB,
|
||
|
BOOL bShow
|
||
|
)
|
||
|
{
|
||
|
INT iSel;
|
||
|
RECT rc;
|
||
|
|
||
|
if (bShow == fShowSourceBitmaps)
|
||
|
return;
|
||
|
|
||
|
fShowSourceBitmaps = bShow;
|
||
|
|
||
|
/* Invalidate the bitmap parts of all visible, selected items. */
|
||
|
iSel = (WORD)SendMessage(hwndLB, LB_GETTOPINDEX, 0, 0L);
|
||
|
|
||
|
while (SendMessage(hwndLB, LB_GETITEMRECT, iSel, (LPARAM)&rc) != LB_ERR) {
|
||
|
/* Is this item selected? */
|
||
|
if ((BOOL)SendMessage(hwndLB, LB_GETSEL, iSel, 0L)) {
|
||
|
/* Invalidate the bitmap area. */
|
||
|
rc.right = rc.left + dxFolder + dyBorderx2 + dyBorder;
|
||
|
InvalidateRect(hwndLB, &rc, FALSE);
|
||
|
}
|
||
|
iSel++;
|
||
|
}
|
||
|
UpdateWindow(hwndLB);
|
||
|
}
|
||
|
|
||
|
|
||
|
INT
|
||
|
CharCountToTab(
|
||
|
LPSTR pStr
|
||
|
)
|
||
|
{
|
||
|
LPSTR pTmp = pStr;
|
||
|
|
||
|
while (*pStr && *pStr != '\t') {
|
||
|
pStr = AnsiNext(pStr);
|
||
|
}
|
||
|
|
||
|
return (INT)(pStr-pTmp);
|
||
|
}
|
||
|
|
||
|
|
||
|
// this only deals with opaque text for now
|
||
|
|
||
|
VOID
|
||
|
RightTabbedTextOut(
|
||
|
HDC hdc,
|
||
|
INT x,
|
||
|
INT y,
|
||
|
LPSTR pLine,
|
||
|
WORD *pTabStops,
|
||
|
INT x_offset
|
||
|
)
|
||
|
{
|
||
|
INT len, cch;
|
||
|
INT x_ext;
|
||
|
INT x_initial;
|
||
|
RECT rc;
|
||
|
|
||
|
len = lstrlen(pLine);
|
||
|
|
||
|
// setup opaquing rect (we adjust the right border as we
|
||
|
// output the string)
|
||
|
|
||
|
rc.left = x;
|
||
|
rc.top = y;
|
||
|
rc.bottom = y + dyText; // global max char height
|
||
|
|
||
|
x_initial = x;
|
||
|
|
||
|
cch = CharCountToTab(pLine);
|
||
|
MGetTextExtent(hdc, pLine, cch, &x_ext, NULL);
|
||
|
|
||
|
// first position is left alligned so bias initial x value
|
||
|
x += x_ext;
|
||
|
|
||
|
while (len) {
|
||
|
|
||
|
len -= cch + 1;
|
||
|
|
||
|
rc.right = x;
|
||
|
ExtTextOut(hdc, x - x_ext, y, ETO_OPAQUE, &rc, pLine, cch, NULL);
|
||
|
|
||
|
if (len <= 0)
|
||
|
return;
|
||
|
|
||
|
rc.left = rc.right;
|
||
|
pLine += cch + 1;
|
||
|
|
||
|
cch = CharCountToTab(pLine);
|
||
|
MGetTextExtent(hdc, pLine, cch, &x_ext, NULL);
|
||
|
|
||
|
x = *pTabStops + x_offset;
|
||
|
pTabStops++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* DrawItem() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
|
||
|
VOID
|
||
|
APIENTRY
|
||
|
DrawItem(
|
||
|
LPDRAWITEMSTRUCT lpLBItem,
|
||
|
LPSTR szLine,
|
||
|
DWORD dwAttrib,
|
||
|
BOOL bHasFocus,
|
||
|
WORD *pTabs
|
||
|
)
|
||
|
{
|
||
|
INT x, y;
|
||
|
CHAR ch;
|
||
|
LPSTR psz;
|
||
|
HDC hDC;
|
||
|
BOOL bDrawSelected;
|
||
|
HWND hwndLB;
|
||
|
INT iBitmap;
|
||
|
|
||
|
hwndLB = lpLBItem->hwndItem;
|
||
|
|
||
|
bDrawSelected = (lpLBItem->itemState & ODS_SELECTED);
|
||
|
|
||
|
hDC = lpLBItem->hDC;
|
||
|
|
||
|
if (bHasFocus && bDrawSelected) {
|
||
|
SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
||
|
SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
|
||
|
}
|
||
|
|
||
|
if (lpLBItem->itemAction == ODA_FOCUS)
|
||
|
goto FocusOnly;
|
||
|
|
||
|
/* Draw the black/white background. */
|
||
|
ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &lpLBItem->rcItem, NULL, 0, NULL);
|
||
|
|
||
|
x = lpLBItem->rcItem.left + 1;
|
||
|
y = lpLBItem->rcItem.top + (dyFileName/2);
|
||
|
|
||
|
if (fShowSourceBitmaps || (hwndDragging != hwndLB) || !bDrawSelected) {
|
||
|
|
||
|
if (dwAttrib & ATTR_DIR) {
|
||
|
if (dwAttrib & ATTR_PARENT) {
|
||
|
iBitmap = BM_IND_DIRUP;
|
||
|
szLine = szNULL; // no date/size stuff!
|
||
|
} else
|
||
|
iBitmap = BM_IND_CLOSE;
|
||
|
} else {
|
||
|
|
||
|
// isolate the name so we can see what type of file this is
|
||
|
|
||
|
psz = szLine + CharCountToTab(szLine);
|
||
|
ch = *psz;
|
||
|
*psz = 0;
|
||
|
|
||
|
if (dwAttrib & (ATTR_HIDDEN | ATTR_SYSTEM))
|
||
|
iBitmap = BM_IND_RO;
|
||
|
else if (IsProgramFile(szLine))
|
||
|
iBitmap = BM_IND_APP;
|
||
|
else if (IsDocument(szLine))
|
||
|
iBitmap = BM_IND_DOC;
|
||
|
else
|
||
|
iBitmap = BM_IND_FIL;
|
||
|
|
||
|
*psz = ch; // resore the old character
|
||
|
}
|
||
|
|
||
|
BitBlt(hDC, x + dyBorder, y-(dyFolder/2), dxFolder, dyFolder, hdcMem,
|
||
|
iBitmap * dxFolder, (bHasFocus && bDrawSelected) ? dyFolder : 0, SRCCOPY);
|
||
|
}
|
||
|
|
||
|
x += dxFolder + dyBorderx2;
|
||
|
|
||
|
if ((wTextAttribs & TA_LOWERCASE) && !(dwAttrib & ATTR_LFN))
|
||
|
AnsiLower(szLine);
|
||
|
|
||
|
RightTabbedTextOut(hDC, x, y-(dyText/2), szLine, (WORD *)pTabs, x);
|
||
|
|
||
|
if (lpLBItem->itemState & ODS_FOCUS)
|
||
|
FocusOnly:
|
||
|
DrawFocusRect(hDC, &lpLBItem->rcItem); // toggles focus (XOR)
|
||
|
|
||
|
|
||
|
if (bDrawSelected) {
|
||
|
if (bHasFocus) {
|
||
|
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
|
||
|
SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
|
||
|
} else {
|
||
|
HBRUSH hbr;
|
||
|
RECT rc;
|
||
|
|
||
|
if (hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT))) {
|
||
|
rc = lpLBItem->rcItem;
|
||
|
rc.right = rc.left + (INT)SendMessage(hwndLB, LB_GETHORIZONTALEXTENT, 0, 0L);
|
||
|
|
||
|
if (lpLBItem->itemID > 0 &&
|
||
|
(BOOL)SendMessage(hwndLB, LB_GETSEL, lpLBItem->itemID - 1, 0L))
|
||
|
rc.top -= dyBorder;
|
||
|
|
||
|
FrameRect(hDC, &rc, hbr);
|
||
|
DeleteObject(hbr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* SelectItem() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
VOID
|
||
|
SelectItem(
|
||
|
HWND hwndLB,
|
||
|
WPARAM wParam,
|
||
|
BOOL bSel
|
||
|
)
|
||
|
{
|
||
|
/* Add the current item to the selection. */
|
||
|
SendMessage(hwndLB, LB_SETSEL, bSel, (DWORD)wParam);
|
||
|
|
||
|
/* Give the selected item the focus rect and anchor pt. */
|
||
|
SendMessage(hwndLB, LB_SETCARETINDEX, wParam, 0L);
|
||
|
SendMessage(hwndLB, LB_SETANCHORINDEX, wParam, 0L);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// void APIENTRY DSDragLoop(register HWND hwndLB, WPARAM wParam, LPDROPSTRUCT lpds, BOOL bSearch)
|
||
|
//
|
||
|
// called by for the directory and search drag loops. this must handle
|
||
|
// detecting all kinds of different destinations.
|
||
|
//
|
||
|
// in:
|
||
|
// hwndLB source listbox (either the dir or the sort)
|
||
|
// wParam same as sent for WM_DRAGLOOP (TRUE if we are on a dropable sink)
|
||
|
// lpds drop struct sent with the message
|
||
|
// bSearch TRUE if we are in the search listbox
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
APIENTRY
|
||
|
DSDragLoop(
|
||
|
HWND hwndLB,
|
||
|
WPARAM wParam,
|
||
|
LPDROPSTRUCT lpds,
|
||
|
BOOL bSearch
|
||
|
)
|
||
|
{
|
||
|
BOOL bTemp;
|
||
|
BOOL bShowBitmap;
|
||
|
LPMYDTA lpmydta;
|
||
|
HWND hwndMDIChildSink, hwndDir;
|
||
|
|
||
|
|
||
|
// bShowBitmap is used to turn the source bitmaps on or off to distinguish
|
||
|
// between a move and a copy or to indicate that a drop can
|
||
|
// occur (exec and app)
|
||
|
|
||
|
// hack: keep around for drop files!
|
||
|
hwndGlobalSink = lpds->hwndSink;
|
||
|
|
||
|
bShowBitmap = TRUE; // default to copy
|
||
|
|
||
|
if (!wParam)
|
||
|
goto DragLoopCont; // can't drop here
|
||
|
|
||
|
// Is the user holding down the CTRL key (which forces a copy)?
|
||
|
if (GetKeyState(VK_CONTROL) < 0) {
|
||
|
bShowBitmap = TRUE;
|
||
|
goto DragLoopCont;
|
||
|
}
|
||
|
|
||
|
// Is the user holding down the ALT or SHIFT key (which forces a move)?
|
||
|
if (GetKeyState(VK_MENU)<0 || GetKeyState(VK_SHIFT)<0) {
|
||
|
bShowBitmap = FALSE;
|
||
|
goto DragLoopCont;
|
||
|
}
|
||
|
|
||
|
hwndMDIChildSink = GetMDIChildFromDecendant(lpds->hwndSink);
|
||
|
|
||
|
// Are we over the source listbox? (sink and source the same)
|
||
|
|
||
|
if (lpds->hwndSink == hwndLB) {
|
||
|
|
||
|
// Are we over a valid listbox entry?
|
||
|
if (LOWORD(lpds->dwControlData) == 0xFFFF) {
|
||
|
goto DragLoopCont;
|
||
|
} else {
|
||
|
/* Yup, are we over a directory entry? */
|
||
|
if (bSearch) {
|
||
|
|
||
|
bTemp = (GetSearchAttribs(hwndLB, (WORD)(lpds->dwControlData)) & ATTR_DIR) != 0L;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
SendMessage(hwndLB, LB_GETTEXT, (WORD)(lpds->dwControlData), (LPARAM)&lpmydta);
|
||
|
|
||
|
bTemp = lpmydta->my_dwAttrs & ATTR_DIR;
|
||
|
|
||
|
}
|
||
|
if (!bTemp)
|
||
|
goto DragLoopCont;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Now we need to see if we are over an Executable file. If so, we
|
||
|
* need to force the Bitmaps to draw.
|
||
|
*/
|
||
|
|
||
|
/* Are we over a directory window? */
|
||
|
|
||
|
if (hwndMDIChildSink)
|
||
|
hwndDir = HasDirWindow(hwndMDIChildSink);
|
||
|
else
|
||
|
hwndDir = NULL;
|
||
|
|
||
|
if (hwndDir && (hwndDir == GetParent(lpds->hwndSink))) {
|
||
|
|
||
|
// Are we over an occupided part of the list box?
|
||
|
|
||
|
if (LOWORD(lpds->dwControlData) != 0xFFFF) {
|
||
|
|
||
|
// Are we over an Executable?
|
||
|
|
||
|
SendMessage(lpds->hwndSink, LB_GETTEXT, (WORD)(lpds->dwControlData), (LPARAM)&lpmydta);
|
||
|
|
||
|
bTemp = IsProgramFile(lpmydta->my_cFileName);
|
||
|
|
||
|
if (bTemp)
|
||
|
goto DragLoopCont;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Are we dropping into the same drive (check the source and dest drives)
|
||
|
|
||
|
bShowBitmap = ((INT)SendMessage(GetParent(hwndLB), FS_GETDRIVE, 0, 0L) !=
|
||
|
GetDrive(lpds->hwndSink, lpds->ptDrop));
|
||
|
|
||
|
DragLoopCont:
|
||
|
|
||
|
ShowItemBitmaps(hwndLB, bShowBitmap);
|
||
|
|
||
|
// hack, set the cursor to match the move/copy state
|
||
|
if (wParam)
|
||
|
SetCursor(GetMoveCopyCursor());
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* DSRectItem() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
VOID
|
||
|
APIENTRY
|
||
|
DSRectItem(
|
||
|
HWND hwndLB,
|
||
|
INT iItem,
|
||
|
BOOL bFocusOn,
|
||
|
BOOL bSearch
|
||
|
)
|
||
|
{
|
||
|
RECT rc;
|
||
|
RECT rcT;
|
||
|
HDC hDC;
|
||
|
BOOL bSel;
|
||
|
WORD wColor;
|
||
|
HBRUSH hBrush;
|
||
|
LPMYDTA lpmydta;
|
||
|
CHAR szTemp[MAXPATHLEN];
|
||
|
|
||
|
/* Are we over an unused part of the listbox? */
|
||
|
if (iItem == 0xFFFF)
|
||
|
return;
|
||
|
|
||
|
/* Are we over ourselves? (i.e. a selected item in the source listbox) */
|
||
|
bSel = (BOOL)SendMessage(hwndLB, LB_GETSEL, iItem, 0L);
|
||
|
if (bSel && (hwndDragging == hwndLB))
|
||
|
return;
|
||
|
|
||
|
/* We only put rectangles around directories and program items. */
|
||
|
if (bSearch) {
|
||
|
SendMessage(hwndLB, LB_GETTEXT, iItem, (LPARAM)szTemp);
|
||
|
|
||
|
// this is bused, we must test this as attributes
|
||
|
|
||
|
if (!(BOOL)(GetSearchAttribs(hwndLB, (WORD)iItem) & ATTR_DIR) && !IsProgramFile((LPSTR)szTemp))
|
||
|
return;
|
||
|
} else {
|
||
|
SendMessage(hwndLB, LB_GETTEXT, iItem, (LPARAM)&lpmydta);
|
||
|
|
||
|
if (!(lpmydta->my_dwAttrs & ATTR_DIR) &&
|
||
|
!IsProgramFile(lpmydta->my_cFileName)) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Turn the item's rectangle on or off. */
|
||
|
|
||
|
SendMessage(hwndLB, LB_GETITEMRECT, iItem, (LPARAM)&rc);
|
||
|
GetClientRect(hwndLB,&rcT);
|
||
|
IntersectRect(&rc,&rc,&rcT);
|
||
|
|
||
|
if (bFocusOn) {
|
||
|
hDC = GetDC(hwndLB);
|
||
|
if (bSel) {
|
||
|
wColor = COLOR_WINDOW;
|
||
|
InflateRect(&rc, -1, -1);
|
||
|
} else
|
||
|
wColor = COLOR_WINDOWFRAME;
|
||
|
|
||
|
if (hBrush = CreateSolidBrush(GetSysColor(wColor))) {
|
||
|
FrameRect(hDC, &rc, hBrush);
|
||
|
DeleteObject(hBrush);
|
||
|
}
|
||
|
ReleaseDC(hwndLB, hDC);
|
||
|
} else {
|
||
|
InvalidateRect(hwndLB, &rc, FALSE);
|
||
|
UpdateWindow(hwndLB);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* DropFilesOnApplication() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
/* this function will determine whether the application we are currently
|
||
|
* over is a valid drop point and drop the files
|
||
|
*/
|
||
|
|
||
|
WORD
|
||
|
DropFilesOnApplication(
|
||
|
LPSTR pszFiles
|
||
|
)
|
||
|
{
|
||
|
POINT pt;
|
||
|
HWND hwnd;
|
||
|
RECT rc;
|
||
|
HANDLE hDrop,hT;
|
||
|
LPSTR lpList;
|
||
|
WORD cbList = 2;
|
||
|
OFSTRUCT ofT;
|
||
|
WORD cbT;
|
||
|
LPDROPFILESTRUCT lpdfs;
|
||
|
CHAR szFile[MAXPATHLEN];
|
||
|
|
||
|
if (!(hwnd = hwndGlobalSink))
|
||
|
return 0;
|
||
|
|
||
|
hwndGlobalSink = NULL;
|
||
|
|
||
|
GetCursorPos(&pt);
|
||
|
|
||
|
cbList = 2 + sizeof (DROPFILESTRUCT);
|
||
|
hDrop = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,cbList);
|
||
|
if (!hDrop)
|
||
|
return 0;
|
||
|
|
||
|
lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop);
|
||
|
|
||
|
GetClientRect(hwnd,&rc);
|
||
|
ScreenToClient(hwnd,&pt);
|
||
|
lpdfs->pt = pt;
|
||
|
lpdfs->fNC = !PtInRect(&rc,pt);
|
||
|
lpdfs->pFiles = sizeof(DROPFILESTRUCT);
|
||
|
|
||
|
GlobalUnlock(hDrop);
|
||
|
|
||
|
while (pszFiles = GetNextFile(pszFiles, szFile, sizeof(szFile))) {
|
||
|
|
||
|
MOpenFile(szFile, &ofT, OF_PARSE);
|
||
|
|
||
|
cbT = (WORD)(lstrlen(ofT.szPathName)+1);
|
||
|
hT = GlobalReAlloc(hDrop,cbList+cbT,GMEM_MOVEABLE|GMEM_ZEROINIT);
|
||
|
if (!hT)
|
||
|
break;
|
||
|
hDrop = hT;
|
||
|
lpList = GlobalLock(hDrop);
|
||
|
OemToAnsi(ofT.szPathName, lpList+cbList-2);
|
||
|
GlobalUnlock(hDrop);
|
||
|
cbList += cbT;
|
||
|
}
|
||
|
|
||
|
PostMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0L);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* DSTrackPoint() - */
|
||
|
/* */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
/* Return 0 for normal mouse tracking, 1 for no mouse single-click processing,
|
||
|
* and 2 for no mouse single- or double-click tracking.
|
||
|
*/
|
||
|
|
||
|
INT
|
||
|
APIENTRY
|
||
|
DSTrackPoint(
|
||
|
HWND hWnd,
|
||
|
HWND hwndLB,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam,
|
||
|
BOOL bSearch
|
||
|
)
|
||
|
{
|
||
|
UINT iSel;
|
||
|
MSG msg;
|
||
|
RECT rc;
|
||
|
WORD wAnchor;
|
||
|
DWORD dwTemp;
|
||
|
LPSTR pch;
|
||
|
BOOL bDir;
|
||
|
BOOL bSelected;
|
||
|
BOOL bSelectOneItem;
|
||
|
BOOL bUnselectIfNoDrag;
|
||
|
CHAR szFileName[MAXPATHLEN+1];
|
||
|
INT iNoYieldCount;
|
||
|
WORD wYieldFlags;
|
||
|
POINT pt;
|
||
|
HANDLE hHackForHDC = NULL; // hDC Express editor relies on this
|
||
|
DRAGOBJECTDATA dodata;
|
||
|
|
||
|
bSelectOneItem = FALSE;
|
||
|
bUnselectIfNoDrag = FALSE;
|
||
|
|
||
|
bSelected = (BOOL)SendMessage(hwndLB, LB_GETSEL, wParam, 0L);
|
||
|
|
||
|
if (GetKeyState(VK_SHIFT) < 0) {
|
||
|
/* What is the state of the Anchor point? */
|
||
|
wAnchor = (WORD)SendMessage(hwndLB, LB_GETANCHORINDEX, 0, 0L);
|
||
|
bSelected = (BOOL)SendMessage(hwndLB, LB_GETSEL, wAnchor, 0L);
|
||
|
|
||
|
/* If Control is up, turn everything off. */
|
||
|
if (!(GetKeyState(VK_CONTROL) < 0))
|
||
|
SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
|
||
|
|
||
|
/* Select everything between the Anchor point and the item. */
|
||
|
SendMessage(hwndLB, LB_SELITEMRANGE, bSelected, MAKELONG(wParam, wAnchor));
|
||
|
|
||
|
/* Give the selected item the focus rect. */
|
||
|
SendMessage(hwndLB, LB_SETCARETINDEX, wParam, 0L);
|
||
|
} else if (GetKeyState(VK_CONTROL) < 0) {
|
||
|
if (bSelected)
|
||
|
bUnselectIfNoDrag = TRUE;
|
||
|
else
|
||
|
SelectItem(hwndLB, wParam, TRUE);
|
||
|
} else {
|
||
|
if (bSelected)
|
||
|
bSelectOneItem = TRUE;
|
||
|
else {
|
||
|
/* Deselect everything. */
|
||
|
SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
|
||
|
|
||
|
/* Select the current item. */
|
||
|
SelectItem(hwndLB, wParam, TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bSearch)
|
||
|
UpdateStatus(GetParent(hWnd));
|
||
|
|
||
|
LONG2POINT(lParam, pt);
|
||
|
ClientToScreen(hwndLB, (LPPOINT)&pt);
|
||
|
ScreenToClient(hWnd, (LPPOINT)&pt);
|
||
|
|
||
|
// See if the user moves a certain number of pixels in any direction
|
||
|
|
||
|
SetRect(&rc, pt.x - dxClickRect, pt.y - dyClickRect,
|
||
|
pt.x + dxClickRect, pt.y + dyClickRect);
|
||
|
|
||
|
SetCapture(hWnd);
|
||
|
wYieldFlags = PM_NOYIELD | PM_REMOVE;
|
||
|
iNoYieldCount = 50;
|
||
|
for (;;) {
|
||
|
#if 0
|
||
|
{
|
||
|
CHAR szBuf[80];
|
||
|
|
||
|
wsprintf(szBuf, "Message %4.4X\r\n", msg.message);
|
||
|
OutputDebugString(szBuf);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (PeekMessage(&msg, NULL, 0, 0, wYieldFlags))
|
||
|
DispatchMessage(&msg);
|
||
|
|
||
|
if (iNoYieldCount <= 0)
|
||
|
wYieldFlags = PM_REMOVE;
|
||
|
else
|
||
|
iNoYieldCount--;
|
||
|
|
||
|
// WM_CANCELMODE messages will unset the capture, in that
|
||
|
// case I want to exit this loop
|
||
|
|
||
|
if (GetCapture() != hWnd) {
|
||
|
msg.message = WM_LBUTTONUP; // don't proceed below
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (msg.message == WM_LBUTTONUP)
|
||
|
break;
|
||
|
|
||
|
LONG2POINT(msg.lParam, pt);
|
||
|
if ((msg.message == WM_MOUSEMOVE) && !(PtInRect(&rc, pt)))
|
||
|
break;
|
||
|
}
|
||
|
ReleaseCapture();
|
||
|
|
||
|
/* Did the guy NOT drag anything? */
|
||
|
if (msg.message == WM_LBUTTONUP) {
|
||
|
if (bSelectOneItem) {
|
||
|
/* Deselect everything. */
|
||
|
SendMessage(hwndLB, LB_SETSEL, FALSE, -1L);
|
||
|
|
||
|
/* Select the current item. */
|
||
|
SelectItem(hwndLB, wParam, TRUE);
|
||
|
}
|
||
|
|
||
|
if (bUnselectIfNoDrag)
|
||
|
SelectItem(hwndLB, wParam, FALSE);
|
||
|
|
||
|
// notify the appropriate people
|
||
|
|
||
|
SendMessage(hWnd, WM_COMMAND,
|
||
|
GET_WM_COMMAND_MPS(0, hwndLB, LBN_SELCHANGE));
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* Enter Danger Mouse's BatCave. */
|
||
|
if ((WORD)SendMessage(hwndLB, LB_GETSELCOUNT, 0, 0L) == 1) {
|
||
|
/* There is only one thing selected.
|
||
|
* Figure out which cursor to use.
|
||
|
*/
|
||
|
if (bSearch) {
|
||
|
SendMessage(hwndLB, LB_GETTEXT, wParam, (LPARAM)szFileName);
|
||
|
bDir = (BOOL)(GetSearchAttribs(hwndLB, (WORD)wParam) & ATTR_DIR);
|
||
|
} else {
|
||
|
LPMYDTA lpmydta;
|
||
|
|
||
|
SendMessage(hwndLB, LB_GETTEXT, wParam, (LPARAM)&lpmydta);
|
||
|
|
||
|
lstrcpy(szFileName, lpmydta->my_cFileName);
|
||
|
bDir = lpmydta->my_dwAttrs & ATTR_DIR;
|
||
|
|
||
|
// avoid dragging the parrent dir
|
||
|
|
||
|
if (lpmydta->my_dwAttrs & ATTR_PARENT) {
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bDir) {
|
||
|
iSel = DOF_DIRECTORY;
|
||
|
} else if (IsProgramFile(szFileName)) {
|
||
|
iSel = DOF_EXECUTABLE;
|
||
|
goto HDC_HACK_FROM_HELL;
|
||
|
} else if (IsDocument(szFileName)) {
|
||
|
iSel = DOF_DOCUMENT;
|
||
|
HDC_HACK_FROM_HELL:
|
||
|
hHackForHDC = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(OFSTRUCT));
|
||
|
if (hHackForHDC) {
|
||
|
LPOFSTRUCT lpof;
|
||
|
|
||
|
lpof = (LPOFSTRUCT)GlobalLock(hHackForHDC);
|
||
|
QualifyPath(szFileName);
|
||
|
lstrcpy(lpof->szPathName, szFileName);
|
||
|
GlobalUnlock(hHackForHDC);
|
||
|
}
|
||
|
} else
|
||
|
iSel = DOF_DOCUMENT;
|
||
|
|
||
|
iCurDrag = SINGLECOPYCURSOR;
|
||
|
} else {
|
||
|
/* Multiple files are selected. */
|
||
|
iSel = DOF_MULTIPLE;
|
||
|
iCurDrag = MULTCOPYCURSOR;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Get the list of selected things. */
|
||
|
pch = (LPSTR)SendMessage(hWnd, FS_GETSELECTION, FALSE, 0L);
|
||
|
|
||
|
/* Wiggle things around. */
|
||
|
hwndDragging = hwndLB;
|
||
|
dodata.pch = pch;
|
||
|
dodata.hMemGlobal = hHackForHDC;
|
||
|
dwTemp = DragObject(GetDesktopWindow(),hWnd,(UINT)iSel,(DWORD)(ULONG_PTR)&dodata,GetMoveCopyCursor());
|
||
|
|
||
|
if (hHackForHDC)
|
||
|
GlobalFree(hHackForHDC);
|
||
|
|
||
|
SetWindowDirectory();
|
||
|
|
||
|
if (dwTemp == DO_PRINTFILE) {
|
||
|
// print these
|
||
|
hdlgProgress = NULL;
|
||
|
WFPrint(pch);
|
||
|
} else if (dwTemp == DO_DROPFILE) {
|
||
|
// try and drop them on an application
|
||
|
DropFilesOnApplication(pch);
|
||
|
}
|
||
|
|
||
|
LocalFree((HANDLE)pch);
|
||
|
|
||
|
if (IsWindow(hWnd))
|
||
|
ShowItemBitmaps(hwndLB, TRUE);
|
||
|
|
||
|
hwndDragging = NULL;
|
||
|
|
||
|
if (!bSearch && IsWindow(hWnd))
|
||
|
UpdateStatus(GetParent(hWnd));
|
||
|
|
||
|
return 2;
|
||
|
}
|