WinAPI Window Closes Instantly - c++

I have been experimenting with the WINAPI trying to learn it but the window I have created closes instantly. As you see when the W key is pressed or the left button is pressed it will close the program but when running it with no buttons being pressed it still closes.
#include <windows.h>
#include <windowsx.h>
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass1";
// register the window class
RegisterClassEx(&wc);
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"Game", // title of the window
WS_OVERLAPPEDWINDOW, // window style
1, // x-position of the window
1, // y-position of the window
1800, // width of the window
1000, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
// enter the main loop:
// this struct holds Windows event messages
MSG msg;
// wait for the next message in the queue, store the result in 'msg'
while (GetMessage(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch (message)
{
// this message is read when the window is closed
case WM_MOUSEMOVE:
{
// Retrieve mouse screen position
int x = (short)LOWORD(lParam);
int y = (short)HIWORD(lParam);
// Check to see if the left button is held down:
bool leftButtonDown = wParam & MK_LBUTTON;
// Check if right button down:
bool rightButtonDown = wParam & MK_RBUTTON;
if (leftButtonDown == true)
{
//left click
//example lets close the program when press w
PostQuitMessage(0);
return 0;
}
}
case WM_KEYDOWN:
{
switch (wParam)
{
case 'W':
//w pressed
//example lets close the program when press w
PostQuitMessage(0);
return 0;
}
}
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
}
default:
break;
}
// Handle any messages the switch statement didn't
return DefWindowProc(hWnd, message, wParam, lParam);
}

You're missing some break statements in your switch, so for example, if you get the WM_MOUSEMOVE message and the leftButtonDown != true, execution will fall through to WM_KEYDOWN, etc.
Eventually you get to case WM_DESTROY:, which will Post you a lovely QuitMessage.
As an aside, this would be very easy to spot by stepping through, statement-by-statement, in a debugger.

There is no break in your switch statement.
You end up exetuting
PostQuitMessage(0);
You could do something like this:
case WM_FOO:
{
if ( bar ) {
return 0;
}
break;
}

Don't detect clicks via the WM_MOUSEMOVE message, use the WM_MOUSEDOWN instead.
The problem is that your code is probably launched by you clicking on something, so when your window gets its first WM_MOUSEMOVE message, the button is still actually pressed. Code runs much faster than fingers..

Related

Windows keyboard messages and Alt keys

I'm trying to understand how does the Message Loop and generally keyboard messages works in the Windows systems. I've written a simple program featuring the Message Loop:
// include the basic windows header file
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
char MsgBuff[300];
template <typename T>
char* BinVal(T SrcVal) {
const short BitsCount = sizeof(T) * CHAR_BIT;
const short SeparatorCount = sizeof(T) * 2 - 1;
static char BinValStr[BitsCount + SeparatorCount] = { 0 };
printf("BitsCount: %d\n", BitsCount);
printf("SeparatorCount: %d\n", SeparatorCount);
printf("BinValStr size: %d\n", BitsCount + SeparatorCount);
int i = 0;
int j = 0;
for (i = BitsCount + SeparatorCount - 1; i >= 0; i--) {
if ((j + 1) % 5 == 0) {
BinValStr[i] = ' ';
}
else {
if ((SrcVal & 1) == 1)
BinValStr[i] = '1';
else
BinValStr[i] = '0';
SrcVal >>= 1;
}
j++;
//printf(": %d, %d\n", i, SrcVal&1);
}
return BinValStr;
}
// the entry point for any Windows program
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow) {
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass1";
// register the window class
RegisterClassEx(&wc);
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"Our First Windowed Program", // title of the window
WS_OVERLAPPEDWINDOW, // window style
300, // x-position of the window
300, // y-position of the window
500, // width of the window
400, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
// enter the main loop:
// this struct holds Windows event messages
MSG msg;
// Enter the infinite message loop
while (TRUE) {
// Check to see if any messages are waiting in the queue
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// If the message is WM_QUIT, exit the while loop
if (msg.message == WM_QUIT)
break;
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
int LoopCnt = 0;
int BinMask = 0b00000000'00000000'00000000'11111111;
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_DESTROY: {
PostQuitMessage(0);
} break;
case WM_KEYDOWN: {
sprintf_s(MsgBuff, 300, "WM_KEYDOWN(#%i) wParam (virtual-key code): %d (%Xh), scan code: %X, lParam(bin): %s\n", LoopCnt, wParam, wParam, lParam & BinMask, BinVal(lParam));
OutputDebugStringA(MsgBuff);
} break;
case WM_CHAR: {
sprintf_s(MsgBuff, 300, "WM_CHAR(#%i) wParam (virtual-key code): %d (%Xh), scan code: %X, lParam(bin): %s\n", LoopCnt, wParam, wParam, lParam & BinMask, BinVal(lParam));
OutputDebugStringA(MsgBuff);
} break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
LoopCnt++;
}
There i examine the WM_KEYDOWN message lParam param for the scan code send.
Now i have following questions:
Why pressing the left Alt key doesn't generate a WM_KEYDOWN message while pressing right Alt does? (the debugger doesn't go into the WM_KEYDOWN: case statement when pressing the left Alt)
Why pressing the right Alt key generates TWO WM_KEYDOWN messages simultaneously - having 1D(hex) & 38 (hex) scan codes respectively?

