Version 18.03
ダイアログプロシージャを static メンバ関数にする
「さて、前回説明したプログラムは API だけで作ってあるわけですが、こ
れをクラスで作っていきます」
『 MFC がそうだからできる、っていうのは分かるんだけど、なんかイメージ
掴めない……』
「そのための練習だしね。さて、まずヘッダーファイルを作成します。
メニューの【ファイル】-【新規作成】を選んでください」
『いつものだね』
「左の欄で【C/C++ ヘッダー ファイル】を選択して、ファイル名は Dialog.h
にしてください」
『ほい』
「で、この中に以下のように書いてください」
// Dialog.h
// Dialog クラス。
class CDialog
{
public:
static BOOL CALLBACK DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
);
};
『 CDialog クラス作るんだね』
「この CDialog クラスが、ダイアログの基本クラスになります。このクラス
の DialogProc() メンバ関数が前回の DialogProc() 関数」
『つまり普通の関数を CDialog クラスのメンバ関数にするってことね』
「そういうこと。で、このメンバ関数が static メンバ関数っていう点に注
意して」
↓これ
static BOOL CALLBACK DialogProc
『そか、確か普通の関数の代わりに static メンバ関数が使えるって言って
たね』
「 Version 16.28 ( No.355 ) で説明したように普通の関数、特に
コールバック関数の代わりにすることができるんです。
ダイアログプロシージャはコールバック関数でしょ」
『 Windows から呼び出される関数だもんね。だから static メンバ関数に
してるの?』
「そういうこと。こうすることで、メンバ関数でも外から呼び出してもらえ
るようになるわけです」
『なるほどねー』
「では次に、このクラスの本体、ソースファイルを作ります。メニューの
【ファイル】-【新規作成】を選んで、左の欄で【C++ ソース ファイル】を
選択して、ファイル名は Dialog.cpp にしてください」
『ほいと』
「で、この中に以下のように書き込んでください」
// Dialog.cpp
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#include "Dialog.h"
// ダイアログプロシージャ。
BOOL CALLBACK CDialog::DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
if( p_uiMessage == WM_COMMAND )
{
if( LOWORD( p_wParam ) == IDOK )
{
// OK ボタンが押されました。
EndDialog( p_hDlgWnd, IDOK );
return TRUE;
}
else if( LOWORD( p_wParam ) == IDC_B_EQUAL )
{
// 各エディットボックスのウィンドウハンドル
// を取得します。
HWND hLeftWnd
= GetDlgItem( p_hDlgWnd, IDC_E_LEFT );
HWND hRightWnd
= GetDlgItem( p_hDlgWnd, IDC_E_RIGHT );
HWND hAnswerWnd
= GetDlgItem( p_hDlgWnd, IDC_E_ANSWER );
// 各エディットボックス用文字列を用意します。
char pchLeft[256];
char pchRight[256];
char pchAnswer[256];
// IDC_E_LEFT と IDC_E_RIGHT の文字列を取得します。
GetWindowText( hLeftWnd, pchLeft, 255 );
GetWindowText( hRightWnd, pchRight, 255 );
// それぞれ int 型に変換します。
int iLeft = atoi( pchLeft );
int iRight = atoi( pchRight );
// 足した結果を pchAnswer に文字列変換します。
sprintf( pchAnswer, "%d", iLeft + iRight );
// それを IDC_E_ANSWER にセットします。
SetWindowText( hAnswerWnd, pchAnswer );
return TRUE;
}
}
return FALSE;
}
「ほとんど DialogProc() 関数と同じ。違うのは、 CDialog クラスの
メンバ関数っていう点だけ」
これが加わった
↓
BOOL CALLBACK CDialog::DialogProc
『これだけでいいんだね』
「そう、それだけで static メンバ関数になります。詳しくは
Version 16.26 ( No.353 ) を参考にしてください」
『 DialogProc() メンバ関数の中身は同じだよね』
「うん、 DialogProc() 関数の時と同じ。ということは、 Main.cpp の
DialogProc() 関数が移動したということなので、以下のように修正します」
// Main.cpp
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#include "Dialog.h"
// ここにあった DialogProc() 関数が、 CDialog クラスの
// メンバ関数になりました。
// WinMain() 。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
int iRet
= DialogBox
( p_hInstance
, MAKEINTRESOURCE( IDD_MAIN )
, NULL
, CDialog::DialogProc
);
return 0;
}
『まず CDialog クラスを使う必要があるので Dialog.h ヘッダーファイルを
インクルードします』
#include "Dialog.h" ←この行が追加されました。
「これでこのソースファイルから CDialog クラスを使うことができます。
次に DialogProc() 関数は CDialog クラスのメンバ関数にしたので削除し
ます」
// ここにあった DialogProc() 関数が、 CDialog クラスの
// メンバ関数になりました。
「最後に、 DialogBox() 関数の第4引数には、 DialogProc() 関数のアドレス
ではなく CDialog クラスの DialogProc() メンバ関数を渡すようにします」
int iRet
= DialogBox
( p_hInstance
, MAKEINTRESOURCE( IDD_MAIN )
, NULL
, CDialog::DialogProc ←ここが変わりました。
);
『この使い方も Version 16.28 ( No.355 ) と同じね』
「そういうこと。つまり、ウィンドウプロシージャみたいなコールバック関数
をメンバ関数にしたい場合には、〈 static メンバ関数〉にすればいいわけ
です」
『そう考えると難しいことじゃないよね』
「うん、今回は正式な方法で、ってことでソースファイルやヘッダーファイル
を作ったから複雑になったかもしれないけど、それを別にすれば、単に普通の
関数を static メンバ関数にしただけだから」
『……それってメリットあるの?』
「う”、今回だけだとほとんどメリットないかも」
/*
Preview Next Story!
*/
『むー、無駄教えられたー』
「でもこれは次回への布石だから」
『えー、ホントー? なんかタイトルがそれっぽくないけど』
「というわけで次回」
< Version 18.04 ウィンドウの 32 ビット整数値 >
『につづく!』
「それにこれと同じ方法で WinMain() も static メンバ関数にできるよ?」
『してどうするの?』
「うーん」