I’m trying to display 3 windows, however it fails to create window 2 of which I am not sure why. It creates the first window and i’ve done the same for the other two.
Here is the code:
#include <Windows.h>
// Store handles to the main window and application instance globally.
HWND ghMainWnd = 0;
HWND ghSecdWnd = 0;
HWND ghThrdWnd = 0;
HINSTANCE ghAppInst = 0;
//========================================================================================
// WINDOW 1
// Step 1: Define and implement the window procedure.
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
// Handle left mouse button click message.
case WM_LBUTTONDOWN:
MessageBox(hWnd, "Left Mouse Button Click", "Message", MB_OK);
return 0;
// Handle key down message.
case WM_KEYDOWN:
if( wParam == VK_ESCAPE )
if( MessageBox(hWnd, "Are you sure?", "Quit", MB_YESNO) == IDYES )
DestroyWindow(ghMainWnd);
return 0;
// Handle destroy window message.
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
// Forward any other messages we didn't handle to the default window procedure.
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//========================================================================================
// WINDOW 2
//========================================================================================
LRESULT CALLBACK
WndProc2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
// Handle down arrow pressed.
case WM_KEYDOWN:
if( wParam == VK_DOWN )
MessageBox(hWnd, "Down arrow pressed 2.", "Information", MB_OK);
return 0;
case WM_LBUTTONDOWN:
MessageBox(hWnd, "Window 2", "Window 2", MB_OK);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//========================================================================================
// WINDOW 3
//========================================================================================
LRESULT CALLBACK
WndProc3(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch( msg )
{
// Handle down arrow pressed.
case WM_KEYDOWN:
if( wParam == VK_DOWN )
MessageBox(hWnd, "Down arrow pressed 3.", "Information", MB_OK);
return 0;
case WM_LBUTTONDOWN:
MessageBox(hWnd, "Window 3", "Window 3", MB_OK);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// WinMain: Entry point for windows application.
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdLine, int showCmd)
{
// Save handle to application instance.
ghAppInst = hInstance;
// Step 2: Fill out a WNDCLASS instance.
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ghAppInst;
wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = "MyWndClassName";
// Window 2
WNDCLASS wc2;
wc2.style = CS_HREDRAW | CS_VREDRAW;
wc2.lpfnWndProc = WndProc2;
wc2.cbClsExtra = 0;
wc2.cbWndExtra = 0;
wc2.hInstance = ghAppInst;
wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
wc2.hCursor = ::LoadCursor(0, IDC_ARROW);
wc2.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
wc2.lpszMenuName = 0;
wc2.lpszClassName = "MyWndClassTwo";
// Window 3
WNDCLASS wc3;
wc3.style = CS_HREDRAW | CS_VREDRAW;
wc3.lpfnWndProc = WndProc3;
wc3.cbClsExtra = 0;
wc3.cbWndExtra = 0;
wc3.hInstance = ghAppInst;
wc3.hIcon = ::LoadIcon(0, IDI_APPLICATION);
wc3.hCursor = ::LoadCursor(0, IDC_ARROW);
wc3.lpszMenuName = 0;
wc3.lpszClassName = "MyWndClassThree";
// Step 3: Register with WNDCLASS instance with windows.
RegisterClass( &wc );
RegisterClass( &wc2 );
RegisterClass( &wc3 );
// Step 4: Create the window, and save the handle in global window handle variable ghMainWnd.
ghMainWnd = ::CreateWindow("MyWndClassName", "Window 1", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, 500, 500, 0, 0, ghAppInst, 0);
ghSecdWnd = ::CreateWindow("MyWndClassTwo", "Window 2", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 510, 0, 500, 500, 0, 0, ghAppInst, 0);
ghThrdWnd = ::CreateWindow("MyWndClassThree", "Window 3", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 510, 500, 500, 0, 0, ghAppInst, 0);
if( ghMainWnd == 0 )
{
::MessageBox(0, "Create Window 1 - Failed", 0, 0);
return false;
}
if( ghSecdWnd == 0 )
{
::MessageBox(0, "Create Window 2 - Failed", 0, 0);
return false;
}
if( ghThrdWnd == 0 )
{
::MessageBox(0, "Create Window 3 - Failed", 0, 0);
return false;
}
// Step 5: Show and update the window.
ShowWindow(ghMainWnd, showCmd);
UpdateWindow(ghMainWnd);
ShowWindow(ghSecdWnd, showCmd);
UpdateWindow(ghSecdWnd);
ShowWindow(ghThrdWnd, showCmd);
UpdateWindow(ghThrdWnd);
// Step 6: Enter the message loop and don't quit until a WM_QUIT message is received.
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while( GetMessage(&msg, 0, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Return exit code back to operating system.
return (int)msg.wParam;
}
It doesn’t throw any errors, but on the ghSecdWnd == 0 it displays that error message.
There are two problems: The one you’re experiencing, and one with window 3.
Calling
GetLastError()after creating the second window (but before creating the third) results in"Cannot find the window class.". Looking at the class setup, you’ve done the following:What you actually need is to set the icon of
wc2. Even checking the return value ofRegisterClasswhen you register the second class results in an error of"The parameter is incorrect.", indicating a problem withwc2. It’s also an earlier location in your code to catch the error, which is always a good thing.Secondly, there’s a problem with the third window. You haven’t set the background brush on it. Add this line to the
wc3setup:You should always check the documentation to find out what functions do when they fail and take appropriate action. For example, if
CreateWindowfails, the return value isNULL, and you can callGetLastErrorto get more info. You should do this on a per-function basis. Here’s an example with the two main functions for Window 2. Keep in mind that others, such asGetStockObject, can fail as well.First, looking at
RegisterClass, you see under Return value that it returns 0 on failure and states that you can callGetLastError()for extended error information, so I output that.CreateWindowsays the same, but it’sNULLinstead becauseHWNDis a pointer. You can take the error codes you get and check them against the MSDN System Error Codes article, or useFormatMessagewithFORMAT_MESSAGE_FROM_SYSTEMto do that for you.