C++ Close window not application - c++

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);

Related

How to handle a button press (Desktop Application)

I am making a desktop application, and I got it to display a button. Now what I am trying to do is somehow handle the button press, but I do not know how. Here is my code so far:
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("DesktopApp");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("First Desktop Application");
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// Store instance handle in our global variable
hInst = hInstance;
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 500,
NULL,
NULL,
hInstance,
NULL
);
HWND hwndButton = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"Test2", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
10, // x position
100, // y position
100, // Button width
20, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Test");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
It is a Windows Desktop Wizard project on Visual Studio 2019. I just want it to do something simple like display some text on the screen or something when the button is pressed.
This is what the window looks like:
When a BUTTON is clicked, it sends a BN_CLICKED notification message to its parent window. You would simply handle that message in your WndProc(), eg:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
...
case WM_COMMAND:
{
if (HIWORD(wParam) == BN_CLICKED)
{
// LOWORD(wParam) is the button's ID
// HWND(lParam) is the button's HWND
// do something with them as needed...
return 0;
}
break;
}
...
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This is explained in the BUTTON documentation on MSDN:
Button Messages
Handling Messages from a Button
Notifications from a button are sent as either WM_COMMAND or WM_NOTIFY messages. Information about which message is used can be found on the reference page for each notification.
For more information on how to handle messages, see Control Messages. See also Button Messages.
Notification Messages from Buttons
When the user clicks a button, its state changes, and the button sends notification codes, in the form of WM_COMMAND messages, to its parent window. For example, a push button control sends the BN_CLICKED notification code whenever the user chooses the button. In all cases (except for BCN_HOTITEMCHANGE), the low-order word of the wParam parameter contains the control identifier, the high-order word of wParam contains the notification code, and the lParam parameter contains the control window handle.

WINAPI GetMessage HWND

I am working on window creation with Win32 API and I'm having a problem with this part:
GetMessage(&message, NULL, 0, 0);
My problem is that when I try to change the second parameter (hwnd) which is going to receive the messages to the window I previously made, it doesn't work; for example, when I try to close the window, it only hides and doesn't close.
Here is the full code:
#include <windows.h>
LRESULT CALLBACK WinProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASS window;
window.cbClsExtra = NULL;
window.cbWndExtra = NULL;
window.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
window.hCursor = LoadCursor(hInst, IDC_ARROW);
window.hIcon = NULL;
window.hInstance = hInst;
window.lpfnWndProc = WinProc;
window.lpszClassName = "WINDOW";
window.lpszMenuName = NULL;
window.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&window);
HWND hwnd = CreateWindow("WINDOW", "Win32 Window Application", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, NULL, NULL, hInst, NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return 1;
}
LRESULT CALLBACK WinProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
{
PostQuitMessage(0);
break;
}
default:
break;
}
return DefWindowProc(window, message, wParam, lParam);
}
"... when I try to change the second parameter (hwnd) which is going to receive the messages to the window I previously made, it doesn't work."
Thread messages are not sent to a window; they're posted to the thread message queue with a NULL window handle, and will NOT be picked up with a GetMessage() loop tailored to a specific window handle.
Ex: PostQuitMessage() posts a thread message; not a window message. You need the NULL. From the GetMessage() docs:
If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.

WinAPI Window Closes Instantly

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..

C++ How does Allegro or SDL create window?

