C++ による Windows プログラミングの学習 1-6 アプリケーション状態を管理する

MSDN ライブラリ>Windows 開発>C++ による Windows プログラミングの学習>モジュール 1. 初めての Windows プログラム>アプリケーション状態を管理する
https://msdn.microsoft.com/ja-jp/library/ff381400(v=vs.85).aspx

今回は1-3で触れたウィンドウプロシージャをメンバ関数にする話です。

まず、ウィンドウを表すクラスのコンストラクタで呼び出している
CreateWindowEx()の最後の引数lpParamにthisポインタ,作成中のオブジェクト自身を渡します。
渡されたオブジェクトはWM_NCCREATE,WM_CREATEメッセージのlParamに渡される
CREATESTRUCT型のオブジェクトのメlpCreateParamンバに代入されます。

WM_NCCREATEでこれを回収し、 SetWindowLongPtr()関数でウィンドウハンドルと関連付けます。
GetWindowLongPtr()関数でハンドルに関連付けられたオブジェクトを取得できるので、
ウィンドウプロシージャ内でメンバ関数を呼び出すことが出来ます。

WM_NCCREATE,WM_CREATEはCreateWindowEx()の終了前に呼び出されるので
ウィンドウハンドルをウィンドウを表すオブジェクトのメンバに保存する処理は、
これらのメッセージの処理内で行うようにします。

CreateWindowEx
https://msdn.microsoft.com/ja-jp/library/cc410714.aspx

SetWindowLongPtr()
https://msdn.microsoft.com/ja-jp/library/cc411204.aspx

GetWindowLongPtr()
https://msdn.microsoft.com/ja-jp/library/cc364762.aspx

class Form
{
public:
	static LRESULT CALLBACK WindowProc
            (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
				
private:
	LRESULT  WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam);
	HWND hwnd_;
public:
	Form();
	virtual ~Form();
	bool Show();
};
Form::Form()
{
	// ウィンドウ クラスを登録する
	const wchar_t CLASS_NAME[] = L"Form";
	WNDCLASSEXW wc = {};
	wc.cbSize = sizeof(WNDCLASSEXW);
	wc.lpfnWndProc = Form::WindowProc;
	wc.lpszClassName = CLASS_NAME;

	Application::Instance().RegisterWindowClass(wc);


	// ウィンドウを作成する
	CreateWindowEx(
		0,                              // オプションのウィンドウ スタイル
		CLASS_NAME,                     // ウィンドウ クラス
		L"Title",    // ウィンドウ テキスト
		WS_OVERLAPPEDWINDOW,            // ウィンドウ スタイル
										// サイズと位置
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL,       // 親ウィンドウ    
		NULL,       // メニュー
		Application::Instance().getHandle(),  // インスタンス ハンドル
		this        // 追加のアプリケーション データ
	);
}


/// static版ウィンドウプロシージャ
LRESULT CALLBACK Form::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// ウィンドウ作成時メッセージ
	if (uMsg == WM_NCCREATE)
	{
		// lParamからCREATESTRUCTを取り出す。
		CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);

		// CREATESTRUCTからウィンドウオブジェクトを取り出す。
		Form* f = reinterpret_cast<Form*>(pCreate->lpCreateParams);

		// ウィンドウハンドルを保存
		f->hwnd_ = hwnd;
		// ウィンドウオブジェクトとハンドルを関連付け
		SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(f));

	}

	{
		// ウィンドウハンドルに関連付けられたウィンドウオブジェクトを取得する
		LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
		if (ptr != 0)
		{
			// 関連付けされていた場合
			// メンバ関数版ウィンドウプロシージャを呼び出す。
			Form *f = reinterpret_cast<Form*>(ptr);
			return f->WindowProc(uMsg, wParam, lParam);
		}
		else
		{
			//関連付けられていなければデフォルトの処理を実行
			return DefWindowProc(hwnd, uMsg, wParam, lParam);
		}
	}
}

/// メンバ版ウィンドウプロシージャ
LRESULT Form::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	//とりあえずデフォルト処理
	return DefWindowProc(hwnd_, uMsg, wParam, lParam);
}

最後にこれらの処理をまとめて基底クラスへ移動します。

class Wnd
{
public:
	static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

protected:

	virtual LRESULT  WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
	HWND hwnd_;
public:
	Wnd();
	virtual ~Wnd();
};

/// static版ウィンドウプロシージャ
LRESULT CALLBACK Wnd::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// ウィンドウ作成時メッセージ
	if (uMsg == WM_NCCREATE)
	{
		// lParamからCREATESTRUCTを取り出す。
		CREATESTRUCT *pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);

		// CREATESTRUCTからウィンドウオブジェクトを取り出す。
		Wnd* f = reinterpret_cast<Wnd*>(pCreate->lpCreateParams);

		// ウィンドウハンドルを保存
		f->hwnd_ = hwnd;
		// ウィンドウオブジェクトとハンドルを関連付け
		SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(f));

	}

	{
		// ウィンドウハンドルに関連付けられたウィンドウオブジェクトを取得する
		LONG_PTR ptr = GetWindowLongPtr(hwnd, GWLP_USERDATA);
		if (ptr != 0)
		{
			// 関連付けされていた場合
			// メンバ関数版ウィンドウプロシージャを呼び出す。
			Wnd *f = reinterpret_cast<Wnd*>(ptr);
			return f->WindowProc(uMsg, wParam, lParam);
		}
		else
		{
			//関連付けられていなければデフォルトの処理を実行
			return DefWindowProc(hwnd, uMsg, wParam, lParam);
		}
	}
}

/// メンバ版ウィンドウプロシージャ
LRESULT Wnd::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	//とりあえずデフォルト処理
	return DefWindowProc(hwnd_, uMsg, wParam, lParam);
}

Wnd::Wnd(){}
Wnd::~Wnd(){}

class Form:public Wnd
{
protected:			
	LRESULT  WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
	Form();
	virtual ~Form();
	bool Show();
};

Form::Form()
{
	// ウィンドウ クラスを登録する
	const wchar_t CLASS_NAME[] = L"Form";
	WNDCLASSEXW wc = {};
	wc.cbSize = sizeof(WNDCLASSEXW);
	wc.lpfnWndProc = Wnd::WindowProc;
	wc.lpszClassName = CLASS_NAME;

	Application::Instance().RegisterWindowClass(wc);

	// ウィンドウを作成する
	//this->hwnd_ = 
	CreateWindowEx(
		0,                              // オプションのウィンドウ スタイル
		CLASS_NAME,                     // ウィンドウ クラス
		L"Title",    // ウィンドウ テキスト
		WS_OVERLAPPEDWINDOW,            // ウィンドウ スタイル
										// サイズと位置
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL,       // 親ウィンドウ    
		NULL,       // メニュー
		Application::Instance().getHandle(),  // インスタンス ハンドル
		this        // 追加のアプリケーション データ
	);
}

Form::~Form(){}
bool Form::Show()
{
	BOOL b = ShowWindow(hwnd_, Application::Instance().getCmdShow());
	return (b != 0);
}

/// メンバ版ウィンドウプロシージャ
LRESULT Form::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return Wnd::WindowProc(uMsg, wParam, lParam);
}

広告

akatukisiden について

フリーランスプログラマ 使用言語はC++,C#とそのつなぎのC++/CLI 専門はクライアントアプリ開発
カテゴリー: C++, WinAPI タグ: , , , , パーマリンク

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中