理论:
拖放,是指用鼠标拖动的方法,在不同程序的窗口之间、同 一个程序的不同窗口之间或同一程序同一窗口的不同控件之间,进行移动、复制和粘贴等操作的技术。拖放操作是在操作系统的帮助下完成的。被拖动的对象首先向 操作系统注册它使用的数据格式,并按指定的数据格式提供数据,拖放操作结束时,接收拖放的窗口按指定的数据格式提取有关数据,并根据提取的数据生成相应的 对象。
拖放有两种类型:OLE拖放和文件管理器拖放。这两种方式是完全不同的机制。文件管理器拖放只能处理文件名,通过映射目的窗口的WM_DROPFILES消息,窗口就可以收到拖放进来的文件名。OLE拖放则更加通用一些,它允许你拖放可同时被保存在剪贴板上的任何数据。本文只介绍下文件管理器拖放。
这种方式的实质就是产生一个消息WM_DROPFILES。技术上没有什么难点,主要用到下面几个API函数:DragQueryFile、DragQueryPoint、DragFinish。它们的原型和注解分别如下:
代码:见光盘DragDrop
#include "windows.h"
/***************************************************************/
char title[] = "This is the file you dropped into the window";
char szClassName[] = "Project_Class";
char szDisplayName [] = "Drag and Drop a file into this window";
HWND g_hWnd;
HINSTANCE g_hInstance;
HICON g_hIcon;
DWORD TopXY(DWORD wDim, DWORD sDim);
void Paint_Proc(HWND hWin,HDC hDC);
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
/***************************************************************/
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wc;
MSG msg;
DWORD Wwd;
DWORD Wht;
DWORD Wtx;
DWORD Wty;
g_hInstance = hInstance;
g_hIcon = LoadIcon(g_hInstance,MAKEINTRESOURCE(500));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIcon = g_hIcon;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hIconSm = g_hIcon;
RegisterClassEx(&wc);
Wwd = 300;
Wht = 300;
Wtx = TopXY(Wht,GetSystemMetrics(SM_CXSCREEN));
Wty = TopXY(Wht,GetSystemMetrics(SM_CYSCREEN));
g_hWnd = CreateWindowEx(WS_EX_LEFT|WS_EX_ACCEPTFILES,
szClassName,szDisplayName,WS_OVERLAPPED | WS_SYSMENU,Wtx,
Wty,Wwd,Wht,NULL,NULL,hInstance,NULL);
ShowWindow(g_hWnd,SW_SHOWNORMAL);
UpdateWindow(g_hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
RECT Rct;
HDC hDC;
PAINTSTRUCT ps;
char buffer1[128];
switch(uMsg)
{
case WM_DROPFILES:
DragQueryFile((HDROP)wParam,0,buffer1,128);
MessageBox(hwnd,buffer1,title,MB_OK);
DragFinish((HDROP)wParam);
break;
case WM_PAINT:
hDC = BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&Rct);
DrawText(hDC,szDisplayName,lstrlen(szDisplayName),&Rct,DT_LEFT);
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
DWORD TopXY(DWORD wDim, DWORD sDim)
{
sDim = (sDim - wDim)/2;
return sDim;
}
分析:
代码比较简单,首先在创建窗口时,加入WS_EX_ACCEPTFILES 风格。这样窗口就可以接受拖放操作了。
g_hWnd = CreateWindowEx(WS_EX_LEFT|WS_EX_ACCEPTFILES,
szClassName,szDisplayName,WS_OVERLAPPED | WS_SYSMENU,Wtx,
Wty,Wwd,Wht,NULL,NULL,hInstance,NULL);
当有文件拖放到窗口时,窗口会收到消息WM_DROPFILES。我们在这个消息中,进行拖放处理就可以了。
case WM_DROPFILES:
DragQueryFile((HDROP)wParam,0,buffer1,128);
MessageBox(hwnd,buffer1,title,MB_OK);
DragFinish((HDROP)wParam);
break;
运行此程序可以看到,拖动的文件只要一进入对话框的边界,鼠标上立刻会现一个“+”,在对话框上的任意位置释放鼠标,拖放的文件都会被接受。
拖放,是指用鼠标拖动的方法,在不同程序的窗口之间、同 一个程序的不同窗口之间或同一程序同一窗口的不同控件之间,进行移动、复制和粘贴等操作的技术。拖放操作是在操作系统的帮助下完成的。被拖动的对象首先向 操作系统注册它使用的数据格式,并按指定的数据格式提供数据,拖放操作结束时,接收拖放的窗口按指定的数据格式提取有关数据,并根据提取的数据生成相应的 对象。
拖放有两种类型:OLE拖放和文件管理器拖放。这两种方式是完全不同的机制。文件管理器拖放只能处理文件名,通过映射目的窗口的WM_DROPFILES消息,窗口就可以收到拖放进来的文件名。OLE拖放则更加通用一些,它允许你拖放可同时被保存在剪贴板上的任何数据。本文只介绍下文件管理器拖放。
这种方式的实质就是产生一个消息WM_DROPFILES。技术上没有什么难点,主要用到下面几个API函数:DragQueryFile、DragQueryPoint、DragFinish。它们的原型和注解分别如下:
UINT DragQueryFile(HDROP hDrop, UINT iFile, LPTSTR lpszFile, UINT cch)
本函数用来取得拖放的文件名。其中,hDrop是一个指向含有被拖放的文件名的结构体的句柄;iFiles是要查询的文件序号,因为一次可能同时拖动很多个文件;lpszFiles是出口缓冲区指针,保存iFiles指定序号的文件的路径名,cch指定该缓冲区的大小。有两点值得注意,第一,如果我们在调用该函数的时候,指定iFile为0xFFFFFFFF,则DragQueryFile将忽略lpszFile和cch参数,返回本次拖放操作的文件数目;第二,如果指定lpszFile为NULL,则函数将返回实际所需的缓冲区长度。
BOOL DragQueryPoint(HDROP hDrop, LPPOINT lppt);
本函数用来获取,当拖放操作正在进行时,鼠标指针的位置。第二个参数lppt是一个指向POINT结构体的指针,用来保存文件放下时,鼠标指针的位置。窗口可以调用该函数以查询文件是否落在自己的窗口矩形中。
void DragFinish(HDROP hDrop);
当拖放操作处理完毕后需调用该函数释放系统分配来传输文件名的内存。代码:见光盘DragDrop
#include "windows.h"
/***************************************************************/
char title[] = "This is the file you dropped into the window";
char szClassName[] = "Project_Class";
char szDisplayName [] = "Drag and Drop a file into this window";
HWND g_hWnd;
HINSTANCE g_hInstance;
HICON g_hIcon;
DWORD TopXY(DWORD wDim, DWORD sDim);
void Paint_Proc(HWND hWin,HDC hDC);
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
/***************************************************************/
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wc;
MSG msg;
DWORD Wwd;
DWORD Wht;
DWORD Wtx;
DWORD Wty;
g_hInstance = hInstance;
g_hIcon = LoadIcon(g_hInstance,MAKEINTRESOURCE(500));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIcon = g_hIcon;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hIconSm = g_hIcon;
RegisterClassEx(&wc);
Wwd = 300;
Wht = 300;
Wtx = TopXY(Wht,GetSystemMetrics(SM_CXSCREEN));
Wty = TopXY(Wht,GetSystemMetrics(SM_CYSCREEN));
g_hWnd = CreateWindowEx(WS_EX_LEFT|WS_EX_ACCEPTFILES,
szClassName,szDisplayName,WS_OVERLAPPED | WS_SYSMENU,Wtx,
Wty,Wwd,Wht,NULL,NULL,hInstance,NULL);
ShowWindow(g_hWnd,SW_SHOWNORMAL);
UpdateWindow(g_hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc( HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
RECT Rct;
HDC hDC;
PAINTSTRUCT ps;
char buffer1[128];
switch(uMsg)
{
case WM_DROPFILES:
DragQueryFile((HDROP)wParam,0,buffer1,128);
MessageBox(hwnd,buffer1,title,MB_OK);
DragFinish((HDROP)wParam);
break;
case WM_PAINT:
hDC = BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&Rct);
DrawText(hDC,szDisplayName,lstrlen(szDisplayName),&Rct,DT_LEFT);
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}
DWORD TopXY(DWORD wDim, DWORD sDim)
{
sDim = (sDim - wDim)/2;
return sDim;
}
分析:
代码比较简单,首先在创建窗口时,加入WS_EX_ACCEPTFILES 风格。这样窗口就可以接受拖放操作了。
g_hWnd = CreateWindowEx(WS_EX_LEFT|WS_EX_ACCEPTFILES,
szClassName,szDisplayName,WS_OVERLAPPED | WS_SYSMENU,Wtx,
Wty,Wwd,Wht,NULL,NULL,hInstance,NULL);
当有文件拖放到窗口时,窗口会收到消息WM_DROPFILES。我们在这个消息中,进行拖放处理就可以了。
case WM_DROPFILES:
DragQueryFile((HDROP)wParam,0,buffer1,128);
MessageBox(hwnd,buffer1,title,MB_OK);
DragFinish((HDROP)wParam);
break;
运行此程序可以看到,拖动的文件只要一进入对话框的边界,鼠标上立刻会现一个“+”,在对话框上的任意位置释放鼠标,拖放的文件都会被接受。