WEBアプリケーション研究室 開発ノート TOP

WEBアプリケーション研究室 開発ノート [C++][Win32API] ウィンドウをクラス化。プロシージャをクラスメソッドに

スポンサーサイト

-------- --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

    このエントリーをはてなブックマークに追加

最近C++でウィンドウズアプリ開発に挑戦・・・というか、勉強しています。
どうせならネイティブアプリと思うし、やっぱりWindows根元の部分の理解が進むという意見もありWin32APIでやってます。

まず、Windowを作る部分ですが、これを使いまわせるようにクラス化をしようと思います。で、問題になったのがプロシージャの処理です。ウィンドウプロシージャは


typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
こんな定義になってます。で、Windowクラスメンバ関数のポインタは

LRESULT (Window::*windowProc)(HWND, UINT, WPARAM, LPARAM);
なので、当然ですがWNDCLASSEX.lpfnWndProcには代入できません。代入するにはstaticで宣言する必要があります。

ただ、staticにしてしまうと、staticなプロパティにしかアクセスできないし、全てのインスタンスで共用されてしまうので継承して使いまわすことができません。

そこでインスタンス自身のポインタをstaticなプロパティに保持してstaticなwindowProcの中から呼び出せないか試してみました。※これではまた、別々のインスタンスを保持できません。まさにstatic地獄

こちらのサイトを参考にSetWindowLong/GetWindowLongをつかって実現してみました。

class Window
{
protected:
virtual LRESULT proc(UINT uMsg, WPARAM wParam, LPARAM lParam){}
private:
HWND hWnd;
WNDCLASSEX wc;
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
Window(HINSTANCE hInstance, PTSTR appName);
bool createWindow(bool show=true);
}
実装はこんな感じです。

#include "Gomo/Window.h"

Window::Window(HINSTANCE hInstance, PTSTR appName)
{
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wc.lpfnWndProc = windowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = appName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

selfInstance = this;
}

LRESULT CALLBACK Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
Window* instance = (Window*)GetWindowLong( hWnd, GWL_USERDATA );

if(instance)
{
return instance->prop(uMsg, wParam, lParam);
}

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

bool Window::createWindow(bool show)
{
//CreateWindowの処理
SetWindowLong( hWnd, GWL_USERDATA, (LONG)this );
}
実際動かしてるものは、プロシージャでswitch文を使いたくなかったのでもうちょっと複雑になってます。話を簡単にするため細かいところははしょって書き換えてますので、コンパイル通らないかもしれません。

まだ、C++は良くわかってないので無茶をしてるかもしれませんが、一応動いてるようです。突込みがあったらコメントいただけると幸いです。
スポンサーサイト

    このエントリーをはてなブックマークに追加
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。