win32 API实现文件拖拽打开
在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! ")); } file_size = GetFileSize(hFile,NULL); chBuffer = (TCHAR*)malloc(file_size*sizeof(TCHAR) +1);//多分配一字符用于存储" " ReadFile(hFile,chBuffer,file_size,&dwReadSize,NULL); chBuffer[file_size] = " "; 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] = " "将字符串的最后一个字符设为" "结束符。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。