NO IMAGE

    現在有很多軟體都支援拖拽功能,就是用滑鼠拖著檔案放到軟體視窗中某個位置,軟體就可以做出相應的反應。比如,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!要不,上面寫的那些程式碼是不起作用的!