核心 API 流程
- `DragAcceptFiles(hWnd, TRUE)` 啟用拖放 (在 `WM_CREATE`)。
- `WM_DROPFILES`:`wParam` 為 `HDROP`,呼叫 `DragQueryFile` 列舉檔案、`DragQueryPoint` 取得滑鼠位置。
- `DragFinish(hDrop)` 釋放資源 (在 `WM_DROPFILES` 結束)。
- `DragAcceptFiles(hWnd, FALSE)` 關閉 (在 `WM_DESTROY`)。
完整 WinMain + 視窗程式 (精簡)
#include
#include // DragQueryFile, DragFinish, etc.
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
HDC hDC;
switch (uMsg) {
case WM_CREATE:
DragAcceptFiles(hWnd, TRUE);
break;
case WM_DROPFILES: {
HDROP hDrop = (HDROP)wParam;
hDC = GetDC(hWnd);
// 顯示檔案資訊 (見下方 ShowFileInfo)
ShowFileInfo(hWnd, hDC, hDrop);
DragFinish(hDrop);
ReleaseDC(hWnd, hDC);
break;
}
case WM_DESTROY:
DragAcceptFiles(hWnd, FALSE);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
// 顯示檔案名、類型、圖示
BOOL ShowFileInfo(HWND hWnd, HDC hDC, HDROP hDrop) {
POINT pt; DragQueryPoint(hDrop, &pt);
UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
if (nFiles > 1) { /* 顯示「多檔案」文字 */ return FALSE; }
char szFile[MAX_PATH];
DragQueryFile(hDrop, 0, szFile, MAX_PATH);
SHFILEINFO sfi;
SHGetFileInfo(szFile, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_TYPENAME);
char szBuf[1024];
wsprintf(szBuf, "Name: %s Type: %s", sfi.szDisplayName, sfi.szTypeName);
HICON hIcon = ExtractIcon(GetWindowLong(hWnd, GWL_HINSTANCE), szFile, 0);
if (hIcon && hIcon != (HICON)1) {
DrawIcon(hDC, pt.x, pt.y, hIcon);
TextOut(hDC, pt.x, pt.y+32, szBuf, lstrlen(szBuf));
} else {
TextOut(hDC, pt.x, pt.y, szBuf, lstrlen(szBuf));
}
return TRUE;
}
關鍵點
- 無需 MFC/VCL,純 SDK 即可實現拖放。
- `DragQueryFile(hDrop, 0xFFFFFFFF, ...)` 取得檔案總數。
- `SHGetFileInfo` 取得顯示名稱、類型名稱、系統圖示。
- `ExtractIcon` 取得檔案關聯圖示 (索引 0 為預設大圖示)。