After sending a WM_CHANGEUISTATE to the window app, the mnemonics are not shown on the system menu, when the menu is accessed with the mouse

The code below, sends a WM_CHANGEUISTATE to the window procedure itself, with the arguments:
LOWORD(wParam) = UIS_CLEAR
HIWORD(wParam) = UISF_HIDEACCEL
lParam = 0x00000000
when the window client area is left clicked with the mouse.
According to this blog by Raymond Chen this should make the mnemonics in the System menu to be shown, when the menu is accessed with the mouse. The paragraph below was extracted from this article:
Clearing a flag shows the corresponding indicator. For example, if you
have a UIS_CLEAR for UISF_HIDEĀ­FOCUS, that means that you want to show
focus indicators.
In my case, I have a UIS_CLEAR for UISF_HIDEACCEL, meaning that I want to show the menu accelerators.
If you run the code below and click with the mouse left button on the app client area, you should make the accelerators visible in the System menu, even when this menu is accessed with the mouse. But that doesn't happen, i.e., if you activate the system menu with a left click on the window's icon, or with a right click on the window's title bar, the mnemonics in the System menu will not be shown. What am I missing?
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
{
WNDCLASSEX wndclassx;
wchar_t szAppName[] = L"WM_CHANGEUISTATE";
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = CS_HREDRAW | CS_VREDRAW;
wndclassx.lpfnWndProc = WndProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = LoadCursor(0, IDC_ARROW);
wndclassx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclassx.lpszClassName = szAppName;
wndclassx.lpszMenuName = nullptr;
wndclassx.hIconSm = 0;
if (!RegisterClassEx(&wndclassx)) return 0;
HWND hWnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0);
ShowWindow(hWnd, SW_MAXIMIZE);
UpdateWindow(hWnd);
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
{
BOOL b;
// Note that in my system (Windows 10) I have:
//
// Control Panel > Ease of Access > Ease of Access Center > Make the keyboard easier
//
// and the option "Underline keyboard shortcuts and access keys" unmarked (the default). Therefore, the value
// returned in b below will be 0x00000000 (FALSE).
SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &b, 0);
// If b = FALSE, the SendMessage() below should underline the accelerators in the System menu, when this menu is
// accessed with the mouse. But that doesn't work. Why?
if( !b ) SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL), NULL);
}
break;
// Setting a break in the return below, one can see that WM_CHANGEUISTATE message is being sent to the window and
// passed to DefWindowProc().
case WM_CHANGEUISTATE:
return DefWindowProc(hwnd, message, wParam, lParam);
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
This seems like a bug/oversight in Windows. DefWindowProc does not send WM_QUERYUISTATE before displaying the system menu. The menu implementation checks the last input event directly and if it was from a keyboard it displays the underlines.
I tried sending and posting WM_CHANGEUISTATE and WM_UPDATEUISTATE in response to WM_ENTERMENULOOP, WM_INITMENUPOPUP, WM_NCRBUTTONDOWN and WM_SYSCOMMAND without any luck.
The only workaround I was able to come up with is to hack the HTSYSMENU/icon menu by changing SC_MOUSEMENU to SC_KEYMENU:
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_MOUSEMENU)
{
return SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, ' ');
}
return DefWindowProc(hwnd, message, wParam, lParam);
SC_KEYMENU has special handling in DefWindowProc and forces underlines if applicable.
This does not handle right-click on the icon, caption nor task bar...

