Version 18.07
ウィンドウプロシージャを純粋仮想関数にする、の続き
「前回は、ダイアログプロシージャを純粋仮想関数にするところまでしまし
た」
『なんかすごく中途半端なところで終わったんだけど』
「プログラム、半分しか紹介しなかったからね。前回のプログラムでは
CDialog クラスに以下の修正をしました」
・DialogProc() メンバ関数を純粋仮想関数に。
・デストラクタを追加。
「 DialogProc() メンバ関数を純粋仮想関数にしたことでメンバ関数の
中身がなくなりました」
『中身がなくても呼べるんだから不思議よねぇ』
// ダイアログプロシージャ(形式上)。
BOOL CALLBACK CDialog::DispatchDialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
)
{
// 略
// メンバ関数のダイアログプロシージャを呼び出します。
return
pcDialog->DialogProc ←純粋仮想関数を呼び出しています。
( p_hDlgWnd
, p_uiMessage
, p_wParam
, p_lParam
);
}
「 Version 17.16 ( No.371 ) で説明したように、純粋仮想関数は中身を
派生クラスに作って、そちらを呼び出します」
『つまり、この CDialog クラスだけじゃなくて、別に派生クラス作って継承
させるってわけね』
「そういうこと。そこで、 Version 18.03 ( No.390 ) と同じ方法で
ソースファイルとヘッダーファイルを追加してクラスを追加します。作成す
るファイルは以下の2つです」
・NewCalcDialog.h
・NewCalcDialog.cpp
『追加するクラスは CNewCalcDialog クラスね』
「というわけで、この2つのファイルに以下のプログラムを書いてくださ
い。まず NewCalcDialog.h から」
// NewCalcDialog.h
// CNewCalcDialog クラス。
class CNewCalcDialog : public CDialog
{
public:
// ダイアログプロシージャ。
BOOL DialogProc
( HWND p_hDlgWnd
, UINT p_uiMessage
, WPARAM p_wParam
, LPARAM p_lParam
);
};
『 CNewCalcDialog クラスね。お、ちゃんと CDialog クラスから継承して
る!』
「この CNewCalcDialog クラスは CDialog クラスの派生クラスで、
DialogProc() メンバ関数をオーバーライド、正確には実装しています」
『純粋仮想関数だった DialogProc() メンバ関数に中身作ったわけね』
「その DialogProc() メンバ関数の中身は NewCalcDialog.cpp ファイルに
書きます。それが以下のプログラム」
// NewCalcDialog.cpp
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#include "Dialog.h"
#include "NewCalcDialog.h"
// ダイアログプロシージャ。
BOOL CNewCalcDialog::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 );
// ここで SetWindowLong() していた箇所は
// 削除してください。
return TRUE;
}
}
return FALSE;
}
「 DialogProc() メンバ関数の中身はこれまでと同じなのでそのままコピペ
しても構いません」
『ホントだ、そのまま派生クラスに移動したって感じね』
「最後に、 Main.cpp もちょこっと修正します」
// Main.cpp
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#include "Dialog.h"
#include "NewCalcDialog.h" // ←追加してください。
// WinMain() 。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
// CNewCalcDialog クラスでダイアログを作成します。
CNewCalcDialog cDialog; // ←クラス名を変更してください。
cDialog.DoModal( p_hInstance, IDD_MAIN );
return 0;
}
「修正箇所は2ヶ所。まず NewCalcDialog.h ヘッダーファイルを
インクルードしてください。そのあと、 CDialog クラスの変数を宣言して
いた所を、 CNewCalcDialog クラスに変更してください」
『 CDialog クラスから CNewCalcDialog クラスに切り替えたわけね。それ
って CDialog クラスだと変数作れないから?』
「そう! 純粋仮想関数を持っている CDialog クラスは変数を作ることが
できないんです。だから CNewCalcDialog クラスに変更するわけです」
『なるほどねー』
「修正する所は以上です。ビルドして実行してみて」
『ほい。うん、同じように計算できるよ』
「そう、今回の修正はプログラムの構造を変えただけで、機能は変わってな
いから」
『……でも、じゃあ何のためにやったの?』
「その説明は次回に」
/*
Preview Next Story!
*/
『んー、なんかファイル増えただけで意味なくない?』
「意味はちゃんとあるんです」
『ホントに? つかなんだかクラスが増えて頭こんがらがってきたんだけど』
「 MFC に比べればずっと少ないでしょ」
『え、 MFC に比べればそりゃねぇ……』
「というわけで次回」
< Version 18.08 継承で機能を分けて再利用 >
『につづく!』
「楽しくなると自分で MFC くらいクラス作るようになるから」
『嫌! それはすっごく嫌!』