How does Allegro or SDL create window for Windows and how to do it by myself?
I'm trying to write WinApi wrapper for games, but I'm completly lost, when I see basic WinApi template and want to wrap it to something like this
init();
while()
{
update();
}
exit();
They use CreateWindowEx. A really simple WinAPI app that creates a window looks a little like this:
#include <Windows.h>
// If you're using MSVC, this is the easiest HINSTANCE. Other compilers
// get it from WinMain and pass in to constructor.
extern "C" IMAGE_DOS_HEADER __ImageBase;
HINSTANCE hInstance = (HINSTANCE)&__ImageBase;
class Window {
HWND hWnd;
static LRESULT __stdcall WindowProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
if (Window* ptr = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWLP_USERDATA)))
return ptr->DoMessage(hWnd, message, wParam, lParam);
else
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT DoMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
public:
bool DoMessages() {
MSG msg;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
// Translate the message and dispatch it to WindowProc()
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.message == WM_QUIT) {
return false;
}
return true;
}
Window() {
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";
RegisterClassEx(&wc);
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"Wide::Development", // title of the window
WS_OVERLAPPEDWINDOW, // window style. Always windowed for now.
0, // x-position of the window
0, // y-position of the window
1, // width of the window
1, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL);
ShowWindow(hWnd, SW_MAXIMIZE); // Snap our window to the user's desktop res, minus taskbar etc.
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); // Make sure that our WindowLongPtr is updated.
}
};
int main() {
Window window;
while(window.DoMessages()) {
// Do app updates, or sleep() if you're mostly waiting on user input
Sleep(50);
}
// When DoMessages() returns false, the window was destroyed, so return.
}
You can look up the MSDN documentation for more information on what these functions do. Essentially, all it does is create a very simple maximized non-fullscreen window, register for input, and when the window is destroyed, quit the application. You'll notice that I actually forwarded the input to the Window object, so this most basic of all frameworks is object-orientated and you can play with inheritance here if you want, just don't forget that the WindowLongPtr functions use a void* and are not type safe.
It's also worth mentioning that on some compilers like MSVC, if you #include <Windows.h>, they expect for you to use the WinMain entry point, not main().
The game rendering and update code is typically miles more complex and difficult than the WinAPI, so I'd grab a book on DirectX9.0c or DirectX10.

WS_EX_TOOLWINDOW jumping to background on window destroy

Weird issue:
Open a large notepad window
create a toolwindow (style WS_EX_TOOLWINDOW)
create 2 more windows (normal overlapped) (WS_OVERLAPPED)
close those 2 overlapped windows (child of desktop or the toolwindow)
the toolwindow jumps behind the notepad window
Does anyone know why this is the case? Or what I could be doing wrong? I would say 'bug in windows', but that is rarely the case.
To answer questions:
It is not a dialog window, but a full window. If i make it have correct children (ie: not a child of desktop), the taskbar entry for the children do not appear (probably easily fixable), but either way, the bug still happens.
I have included example code that shows the issue. I am hoping I am just creating the window wrong or required to respond to a message I am not responding to.
In this example, a tool window will open (no task bar entry, which is what is wanted). Then you click on that window, a subwindow will open. You click on the subwindow, another window will open. Then close both new subwindows and the original window, instead of getting focus, jumps immediately to behind other windows (notepad, etc).
Thanks for any help!
Example code to clarify:
// WindowToback.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "WindowToback.h"
// Global Variables:
HINSTANCE g_instance;
HWND g_mainWnd = NULL;
wchar_t *szWindowClass = L"WindowToBackSub";
wchar_t *szWindowClass2 = L"WindowToBackSub2";
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc2(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWTOBACK));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDOWTOBACK);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&wcex);
wcex.lpfnWndProc = WndProc2;
wcex.lpszClassName = szWindowClass2;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
g_instance = hInstance;
g_mainWnd = CreateWindowEx(WS_EX_TOOLWINDOW,szWindowClass, szWindowClass,WS_OVERLAPPED,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!g_mainWnd) return FALSE;
ShowWindow(g_mainWnd, nCmdShow);
UpdateWindow(g_mainWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
HWND l_hwnd = CreateWindow(szWindowClass2, szWindowClass2, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_instance, NULL);
ShowWindow(l_hwnd,SW_SHOW);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
HWND l_hwnd = CreateWindow(szWindowClass2, szWindowClass2, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_instance, NULL);
ShowWindow(l_hwnd,SW_SHOW);
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This isn't surprising. In fact, it's exactly the behavior I'd expect.
You're tool window isn't jumping down; rather Notepad is jumping up.
You closed the window that had activation. The system is going to activate the next-highest top-level window in the z-order. Your tool window doesn't a count as a top-level window in this regard (that's part of what being a tool window means). So Notepad gets activated, and it comes to the top.
If you want your tool window to get activated instead, you probably don't really want a tool window.
Are the three windows dialogs to another main window or are they applications in their own right?
If they are dialog windows then I would check that their parent window is correctly assigned.
If they are application windows then I would check that they are appearing in the taskbar.
Without more information about the problem it is hard to give a more meaningful answer.