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] = " "将字符串的最后一个字符设为" "结束符。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
