作者:ryan__bug | 来源:互联网 | 2023-10-12 14:47
其实实现的原理很简单,就是让程序响应和处理WM_DROPFILES消息。主要用到三个函数:VOIDDragAcceptFiles(HWNDhWnd,BOOLfAcce
其实实现的原理很简单,就是让程序响应和处理WM_DROPFILES消息。主要用到三个函数:
VOID DragAcceptFiles(
HWND hWnd,
BOOL fAccept
);
UINT DragQueryFile(
HDROP hDrop,
UINT iFile,
LPTSTR lpszFile,
UINT cch
);
VOID DragFinish( HDROP hDrop);
首先我们建立一个MFC的单文档程序,命名为DragFiles
在生成的CDragFilesView类的OnCreate函数的末尾添加一条函数调用
DragAcceptFiles(TRUE);//支持文件拖拽
在MSDN中DragAcceptFiles的描述是这样的
DragAcceptFiles Function
Registers whether a window accepts dropped files.
//注册一个窗口,是否支持拖拽文件
Syntax
VOID DragAcceptFiles(
HWND hWnd,
BOOL fAccept
);
Parameters
-
hWnd
-
The identifier of the window that is registering whether it will accept dropped files.
-
//需要支持拖拽操作的窗口句柄
-
fAccept
-
A value that indicates if the window identified by the
hWnd parameter accepts dropped files. This value is TRUE to accept dropped files or FALSE to discontinue accepting dropped files.
-
一个布尔值,指示是否支持拖拽
Return Value
No return value.
Remarks
An application that calls DragAcceptFiles with the fAccept parameter set to TRUE has identified itself as able to process the WM_DROPFILES message from File Manager.
如果一个应用程序调用了DragAcceptFiles函数并将fAccept参数设置成了TRUE,那么它就指定了自己可以处理来自文件管理器的WM_DROPFILES消息。
Function Information
Minimum DLL Version |
shell32.dll version 4.0 or later |
Custom Implementation |
No |
Header |
shellapi.h |
Import library |
shell32.lib |
Minimum operating systems |
Windows NT 3.1, Windows 95 |
可以看到在调用这个API函数的时候需要包含shellapi.h头文件,并且导入lib文件
#pragma comment(lib,"shell32.lib")
但是我们上面调用的函数只有一个参数,这是因为我们调用的那个函数时MFC封装过得函数,是CWnd类的一个成员函数。包含在atlwin.h 中,底层还是调用上面的那个API函数实现的。
由于文档是覆盖在主窗体上的,所以必须用文档类来处理WM_DROPFILES消息。
接下来我们给文档类添加WM_DROPFILES的消息处理函数:
void CDragFilesView::OnDropFiles(HDROP hDropInfo)
{
// TODO: Add your message handler code here and/or call default
UINT nFileNum = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); // 拖拽文件个数
TCHAR strFileName[MAX_PATH]; //定义一个缓冲区,接收文件名字
for (int i = 0; i {
DragQueryFile(hDropInfo, i, strFileName, MAX_PATH);//获得拖曳的文件名
m_vetFileNames.push_back(strFileName); //m_vetFileNames是一个文档类中的成员变量,std::vector 保存文件名
}
DragFinish(hDropInfo); //释放hDrop ,销毁系统为存储拖拽文件的文件名所开辟的内存块
Invalidate(TRUE);//让窗口无效,重绘
CView::OnDropFiles(hDropInfo);
}
在启动拖拽动作时,操作系统会分配一块内存存储拖拽的文件的信息,并通过一个HDROP类型的句柄把该块内存的地址传递给函数OnDropFiles函数。
然后我们调用DragQueryFile。这个函数的原型是:
UINT DragQueryFile(
HDROP hDrop, //包含拖拽文件的文件名的结构标识
UINT iFile, //拖拽的文件索引,如果是0xFFFFFFFF,那么函数返回拖拽的文件的个数,否则根据索引将文件名字拷贝到lpszFile缓冲区中
LPTSTR lpszFile, //接收文件名的缓冲区,如果是NULL,函数返回缓冲区需要的大小
UINT cch //lpszFile buffer的大小
);
如果iFile设置了0xFFFFFFFF返回拖拽文件的个数,否则返回拷贝文件名的字符数
//为了验证拖拽效果,我们将文件名输出到文档中
//在OnDrow中处理
void CDragFilesView::OnDraw(CDC* pDC)
{
CDragFilesDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码std::vector::iterator pos;int y=0;TEXTMETRIC tm;//系统字体信息结构体pDC->GetTextMetrics(&tm);//获得系统字体信息,为了得到字体高度for(pos=m_vetFileNames.begin();pos!=m_vetFileNames.end();pos++)//将文件名输出{pDC->TextOut(0,y,*pos);y+=tm.tmHeight;}}
最后执行效果: