利用消息"拖放"文件到其他程序,《Windows 95 程式设计指南》的例子 :<br><br>// -----------------------------------------------------------<br><br>// Module name: DFSrc.c ->> DFSrc.pas<br>// Written by: Jeffrey Richter<br>// Notices: Copyright (c) 1995 Jeffrey Richter<br>// Purpose: Drop file source library functions.<br>// Translator: 刘麻子, Liu_mazi@126.com<br><br>unit DFSrc;<br><br>interface<br><br>uses Windows, ShlObj, ShellAPI, CommDlg;<br><br> // 取第nIndex个字符串(文件名)<br>function MultiStrUtil_FindStr(szStrAll: PChar; nIndex: Integer; pnMax: PInteger): PChar; stdcall;<br><br> // 是否选择了多个文件<br>function FileOpenUtil_AreMultipleFilesSelected(pofn: POpenFilename): BOOL; stdcall;<br><br> // 文件列表内含文件个数<br>function FileOpenUtil_GetNumFiles(pofn: POpenFilename): Integer; stdcall;<br><br> // 取第nIndex个文件完整路径<br>function FileOpenUtil_GetFile(pofn: POpenFilename; nIndex: Integer; szPathname: PChar): Integer; stdcall;<br><br> // 目标或其父窗口是否接受文件拖放<br>function DFSrc_OkToDrop(ppt: PPOINT): HWND; stdcall;<br><br> // 分配头部结构内存块<br>function DFSrc_Create(ppt: PPOINT; fNC, fWide: BOOL): HDROP; stdcall;<br><br> // 向结构尾部追加文件<br>function DFSrc_AppendPathname(hdrop: HDROP; pvPathname: Pointer): HDROP; stdcall;<br> <br>implementation<br><br> // (单个)目标窗口是否接受文件拖放<br>function IsAcceptingFiles(hWnd: HWND): Boolean;<br>begin<br> Result := (GetWindowLong(hWnd, GWL_EXSTYLE) and WS_EX_ACCEPTFILES) <> 0;<br>end;<br><br> // 目标或其父窗口是否接受文件拖放<br>function DFSrc_OkToDrop(ppt: PPoint): HWND; stdcall;<br>var<br> ptMousePos: TPoint;<br>begin<br> if (ppt = nil) then<br> begin<br> ptMousePos.x := LOWORD(GetMessagePos());<br> ptMousePos.y := HIWORD(GetMessagePos());<br> end else<br> ptMousePos := ppt^; // 这句我自己加的 ^^<br><br> // 取得指定位置所处的窗口<br> Result := WindowFromPoint(ptMousePos);<br><br> // 看看目标窗囗或其父窗口是否接受文件拖放<br> while IsWindow(Result) and (IsAcceptingFiles(Result) = FALSE) do<br> Result := GetParent(Result);<br><br> // 如果接受, 返回其句柄, 否则返回"空"句柄<br> if (IsWindow(Result) = FALSE) or (IsAcceptingFiles(Result) = FALSE) then<br> Result := 0;<br>end;<br><br> // 分配头部结构内存<br>function DFSrc_Create(ppt: PPoint; fNC, fWide: BOOL): HDROP; stdcall;<br>var<br> PtDropFiles: PDropFiles;<br>begin<br> // 分配头部结构<br> if fWide then<br> Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(TDropFiles) + SizeOf(WideChar))<br> else<br> Result := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, SizeOf(TDropFiles) + SizeOf(Char));<br><br> // 填写结构成员<br> if (Result <> 0) then<br> begin<br> PtDropFiles := PDropFiles(GlobalLock(Result));<br><br> PtDropFiles.pFiles := SizeOf(TDropFiles);<br> PtDropFiles.pt := ppt^;<br> PtDropFiles.fNC := fNC;<br> PtDropFiles.fWide := fWide;<br><br> GlobalUnlock(Result);<br> end;<br>end;<br><br> // 向结构尾部追加文件<br>function DFSrc_AppendPathname(hDrop: HDROP; pvPathname: Pointer): HDROP; stdcall;<br>var<br> PtDropFiles: PDropFiles;<br> szPathA: PChar;<br> szPathW: PWideChar;<br> nOffsetOfNewPathname, nPathSize: Integer;<br>begin<br> PtDropFiles := PDropFiles(GlobalLock(hdrop));<br><br> // 定位至结构头尾部<br> szPathA := PChar(DWORD(PtDropFiles) + PtDropFiles.pFiles);<br> szPathW := PWideChar(szPathA);<br><br> // 是Unicode宽字符?<br> if (PtDropFiles.fWide) then<br> begin<br> // 定位尾部<br> while (szPathW^ <> #0) do<br> begin<br> while (szPathW^ <> #0) do Inc(szPathW);<br> Inc(szPathW);<br> end;<br><br> // 首尾间距<br> nOffsetOfNewPathname := Integer(szPathW) - Integer(PtDropFiles);<br> <br> // 新串长度<br> nPathSize := SizeOf(WideChar) * (lstrlenW(pvPathname) + 2);<br> end else<br> begin<br> // 定位尾部<br> while (szPathA^ <> #0) do<br> begin<br> while (szPathA^ <> #0) do Inc(szPathA);<br> Inc(szPathA);<br> end;<br><br> // 首尾间距<br> nOffsetOfNewPathname := Integer(szPathA) - Integer(PtDropFiles);<br><br> // 新串长度<br> nPathSize := SizeOf(Char) * (lstrlenA(pvPathname) + 2);<br> end;<br><br> GlobalUnlock(hdrop);<br><br> // 重新分配<br> hdrop :=<br> GlobalReAlloc(hdrop, nPathSize + nOffsetOfNewPathname, GMEM_MOVEABLE or GMEM_ZEROINIT);<br><br> // 分配成功<br> if (hdrop <> 0) then<br> begin<br> PtDropFiles := PDropFiles(GlobalLock(hdrop));<br> if (PtDropFiles.fWide) then<br> lstrcmpW(PWideChar(Integer(PtDropFiles) + nOffsetOfNewPathname), pvPathname)<br> else<br> lstrcpyA(PChar(Integer(PtDropFiles) + nOffsetOfNewPathname), pvPathname);<br> GlobalUnlock(hdrop);<br> end;<br><br> // 返回句柄 <br> Result := hdrop;<br>end;<br><br> // 取第nIndex个字符串(文件名)<br>function MultiStrUtil_FindStr(szStrAll: PChar; nIndex: Integer; pnMax: PInteger): PChar; stdcall;<br> // 定位#0, 单个字符串尾部<br> function SearchEnd(const P: PChar): PChar;<br> begin<br> Result := P;<br> while (Result^ <> #0) do Inc(Result);<br> end;<br>var<br> nNumStrs: Integer;<br> szStrSingle: PChar;<br>begin<br> if (nIndex = -1) then nIndex := MaxInt;<br><br> // 定位第nIndex个字符串<br> szStrSingle := szStrAll;<br> nNumStrs := 0; <br> while (szStrSingle^ <> #0) and (nNumStrs < nIndex) do<br> begin<br> szStrSingle := SearchEnd(szStrSingle) + 1;<br> Inc(nNumStrs);<br> end;<br><br> if (pnMax <> nil) then pnMax^ := nNumStrs;<br><br> // 一直搜索到尾部也未找到<br> if (nNumStrs < nIndex) then<br> Result := nil<br> else<br> Result := szStrSingle;<br>end;<br><br> // 是否选择了多个文件<br>function FileOpenUtil_AreMultipleFilesSelected(pofn: POpenFilename): BOOL; stdcall;<br>begin<br> // 如果选择多个文件,nFileOffset是到第一个文件名的偏移(肯定超过路径字符串的长度)<br> Result := lstrlen(pofn.lpstrFile) < pofn.nFileOffset;<br>end;<br><br> // 文件列表内含文件个数<br>function FileOpenUtil_GetNumFiles(pofn: POpenFilename): Integer; stdcall;<br>begin<br> Result := 1;<br> if FileOpenUtil_AreMultipleFilesSelected(pofn) then<br> begin<br> // 最后一个(也即列表长度)<br> MultiStrUtil_FindStr(pofn.lpstrFile, -1, @Result);<br> Dec(Result);<br> end;<br>end;<br><br> // 取第nIndex个文件完整路径<br>function FileOpenUtil_GetFile(pofn: POpenFilename; nIndex: Integer; szPathname: PChar): Integer; stdcall;<br>begin<br> lstrcpy(szPathname, MultiStrUtil_FindStr(pofn.lpstrFile, 0, nil));<br> if FileOpenUtil_AreMultipleFilesSelected(pofn) then<br> begin<br> lstrcat(szPathname, '/');<br> lstrcat(szPathname, MultiStrUtil_FindStr(pofn.lpstrFile, nIndex + 1, nil));<br> end;<br> Result := lstrlen(szPathname);<br>end;<br><br>end.<br><br>// -----------------------------------------------------------<br><br>// Module name: DFSrcDem.c ->> DFSrcDem.dpr<br>// Written by: Jeffrey Richter<br>// Notices: Copyright (c) 1995 Jeffrey Richter<br>// Purpose: Demonstrates how to create a dropfile source application<br>// Translator: 刘麻子, Liu_mazi@126.com<br><br>program DFSrcDem;<br><br>{$R DFSrcDem.res}<br><br>uses Windows, Messages, ShellAPI, CommDlg, DFSrc in 'DFSrc.pas';<br><br>const<br> // 光标资源ID<br> IDC_DROPOK = 103;<br><br> // 图标资源ID<br> IDI_DFSRCDEMO = 104;<br><br> // 模板资源ID<br> IDD_DFSRCDEMO = 105;<br><br> // 控件标识ID <br> IDC_NUMFILES = 1001;<br> IDC_SELECTFILES = 1002;<br> IDC_PATHNAMELIST = 1003;<br><br> // WM_INITDIALOG消息处理<br>function DFSrcDem
nInitDialog(hWnd, hWndFocus: HWND; lParam: LPARAM): BOOL;<br>begin<br> // 设置窗体图标<br> SendMessage(hWnd, WM_SETICON, ICON_BIG, LoadIcon(HInstance, MakeIntResource(IDI_DFSRCDEMO)));<br><br> // 加水平滚动条<br> SendMessage(GetDlgItem(hWnd, IDC_PATHNAMELIST),<br> LB_SETHORIZONTALEXTENT, MAX_PATH * LOWORD(GetDialogBaseUnits()), 0);<br><br> // 接受默认焦点<br> Result := TRUE;<br>end;<br><br> // WM_COMMAND消息处理<br>procedure DFSrcDem
nCommand(hWnd: HWND; id: Integer; hWndCtl: HWND; codeNotify: UINT);<br>var<br> szAllFileNames: array[0..1024] of Char;<br> szPathname: array[0..MAX_PATH] of Char;<br> ofn: TOpenFilename;<br> nNumFiles, nIndex: Integer;<br> hWndLB: LongWord; // HWND<br>begin<br> case (id) of<br> IDCANCEL: // 关闭对话框<br> begin<br> EndDialog(hWnd, id);<br> end;<br><br> IDC_SELECTFILES: // 选择文件<br> begin<br> // 清空ListBox<br> hWndLB := GetDlgItem(hWnd, IDC_PATHNAMELIST);<br> SendMessage(hWndLB, LB_RESETCONTENT, 0, 0);<br><br> // 初始化ofn结构<br> ZeroMemory(@ofn, SizeOf(TOpenFilename));<br> ofn.lStructSize := SizeOf(TOpenFilename);<br><br> ofn.hwndOwner := hWnd;<br> ofn.lpstrFilter := 'All files'#0'*.*'#0;<br> ofn.Flags := OFN_ALLOWMULTISELECT or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_EXPLORER;<br><br> szAllFileNames[0] := #0;<br> ofn.lpstrFile := @szAllFileNames[0];<br> ofn.nMaxFile := SizeOf(szAllFileNames);<br><br> // 选择了文件<br> if GetOpenFileName(ofn) then<br> begin<br> // 选择文件的数量<br> nNumFiles := FileOpenUtil_GetNumFiles(@ofn);<br><br> // 添加至ListBox<br> for nIndex := 0 to nNumFiles - 1 do<br> begin<br> FileOpenUtil_GetFile(@ofn, nIndex, szPathname);<br> SendMessage(hWndLB, LB_ADDSTRING, 0, Integer(@szPathname[0]));<br> end;<br> end else<br> begin<br> nNumFiles := 0;<br> end;<br><br> // 选择文件的数量<br> SetDlgItemInt(hWnd, IDC_NUMFILES, nNumFiles, FALSE);<br> end;<br> end; // END: case (id) of<br>end;<br><br> // WM_LBUTTONDOWN消息处理<br>procedure DFSrcDem
nLButtonDown(hWnd: HWND; fDoubleClick: BOOL; nIndex, y: Integer; keyFlags: UINT);<br>begin<br> if SendMessage(GetDlgItem(hWnd, IDC_PATHNAMELIST), LB_GETCOUNT, 0, 0) = 0 then<br> // 文件列表为空<br> MessageBox(GetActiveWindow(), 'No files to drop.', 'DFSrcDem', 0)<br> else<br> // 捕获鼠标消息<br> SetCapture(hWnd);<br>end;<br><br> // WM_MOUSEMOVE消息处理<br>procedure DFSrcDem
nMouseMove(hWnd: HWND; x, y: Integer; keyFlags: UINT);<br>begin<br> // 鼠标并未按下(说明不是'拖拽')<br> if (GetCapture() <> hWnd) then Exit;<br><br> // 根据鼠标下窗体的风格设置光标<br> if IsWindow(DFSrc_OkToDrop(nil)) then<br> SetCursor(LoadCursor(HInstance, MakeIntResource(IDC_DROPOK)))<br> else<br> SetCursor(LoadCursor(0, IDC_NO));<br>end;<br><br> // WM_LBUTTONUP消息处理<br>procedure DFSrcDem
nLButtonUp(hWnd: HWND; x, y: Integer; keyFlags: UINT);<br>var<br> hWndTarget, hWndLB: LongWord; // HWND<br> rc: TRect;<br> ptMousePos: TPoint; // **<br> nIndex, nNumFiles: Integer;<br> hdrop, hdropT: Longint; // HDROP<br> szPathName: array[0..MAX_PATH] of Char;<br>begin<br> // 之前并非拖拽状态<br> if (GetCapture() <> hWnd) then Exit;<br><br> // 释放鼠标消息捕捉<br> ReleaseCapture();<br><br> // 文件拖放目标窗口<br> GetCursorPos(ptMousePos); // **<br> hWndTarget := DFSrc_OkToDrop(@ptMousePos);<br><br> // 如果窗口句柄非法<br> if (IsWindow(hWndTarget) = FALSE) then Exit;<br><br> // 窗口客户区范围<br> GetClientRect(hWndTarget, rc);<br> ScreenToClient(hWndTarget, ptMousePos);<br><br> // 分配内存并初始化<br> hdrop := DFSrc_Create(@ptMousePos, not PtInRect(rc, ptMousePos), FALSE);<br> if (hdrop = 0) then<br> begin<br> MessageBox(GetActiveWindow(), 'Insufficient memory to drop file(s).', 'DFSrcDem', 0);<br> Exit;<br> end;<br><br> // ListBox文件数量<br> hWndLB := GetDlgItem(hWnd, IDC_PATHNAMELIST);<br> nNumFiles := SendMessage(GetDlgItem(hWnd, IDC_PATHNAMELIST), LB_GETCOUNT, 0, 0);<br> <br> // 添加文件列表<br> for nIndex := 0 to nNumFiles - 1 do<br> begin<br> SendMessage(hWndLB, LB_GETTEXT, nIndex, Integer(@szPathName[0]));<br> hdropT := DFSrc_AppendPathname(hdrop, @szPathName[0]);<br><br> if (hdropT = 0) then<br> begin<br> MessageBox(GetActiveWindow(), 'Insufficient memory to drop file(s).', 'DFSrcDem', 0);<br> hdrop := GlobalFree(hdrop);<br> Break; // Terminates the 'for' loop.<br> end else<br> begin<br> hdrop := hdropT;<br> end;<br> end;<br><br> // 添加文件列表成功<br> if (hdrop <> 0) then<br> begin<br> // 向拖放目标发消息<br> PostMessage(hWndTarget, WM_DROPFILES, hdrop, 0);<br><br> // 清空文件列表<br> SetDlgItemInt(hWnd, IDC_NUMFILES, 0, FALSE);<br> SendMessage(hWndLB, LB_RESETCONTENT, 0, 0);<br><br> // 注意: 我们不应该用 GlobalFree(hdrop) 来释放这块内存,<br> // 系统会在目标进程空间重新分配内存并作拷贝之后自动释放,<br> // 新的内存块, 由目标进程负责调用DragFinish()来释放 ..<br> end;<br>end;<br><br> // 对话框消息处理回调<br>function DFSrcDemo_Proc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;<br>begin<br> case (uMsg) of<br> WM_INITDIALOG:<br> begin<br> Result := BOOL(SetWindowLong(hWnd, DWL_MSGRESULT,<br> Longint(DFSrcDem
nInitDialog(hWnd, wParam, lParam))));<br> end;<br><br> WM_COMMAND:<br> begin<br> DFSrcDem
nCommand(hWnd, LOWORD(wParam), lParam, HIWORD(wParam));<br> Result := TRUE;<br> end;<br><br> WM_LBUTTONDOWN:<br> begin<br> DFSrcDem
nLButtonDown(hWnd, FALSE, LOWORD(lParam), HIWORD(lParam), wParam);<br> Result := TRUE;<br> end;<br><br> WM_MOUSEMOVE:<br> begin<br> DFSrcDem
nMouseMove(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);<br> Result := TRUE;<br> end;<br><br> WM_LBUTTONUP:<br> begin<br> DFSrcDem
nLButtonUp(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);<br> Result := TRUE;<br> end;<br><br> else Result := FALSE;<br> end;<br>end;<br><br> // 程序'主线程'入口<br>begin<br> DialogBox(HInstance, MakeIntResource(IDD_DFSRCDEMO), 0, @DFSrcDemo_Proc);<br>end.