ウィンドウクラスカプセル化--ウィンドウオブジェクトメッセージ処理のマッピング方法(1)
3686 ワード
インタフェースをカプセル化するには、一般的にはウィンドウのクラスです.例えば、最も基本的なウィンドウクラスCMyWndを実現するには、必ずウィンドウプロセスをこのクラスのメンバー関数として使用しますが、WINAPIを使用してウィンドウを作成する場合は、クラスWNDCLASSを登録する必要があります.メンバーデータlpfnWndProcにはWNDPROCの関数ポインタが必要です.一般的なアイデアは、ウィンドウクラスのメッセージ処理関数ポインタを渡し、静的クラスメンバー関数、またはグローバルなメッセージ処理関数を使用することです.そうしないと、WNDPROCに変換できません.
静的メッセージ処理関数:欠点は、メッセージ処理関数がウィンドウオブジェクトのウィンドウハンドルを取得できないことです.
≪グローバル・メッセージ処理関数|Global Message Processing Function|ldap≫:ウィンドウ・クラスのオブジェクト・ポインタを取得できません.
1つの解決策は,ウィンドウリストを用いて構造配列を開き,ウィンドウクラスオブジェクトがウィンドウを作成する際にウィンドウHWNDとthisポインタを配列に入れ,グローバルメッセージ処理関数が配列を遍歴し,HWNDを用いてthisポインタを探し出し,オブジェクト内部に位置決めするメッセージ処理関数である.この方法でオブジェクトを検索する時間は、ウィンドウの数が増えるにつれて増加します.コードは次のとおりです.
静的メッセージ処理関数:欠点は、メッセージ処理関数がウィンドウオブジェクトのウィンドウハンドルを取得できないことです.
≪グローバル・メッセージ処理関数|Global Message Processing Function|ldap≫:ウィンドウ・クラスのオブジェクト・ポインタを取得できません.
1つの解決策は,ウィンドウリストを用いて構造配列を開き,ウィンドウクラスオブジェクトがウィンドウを作成する際にウィンドウHWNDとthisポインタを配列に入れ,グローバルメッセージ処理関数が配列を遍歴し,HWNDを用いてthisポインタを探し出し,オブジェクト内部に位置決めするメッセージ処理関数である.この方法でオブジェクトを検索する時間は、ウィンドウの数が増えるにつれて増加します.コードは次のとおりです.
#ifndef _WINDOW_H_
#define _WINDOW_H_
#include "stdafx.h"
#include "Resource.h"
#include <map>
class window{
public:
window():_hwnd(NULL){}
~window(){}
bool Create(HINSTANCE hInstance,const LPCTSTR lpszClassName);
protected:
HWND _hwnd;
private:
LRESULT CALLBACK WndProc(UINT message, WPARAM wParam, LPARAM lParam);
void RemoveHwndFormMap();
protected:
static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static std::map<HWND,window*>* _sWindowMap;
};
std::map<HWND,window*>* window::_sWindowMap = new std::map<HWND,window*>;
bool window::Create(HINSTANCE hInstance,LPCTSTR lpszClassName)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = StaticWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TEST);
wcex.lpszClassName = lpszClassName;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&wcex);
_hwnd = CreateWindow(lpszClassName, NULL, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (_hwnd == NULL)
{
MessageBox(NULL,TEXT("Error"),NULL,NULL);
return FALSE;
}
//_sWindowMap[_hwnd] = this;
(*_sWindowMap).insert(std::make_pair(_hwnd,this));
ShowWindow(_hwnd, SW_SHOW);
UpdateWindow(_hwnd);
return TRUE;
}
LRESULT CALLBACK window::StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if ((*_sWindowMap).empty())
{
return ::DefWindowProcW(hWnd, message, wParam, lParam);
}else
return (*_sWindowMap)[hWnd]->WndProc( message, wParam, lParam);
}
LRESULT CALLBACK window::WndProc(UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// :
switch (wmId)
{
case IDM_ABOUT:
//DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
MessageBox(NULL,TEXT("AboutDlg"),TEXT(" "),NULL);
break;
case IDM_EXIT:
DestroyWindow(_hwnd);
RemoveHwndFormMap();
break;
default:
return DefWindowProc(_hwnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(_hwnd, &ps);
// TODO: ...
EndPaint(_hwnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
RemoveHwndFormMap();
break;
default:
return ::DefWindowProc(_hwnd, message, wParam, lParam);
}
return 0;
}
void window::RemoveHwndFormMap()
{
std::map<HWND,window*>::iterator it;
it = (*_sWindowMap).find(_hwnd);
(*_sWindowMap).erase(it);
}
#endif