C++ Close window not application

I'm trying to create two instances of a window class.
When the primary one is closed it should close the application but when the secondary one is closed it should just close that window.
However when either window is closed the application exits, and I'm not sure why. I've tried comparing the hWnd to check which window is being closed.
// include the basic windows header file
#include <windows.h>
#include <windowsx.h>
//Forgive me now
#define MAX_WINDOWS 1024
HWND hWindows[MAX_WINDOWS];
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass1";
RegisterClassEx(&wc);
hWindows[0] = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"Our First Windowed Program", // title of the window
WS_OVERLAPPEDWINDOW, // window style
300, // x-position of the window
300, // y-position of the window
500, // width of the window
400, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
hWindows[1] = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"Our First Windowed Program", // title of the window
WS_OVERLAPPEDWINDOW, // window style
300, // x-position of the window
300, // y-position of the window
500, // width of the window
400, // height of the window
hWindows[0], // primary window
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
ShowWindow(hWindows[0], nCmdShow);
ShowWindow(hWindows[1], nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch (message)
{
case WM_CLOSE:
{
if (hWnd = hWindows[0]) {
// close the application entirely
PostQuitMessage(0);
}
else {
DestroyWindow(hWnd);
}
return 0;
} break;
}
// Handle any messages the switch statement didn't
return DefWindowProc(hWnd, message, wParam, lParam);
}
if (hWnd = hWindows[0])
That's assignment. Since hWindows[0] is non-zero, that expression always evaluates true.
You mean:
if (hWnd == hWindows[0])
You should call PostQuitMessage in response to WM_DESTROY. And since the default window procedure calls DestroyWindow in response to WM_CLOSE, you can write it like this:
switch (message)
{
case WM_DESTROY:
{
if (hWnd == hWindows[0]) {
// close the application entirely
PostQuitMessage(0);
}
return 0;
}
break;
}
// Handle any messages the switch statement didn't
return DefWindowProc(hWnd, message, wParam, lParam);

WM_Quit message being sent when i click on textbox

