1

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

dale
  • 439
  • 3
  • 11
  • 28
  • Menus are application specific, you get a message that a menu item have been selected and then you have to check which menu item it was yourself. In short, there's no "message" that means "File -> Exit". – Some programmer dude Jan 10 '20 at 05:08
  • 3
    Also since your application handles the menu items, there's nothing to stop your application from showing some kind of confirmation dialog on "File -> Exit". Actually, such a dialog is part of the application logic for `WM_CLOSE` as well, it's not something built into Windows or the Windows API itself, because it don't know what conditions the applications needs to consider data "unsaved" and needing a confirmation dialog. – Some programmer dude Jan 10 '20 at 05:11
  • Send yourself a WM_SHUTDOWN. Is there some cogent reason why this suggestion was removed? – user207421 Jan 10 '20 at 05:29
  • @user207421 WM_SHUTDOWN isn't a standard Windows message. – Jonathan Potter Jan 10 '20 at 05:42
  • Thanks @Someprogrammerdude, I'm convinced by your comments. There is actually an option to toggle the confirmation dialog to "not" appear when close the window. So it's more of an application logic is to be dealt with than Windows. Thanks again! – dale Jan 10 '20 at 05:47
  • @JonathanPotter Must be an OS/2 thing? – user207421 Jan 10 '20 at 05:48
  • @user207421 Maybe, next time I visit the 1980s I'll look it up :) – Jonathan Potter Jan 10 '20 at 05:58

2 Answers2

2

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);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

There's no specific message to handle your File>Exit. You must handle it as any other menu item:

  1. Define an identifier for your menu item. Choose anything you want, it has no particular meaning for windows.
  2. When constructing your menu, specifiy this identifier in AppendMenu/InsertMenu/etc. or in your resource file
  3. 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)

QuentinC
  • 12,311
  • 4
  • 24
  • 37
  • 1
    "*In the handing of WM_CLOSE, ... BY default the DefWindowProc does nothing, leaving the window open.* - not true. If `DefWindowProc()` receives a `WM_CLOSE` message, it destroys the window. This is documented behavior, [here](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-close) and [here](https://learn.microsoft.com/en-us/windows/win32/learnwin32/closing-the-window). – Remy Lebeau Jan 10 '20 at 06:40
  • Oh, yes, sorry, I'll edit my answer. I should have checked myself first. Thank you. – QuentinC Jan 10 '20 at 12:24