Winapi - альтернативы WM_CLOSE - PullRequest
       83

Winapi - альтернативы WM_CLOSE

0 голосов
/ 10 января 2020

Я знаю с уведомлением Windows, WM_CLOSE означает закрытие окна с помощью кнопки "X" в верхнем правом углу окна.

Кто-нибудь знает сообщение с уведомлением о закрытии с помощью File- > Выход?

Причина, по которой я спросил, заключается в том, что я пытаюсь реализовать собственный код JNI, чтобы изящно закрыть окно, когда пользователь инициировал выключение системы. см. мой предыдущий пост ( Winapi - SetWindowLongPtr в ShutdownBlockReasonCreate / уничтожить реализацию собственного кода JNI ) для фона.

При нажатии «X» для закрытия появляется диалоговое окно подтверждения, которое предотвращает сообщение о причине выключения исчезает (когда я ожидаю, что оно исчезнет через некоторое время). Я знаю, что Файл-> Выход из строки меню не запрашивает подтверждения, но как мне реализовать это, используя windows уведомляющее сообщение?

После некоторого изучения единственного предложения, которое я нашел, это использовать DestroyWindow. Поэтому я попытался закрыть окно с помощью функции DestroyWindow (), но оно только «разрушает» окно, а не завершает все приложение. Вот мой оператор switch в моей функции WndPro c CallBack:

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

Любая помощь будет принята с благодарностью!

Приветствия

Ответы [ 2 ]

2 голосов
/ 10 января 2020

Я знаю с Windows уведомлением, WM_CLOSE означает закрытие окна с помощью кнопки "X" в верхнем правом углу окна.

На самом деле, когда окно щелкают по стандартной кнопке «X» (или, если она включена, выбирается стандартный элемент «Закрыть» в верхнем левом углу окна, или окно получает нажатие клавиши ALT + F4 ), сообщение WM_SYSCOMMAND выдается окну с wParam, содержащим флаг SC_CLOSE. Если это сообщение передается DefWindowProc() (поведение по умолчанию), оно выдает в окно сообщение WM_CLOSE.

См. Закрытие окна .

Возможно, что из-за других условий также будет выдано сообщение WM_CLOSE.

Кто-нибудь знает сообщение с уведомлением о закрытии с помощью File-> Exit?

Что происходит при выборе этого пункта меню, определяется приложением, а не ОС. Приложение может делать все, что захочет, включая немедленное уничтожение окна, если оно того хочет.

Однако при этом, если меню является стандартным меню Win32, то окно получит сообщение WM_COMMAND, содержащее идентификатор выбранного пункта меню, по крайней мере.

Причина, по которой я спросил, заключается в том, что я пытаюсь реализовать собственный код JNI, чтобы изящно закрыть окно, когда пользователь инициировал выключение системы.

По умолчанию вам ничего не нужно делать для этого. ОС автоматически закрывает все открытые windows во время выключения системы. Вместо того, чтобы закрывать окно вручную, вы должны реагировать на его закрытие, если вам нужно очистить какие-либо ресурсы.

Когда вы нажимаете «X», чтобы закрыть, появляется диалоговое окно подтверждения, которое предотвращает исчезновение сообщения о причине завершения работы (когда я ожидаю, что оно исчезнет через некоторое время).

Тогда приложение неправильно обрабатывает завершение работы системы.

В большинстве приложений отображается такое окно подтверждения в ответ на получение сообщения WM_CLOSE. Если подтверждение отменяется, приложение отбрасывает сообщение и продолжает работу. Однако приложения не должны запрашивать подтверждение у пользователя во время выключения системы. Но не все приложения следуют этому правилу.

Я знаю, что Файл-> Выход из строки меню не запрашивает подтверждения

Опять же, это решение для приложения. , а не ОС.

как мне реализовать это с помощью windows уведомления? После некоторых поисков я нашел только одно: DestroyWindow.

Правильно. Или вы можете вместо этого отправить сообщение WM_QUIT в очередь сообщений. См. Функцию PostQuitMessage().

Поэтому я попытался закрыть окно с помощью функции DestroyWindow (), но оно только «разрушает» окно, а не завершает все приложение.

Приложение несет ответственность за его завершение, обычно путем выхода из сообщения l oop, когда его главное окно было уничтожено.

Вот мой оператор switch в моей функции WndPro c CallBack :

Нет необходимости отправлять WM_CLOSE в ответ на WM_QUERYENDSESSION или WM_ENDSESSION. Пусть ОС справится с этим за вас.

Если вы не хотите, чтобы подтверждение появлялось во время выключения системы, измените свой код на что-то вроде этого:

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);
}
0 голосов
/ 10 января 2020

Нет конкретного сообщения c для обработки вашего файла> Выход. Вы должны обращаться с ним как с любым другим пунктом меню:

  1. Определите идентификатор для вашего пункта меню. Выберите все, что вы хотите, это не имеет особого значения для windows.
  2. . При создании меню укажите этот идентификатор в AppendMenu / InsertMenu / et c. или в вашем файле ресурсов
  3. В вашей оконной процедуре перехватите сообщение WM_COMMAND. Если LOWORD(wParam) соответствует идентификатору, это означает, что пункт меню активирован

Типичным способом обработки команды выхода является отправка сообщения WM_CLOSE, как вы уже делаете в своем примере код. Таким образом, вы избежите дублирования кода и будете уверены, что поведение будет одинаковым независимо от того, как пользователь выберет выход из вашего приложения (через меню нажмите «x» или Alt + F4)

В вручая WM_CLOSE, вы можете выбрать отображение окна сообщения, уничтожить окно, опубликовать сообщение о выходе или что угодно еще. По умолчанию DefWindowPro c вызывает DestroyWindow, который, в свою очередь, отправляет сообщение WM_DESTROY. Обратите внимание, что WM_CLOSE также запускается при выборе пункта «Закрыть» в системном меню (Alt + Пробел или щелчок на значке окна слева рядом с заголовком окна)

...