so title says it all. i was thinking maybe because there are 81 textboxes it has somthing to do with layers but quite frankly i have no idea.. just started learning windows api like 2 days ago and ive been learning streight off the msdn library for functions.. i googled this problem multiple times and no luck so here i am. the help is much appreciated ^.^
// Win32Project9.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Win32Project9.h"
#include "Resource.h"
#include <Windows.h>
#include <vector>
#include <cstring>
using namespace std;
HWND Hwnd;
HMENU hMenu;
HWND boxes[81];
int x, y;
vector<LPWSTR> BoxNum;
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_EXIT:
PostQuitMessage(0);
return 0;
break;
case ID_SOLVE:
for (int i = 0; i < 81; i++)
{
GetWindowText(boxes[i], BoxNum[i], NULL);
}
break;
}
break;
}
if (msg == WM_COMMAND)
{
if (LOWORD(wParam) > 199 && LOWORD(wParam) < 281)
{
if (HIWORD(wParam) == EN_SETFOCUS | HIWORD(wParam) == EN_UPDATE)
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
}
else if (msg == WM_CLOSE)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void DrawBoard()
{
x = 10;
y = 10;
int count = 0;
for (int i = 0; i < 81; i++)
{
int BOX_ID = 200 + i;
boxes[i] = CreateWindow(TEXT("Edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE, x, y, 20, 20, Hwnd, (HMENU)BOX_ID, NULL, NULL);
x += 30;
count++;
if (count == 9)
{
y += 30;
x = 10;
count = 0;
}
}
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//structure to hold window specs
WNDCLASSEX Wc;
//allocate memory for window class
ZeroMemory(&Wc, sizeof(WNDCLASSEX));
//fill in neccessary info
Wc.cbSize = sizeof(WNDCLASSEX);
Wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
Wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
Wc.hInstance = hInstance;
Wc.lpfnWndProc = WindowProcedure;
Wc.lpszClassName = L"MyClass";
Wc.style = CS_HREDRAW | CS_VREDRAW;
//register class
RegisterClassEx(&Wc);
//load menu into handle
hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(ID_MENU));
//Create Window with class and create handle
Hwnd = CreateWindow(L"MyClass", L"Sudoku", WS_OVERLAPPEDWINDOW, 0, 0, 300, 340, NULL, hMenu, hInstance, NULL);
//DisplayWindow
ShowWindow(Hwnd, nCmdShow);
DrawBoard();
//structure to hold input stream
MSG msg;
//listen for input
while(GetMessage(&msg, Hwnd, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
also i read that wm_close is processed when i press the x button. well this message is being recieved even when i click the text boxes. and if you look at my case WM_Close.. i coded it to make a message box and give the user a chance to accept or not.... so when this happens after clicking on a text box i click no and another message box apperas asking again, i click no and it goes away but when i click the x button and i click no the window still dissapears .....
The problem is probably that WM_COMMAND is not handled properly.
The arguments received are as follows:
WORD code = HIWORD(wParam);
WORD id = LOWORD(lParam);
The problem is that code depends on the type of control you are using. For example, if it is a button it will be some of the BTN_* values, if it is an edit it will be EN_* and so on. But these values overlap badly, so you cannot use them in a single switch.
For example CBN_KILLFOCUS==4, but also LBN_SETFOCUS==4... Also menu items will get here a 0 and accelerators a 1. By the way, BN_CLICKED==0 and it looks like no other notification message uses 0, so you can use the same IDs in menus and buttons and it will just work. And accelerators too, with a bit of care... BN_PAINT==1, I think this one does not exist anymore, but you get the point...
Anyway, to your problem. My guess is that you have an EDIT that happens to have an ID equal to IDM_EXIT. Since you are not checking the HIWORD(wParam) you are quitting when you receive the EN_SETFOCUS on this control.
The solution is: First, always check both WORDs from wParam. Second, avoid collisions between menu options and ID controls, except maybe with buttons.
case WM_COMMAND:
switch (LOWORD(wParam))
That isn't quite good enough. Edit controls also send WM_COMMAND messages to notify their parent window about stuff going on. Like EN_UPDATE whenever you type a character. Or EN_SETFOCUS when they get the focus, sounds like your case when you see this go wrong when you click on them. These notifications are wrapped in a WM_COMMAND message.
You must therefore pay attention to where the WM_COMMAND message came from. The LPARAM argument tells you. If IDM_EXIT comes from a menu item then you must verify that LPARAM is 0. Check the MSDN library for details.

win32 program for multiple windows

i am trying to write a program for multiple windows. In this program when user left click on one window it should a message which window was clicked. Here is my code:
#include<Windows.h>
// Store handles to the main window and application instance globally.
HWND ghFirstWnd =0;
HWND ghSecondWnd=0;
HWND ghThirdWnd=0;
HINSTANCE ghAppInst=0;
//========================================================================================
// WINDOW 1
// Step 1: Define and implement the window procedure.
LRESULT CALLBACK
WndProc1(HWND hWnd,UINT msg,WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
// Handle left mouse button click message.
case WM_LBUTTONDOWN:
MessageBox(0,L"first window ",L"MSG",MB_OK);
return 0;
// Handle key down message.
case WM_KEYDOWN:
if(wParam==VK_ESCAPE)
if(MessageBox(hWnd,L"sure ??",L"confirmation",MB_YESNO)==IDYES)
DestroyWindow(ghFirstWnd);
return 0;
// Handle destroy window message.
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//========================================================================================
// WINDOW 2
//========================================================================================
LRESULT CALLBACK
WndProc2(HWND hWnd,UINT msg, WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
MessageBox(0,L"second window",L"msg",MB_OK);
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//========================================================================================
// WINDOW 3
//========================================================================================
LRESULT CALLBACK
WndProc3(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
MessageBox(0,L"third window",L"msg",MB_OK);
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 wc1;
wc1.style =CS_HREDRAW|CS_VREDRAW;
wc1.lpfnWndProc =WndProc1;
wc1.cbClsExtra=0;
wc1.cbWndExtra=0;
wc1.hInstance=ghAppInst;
wc1.hIcon=::LoadIcon(0,IDI_APPLICATION);
wc1.hCursor=::LoadCursor(0,IDC_ARROW);
wc1.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
wc1.lpszMenuName=0;
wc1.lpszClassName=L"first class";
// Window 2
WNDCLASS wc2;
wc2.style=CS_HREDRAW|CS_VREDRAW;
wc2.lpfnWndProc=WndProc2;
wc2.cbClsExtra=0;
wc2.cbWndExtra=0;
wc2.hInstance=ghAppInst;
wc2.hIcon=::LoadIcon(0,IDI_APPLICATION);
wc2.hCursor=::LoadCursor(0,IDC_ARROW);
wc2.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
wc2.lpszMenuName=0;
wc2.lpszClassName=L"second class";
// 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.hbrBackground=(HBRUSH)::GetStockObject(WHITE_BRUSH);
wc3.lpszMenuName=0;
wc3.lpszClassName=L"third class";
// Step 3: Register with WNDCLASS instance with windows.
RegisterClass(&wc1);
RegisterClass(&wc2);
RegisterClass(&wc3);
// Step 4: Create the window, and save the handle in global window handle variable ghMainWnd.
ghFirstWnd=::CreateWindow(L"MyWndClassName",L"MyWindow1",WS_OVERLAPPEDWINDOW,0,0,50,50,0,0,ghAppInst,0);
ghSecondWnd=::CreateWindow(L"MyWndClassName",L"MyWindow2",WS_OVERLAPPEDWINDOW,50,0,50,50,0,0,ghAppInst,0);
ghThirdWnd=::CreateWindow(L"MyWndClassName",L"MyWindow3",WS_OVERLAPPEDWINDOW,100,0,50,50,0,0,ghAppInst,0);
if(ghFirstWnd==0)
{
::MessageBox(0,L"create window1-failed",0,0);
return false;
}
if(ghSecondWnd==0)
{
::MessageBox(0,L"create window2 failed",0,0);
return false;
}
if(ghThirdWnd==0)
{
::MessageBox(0,L"create window3 failed",0,0);
return false;
}
// Step 5: Show and update the window.
ShowWindow(ghFirstWnd,showCmd);
UpdateWindow(ghFirstWnd);
ShowWindow(ghSecondWnd,showCmd);
UpdateWindow(ghSecondWnd);
ShowWindow(ghThirdWnd,showCmd);
UpdateWindow(ghThirdWnd);
// 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;
}
problem is when i try to execute the code it just say create window1- failed!!
Cutting the program down, you can end up with something similar to this (I've made a couple changes to the code itself, but it should still work in C++03):
#include <Windows.h>
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE, PSTR,int showCmd)
{
WNDCLASS wc1 = {};
wc1.style = CS_HREDRAW|CS_VREDRAW;
wc1.lpfnWndProc = DefWindowProc;
wc1.hInstance = hInstance;
wc1.hIcon = ::LoadIcon(0,IDI_APPLICATION);
wc1.hCursor = ::LoadCursor(0,IDC_ARROW);
wc1.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
wc1.lpszClassName = L"first class";
RegisterClass(&wc1);
HWND ghFirstWnd = ::CreateWindow(L"MyWndClassName",L"MyWindow1",WS_OVERLAPPEDWINDOW,0,0,50,50,0,0,hInstance,0);
if(!ghFirstWnd)
{
::MessageBox(0,L"create window1-failed",0,0);
return 1;
}
return 0;
}
With this little code, it's much easier to spot your mistake. Your window class is named "first class", but in your CreateWindow call, you use a class named "MyWndClassName". The class cannot be found, so no window can be created using it.
On a side note, you have little error checking. One thing that would really beef it up is using GetLastError appropriately.
CreateWindow function returns handle to the windows or when fails then returns NULL.
So replace 'if(ghFirstWnd==0)" with "if(ghFirstWnd==NULL)" and check what happens. I'm not sure because I don't use Win32.
If only "create window1-failed" message is displaying maybe try to replace "if(ghSecondWnd==0)" with "if(ghSecondWnd==1)" and then two message boxes should appear.