1日でわかるMFC (GARAさんのページ)
Sample_C ボタンを持つWindowsプログラム
プログラム概要
・ ボタンをクリックするとメッセージボックスを表示します。
・ 右側のボタンはサブクラス化(MFCのクラスとは別物)して独自の処理(右クリック処理)を追加しています。
共通ファイル
1)
Sample_C.h
#define MENU_NAME NULL // メニュー名
#define WIN_W 500 // Window の幅
#define WIN_H 180 // Window の高
#define WIN_X 100 // Window の水平座標
#define WIN_Y 50 // Window の垂直座標
#define BTN_ID0 200 // ボタンID
#define BTN_ID1 201
#define BTN_ID2 202
Sample_C1.c SDKのプログラム (緑色の部分は各 .c ファイル共通です)
/** Sample_C1.c:ボタンを持つWindowsプログラム (by GARA) **/
#include <windows.h>
#include "Sample_C.h"
/* Define */
#define CLASS_NAME "Sample_C1Class" // クラス名
#define WIN_TITLE "Sample_C1" // タイトル
/* Global */
HINSTANCE hInst;
HWND hButton[3];
WNDPROC BtnDefProc[3];
/* Proto Type */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL InitApplication(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
void PutButton(HWND, int, int, int, int, int, char *);
void ClrButton(int);
LRESULT CALLBACK BtnProc_2(HWND, UINT, WPARAM, LPARAM);
/* WinMain */
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
Sample_A1.c と同じ
}
/* ウィンドウクラスの登録 */
BOOL InitApplication(HINSTANCE hInstance)
{
Sample_A1.c と同じ
}
/* ウィンドウの作成と表示 */
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
Sample_A1.c と同じ
}
/* ウィンドウプロシージャ */
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
switch(uMsg) {
case WM_CREATE:
PutButton(hWnd, 1, 70, 100, 150, 30, "左クリックボタン");
PutButton(hWnd, 2, 280, 100, 150, 30, "右クリックボタン");
break;
case WM_PAINT:
BeginPaint(hWnd, &ps);
hDC = ps.hdc;
TextOut(hDC, 10, 10, "SDK -> MFC", 10);
EndPaint(hWnd, &ps);
break;
case WM_COMMAND: // ボタンか押された
switch(LOWORD(wParam)) {
case BTN_ID1: // ボタン1
MessageBox(hWnd, "左側のボタンが押されました", "ボタン", MB_OK);
break;
case BTN_ID2: // ボタン2
MessageBox(hWnd, "右側のボタンが押されました", "ボタン", MB_OK);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
break;
case WM_DESTROY:
ClrButton(1);
ClrButton(2);
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
}
return 0;
}
/* ボタン作成サブルーチン */
void PutButton(HWND hWndMain, int no, int left, int top, int width, int height, char *cap)
{
hButton[no] = CreateWindow(
"button", // クラス名
cap, // Window のタイトル
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // Window のスタイル
left, // Window の水平座標
top, // Window の垂直座標
width, // Window の幅
height, // Window の高
hWndMain, // 親Window のハンドル
(HMENU)(BTN_ID0 + no), // Window ID
hInst, // インスタンスハンドル
NULL); //
// 右側ボタンの処理を変更する(ボタンのサブクラス化)
if(no == 2)
BtnDefProc[no] = (WNDPROC)SetWindowLong(hButton[no], GWL_WNDPROC, (LONG)BtnProc_2);
return;
}
/* ボタン削除サブルーチン */
void ClrButton(int no)
{
DestroyWindow(hButton[no]);
return;
}
/* 右側ボタンのボタンプロシージャ */
LRESULT CALLBACK BtnProc_2(HWND hBtn, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HWND hWnd;
int no;
no = GetWindowLong(hBtn, GWL_ID); // ボタンのIDを取得
switch(iMessage) {
case WM_LBUTTONDOWN: // 左クリック -> 無効
case WM_LBUTTONDBLCLK: // 左ダブルクリック -> 無効
return 0;
case WM_RBUTTONDOWN: // 右クリック -> 有効
hWnd = GetParent(hBtn);
PostMessage(hWnd, WM_COMMAND, no, (LPARAM)hBtn);
return 0;
default:
no -= BTN_ID0;
return CallWindowProc(BtnDefProc[no], hBtn, iMessage, wParam, lParam);
}
}
Sample_C2.cpp メインウィンドウをクラス化 (緑色の部分は各 .cpp ファイル共通です)
/** Sample_C2.cpp:ボタンを持つWindowsプログラム (by GARA) **/
#include <afxwin.h>
#include "Sample_C.h"
/* Define */
#define CLASS_NAME "Sample_C2Class" // クラス名
#define WIN_TITLE "Sample_C2" // タイトル
/* Global */
HINSTANCE hInst;
HWND hButton[3];
WNDPROC BtnDefProc[3];
/* Proto Type */
void PutButton(HWND, int, int, int, int, int, char *);
void ClrButton(int);
LRESULT CALLBACK BtnProc_2(HWND, UINT, WPARAM, LPARAM);
/* ウィンドウクラスの宣言 */
class CMainFrame : public CFrameWnd // ウィンドウクラス CWnd -> CFrameWnd
{
public:
// コンストラクタ
CMainFrame();
// メンバ関数
virtual BOOL PreCreateWindow(CREATESTRUCT&);
// メッセージハンドラ
afx_msg int OnCreate(LPCREATESTRUCT); // WM_CREATE に対応
afx_msg void OnPaint(); // WM_PAINT に対応
afx_msg void OnBtn(UINT); // WM_COMMAND に対応(2対1)
afx_msg void OnDestroy(); // WM_DESTROY に対応
DECLARE_MESSAGE_MAP()
};
/* メッセージマップの定義 */
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) // 第1引数:メッセージマップを所有するクラスの名前、第2引数:基本クラス名
ON_WM_CREATE()
ON_WM_PAINT()
ON_COMMAND_RANGE(BTN_ID1, BTN_ID2, OnBtn)
ON_WM_DESTROY()
END_MESSAGE_MAP()
/* アプリケーションクラスの宣言 */
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance(); // インスタンスを初期化する関数
};
/* ウィンドウクラスのメンバ */
// コンストラクタ
CMainFrame::CMainFrame() // コンストラクタ
{
Create(NULL, ""); // ウィンドウの作成。第1引数:クラス名、第2引数:ウィンドウ名
}
// メンバ関数
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) // PreCreateWindow() のオーバーライド
{
Sample_A2.cpp と同じ
}
// メッセージハンドラ
int CMainFrame::OnCreate(LPCREATESTRUCT cs)
{
// インスタンスハンドルの取得
hInst = AfxGetInstanceHandle();
// ボタンの作成
PutButton(m_hWnd, 1, 70, 100, 150, 30, "左クリックボタン");
PutButton(m_hWnd, 2, 280, 100, 150, 30, "右クリックボタン");
return 0;
}
void CMainFrame::OnPaint() // OnPaint() のオーバーライド
{
HWND hWnd;
HDC hDC;
PAINTSTRUCT ps;
hWnd = m_hWnd; // m_hWnd は CWnd のメンバ変数
::BeginPaint(hWnd, &ps); // ::(グローバルスコープ解決演算子)をつける
hDC = ps.hdc;
TextOut(hDC, 10, 10, "SDK -> MFC", 10);
::EndPaint(hWnd, &ps);
return;
}
void CMainFrame::OnBtn(UINT wParam) // 独自メンバー関数(オーバーライドでない)
{
HWND hWnd;
hWnd = m_hWnd;
switch(LOWORD(wParam)) {
case BTN_ID1: // ボタン1
::MessageBox(hWnd, "左側のボタンが押されました", "ボタン", MB_OK);
break;
case BTN_ID2: // ボタン2
::MessageBox(hWnd, "右側のボタンが押されました", "ボタン", MB_OK);
break;
}
return;
}
void CMainFrame::OnDestroy()
{
ClrButton(1);
ClrButton(2);
PostQuitMessage(0);
return;
}
/* ボタン作成サブルーチン */
void PutButton(HWND hWndMain, int no, int left, int top, int width, int height, char *cap)
{
hButton[no] = CreateWindow(
"button", // クラス名
cap, // Window のタイトル
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // Window のスタイル
left, // Window の水平座標
top, // Window の垂直座標
width, // Window の幅
height, // Window の高
hWndMain, // 親Window のハンドル
(HMENU)(BTN_ID0 + no), // Window ID
hInst, // インスタンスハンドル
NULL); //
// 右側ボタンの処理を変更する(ボタンのサブクラス化)
if(no == 2)
BtnDefProc[no] = (WNDPROC)SetWindowLong(hButton[no], GWL_WNDPROC, (LONG)BtnProc_2);
return;
}
/* ボタン削除サブルーチン */
void ClrButton(int no)
{
DestroyWindow(hButton[no]);
return;
}
/* アプリケーションクラスのメンバ */
// メンバ関数
BOOL CMyApp::InitInstance() // InitInstance() のオーバーライド
{
m_pMainWnd = new CMainFrame(); // メインウィンドウの作成
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
/* アプリケーションの生成(実行)*/
CMyApp MyApp;
/* 右側ボタンのボタンプロシージャ */
LRESULT CALLBACK BtnProc_2(HWND hBtn, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HWND hWnd;
int no;
no = GetWindowLong(hBtn, GWL_ID); // ボタンのIDを取得
switch(iMessage) {
case WM_LBUTTONDOWN: // 左クリック -> 無効
case WM_LBUTTONDBLCLK: // 左ダブルクリック -> 無効
return 0;
case WM_RBUTTONDOWN: // 右クリック -> 有効
hWnd = GetParent(hBtn);
PostMessage(hWnd, WM_COMMAND, no, (LPARAM)hBtn); // hBtn を渡さないと Debugモードで実行時アボート
return 0;
default:
no -= BTN_ID0;
return CallWindowProc(BtnDefProc[no], hBtn, iMessage, wParam, lParam);
}
}
Sample_C3.cpp メインウィンドウとボタンをクラス化 (緑色の部分は各 .cpp ファイル共通です)
・ OnPaint で CPaintDC を使用しています。
/** Sample_C3.cpp:ボタンを持つWindowsプログラム (by GARA) **/
#include <afxwin.h>
#include "Sample_C.h"
/* Define */
#define CLASS_NAME "Sample_C3Class" // クラス名
#define WIN_TITLE "Sample_C3" // タイトル
/* Global */
WNDPROC BtnDefProc[3];
/* Proto Type */
LRESULT CALLBACK BtnProc_2(HWND, UINT, WPARAM, LPARAM);
/* ウィンドウクラスの宣言 */
class CMainFrame : public CFrameWnd // ウィンドウクラス CWnd -> CFrameWnd
{
private:
CButton *pButton[3]; // 動的に作成する場合
// CButton cButton[3]; // 静的に作成する場合
public:
// コンストラクタ
CMainFrame();
// メンバ関数
virtual BOOL PreCreateWindow(CREATESTRUCT&);
// メッセージハンドラ
afx_msg int OnCreate(LPCREATESTRUCT); // WM_CREATE に対応
afx_msg void OnPaint(); // WM_PAINT に対応
afx_msg void OnBtn(UINT); // WM_COMMAND に対応(2対1)
afx_msg void OnDestroy(); // WM_DESTROY に対応
DECLARE_MESSAGE_MAP()
};
/* メッセージマップの定義 */
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) // 第1引数:メッセージマップを所有するクラス名、第2引数:基本クラス名
ON_WM_CREATE()
ON_WM_PAINT()
ON_COMMAND_RANGE(BTN_ID1, BTN_ID2, OnBtn)
ON_WM_DESTROY()
END_MESSAGE_MAP()
/* アプリケーションクラスの宣言 */
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance(); // インスタンスを初期化する関数
};
/* ウィンドウクラスのメンバ */
// コンストラクタ
CMainFrame::CMainFrame() // コンストラクタ
{
Create(NULL, ""); // ウィンドウの作成。第1引数:クラス名、第2引数:ウィンドウ名
}
// メンバ関数
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) // PreCreateWindow() のオーバーライド
{
Sample_A2.cpp と同じ
}
// メッセージハンドラ
int CMainFrame::OnCreate(LPCREATESTRUCT cs)
{
DWORD style;
style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
// ボタンを動的に作成
pButton[1] = new CButton();
pButton[1]->Create("左クリックボタン", style, CRect( 70, 100, 220, 130), this, BTN_ID1);
pButton[2] = new CButton();
pButton[2]->Create("右クリックボタン", style, CRect(280, 100, 430, 130), this, BTN_ID2);
// ボタンを静的に作成
// cButton[1].Create("左クリックボタン", style, CRect( 70, 100, 220, 130), this, BTN_ID1);
// cButton[2].Create("右クリックボタン", style, CRect(280, 100, 430, 130), this, BTN_ID2);
// 右側ボタンのサブクラス化
BtnDefProc[2] = (WNDPROC)SetWindowLong(pButton[2]->m_hWnd, GWL_WNDPROC, (LONG)BtnProc_2); // 動的
// BtnDefProc[2] = (WNDPROC)SetWindowLong(cButton[2].m_hWnd, GWL_WNDPROC, (LONG)BtnProc_2); // 静的
return 0;
}
void CMainFrame::OnPaint() // OnPaint() のオーバーライド
{
CPaintDC dc(this); // CPaintDC のコンストラクタの引数に this(CMainFrame オブジェクトへのポインタ)をセット
dc.TextOut(10, 10, "SDK -> MFC", 10);
return;
}
void CMainFrame::OnBtn(UINT wParam) // 独自メンバー関数(オーバーライドでない)
{
switch(LOWORD(wParam)) {
case BTN_ID1: // ボタン1
MessageBox("左側のボタンが押されました", "ボタン", MB_OK); // CWnd のメンバ関数を使用
break;
case BTN_ID2: // ボタン2
MessageBox("右側のボタンが押されました", "ボタン", MB_OK); // CWnd のメンバ関数を使用
break;
}
return;
}
void CMainFrame::OnDestroy()
{
delete pButton[1]; // 動的に作成した場合
delete pButton[2]; // 動的に作成した場合
PostQuitMessage(0);
return;
}
/* アプリケーションクラスのメンバ */
// メンバ関数
BOOL CMyApp::InitInstance() // InitInstance() のオーバーライド
{
m_pMainWnd = new CMainFrame(); // メインウィンドウの作成
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
/* アプリケーションの生成(実行)*/
CMyApp MyApp;
/* 右側ボタンのボタンプロシージャ */
LRESULT CALLBACK BtnProc_2(HWND hBtn, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HWND hWnd;
int no;
no = GetWindowLong(hBtn, GWL_ID); // ボタンのIDを取得
switch(iMessage) {
case WM_LBUTTONDOWN: // 左クリック -> 無効
case WM_LBUTTONDBLCLK: // 左ダブルクリック -> 無効
return 0;
case WM_RBUTTONDOWN: // 右クリック -> 有効
hWnd = GetParent(hBtn);
PostMessage(hWnd, WM_COMMAND, no, (LPARAM)hBtn); // hBtn を渡さないと Debugモードで実行時アボート
return 0;
default:
no -= BTN_ID0;
return CallWindowProc(BtnDefProc[no], hBtn, iMessage, wParam, lParam);
}
}
BACK TOP