第2章 テキストの表示 その1


今回は、前回作ったウィンドウにテキストを表示してみます。 SDKでは、どうやったかというとWM_PAINTメッセージを捕まえて 描画をしました。MFCではどうするのでしょうか。 いろいろ説明するよりサンプルを見た方が早いです。

// 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()

CMyWindowというのは、自分で作ったクラスです。 どこから派生させたかというとCFrameWndクラスという既成の クラスです。(しばらくの間はたいていここから派生させます) コンストラクタの次にOnPaintというメンバ関数が宣言されています。 SDKでWM_何とかというメッセージを処理する関数は On何とかというメンバ関数が用意されています。 OnPaint関数はCWndクラスのメンバ関数です。CFrameWndクラスは CWndクラスから派生しています。このへんはヘルプの「階層図」を 見るとわかります。

次に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::CMyWindow() { Create(NULL, "猫でもわかるMFC", WS_OVERLAPPEDWINDOW, CRect(100, 100, 100+270, 100+85)); }

自分で作ったクラスCMyWindowのコンストラクタです。 前章ではCreate関数の引数は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 );

これは、CFrameWndクラスのメンバ関数で3番目以降の 引数にはデフォルトが指定されています。

lpszClassNameには、クラス名を指定します。NULLの時は デフォルトのCFrameWnd属性が自動的に使われます。

lpszWindowNameには、タイトルバーに表示するテキストを指定します。

dwStyleはウィンドウスタイルを指定します。

rectには、ウィンドウの位置、大きさを指定します。

pParentWndには、親ウィンドウを指定します。 自分が親の時はNULLです。

lpszMenuNameにはメニューリソースの名前を指定します。

dwExStyleには、拡張ウィンドウスタイルを指定します。

pContextには、CCreateContext構造体のポインタを指定します。

なんかこれ、APIのCreateWindow関数と似ているな・・

はい、そうです。たいていのメンバ関数はAPI関数と殆ど同じ働きをします。

さて、サンプルではCreate()関数の4番目の引数をいきなり

CRect(100, 100, 100+270, 100+85)

としたのでわかりにくいかもしれませんが、 次のように書いても同じです。

CRect MyRect(100, 100, 100+270, 100+85); Create(NULL, "猫でもわかるMFC", WS_OVERLAPPEDWINDOW, MyRect);

CRectクラスはRECT構造体と同じです。 いろいろ便利な演算子があります。

void CMyWindow::OnPaint() { CPaintDC dc(this); dc.TextOut(20, 20, "猫でもわかるプログラミング", 26); }

さて、いよいよWM_PAINTメッセージの処理ですが SDKで書いたときはデバイスコンテキストハンドルが必要でした。 ここではCPaintDCクラスからdcオブジェクトを作成します。 CPaintDCオブジェクトは通常WM_PAINTメッセージの処理の時のみ 使います。また、CPaintDCクラスの派生元のCDCクラスは描画に関係する 多数のメンバ関数を持っています。

ところで、BeginPaint()とか、EndPaint()関数はどうしたの?

はい、CPaintDCクラスが勝手にやってくれています。 正確にはクラスの構築時にBeginPaint関数を消滅時にEndPaint関数を 実行してくれています。

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;

このところは前回と全く同じです。 ウィンドウの初期化関係です。


さて、今回はクライアント領域にテキストを表示するだけの簡単なものでした。 では、クライアント領域を左クリックするとクリックされた旨 メッセージボックスを出すにはどうしたらよいのでしょうか。


[MFC Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 06/Jan/1998 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。