それと、今回はWM_LBUTTONDOWNとWM_RBUTTONDOWNメッセージの処理を 行います。右クリックと、左クリックの回数を親ウィンドウの クライアント領域に表示するプログラムを作ります。
スタティックコントロールの部分が色つきになっています。
これが嫌な人はエジットコントロールを使うという手もあります。
では、スタティックコントロールを親ウィンドウに貼り付けるには どうしたらよいでしょうか。これには、いくつかの方法が 考えられます。その中の1つをまず紹介してその後他の方法を解説します。
次に、WM_LBUTTONDOWNとWM_RBUTTONDOWNメッセージの処理は どうしたらよいでしょうか?1.CStaticクラスのポインタを保存する変数を クラスのメンバ変数として宣言する 2.適当なタイミングでnewでオブジェクトを生成して ポインタ変数にそのアドレスを保存する 3.Create()メンバ関数を使ってスタティックコントロールを作成する 4.この時、ウィンドウスタイルは最低限 WS_CHILD | WS_VISIBLE の属性を持たせる 5.newしたものはdeleteする
これも類推から想像できますね。CWndクラスにはWM_何とかメッセージを 受け取ったときに動作するOn何とか関数をメンバに持っていました。 従ってOnLButtonDown()とかOnLButtonDown()関数なんていうのが きっとあるに違いありません。
あ、やっぱりありました。引数のnFlagsはどの仮想キーが 押されたかを示します。pointはマウスの位置ですね。 OnRButtonDown()関数も同じです。 また、引数はSDKのときのWPARAMとかLPARAMみたいなものですね。 (WM_LBUTTONDOWNのwParamは仮想キー、lParamはカーソル位置でした) では、実際のプログラムを見てみましょう。CWnd::OnLButtonDown afx_msg void OnLButtonDown( UINT nFlags, CPoint point );
型どおりクラス宣言時にポインタを保存する変数 pMyStatic1, pMyStatic2をクラスのメンバ変数にします。 今回はデストラクタも宣言します。 デストラクタはvirtualで宣言するのが一般的です。// text02.cpp #include <afxwin.h> class CMyWindow : public CFrameWnd { CStatic *pMyStatic1; CStatic *pMyStatic2; public: CMyWindow(); //コンストラクタ virtual ~CMyWindow();//デストラクタ afx_msg void OnPaint(); afx_msg void OnLButtonDown(UINT, CPoint); afx_msg void OnRButtonDown(UINT, CPoint); DECLARE_MESSAGE_MAP() };
メッセージマップです。BEGIN_MESSAGE_MAP(CMyWindow, CFrameWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() END_MESSAGE_MAP()
今回は、簡単のためにコンストラクタでスタティックコントロールを 作ってみました。(他にWM_CREATEメッセージの時に作るという方法も よく行われます。) ここでは、単にコントロールを作るだけでまだ何も文字を表示していません。CMyWindow::CMyWindow() { Create(NULL, "猫でもわかるテキスト表示"); pMyStatic1 = new CStatic(); pMyStatic1->Create("", WS_CHILD | WS_VISIBLE, CRect(20, 20, 40, 40), this); pMyStatic2 = new CStatic(); pMyStatic2->Create("", WS_CHILD | WS_VISIBLE, CRect(20, 40, 40, 60), this); }
エジットコントロールをCreateする場合、ちょっと引数が 違うので注意してください。CStatic::Create BOOL Create( LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff );
newしたものをdeleteするのはデストラクタで行うのが一般的です。 最後に本来のCFrameWndクラスのデストラクタを呼んでおきます。CMyWindow::~CMyWindow() { delete pMyStatic1; delete pMyStatic2; CFrameWnd::~CFrameWnd(); }
WM_PAINTメッセージの処理です。void CMyWindow::OnPaint() { CPaintDC dc(this); CString str1 = "回 左クリックされました"; CString str2 = "回 右クリックされました"; dc.TextOut(40, 20, str1); dc.TextOut(40, 40, str2); }
左クリックされたときの処理です。 クリックされる度にnを1ずつ増やしていきます。 スタティックコントロールにテキストを表示するのは SetWindowTextで行います。void CMyWindow::OnLButtonDown(UINT nFlags, CPoint pt) { static int n = 1; char *szNum = "%d"; char str[8]; wsprintf(str, szNum, n++); pMyStatic1->SetWindowText(str); }
ま、これは説明不要ですね。 MFCのメンバ関数は同名のAPI関数とよく似ていますが、 APIの場合、第1引数はウィンドウハンドルや、デバイスコンテキスト ハンドルのことが多いでしたね。逆に言うとAPI関数の 第1引数をとってしまったものがメンバ関数であることが多いようです。CWnd::SetWindowText void SetWindowText( LPCTSTR lpszString );
右ボタンが押されたときの処理です。void CMyWindow::OnRButtonDown(UINT nFlags, CPoint pt) { static int n = 1; char *szNum = "%d"; char str[8]; wsprintf(str, szNum, n++); pMyStatic2->SetWindowText(str); }
これは、前回と全く同じです。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;
さて、コントロール類を親ウィンドウに貼り付ける (子供ウィンドウとして取り扱う)方法は どれも大体同じです。ボタンとか、エジットコントロールを 貼り付けてみてください。
では、もう少し違う方法を説明します。
それは、グローバルな位置にstatic CStatic MyStatic;と宣言してしまうことです そして、適当なタイミングの時にCreateします。 このときMyStaticはポインタではないのでMyStatic.Create(...); となることに注意してください。
Update 08/Jan/1998 By Y.Kumei