CMyMultiOfn クラスの構成の概略

全体の見通しをよくするために、実際のコーディングと構成が異なっています。

////////////////////////////////////////////////////////////////////////
// MyMultiOfn.h
//

#ifndef _MYMULTIOFN_H_
#define _MYMULTIOFN_H_

#include "windows.h"
#include "tchar.h"
#include "commdlg.h"
#include "dlgs.h"
#include "cderr.h"

class CMyMultiOfn
{
public:
CMyMultiOfn ( ) ;
~CMyMultiOfn ( ) ;
GetOpenFileName ( ) ;

OPENFILENAME m_ofn ;
LPTSTR m_lpstrNewFile ; /* NT 系でバッファーサイズが不足した場合に、臨時にバッファーをこのポインターに確保する */
} ;

CMyMultiOfn multiOfn ;

#endif // _MYMULTIOFN_H_ :


////////////////////////////////////////////////////////////////////////
// MyMultiOfn.cpp
//

#include "MyMultiOfn.h"


// ファイル開くダイアログの終了直前にバッファーサイズの調整を行う関数
static void MyOfnResizeBuffer ( ) ;

/*--- ウィンドプロシージャ ---------------------------------------*/
// OPENFILENAME::lpfnHook メンバーでフックしたダイアログ
static UINT CALLBACK MyOfnChildDlgProc ( HWND, UINT, WPARAM, LPARAM ) ;
// ファイル開くダイアログの一番親のダイアログ
static UINT CALLBACK MyOfnMainProc ( HWND, UINT, WPARAM, LPARAM ) ;
// ファイル開くダイアログのリストビュー
static LRESULT CALLBACK MyOfnListProc ( HWND, UINT, WPARAM, LPARAM ) ;
// ファイル開くダイアログのエディットコンロトール
static LRESULT CALLBACK MyOfnEditProc ( HWND, UINT, WPARAM, LPARAM ) ;

/*--- デフォルトのウィンドプロシージャ -------------------------------*/
static DLGPROC MyOfnMainDlgOldProc ;
static WNDPROC MyOfnListOldProc ;
static WNDPROC MyOfnEditOldProc ;

/***********************************************************************
コンストラクタ ***********************************************************************/

