I am in the process of learning the Win32 API. I have a problem where the window is visibly closed but the application is running in the background (I can see this using the Windows 10 task manager). Here is my code that closes the window:
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
My application is called a.exe and you can see it in this screenshot I took of the Windows 10 task manager.
Read the docs:
"The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future.
When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system. The exit value returned to the system must be the wParam parameter of the WM_QUIT message.
The WM_QUIT message is not associated with a window and therefore will never be received through a window's window procedure. It is retrieved only by the GetMessage or PeekMessage functions."
See think link also.
I have discovered the issue. Thanks for all the help but the window was actually being closed but the console was still open in the background. I was running:
FreeConsole();
and that was hiding the console. When I closed the window the console kept running and I am now closing the console as well and it works.
Related
I know with Windows notification message, WM_CLOSE refers to closing the window via "X" button on the top right hand corner of the window.
Does anyone know the notification message for closing with File->Exit?
The reason I asked is because I'm trying to implement JNI native code to gracefully close window when user initiated system shutdown. refer to my earlier post (Winapi - SetWindowLongPtr in ShutdownBlockReasonCreate / Destroy implementation of JNI native code) for background.
When clicking on 'X' to close, confirmation dialog box comes up which prevents shutdown reason message from disappearing (when I expect it to disappear after a while). I know File->Exit from menu bar doesn't ask for confirmation, but how do I implement this using windows notification message?
After some digging around the only suggestions I found is to use DestroyWindow. So I tried closing the window using DestroyWindow() function, but it only "Destroys" the window, rather than ending the whole application. Here's my switch statement in my WndProc CallBack function:
switch (message) {
case WM_QUERYENDSESSION:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
case WM_ENDSESSION:
PostMessage(hWnd, WM_CLOSE, 0, 0);
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, AppWndProc, uIdSubclass);
break;
}
Any help would be much appreciated!
Cheers
I know with Windows notification message, WM_CLOSE refers to closing the window via "X" button on the top right hand corner of the window.
Actually, when the window's standard "X" button is clicked (or the standard "Close" item on the window's top-left corner menu is selected if enabled, or the window receives an ALT+F4 keystroke), a WM_SYSCOMMAND message is issued to the window with the wParam containing the SC_CLOSE flag. If that message is passed to DefWindowProc() (the default behavior), it then issues a WM_CLOSE message to the window.
See Closing the Window.
It is possible that other conditions can also cause a WM_CLOSE message to be issued.
Does anyone know the notification message for closing with File->Exit?
What happens when that menu item is selected is defined by the application, not the OS. The application can do whatever it wants, including destroying the window immediately if it wants to.
However, that being said, if the menu is a standard Win32 menu, then the window will receive a WM_COMMAND message containing the ID of the menu item that was selected, at least.
The reason I asked is because I'm trying to implement JNI native code to gracefully close window when user initiated system shutdown.
By default, you don't need to do anything for that. The OS automatically closes all open windows during system shutdown. Rather than closing your window manually, you should instead react to your window being closed, if you need to clean up any resources.
When clicking on 'X' to close, confirmation dialog box comes up which prevents shutdown reason message from disappearing (when I expect it to disappear after a while).
Then the application is not handling system shutdown correctly.
Most applications present such a confirmation box in response to receiving the WM_CLOSE message. If the confirmation is aborted, the application discards the message and moves on. However, applications shouldn't prompt the user for confirmation during system shutdown. But not all applications follow that rule.
I know File->Exit from menu bar doesn't ask for confirmation
Again, that is for the application to decide, not the OS.
how do I implement this using windows notification message? After some digging around the only suggestions I found is to use DestroyWindow.
Correct. Or, you can alternatively post a WM_QUIT message to the message queue instead. See the PostQuitMessage() function.
So I tried closing the window using DestroyWindow() function, but it only "Destroys" the window, rather than ending the whole application.
It is the application's responsibility to terminate itself, usually by exiting its message loop when its main window has been destroyed.
Here's my switch statement in my WndProc CallBack function:
There is no need to post WM_CLOSE in response to WM_QUERYENDSESSION or WM_ENDSESSION. Let the OS handle that for you.
If you don't want the confirmation to appear during system shutdown, change your code to something more like this:
bool shuttingDown = false;
LRESULT CALLBACK AppWndProc(
_In_ HWND hWnd,
_In_ UINT message,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
_In_ UINT_PTR uIdSubclass,
_In_ DWORD_PTR dwRefData
) {
switch (message) {
case WM_QUERYENDSESSION:
shuttingDown = true;
break;
case WM_ENDSESSION:
if (wParam == FALSE)
shuttingDown = false;
break;
case WM_CLOSE:
if (shuttingDown) {
DestroyWindow(hWnd);
// or:
// PostQuitMessage(0);
return 0;
}
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, AppWndProc, uIdSubclass);
break;
}
return DefSubclassProc(hWnd, message, wParam, lParam);
}
There's no specific message to handle your File>Exit. You must handle it as any other menu item:
Define an identifier for your menu item. Choose anything you want, it has no particular meaning for windows.
When constructing your menu, specifiy this identifier in AppendMenu/InsertMenu/etc. or in your resource file
In your window procedure, intercept the WM_COMMAND message. If LOWORD(wParam) corresponds to the identifier, this means that the menu item has been activated
A typical way of handling an exit command is to send a WM_CLOSE message, as you are already doing in your example code.
So you will avoid code duplication and be sure that the behavior will be the same regardless of how the user choose to exit your application (via menu, click on the "x", or Alt+F4)
In the handing of WM_CLOSE, you can choose to show a message box, destroy the window, post a quit message, or whatever else you want. BY default the DefWindowProc calls DestroyWindow, which in turn sends the WM_DESTROY message.
Note that WM_CLOSE is also triggered when selecting the "Close" item of the system menu (Alt+Space or click on the window icon on the left next to the window title)
I wanted to read out messages in my message loop right before I dispatch them to my window procedure. Most messages I tried reading like this were read correctly, but when I close the window, a WM_CLOSE or WM_DESTROY message could not be read as it seems as if they were never received. Here's what i do:
void Framework::Run(){
while(running){
MSG msg;
while(PeakMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
switch(msg.message){
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_QUIT:
running = false;
break;
//...other cases...
}
DispatchMessage(&msg);
}
//...
}
}
I put a breakpoint at the first case, but even when I close the window (by clicking the 'X') the breakpoint is never hit. Though, when I check for WM_DESTROY in the window procedure, it gets read and every thing goes fine. Why not outside it?
Are such messages sent directly to the window proc? How?
A message loop only sees messages that are posted to the calling thread's message queue. Not all messages go through the message queue. WM_DESTROY is one such message. What you should be doing instead is handling the messages in the window procedure so you see every message that the window receives, whether the message went through the message queue or not.
If you need to look at messages for a window you are not creating yourself, or for a standard window that has a system-provided window procedure, you can subclass the window using SetWindowLongPtr(GWLP_WNDPROC) or SetWindowSubclass(). See Subclassing Controls for more details.
In my demo kinda app
case WM_CLOSE:
DestroyWindow(hndl);
return 0;
and
case WM_CLOSE:
PostQuitMessage(0);
return 0;
do the same. What's different behind the curtains when calling each? Is DestroyWindow more direct, where as PostQuitMessage has to go through the getmessage loop returning false?
DestroyWindow destroys the window (surprise) and posts a WM_DESTROY (you'll also get a WM_NCDESTROY) to the message queue. This is the default behaviour of WM_CLOSE. However, just because a window was destroyed does not mean the message loop should end. This can be the case for having a specific window that ends the application when closed and others that do nothing to the application when closed (e.g., an options page).
PostQuitMessage posts a WM_QUIT to the message queue, often causing the message loop to end. For example, GetMessage will return 0 when it pulls a WM_QUIT out. This would usually be called in the WM_DESTROY handler for your main window. This is not default behaviour; you have to do it yourself.
Neither snippet is correct. The first one will do what the default window procedure already does when it processes the WM_CLOSE message so is superfluous. But doesn't otherwise make the application quit, it should keep running and you'd normally have to force the debugger to stop with Debug + Stop Debugging. If you run it without a debugger then you'll leave the process running but without a window so you can't tell it is still running. Use Taskmgr.exe, Processes tab to see those zombie processes.
The second snippet will terminate the app but will not clean up properly since you don't pass the WM_CLOSE message to the default window procedure. The window doesn't get destroyed. Albeit that the operating system will clean up for you so it does all come to a good end, just without any bonus points for elegance.
The proper way to do it is to quit when your main window is destroyed. You'll know about it from the WM_DESTROY notification that's sent when that happens:
case WM_DESTROY:
PostQuitMessage(0);
return 0;
PostQuitMessage doesn't necessarily mean the end of application. It simply posts WM_QUIT to the message loop and allows you to exit from the message loop, so in most cases, this means the end of the application. However, in a multithread application, if you have the message loop for each thread created, PostQuitMessage only closes that thread.
As a side note, if you ever need more lines of code to execute after the message loop (such as further clean-up), PostQuitMessage is a better way to go, because DestroyWindow destroys the window without going through the message loop, ignoring whatever clean-up codes remaining after the message loop. Some may call it a not-so-good coding practice, but sometimes you can't avoid situations like that.
I create the class that inherited CWinApp and this class has a timer (use a window timer).
When PC go sleep mode and wake-up, timer callback is called exact time of wake-up. I want to make to not call the timer callback when PC is resuming from suspend.
So I tried to use WM_POWERBROADCAST message. But this message didn't catch in PreTranslateMessage() API. Also I tried SetWindowLong() with my own API but still didn't catch the WM_POWERBROADCAST message.
Is there any way to get WM_POWERBROADCAST in CWinApp?
In a Visual Studio C++ MFC application you will need to add an ON_MESSAGE() to your message map looking for the WM_POWERBROADCAST message as in this example:
BEGIN_MESSAGE_MAP(CFrameworkWndApp, CWinApp)
//{{AFX_MSG_MAP(CFrameworkWndApp)
ON_WM_CHAR()
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_POWERBROADCAST, OnPowerMsgRcvd)
END_MESSAGE_MAP()
Then you will need to add the message handler function along with the class definition change to declare the member function for the message handler so that you can check the wParam variable for the message type as in this skeleton. Remember to return an LRESULT value indicating if you handled the message or not.
// Handle the WM_POWERBROADCAST message to process a message concerning power management
// such as going to Sleep or Waking Up.
LRESULT CFrameworkWndApp::OnPowerMsgRcvd(WPARAM wParam, LPARAM lParam)
{
LRESULT lrProcessed = 0; // indicate if message processed or not
switch (wParam) {
case PBT_APMPOWERSTATUSCHANGE:
TRACE0("PBT_APMPOWERSTATUSCHANGE received\n");
break;
case PBT_APMRESUMEAUTOMATIC:
TRACE0("PBT_APMRESUMEAUTOMATIC received\n");
break;
case PBT_APMRESUMESUSPEND:
TRACE0("PBT_APMRESUMESUSPEND received\n");
break;
case PBT_APMSUSPEND:
TRACE0("PBT_APMSUSPEND received\n");
break;
}
// indicate if framework needs to handle message or we did ourselves.
return lrProcessed;
}
See Microsoft documentation - Power Management as well as the particular subsection of that documentation Microsoft documentation - WM_POWERBROADCAST message for details on handling the message.
See also the SetThreadExecutionState() function which affects how Windows determines whether an application is active or not and whether sleep mode should be entered or not.
See also the following Stack Overflow postings:
WM_POWERBROADCAST message not caught in MFC Dlg
WM_POWERBROADCAST not received by message-only window in Windows XP
How to receive WM_POWERBROADCAST inside of a thread?
How can I detect suspend on Windows Mobile?
How to detect Windows suspend message?
It is a Windows message. It gets sent to all Top-Level windows. So, in order to catch this message, create a handler in your main window
I was wondering what the difference between the WM_QUIT, WM_CLOSE, and WM_DESTROY messages in a windows program, essentially: when are they sent, and do they have any automatic effects besides what's defined by the program?
They are totally different.
WM_CLOSE is sent to the window when it is being closed - when its "X" button is clicked, or "Close" is chosen from the window's menu, or Alt-F4 is pressed while the window has focus, etc. If you catch this message, this is your decision how to treat it - ignore it, or really close the window. By default, WM_CLOSE passed to DefWindowProc() causes the window to be destroyed.
WM_DESTROY is sent to the window when it starts to be destroyed. In this stage, in opposition to WM_CLOSE, you cannot stop the process, you can only make any necessary cleanup. When you catch WM_DESTROY, none of its child windows have been destroyed yet.
WM_NCDESTROY is sent to the window when it is finishing being destroyed. All of its child windows have been destroyed by this time.
WM_QUIT is not related to any window (the hwnd got from GetMessage() is NULL, and no window procedure is called). This message indicates that the message loop should be stopped and the application should exit. When GetMessage() reads WM_QUIT, it returns 0 to indicate that. Take a look at a typical message loop snippet - the loop is continued while GetMessage() returns non-zero.
WM_QUIT can be sent by the PostQuitMessage() function. This function is usually called when the main window receives WM_DESTROY (see a typical window procedure snippet).
First of all, the WM_CLOSE and WM_DESTROY messages are associated with particular windows whereas the WM_QUIT message is applicable to the whole application (well thread) and the message is never received through a window procedure (WndProc routine), but only through the GetMessage or PeekMessage functions.
In your WndProc routine the DefWindowProc function takes care of the default behavoir of these messages. The WM_CLOSE messages requests that the application should close and the default behavoir for this is to call the DestroyWindow function. Its when this DestroyWindow function is called that the WM_DESTROY message is sent. Notice that the WM_CLOSE is only a message requesting that you close (like WM_QUIT) - you don't actually have to exit/quit. But the WM_DESTROY message tells you that your window IS being closed and destroyed so you must cleanup any resources, handles etc.
Just so it doesn't get lost in the comments... don't forget about WM_CANCEL. When you click the close (x) button on an MFC dialog, it will certainly send WM_CLOSE. The default OnClose() function will then call the default (base class) OnCancel() function.
However, if you simply type the ESC key, this will lead to the closure of the dialog, but (as far as I can tell) without generating the WM_CLOSE event - it goes directly to the WM_CANCEL/OnCancel() mechanism.
I hereby invite the community to elaborate on this... or edit that elaboration into the accepted answer.
At first let's discuss WM_QUIT - the difference from another messages that this is not associated with window. It is used by application. For example this can be handled by non-visible standalone OLE server (.exe, but not in-proc as .dll)
WM_CLOSE - per msdn: "An application can prompt the user for confirmation, prior to destroying a window" - it is used as notification about intention to close (you can reject this intention).
WM_DESTROY - is a fact that window is closing and all resources must(!) be deallocated.
I know this is old, but just trying to provide a clearer answer for anyone.
// What causes each message?
WM_CLOSE: // Pressed Close Button (X) / Alt+F4 / "Close" in context menu
WM_DESTROY: // Called DestroyWindow(hwnd)
WM_QUIT: // Called PostQuitMessage(exit)
// What do they do by default?
case WM_CLOSE: DestroyWindow(hwnd); return 0; // pressed close? destroy window.
case WM_DESTROY: PostQuitMessage(0); return 0; // destroyed window? quit message loop.
// WM_QUIT isn't associated with a window, so isn't sent to the window procedure
So WM_CLOSE is just so we can request to destroy the window. However you might want it to show a popup in your game asking if you're sure. (and if you want to save first)
And WM_DESTROY doesn't actually post the quit message by default, since you could have multiple windows. That's just the usual event we quit after. You could have WM_CLOSE call PostQuitMessage(exit) and destroy your window(s) after the message loop if you wanted.
If you wanted a custom close button in your game, it should do what WM_CLOSE does.
Also there is the function CloseWindow(hwnd), however it simply minimizes the window.
Hope this helps anyone.