当前位置:编程学习 > C/C++ >>

MFC单文档实现文件拖拽功能

其实实现的原理很简单,就是让程序响应和处理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函数的末尾添加一条函数调用


[cpp]
DragAcceptFiles(TRUE);//支持文件拖拽 

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的消息处理函数:
[cpp]
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 < nFileNum; i++)  //支持同时拖拽多个文件  
    {   
        DragQueryFile(hDropInfo, i, strFileName, MAX_PATH);//获得拖曳的文件名    
        m_vetFileNames.push_back(strFileName); //m_vetFileNames是一个文档类中的成员变量,std::vector<CString> 保存文件名   
    }   
    DragFinish(hDropInfo);      //释放hDrop ,销毁系统为存储拖拽文件的文件名所开辟的内存块  
 
    Invalidate(TRUE);//让窗口无效,重绘  
    CView::OnDropFiles(hDropInfo); 

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 < nFileNum; i++)  //支持同时拖拽多个文件
 { 
  DragQueryFile(hDropInfo, i, strFileName, MAX_PATH);//获得拖曳的文件名 
  m_vetFileNames.push_back(strFileName); //m_vetFileNames是一个文档类中的成员变量,std::vector<CString> 保存文件名
 } 
 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中处理[cpp] view plaincopyprint?void CDragFilesView::OnDraw(CDC* pDC)     void CDragFilesView::OnDraw(CDC* pDC) [cpp] view plaincopyprint?{  {[cpp] view plaincopyprint?    CDragFilesDoc* pDoc = GetDocument();      ASSERT_VALID(pDoc);      if (!pDoc)          return;        // TODO: 在此处为本机数据添加绘制代码       std::vector<CString>::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;      }  }   CDragFilesDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if (!pDoc)
  return;

 // TODO: 在此处为本机数据添加绘制代码
 std::vector<CString>::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;
 }
}最后执行效果:


\

 
  
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,