Reputation: 500
I'm learning C++
and I have some questions. Some researches at msdn didn't help me. I wanna create two windows in one app. One window - dialog with options and another for graphic output. Here is the code that I use. But I have some problems with it:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
{
InitCommonControls();
if(FAILED(DialogWindow_OnCreate(hInstance)))
return 1;
if(FAILED(GraphicWindow_OnCreate(hInstance)))
return 1;
MSG msg;
memset(&msg, 0, sizeof(MSG));
while(msg.message != WM_QUIT)
{
while(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
OnUpdate();
}
GraphicWindow_OnClose();
return 0;
}
Creation of main window (Dialog):
HRESULT DialogWindow_OnCreate(HINSTANCE hInst)
{
g_hDialogWindow = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogWindow_WndProc);
if(!g_hDialogWindow)
return E_NOTIMPL;
UpdateWindow(g_hDialogWindow);
return S_OK;
}
Main window proc (Dialog):
INT_PTR CALLBACK DialogWindow_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
{
g_hDialogWindow = hWnd;
// Some init actions ...
return (INT_PTR)TRUE;
}
case WM_COMMAND:
int wmId, wmEvent;
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch(wmEvent)
{
case NULL: // Menu used
{
switch(wmId)
{
case IDC_BTN_1:
{
DialogWindow_OnBtn1();
MessageBoxA(NULL, "Some message", "Some title", MB_OK);
return (INT_PTR)TRUE;
} break;
case IDC_BTN_2:
{
DialogWindow_OnBtn2();
return (INT_PTR)TRUE;
} break;
// ...
case IDCANCEL:
{
// Close window
DefWindowProc(hWnd, WM_CLOSE, wParam, lParam);
} break;
case IDOK:
{
// Close window
DefWindowProc(hWnd, WM_CLOSE, wParam, lParam);
} break;
}
}
}
case WM_CLOSE:
DefWindowProc(hWnd, message, wParam, lParam);
return (INT_PTR)TRUE;
break;
case WM_DESTROY:
PostQuitMessage(0);
return (INT_PTR)TRUE;
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return (INT_PTR)FALSE;
}
Second window (Graphic) creation:
HRESULT GraphicWindow_OnCreate(HINSTANCE hInst)
{
HWND g_hGraphicWindow = NULL;
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = GraphicWindow_WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInst;
wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP_ICO));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = _T("MyApp");
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
if(!RegisterClassEx(&wcex))
{
DWORD dwError = GetLastError();
if(dwError != ERROR_CLASS_ALREADY_EXISTS)
{
MessageBoxA(NULL, "GraphicWindow: RegisterClass() failed!", "Error", MB_OK | MB_ICONERROR);
return HRESULT_FROM_WIN32(dwError);
}
}
// Set window's initial size, but it might be changed later
int nDefaultWidth = 320;
int nDefaultHeight = 240;
RECT rc;
SetRect(&rc, 0, 0, nDefaultWidth, nDefaultHeight);
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
// Create the window
g_hGraphicWindow = CreateWindowA("MyApp", "GraphicWindow", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, (rc.right - rc.left), (rc.bottom - rc.top), 0,
0, hInst, 0);
if(!g_hGraphicWindow)
{
DWORD dwError = GetLastError();
MessageBoxA(NULL, "GraphicWindow: CreateWindow() failed!", "Error", MB_OK | MB_ICONERROR);
return HRESULT_FROM_WIN32(dwError);
}
UpdateWindow(g_hGraphicWindow);
return S_OK;
}
Graphic window proc:
LRESULT CALLBACK GraphicWindow_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_KEYDOWN:
{
switch(wParam)
{
case VK_RETURN:
// Some actions ...
break;
case VK_ESCAPE:
// Some actions ...
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_CLOSE:
ShowWindow(hWnd, SW_HIDE);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Where is my problem? Help me, please.
Upvotes: 0
Views: 219
Reputation: 612794
I have the follow comments to make:
A
suffixes. You'll need to prefix string literals with L
to specify wide strings. For instance, L"foo"
.hWndParent
when you call CreateDialog
. Otherwise, the modeless dailog will be unowned and so have its own taskbar button, and not appear always on top of the main window.hWnd
when you call MessageBox
.Looking in more detail at the message loop, you are not following the rules laid out in the documentation to CreateDialog
, which states:
To support keyboard navigation and other dialog box functionality, the message loop for the dialog box must call the IsDialogMessage function.
So your message loop should be:
while(GetMessage(&msg, NULL, 0, 0))
{
if(!IsDialogMessage(g_hDialogWindow, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Note also that I switched to a GetMessage
based loop. I don't think you need to run a hot loop for your needs. Using GetMessage
allows your app's main thread to yield the CPU and block if it is idle.
Upvotes: 2
Reputation: 7620
In your Dialog Procedure, don't use DefWindowProc
.
See: Dialog Box Default Message Processing.
Upvotes: 0