MFC中實現單個控制元件接收拖拽檔案的功能
現在有很多軟體都支援拖拽功能,就是用滑鼠拖著檔案放到軟體視窗中某個位置,軟體就可以做出相應的反應。比如,Windows自帶的播放軟體Windows Media Player,你可以拖著一個媒體檔案放到它的主視窗中,它就會開始播放這個檔案。
怎麼讓自己的軟體也有這個功能呢?
其實,並不是很難,只要讓你需要有拖拽功能的控制元件響應WM_DROPFILES訊息就行了。下面以Edit控制元件和ListBox控制元件為例子來說明。
首先,從CEdit繼承,自定義一個Edit控制元件。在標頭檔案新增如下的訊息響應函式:
afx_msg void OnDropFiles(HDROP hDropInfo);
然後,在cpp檔案中的訊息對映中新增:
ON_WM_DROPFILES()
最後,在cpp檔案中新增OnDropFiles函式的實現,對拖拽的檔案進行處理。下面是完整的程式碼:
// lxEdit.h
class ClxEdit : public CEdit
{
DECLARE_DYNAMIC(ClxEdit)
public:
ClxEdit();
virtual ~ClxEdit();
afx_msg void OnDropFiles(HDROP hDropInfo);
protected:
DECLARE_MESSAGE_MAP()
};
// lxEdit.cpp
#include “stdafx.h”
#include “lxEdit.h”
IMPLEMENT_DYNAMIC(ClxEdit, CEdit)
ClxEdit::ClxEdit()
{ }
ClxEdit::~ClxEdit()
{ }
BEGIN_MESSAGE_MAP(ClxEdit, CEdit)
ON_WM_DROPFILES()
END_MESSAGE_MAP()
void ClxEdit::OnDropFiles(HDROP hDropInfo)
{
// 被拖拽的檔案的檔名
char szFileName[MAX_PATH + 1];
// 得到被拖拽的檔名
DragQueryFile(hDropInfo, 0, szFileName, MAX_PATH);
// 把檔名顯示出來
SetWindowText(szFileName);
CEdit::OnDropFiles(hDropInfo);
}
可以看到,在上面的程式碼中,得到拖拽檔名的是函式DragQueryFile。這是Windows提供的一個API函式,用來得到一次成功的拖拽操作中的檔名。下面是該函式的原型:
// 引數說明:
// hDrop 控制代碼,由訊息傳入。
// iFile 檔案索引。
// 如果該引數值為0xFFFFFFFF,函式返回拖拽操作中的檔案數量。
// 如果該引數值為0到拖拽檔案數量之間的數值,函式將對應索引的檔名拷貝到引數lpszFile所指的字串內。
// lpszFile 存放檔名的字串。如果該引數為NULL,函式返回需要的字串長度。
// cch 存放檔名的字串的長度。
UINT DragQueryFile(HDROP hDrop, UINT iFile, LPTSTR lpszFile, UINT cch);
從上面對函式引數的說明可以看出,該函式支援一次多選多個檔案。就像Windows Media Player一樣,一次多選好幾個檔案拖拽到它的視窗中,它就會按順序播放檔案。下面我就用一個有拖拽功能的ListBox為例,說明怎麼處理一次拖拽多個檔案。
// lxListBox.h
class ClxListBox : public CListBox
{
DECLARE_DYNAMIC(ClxListBox)
public:
ClxListBox();
virtual ~ClxListBox();
afx_msg void OnDropFiles(HDROP hDropInfo);
protected:
DECLARE_MESSAGE_MAP()
};
// lxListBox.cpp
#include “stdafx.h”
#include “lxListBox.h”
IMPLEMENT_DYNAMIC(ClxListBox, CListBox)
ClxListBox::ClxListBox()
{ }
ClxListBox::~ClxListBox()
{ }
BEGIN_MESSAGE_MAP(ClxListBox, CListBox)
ON_WM_DROPFILES()
END_MESSAGE_MAP()
void ClxListBox::OnDropFiles(HDROP hDropInfo)
{
char szFileName[MAX_PATH];
int iFileNumber;
// 得到拖拽操作中的檔案個數
iFileNumber = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
for (int i = 0; i < iFileNumber; i++)
{
// 得到每個檔名
DragQueryFile(hDropInfo, i, szFileName, MAX_PATH);
if (FindString(0, szFileName) != LB_ERR)
continue;
// 把檔名新增到list中
AddString(szFileName);
}
CListBox::OnDropFiles(hDropInfo);
}
補充一下,函式DragQueryFile得到的檔名,是帶完整路徑的檔名。
最後,提醒一下:要想你的控制元件具有拖拽功能,一定要把它的Accept Files屬性設定為True!要不,上面寫的那些程式碼是不起作用的!