CMyMultiOfn::CMyMultiOfn ( )
{ m_lpstrNewFile = NULL ;

// OPENFILENAME 構造体の初期化処理
ZeroMemory ( &m_ofn, sizeof ( OPENFILENAME ) ;
m_ofn.lStructSize = sizeof ( OPENFILENAME ) ;
m_ofn.hInstance = GetModuleHandle ( NULL ) ;
m_ofn.nMaxFile = MAX_PATH ;
m_ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_ENABLEHOOK ;
m_ofn.lpfnHook = MyOfnChildDlgProc ;
}

/***********************************************************************
デストラクタ ***********************************************************************/

CMyMultiOfn::~CTlMultiOfn ( )
{ if ( m_ofn.lpstrFile ) delete [] m_ofn.lpstrFile ;
if ( m_lpstrNewFile ) delete [] m_lpstrNewFile ;
}

/***********************************************************************
ファイル開くダイアログを呼び出す関数 ***********************************************************************/

void CMyMultiOfn::GetOpenFileName ( )
{ DWORD nError ;

// 初期のバッファーを確保する
if ( !m_ofn.lpstrFile ) if ( ! ( m_ofn.lpstrFile = new TCHAR [m_ofn.nMaxFile] ) )
throw CDERR_MEMALLOCFAILURE ;

// ファイル開くダイアログを呼び出す
if ( ::GetOpenFileName ( &m_ofn ) )
return ;

// エラー処理
nError = ::CommDlgExtendedError ( ) ;

if ( nError == FNERR_BUFFERTOOSMALL && m_lpstrNewFile ) {
/* ここに m_ofn.lpstrFile のポイント先を m_lpstrNewFile に変更する処理を記述 */

} else {
throw nError ;

}
}

/***********************************************************************
OPENFILENAME::lpfnHook メンバーでフックしたダイアログプロシージャ ***********************************************************************/

UINT CALLBACK MyOfnChildDlgProc ( HWND hWnd, UINT wm, WPARAM wp, LPARAM lp )
{ switch ( wm ) {

case WM_INITDIALOG: /* ここに親ダイアログをサブクラス化する処理を記述 */
break ;

case WM_NOTIFY:
switch ( ( ( LPOFNOTIFY ) lp ) -> hdr.code ) {

case CDN_FOLDERCHANGE:
/* ここにエディットコントロールの表示をクリアする処理と、リストコントロールのハンドルが変化していればサブクラス化し直す処理とを記述 */
break ;

case CDN_INITDONE: /* ここにユーザー入力を禁止するためにエディットコントロールをサブクラス化する処理を記述 */
break ;
}
}
return FALSE ;
}

/***********************************************************************
ファイル開くダイアログの一番親のダイアログプロシージャ ***********************************************************************/

UINT CALLBACK MyOfnMainProc ( HWND hWnd, UINT wm, WPARAM wp, LPARAM lp )
{ switch ( wm ) {

case WM_DESTROY:
/* ここに元のプロシージャに戻す処理を記述 */
break ;

case WM_COMMAND:

if ( LOWORD ( wp ) == IDOK ) /* ファイル開くダイアログの終了直前にバッファーサイズ調整を行う */
MyOfnResizeBuffer ( ) ;
break ;
}
return CallWindowProc ( ( WNDPROC ) MyOfnMainOldProc, hWnd, wm, wp, lp ) ;
}

/***********************************************************************
ファイル開くダイアログのリストビュー ウィンドウプロシージャ ***********************************************************************/

LRESULT CALLBACK MyOfnListProc ( HWND hWnd, UINT wm, WPARAM wp, LPARAM lp )
{ switch ( wm ) {

case WM_DESTROY:
/* ここに元のプロシージャに戻す処理を記述 */
break ;

case WM_KEYDOWN:
if ( ( int ) wp == VK_RETURN ) /* ファイル開くダイアログの終了直前にバッファーサイズ調整を行う */
MyOfnResizeBuffer ( ) ;
break ;
}
return CallWindowProc ( MyOfnListOldProc, hWnd, wm, wp, lp ) ;
}

/***********************************************************************
ファイル開くダイアログのエディット ウィンドウプロシージャ ***********************************************************************/

LRESULT CALLBACK MyOfnEditProc ( HWND hWnd, UINT wm, WPARAM wp, LPARAM lp )
{ switch ( wm ) {

case WM_DESTROY:
/* ここに元のプロシージャに戻す処理を記述 */
break ;

case WM_KEYDOWN:
case WM_CHAR:
case WM_PASTE:
/* TRUE を返してユーザー入力を禁止する */
return TRUE ;
}
return CallWindowProc ( MyOfnEditOldProc, hWnd, wm, wp, lp ) ;
}

/***********************************************************************
ファイル開くダイアログの終了直前にバッファーサイズ調整を行う関数 ***********************************************************************/

void MyOfnResizeBuffer ( )
{ /* ここに必要なバッファーサイズを求める処理を記述 */
DWORD nRequestSize = 0 ;

if ( nRequestSize < multiOfn->m_ofn.nMaxFile ) { /* バッファーサイズが小さ過ぎた場合の処理 */
/*
( 1 ) 新たなバッファーを multiOfn->m_lpstrNewFile に確保する処理

( 2 ) ::GetVersionEx を使って Windows 9X 系か NT 系か判定する
9X 系 : 新バッファーを OPENFILENAME::lpstrFile メンバーのポイント先とする
NT 系 : 新バッファーにパスとファイル名を格納し、書式を整える
*/
}
}