CMyWindowというのは、自分で作ったクラスです。 どこから派生させたかというとCFrameWndクラスという既成の クラスです。(しばらくの間はたいていここから派生させます) コンストラクタの次にOnPaintというメンバ関数が宣言されています。 SDKでWM_何とかというメッセージを処理する関数は On何とかというメンバ関数が用意されています。 OnPaint関数はCWndクラスのメンバ関数です。CFrameWndクラスは CWndクラスから派生しています。このへんはヘルプの「階層図」を 見るとわかります。// skelton2.cpp // 手書きMFCの第1歩 #include <afxwin.h> class CMyWindow : public CFrameWnd { public: CMyWindow(); afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; BEGIN_MESSAGE_MAP(CMyWindow, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP()
次にafx_msgという何だかわからんものがついていますが、 これは無視してかまいません。コンパイル時にはコンパイラが 自動的に取り去ってしまいます。(従って初めから書かなくても良い)
DECLARE_MESSAGE_MAP()はマクロです。このクラスではメッセージマップを 使いますよ、という宣言です。メッセージマップとは メッセージに対してウィンドウはどのように対処すべきかを指示するところです。
BEGIN_MESSAGE_MAP(CMyWindow, CFrameWnd)とEND_MESSAGE_MAP() のマクロに挟まれたところがメッセージマップです。この間に書かれたものが メッセージマップエントリと言われるものです。
CWndクラスにはOn****()メンバ関数が山ほど定義されていて、ON_メッセージ
の形のメッセージマップエントリと対応しています。
さて、独自のクラスを用意して以上のような手続きを踏むと メッセージを処理できるようになります。1.WM_PAINTメッセージを処理する関数はOnPaint()関数である。 2.これに対応するメッセージマップエントリはON_WM_PAINT()である。 3.ON_WM_PAINT()エントリをメッセージマップに置くとそのクラスで OnPaint()関数を用意しているという意味になる。 4.このOnPaint()メンバ関数はCWndクラスのOnPaint()メンバ関数と 戻り値、引数が同じでなくてはいけない。
自分で作ったクラスCMyWindowのコンストラクタです。 前章ではCreate関数の引数は3つしかありませんでした。CMyWindow::CMyWindow() { Create(NULL, "猫でもわかるMFC", WS_OVERLAPPEDWINDOW, CRect(100, 100, 100+270, 100+85)); }
これは、CFrameWndクラスのメンバ関数で3番目以降の 引数にはデフォルトが指定されています。CFrameWnd::Create(); BOOL Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle = WS_OVERLAPPEDWINDOW, const RECT& rect = rectDefault, CWnd* pParentWnd = NULL, LPCTSTR lpszMenuName = NULL, DWORD dwExStyle = 0, CCreateContext* pContext = NULL );
lpszClassNameには、クラス名を指定します。NULLの時は デフォルトのCFrameWnd属性が自動的に使われます。
lpszWindowNameには、タイトルバーに表示するテキストを指定します。
dwStyleはウィンドウスタイルを指定します。
rectには、ウィンドウの位置、大きさを指定します。
pParentWndには、親ウィンドウを指定します。 自分が親の時はNULLです。
lpszMenuNameにはメニューリソースの名前を指定します。
dwExStyleには、拡張ウィンドウスタイルを指定します。
pContextには、CCreateContext構造体のポインタを指定します。
さて、サンプルではCreate()関数の4番目の引数をいきなり
CRect(100, 100, 100+270, 100+85)
としたのでわかりにくいかもしれませんが、 次のように書いても同じです。
CRectクラスはRECT構造体と同じです。 いろいろ便利な演算子があります。CRect MyRect(100, 100, 100+270, 100+85); Create(NULL, "猫でもわかるMFC", WS_OVERLAPPEDWINDOW, MyRect);
さて、いよいよWM_PAINTメッセージの処理ですが SDKで書いたときはデバイスコンテキストハンドルが必要でした。 ここではCPaintDCクラスからdcオブジェクトを作成します。 CPaintDCオブジェクトは通常WM_PAINTメッセージの処理の時のみ 使います。また、CPaintDCクラスの派生元のCDCクラスは描画に関係する 多数のメンバ関数を持っています。void CMyWindow::OnPaint() { CPaintDC dc(this); dc.TextOut(20, 20, "猫でもわかるプログラミング", 26); }
このところは前回と全く同じです。 ウィンドウの初期化関係です。class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; BOOL CMyApp::InitInstance() { m_pMainWnd = new CMyWindow(); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } CMyApp MyApp;
さて、今回はクライアント領域にテキストを表示するだけの簡単なものでした。
では、クライアント領域を左クリックするとクリックされた旨
メッセージボックスを出すにはどうしたらよいのでしょうか。
Update 06/Jan/1998 By Y.Kumei