ウィンドウの作成がうまくいきません。
C++で一からWin32Apiでウィンドウを作ろうとしています。
単発のウィンドウ表示はうまくいったのですが、複数のウィンドウを表示しようとすると動作が怪しくなります。
以下にプログラムを載せさせて頂きますのでご指摘お願いします。
(1)LRESULT C_BaseWnd::LocalWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)の関数でメインウィンドウの処理を行っているのですが、メインウィンドウ上で「a(0x61)」キーを入力したとき新しくサブウィンドウを表示させています。その表示したサブウィンドウを閉じて再度メインウィンドウから「a(0x61)」キーを入力してサブウィンドウを表示しようとしても応答がありません。原因と改善方法を教えていただけるとうれしいです。
(2)そのほか全体的に「この記述おかしいだろう」「こうしたほうがいいんじゃないか」など細かいところでも良いので教えていただけるとうれしいです。
よろしくお願いします。
#include <Windows.h>
class C_BaseWnd
{
public:
C_BaseWnd();
virtual ~C_BaseWnd();
virtual HRESULT Init( HINSTANCE hInst, int nCmdShow, LPTSTR className, LPTSTR windowName, UINT width, UINT height, DWORD style, BOOL windowFlag );
virtual void Uninit(void);
protected:
WNDCLASSEX m_wndClassEx;
HWND m_hWnd;
// 親のウィンドウプロシージャ
virtual LRESULT LocalWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// 子のウィンドウプロシージャ
virtual LRESULT ChildWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
private:
// 個々のウィンドウプロシージャを呼び出すコールバック
static LRESULT CALLBACK s_CallWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
// メインウィンドウフラグ格納
bool m_bMain;
};
int WINAPI WinMain( HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow )
{
// 初期化処理
C_BaseWnd *window = new C_BaseWnd();
window->Init( hCurInst, nCmdShow, "Application Name", "Window Name", 1280, 720, WS_OVERLAPPEDWINDOW, true );
MSG msg;
while( GetMessage(&msg, NULL, 0, 0) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
window->Uninit();
delete window;
return 0;
}
C_BaseWnd::C_BaseWnd()
{
m_hWnd = NULL;
m_bMain = false;
}
C_BaseWnd::~C_BaseWnd()
{
}
HRESULT C_BaseWnd::Init(HINSTANCE hInst, int nCmdShow,
LPTSTR className, LPTSTR windowName, UINT width, UINT height, DWORD style, BOOL windowFlag)
{
m_wndClassEx.cbSize = sizeof(WNDCLASSEX);
m_wndClassEx.lpfnWndProc = s_CallWindProc;
m_wndClassEx.style = (CS_HREDRAW | CS_VREDRAW);
m_wndClassEx.cbClsExtra = 0;
m_wndClassEx.cbWndExtra = 0;
m_wndClassEx.hInstance = hInst;
m_wndClassEx.hIcon = NULL;
m_wndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
m_wndClassEx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
m_wndClassEx.lpszMenuName = NULL;
m_wndClassEx.lpszClassName = className;
m_wndClassEx.hIconSm = NULL;
if( RegisterClassEx(&m_wndClassEx) == 0 ) return E_FAIL;
m_hWnd = CreateWindowEx(
0, className, windowName, style,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
NULL, NULL, hInst, NULL);
if( m_hWnd == NULL ) return E_FAIL;
// 自身をウィンドウハンドルにセットする
SetWindowLong( m_hWnd, GWL_USERDATA, (LONG)this );
ShowWindow(m_hWnd, nCmdShow);
UpdateWindow(m_hWnd);
if( windowFlag ) m_bMain = true;
return S_OK;
}
void C_BaseWnd::Uninit(void)
{
UnregisterClass(m_wndClassEx.lpszClassName, m_wndClassEx.hInstance);
}
LRESULT C_BaseWnd::LocalWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg ) {
case WM_CHAR:
if( wParam == 0x61 )
{
// サブウィンドウ初期化処理
C_BaseWnd *window2 = new C_BaseWnd();
window2->Init( (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), SW_SHOW, "Application Name2", "Window Name2", 1920, 1080, WS_OVERLAPPEDWINDOW, false );
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT C_BaseWnd::ChildWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg ) {
case WM_CHAR:
break;
case WM_CLOSE:
break;
default:
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
LRESULT CALLBACK C_BaseWnd::s_CallWindProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// セットした個別のインスタンスを取得
C_BaseWnd *pInst = (C_BaseWnd *)GetWindowLong(hWnd, GWL_USERDATA);
if( !pInst ) {
return DefWindowProc(hWnd, msg, wParam, lParam);
}
if( pInst->m_bMain )
{
return pInst->LocalWindProc(hWnd, msg, wParam, lParam);
}
else
{
return pInst->ChildWindProc(hWnd, msg, wParam, lParam);
}
}
お礼
ありがとうございます! 上記の補足についても納得しました。 以下のように、::PostMessage()を実行することで、問題を解決することができました。 HWND hWnd = m_dlgTest.GetSafeHwnd(); if (hWnd) { ::PostMessage(hWnd, WM_MESSAGE_CLOSEDIALOG, 0, 0); }