Version 3.8
MFCとハンドル
「今回は重要だからしっかり聞くようにねー」
『応!!』
「……えっと、まずこれまでをまとめてみましょう。最初はハンドル」
『ウィンドウのとかアイコンのとかあるんだよね』
「そう。ウィンドウもアイコンも、基本的に〈ウィンドウズのもの〉だから、
直接変数として持つことはできなくて、代わりに〈ハンドル〉を使ったんだ
よね」
『そう、HWND とかの変数をAPIに渡したりするんだよね』
「で、ハンドルはとりあえず置いといて」
『おいといて』
「今度はクラスについて考えてみましょう」
『クラスは int や HWND とかと同じ〈型〉ってので、変数を作るもの』
「そうそう。で?」
『えっと、メンバ関数ってゆー関数を持ってて、あとメンバ変数って変数も
持ってるんだよね』
「そんな感じかな。メンバ関数の中から、同じクラスのメンバ変数を使うこ
とができるんだったよね」
『それがこの前したのだよね』
「で、ここでさっきの〈ハンドル〉と組み合わせて考えてみると」
『みると?』
「SetWindow() って関数、憶えてる?」
『ウィンドウの名前変えるの!』
「そう。これのAPIの方は、Ver 3.5( No.30 )で見たように……」
void CCalcDlg::OnBEqual()
{
HWND hWnd;
hWnd = GetSafeHwnd();
::SetWindowText( hWnd, "あいうえお" );
}
「みたいに呼び出したよね」
『で、MFCはVer 3.2( No.27 )でやったよーに』
void CCalcDlg::OnBEqual()
{
SetWindowText( "あいうえお" );
}
『って感じ?』
「そんな感じ。MFCの方は CWnd のメンバ関数 CWnd::SetWindowText()
を呼び出してるわけだけど」
『やっぱ違いは、ウィンドウハンドルを渡すか渡さないかよねー』
「そう、ここが注目点。というわけで、今のMFCの方のプログラムを書い
て」
『下の方のね。コピー&ペーストっと』
「そしたら CWnd::SetWindowText() を呼び出してる行にブレークポイント
をセットして」
『あ、中に入るんだ。この行クリックして、ツールバーの手のひらボタンを
押して、あ、左っかわに丸が出た』
「じゃ、ビルドして実行して【=ボタン】押して」
『ビルドして……ビルド終了、実行してボタン押して、うん、今の行で止ま
ったよ』
「ここまでの手順が分かんないって人は Ver 2.5( No.16 )を見てくださ
いね」
『見てくださーい。で、中にはいるんでしょ?』
「そ。ツールバーから【中カッコに入る】ボタンを押して」
『押すと、CWnd::SetWindowText() の中身に行って……』
(以下 MFCより引用)
void CWnd::SetWindowText(LPCTSTR lpszString)
{
ASSERT(::IsWindow(m_hWnd));
if (m_pCtrlSite == NULL)
::SetWindowText(m_hWnd, lpszString);
else
m_pCtrlSite->SetWindowText(lpszString);
}
(引用 ここまで)
『そうそう、MFCの中で同じ名前のAPIを読んでるんだよね……あ!』
「ん?」
『……なんか術中にはまってるみたいでやだなー』
「何を今さら」
『うー。よーするにこの m_hWnd ってのが注目点ってことねー』
「そ。この関数の中にない変数、ってことは?」
『CWnd のメンバ変数ってこと?』
「そういうこと! APIを呼び出したときは、ウィンドウハンドルを渡し
てました。で、MFCのを呼び出したときに渡さなくてよかったのは」
『代わりに CWnd が渡してくれてたからってこと、か』
「この辺を徹底的に調べておこうか。まずこのプログラム書いて」
void CCalcDlg::OnBEqual()
{
GetSafeHwnd();
}
『あ、もしかして GetSafeHwnd() に入るってこと?』
「そういうこと」
『じゃ、これ書いて、ブレークポイント付けて、ビルドして実行してボタン
押して、止まったから中カッコの中ボタンっと』
(以下 MFCより引用)
_AFXWIN_INLINE HWND CWnd::GetSafeHwnd() const
{ return this == NULL ? NULL : m_hWnd; }
(引用 ここまで)
『??』
「これは分かりやすく書き直すとこうかな」
HWND CWnd::GetSafeHwnd() const
{
return m_hWnd;
}
『ホントにぃ!?』
「う”、まぁかなりはしょっちゃったけどね。でも基本的にはこういうこと」
『CWnd::GetSafeHwnd() からもらってたウィンドウハンドルは、こんなふう
に CWnd の m_hWnd ってメンバ変数をもらってただけってことなのねー』
「だから、APIを呼び出したときも、MFCを使ったときも同じってこと
だね」
『あ、そういえばそうかも』
「とどめに CWnd のクラスの中を見て、m_hWnd があるかチェックしておき
ましょう」
『って、 CWnd のクラスって、つまり class CWnd とかって書かれてるとこ
ってことでしょ。それ見つけろって言うの?』
「じゃ、全文検索を使ってみようか」
『ぜんぶんけんさく?』
「プログラミングしていくといろんなところにいろんなプログラムが散っちゃ
うから、その中から欲しいプログラムを探すための機能がちゃんと付いてい
るわけ」
『あ、そういえばそんなこと前に言ってたね』
「えっと、まずメニューの【編集】−【ファイルから検索】」
【ファイルから検索】ダイアログが表示される。
『この前のフツーの検索に似てるね』
「使い方は似てるかな。まず【検索文字列】は【class CWnd】にして」
『なんかそのまんまね』
「ま、見つからなかったら変えて検索し直せばいいし。あと【検索するフォ
ルダ】をセットして」
『……って、これが分かんないって話じゃなかったっけ?』
「そういえばそうかも。ま、たいがいは」
C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\VC98\MFC
「のフォルダにMFCのファイルがあるから、これにすればいいかな」
『なかったら?』
「自分でインストールしたんだったら、VCのある場所は分かると思うから、
あとはその辺を手当たり次第調べるとか。それと、インストールした時の設
定で〈CD−ROMに置いておく〉を選んだときにはCD−ROMにある場
合もあるかも」
『なんかあいまいねー』
「ま、確実なのはウィンドウズの検索ダイアログで *.cpp ってファイルを
全ドライブから検索することかな。VC98\MFC ってフォルダが見つかったら
それがそうってことで」
『やっぱあいまいねー』
「実際そうかも。ホントのことを言えば、この辺は〈もちろん知ってるよ〉
ってくらいが一番いいんだけどね」
『なんで?』
「それはまたあとで。さ、検索しちゃおう!」
『おー! 【検索フォルダ】をさっきのにして、検索!』
アウトプットウィンドウが開き、次のように表示される。
'class CWnd' を検索中...
c:\(略)\MFC\Include\AFXCMN.H(680): friend class CWnd;
c:\(略)\MFC\Include\AFXSTAT_.H(169):class CWnd;
c:\(略)\MFC\Include\AFXWIN.H(86): class CWnd;
c:\(略)\MFC\Include\AFXWIN.H(1899):class CWnd : public CCmdTarget
c:\P(略)\MFC\Include\AFXWIN.H(3273): friend class CWnd;
5 個、検索されました。
『だって。どれ?』
「最後にセミコロンが付いてないの。付いてないってことは、そのあとにク
ラスの中身があるってことでしょ」
『あ、そっか。えっと【ファイル】−』
「ちょっと待った! ダブルクリックするだけでファイルを開けるから」
『ダブルクリックって、どこを?』
「この検索結果。だから……」
c:\(略)\MFC\Include\AFXWIN.H(1899):class CWnd : public CCmdTarget
「って書かれてる行をダブルクリックするだけでいいわけ」
『へー。よく考えてみると、この仕組みとか、全文検索とか、かなり便利よ
ね……ま、それはともかくダブルクリック!』
AFXWIN.H が開き、その中程が表示される。
(以下 MFCより引用)
class CWnd : public CCmdTarget
{
DECLARE_DYNCREATE(CWnd)
protected:
static const MSG* PASCAL GetCurrentMessage();
// Attributes
public:
HWND m_hWnd; // must be first data member
// (以下略)
(引用 ここまで)
『あ、この HWND m_hWnd; がさっき使ったメンバ変数だよね!』
「そういうこと。ちゃーんと CWnd の中にあったでしょ」
『うん、あったあった!』
「MFCを理解する1番の近道は、こうやって中身を見ること」
『それってもしかしてさっきの話?』
「そうそう。MFCが勝手にしてくれてる、じゃなくて、どんなふうになっ
てるのか見ることで、プログラミングの理解が進むわけ」
『あれほど〈MFCはダメ!〉とか言っといて?』
「ギク、まぁとりあえず一番手っ取り早いし、反面教師ってのもあるし〜」
『ふーん』
「で、ホントは、僕があれこれ言う前に自分で勝手にこういうところ見て欲
しいかなー」
『好奇心旺盛であれ! みたいな?』
「そういうこと!! もちろんMFCだけじゃなく、いろんなライブラリを
見るのが一番だけどね」
/*
Preview Next Story!
*/
『いろんなライブラリって、どんなのがあるの?』
「まー、実際のところMFCほど広まってるのは少ないんだよね」
『つまり他のライブラリは勉強するの難しいってこと?』
「爆発的に広まる気配はあるけどね」
『というわけで次回』
< Version 3.9 ラッパークラス! >
「につづく!!」
『そーゆーんが、MFCから勉強する理由ってこと?』
「MFCだってライブラリのひとつ、こんくらい軽くこなせなきゃね」
『はっ、オチがない!!』
「なくたっていいやん……」