結局下のようになった。CreateWindow()みたいにlparamにデータを渡せればスマートなんだけど仕方なし。あとCreateDialog()なのにウィンドウプロシージャを使用するあたりやや気持ち悪いが。
[resource.h]
#pragma once
#define APP_CLASS_NAME TEXT("test")
#define APP_TITLE TEXT("test")
#define IDD_MAIN 101
[resource.rc]
#include "resource.h"
#include <windows.h>
IDD_MAIN DIALOG 0, 0, 310, 210
FONT 9, "MS Pゴシック"
STYLE WS_VISIBLE | WS_POPUPWINDOW
CAPTION APP_TITLE
{}
[main.cpp]
#include <windows.h>
#include "resource.h"
class WindowBase
{
protected:
/** constructor */
WindowBase() {}
/** destructor */
virtual ~WindowBase() {}
static void attachWnd( HWND hWnd, LONG_PTR myWndData )
{
SetWindowLongPtr( hWnd, GWL_USERDATA, myWndData );
SetWindowLongPtr( hWnd, GWL_WNDPROC, reinterpret_cast<LONG_PTR>(staticWndProc) );
}
public:
/** 初期化プロシージャ */
static LRESULT CALLBACK initWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if ( uMsg == WM_CREATE )
{
LPCREATESTRUCT cs = reinterpret_cast<LPCREATESTRUCT>( lParam );
WindowBase* wb = static_cast<WindowBase*>( cs->lpCreateParams );
attachWnd( hWnd, reinterpret_cast<LONG_PTR>(wb) );
return wb->wndProc( hWnd, uMsg, wParam, lParam );
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
/** 間接参照プロシージャ */
static LRESULT CALLBACK staticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return reinterpret_cast<WindowBase*>( GetWindowLongPtr(hWnd, GWL_USERDATA) )->wndProc( hWnd, uMsg, wParam, lParam );
}
/** オーバーライドして使用するプロシージャ */
virtual LRESULT wndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
// サブクラス化でない場合は、デフォルトウィンドウプロシージャを呼び出す
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
};
/**
* Main
*/
class Main : public WindowBase
{
public:
/**
* constructor
*/
Main()
: m_hWnd( NULL )
{}
/**
* destructor
*/
~Main() {}
/**
* override wndProc
*/
LRESULT wndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
case WM_CREATE:
break;
case WM_CLOSE:
DestroyWindow( hWnd );
break;
case WM_DESTROY:
ShowWindow( hWnd, SW_HIDE );
PostQuitMessage(0);
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
static LRESULT CALLBACK dummyProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
/**
* WinMain
*/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
// register
{
WNDCLASSEX wc = {0};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = dummyProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.cbSize = sizeof( WNDCLASSEX );
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground= reinterpret_cast<HBRUSH>( GetStockObject( WHITE_BRUSH ) );
wc.lpszMenuName = NULL;
wc.lpszClassName= APP_CLASS_NAME;
if ( !RegisterClassEx( &wc ) ) return 0;
}
m_hWnd = CreateDialog( hInstance, reinterpret_cast<LPCTSTR>(IDD_MAIN), NULL, NULL );
if ( !m_hWnd ) return -1;
attachWnd( m_hWnd, reinterpret_cast<LONG_PTR>(this) );
ShowWindow( m_hWnd, SW_SHOWNORMAL );
SendMessage( m_hWnd, WM_CREATE, 0, 0 );
// message loop
{
MSG msg;
while ( GetMessage(&msg , NULL , 0 , 0) )
{
if ( !IsDialogMessage(m_hWnd, &msg) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
return 0;
}
private:
HWND m_hWnd;
};
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow)
{
Main mainWindow;
return mainWindow.WinMain( hInst, hPrevInst, lpsCmdLine, nCmdShow );
}
迷う点は二つで、WNDCLASSEX のlpfnWndProcと、CreateDialog()の第4引数 lpDialogFunc。
CreateDialogParam()を使用すればLPARAMに好きなデータを渡せるから、INIT_DIALOGでGWL_USERDATAにthisポを保存する計画だった。
でもWNDCLASSEXに指定するプロシージャはLRESULT CALLBACK wndProc()、いわゆるウィンドウプロシージャで、CreateDialogに指定するのはBOOL CALLBACK wndProc()ってダイアログプロシージャと型が違うのね。
両方設定すべく、reinterpret_cast
どちらかのプロシージャ設定でNULLを指定しなければならないようだけど、いろいろ試したが、WNDCLASSEXのプロシージャ設定をNULLにしちゃうとうまく処理できないようだった。というのもダイアログプロシージャのほうはDefWindowProc()とかで汎用処理を行わないから全うに動くはずもない。
0 件のコメント:
コメントを投稿