S-JIS[1998-08-15/2002-12-07]

ファイルのドロップの検出方法

AppWizardで作成したMDIのMFCアプリケーションでは、ファイルのドロップ処理はデフォルトで行われます。
SDIやダイアログベースのMFCアプリケーションでも、ちょっと処理を書いてやるだけで けっこう簡単にファイルのドロップを扱う事が出来ます。

以下、SDIの場合を例にして説明します。 ダイアログの例は後ろにあります。


  1. WM_DROPFILESイベントのハンドラを追加します。

    DropView.h:

    class CDropView : public CView
    {
    〜
    // 生成されたメッセージ マップ関数
    protected:
    	//{{AFX_MSG(CDropView)
    	afx_msg void OnDropFiles(HDROP hDropInfo);
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    〜
    };
    

    DropView.cpp:

    〜
    BEGIN_MESSAGE_MAP(CDropView, CView)
    	//{{AFX_MSG_MAP(CDropView)
    	ON_WM_DROPFILES()
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    〜
    void CDropView::OnDropFiles(HDROP hDropInfo) 
    {
    	// TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください
    
    	CView::OnDropFiles(hDropInfo);
    }
    

  2. しかし、これだけではOnDropFiles()は呼ばれません。呼ばせるような設定をする必要があります。
    下記のような方法があるので、いずれかをコーディングして下さい。

    これで、OnDropFiles()が呼ばれるようになります。


    DragAcceptFiles()を使用する場合

    DropView.h:
    class CDropView : public CView
    {
    〜
    // 生成されたメッセージ マップ関数
    protected:
    	//{{AFX_MSG(CDropView)
    	afx_msg void OnDropFiles(HDROP hDropInfo);
    	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    〜
    };
    

    DropView.cpp:

    〜
    BEGIN_MESSAGE_MAP(CDropView, CView)
    	//{{AFX_MSG_MAP(CDropView)
    	ON_WM_DROPFILES()
    	ON_WM_CREATE()
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    〜
    int CDropView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    	if (CView::OnCreate(lpCreateStruct) == -1)
    		return -1;
    
    	// TODO: この位置に固有の作成用コードを追加してください
    	DragAcceptFiles();
    
    	return 0;
    }
    

    ウィンドウスタイルを変更する場合

    DropView.cpp:
    BOOL CDropView::PreCreateWindow(CREATESTRUCT& cs)
    {
    	// TODO: この位置で CREATESTRUCT cs を修正して Window クラスまたはスタイルを
    	//       修正してください。
    	cs.dwExStyle |= WS_EX_ACCEPTFILES;	//ファイルのドロップを受け付ける
    
    	return CListView::PreCreateWindow(cs);
    }
    

  3. 次に、OnDropFilesの中でドロップされたファイル名を取得する例を示します。

    DropView.cpp:

    void CDropView::OnDropFiles(HDROP hDropInfo) 
    {
    	// TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください
    
    	//ドロップされたファイルの個数を取得
    	UINT uiCount=DragQueryFile(hDropInfo,~0lu,NULL,0);
    
    	for(UINT i=0; i<uiCount; i++){
    		//ファイル名の長さを取得
    		UINT uiLen=DragQueryFile(hDropInfo,i,NULL,0);
    
    		//ファイル名を取得
    		CString name;
    		DragQueryFile(hDropInfo,i,name.GetBuffer(uiLen+1),uiLen+1);
    		name.ReleaseBuffer();
    
    		//name(ファイル名)を使って何らかの処理を行う
    〜
    	}
    
    //	CView::OnDropFiles(hDropInfo);	//必要ないと思われるので呼ばない
    }
    
    ただし、ディレクトリがドロップされた場合、そのディレクトリは ひとつのファイルとして扱われるので注意が必要です。

DragAcceptFiles関数はCWndクラスのメンバーなので、 ドロップ操作はCWndの派生クラス、すなわちフレームやダイアログで行う事が出来ます。

しかし、ダイアログではClassWizardでWM_DROPFILESが表示されないので、 自分でコーディングする必要があります。
また、初期化としてOnInitDialog関数が呼ばれるので、 OnCreateでなくOnInitDialogでDragAcceptFiles()を呼び出すといいでしょう。

DropDlg.cpp:

BOOL CDropDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
〜
	// TODO: 特別な初期化を行う時はこの場所に追加してください。
	DragAcceptFiles();

	return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

[1998-08-22]
しかし、ダイアログの場合、DragAcceptFiles()を呼ばないで済む方法があります。
ダイアログのリソースのプロパティーを開き、「拡張スタイル」タブの「ドラッグアンドドロップを許可」に チェックを付けるだけです。


VC++ページへ戻る / 技術メモへ戻る
メールの送信先:ひしだま