win32 API實現檔案拖拽開啟
阿新 • • 發佈:2019-01-25
在windows中,我們開啟一個文字檔案後,可以將另一個文字檔案拖拽進來,從而實現開啟此檔案。那麼這個功能是怎麼實現的呢?
經過一下午的實踐,現將具體程式碼分享如下:
#include <windows.h> #define ID_EDIT 1 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName[] = TEXT ("記事本") ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 700, 500,//設定寬和高 NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } VOID read_file(HWND hwnd,TCHAR* szFileName){ TCHAR* chBuffer; //緩衝區 int file_size; long dwReadSize = 0; //實際讀取字元數 HWND hEdit = GetDlgItem(hwnd,ID_EDIT); HANDLE hFile = CreateFile(szFileName, //建立檔案的名稱。 GENERIC_READ, // 讀檔案。 0, // 不共享讀寫。 NULL, // 預設安全屬性。 OPEN_EXISTING, // 如果檔案存在。 FILE_ATTRIBUTE_NORMAL, // 一般的檔案。 NULL); // 模板檔案為空。 if (hFile == INVALID_HANDLE_VALUE) { OutputDebugString(TEXT("CreateFile fail!\r\n")); } file_size = GetFileSize(hFile,NULL); chBuffer = (TCHAR*)malloc(file_size*sizeof(TCHAR) +1);//多分配一字元用於儲存'\0' ReadFile(hFile,chBuffer,file_size,&dwReadSize,NULL); chBuffer[file_size] = '\0'; SetWindowText(hEdit,chBuffer); CloseHandle(hFile); free(chBuffer); } VOID OnDropFiles(HWND hwnd, HDROP hDropInfo) { // UINT nFileCount = DragQueryFile(hDropInfo, (UINT)-1, NULL, 0); //查詢一共拖拽了幾個檔案 TCHAR szFileName[MAX_PATH] = TEXT(""); DragQueryFile(hDropInfo, 0, szFileName, sizeof(szFileName)); //開啟拖拽的第一個(下標為0)檔案 read_file(hwnd,szFileName); //完成拖入檔案操作,系統釋放緩衝區 DragFinish(hDropInfo); } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndEdit ; switch (message) { case WM_CREATE : hwndEdit = CreateWindow (TEXT ("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL, 0, 0, 0, 0, hwnd, (HMENU) ID_EDIT, ((LPCREATESTRUCT) lParam) -> hInstance, NULL) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndEdit) ; return 0 ; case WM_SIZE : //設定子視窗的大小與父視窗相同 MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ; return 0 ; case WM_COMMAND : if (LOWORD (wParam) == ID_EDIT) if (HIWORD (wParam) == EN_ERRSPACE || HIWORD (wParam) == EN_MAXTEXT) MessageBox (hwnd, TEXT ("Edit control out of space."), szAppName, MB_OK | MB_ICONSTOP) ; return 0 ; case WM_DROPFILES: OnDropFiles(hwnd, (HDROP)wParam); return 0; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }
此程式手動實現了一個簡單的記事本功能,最重要的是實現了拖拽開啟文字檔案的功能。該程式比起普通的win32程式來說,有幾點不同。
1,採用CreateWindowEx(傳統的CreateWindow缺少一個style的引數),並指定WS_EX_ACCEPTFILES風格。
2,通過DragQueryFiles取得拖拽檔案的檔名,CreateFile、GetFileSize、ReadFile實現讀取檔案內容,並存儲在一個動態的字串指標中。DragQueryFiles的引數形式如下:
此函式用來獲取拖放的檔名。UINT DragQueryFile(HDROP hDrop, UINT iFile, LPTSTR lpszFile, UINT cch);
(1)hDrop是WM_DROPFILES訊息的wParam引數;
(2)設定iFile=0xFFFFFFFF的話,此函式返回拖放的檔案總數,記為count。設定iFile為區間[0, count)之間的任一整數就可以在lpszFile中得到序號為iFile的檔名,這個序號和使用者在shell中點選檔案圖示的順序有關;
(3)cch是該緩衝區的大小;
(4)lpszFile是用於容納檔名的緩衝區,此檔名包含檔案路徑。
3,SetWindowText設定文字內容時,要通過chBuffer[file_size] = '\0'將字串的最後一個字元設為'\0'結束符。