WinAPI - диалоги: как отключается диалоговое окно главного окна при щелчке мыши?

Используя WinAPI в C, есть два способа создать диалог с WinAPI: более распространенный — создать ресурс диалога в файле .rc проекта, а затем использовать его с DialogBox(), который автоматизирует создание стандартного диалога. Другой способ — использовать CreateWindowEx с определенными параметрами, чтобы созданное окно действовало как диалог.

Пример создания диалога с помощью DialogBox можно увидеть на сайте winprog.org: http://www.winprog.org/tutorial/dialogs.html

Из чистого интереса я попытался воссоздать диалог, созданный с помощью DialogBox(), используя CreateWindowEx. Для этого я просто отключил главное окно, а затем CreateWindowEx отредактировал диалог. Однако то, что я получил, все же имело одно отличие от диалога, созданного с помощью DialogBox: когда я нажимаю на отключенное главное окно, мигает диалог, созданный DialogBox (скорее всего, с помощью функции FlashWindowEx).

Вот мой код для создания диалогового окна с CreateWindowEx:

    HWND hwndParent;

    HINSTANCE ghInstance;

    LPCWSTR g_szDialogClassName = L"DialogClass";

    void populateDialog(HWND hwnd){
        /* Create various dialog controls */
    }

    LRESULT CALLBACK aboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam){
        switch(Message){
            case WM_CREATE:
                populateDialog(hwnd);
                return DefWindowProc(hwnd, Message, wParam, lParam);

            case WM_COMMAND:
                switch(LOWORD(wParam)){
                    case IDC_CLOSEDLG:
                        EnableWindow(hwndParent, TRUE);
                        DestroyWindow(hwnd);
                        UnregisterClass(g_szDialogClassName, ghInstance);
                    break;
                }
            break;

            case WM_CLOSE:
                EnableWindow(hwndParent, TRUE);
                DestroyWindow(hwnd);
                UnregisterClass(g_szDialogClassName, ghInstance);
            break;

            default:
                return DefWindowProc(hwnd, Message, wParam, lParam);
        }
        return DefWindowProc(hwnd, Message, wParam, lParam);
    }

    int createDialogBox(HWND hwnd, HINSTANCE hInstance){
        if (registerClass(hInstance, g_szDialogClassName, (WNDPROC)aboutDlgProc) == 0){
            MessageBoxA(NULL, "Dialog Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
            return 0;
        }
        EnableWindow(hwnd, FALSE);
        CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, g_szDialogClassName, L"About", WS_VISIBLE | WS_CAPTION | WS_POPUP | WS_SYSMENU, 100, 100, 450, 150, NULL, NULL, hInstance, NULL);

        hwndParent = hwnd;
    }

Вот мне очень интересно как это делается внутри DialogBox()? Как отключенное окно может получать ввод мыши? Или, может быть, он не был отключен стандартными средствами (чем-то, кроме EnableWindow(hwnd, FALSE))? Или невозможно воспроизвести этот эффект обычными вызовами WinAPI?


person Mints97    schedule 10.08.2014    source источник
comment
Пожалуйста, покажите MCVE, иначе нам придется гадать, какой у вас код.   -  person David Heffernan    schedule 10.08.2014
comment
Это код, встроенный в операционную систему. Он перехватывает сообщение мыши до того, как оно будет возвращено функцией GetMessage(), вместо этого высвечивая окно. Вы также можете сделать это самостоятельно с помощью цикла сообщений. Однако не с DialogBox(), цикл сообщений, который он использует, также встроен.   -  person Hans Passant    schedule 10.08.2014
comment
@HansPassant: в общем, мне нужно обработать сообщение до того, как оно будет обработано GetMessage() в моем цикле сообщений? Как бы я это сделал?   -  person Mints97    schedule 10.08.2014
comment
@DavidHeffernan: добавил мой код.   -  person Mints97    schedule 10.08.2014
comment
Выглядит странно, что у созданного вами окна нет владельца. Конечно, вам нужно, чтобы он принадлежал главному окну. Я думаю, что как только вы это сделаете, вы будете в порядке. Вам также следует прочитать статьи Рэймонда Чена о модальности: stackoverflow.com/questions/15696885/   -  person David Heffernan    schedule 10.08.2014
comment
@DavidHeffernan: спасибо, это решило мою проблему! Windows фактически автоматизирует эффект вспышки, если я создаю диалог как дочернее окно! Вы можете опубликовать это как ответ, и я отмечу его как правильный   -  person Mints97    schedule 10.08.2014


Ответы (1)


Проблема с вашим кодом в том, что вы создали окно, не принадлежащее вам. Укажите главное окно в качестве владельца при вызове CreateWindowEx.

person David Heffernan    schedule 10.08.2014
comment
Это правильный ответ! Windows фактически автоматизирует эффект вспышки, если я создаю диалог как дочернее окно! Большое спасибо! знак равно - person Mints97; 10.08.2014
comment
@ Mints97: операционная система автоматически отображает принадлежащее окно, когда пользователь щелкает владельца. Для этого он вызывает API FlashWindowEx. - person IInspectable; 11.08.2014