WM_CLOSE не работает, и размер приложения нельзя изменить

#c #user-interface #winapi

Вопрос:

  1. Когда я пытаюсь закрыть диалоговое окно, я ожидаю, что приложение закроется, но этого не происходит. Я предполагаю, что что-то не так WM_CLOSE .
  2. Приложение не может быть изменено по размеру. Как мне это сделать?
  3. Действительно ли мне это нужно UpdateWindow(hWnd) ?
 #include <Windows.h>

#include "resource.h"

#pragma comment(linker, ""/manifestdependency:type='win32' 
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' 
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"")

#pragma comment(linker, "/SUBSYSTEM:WINDOWS")

INT_PTR CALLBACK DialogProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
    case WM_INITDIALOG:
        return TRUE;
    case WM_CLOSE:
        DestroyWindow(hwnd);
        PostQuitMessage(0);
        return FALSE;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        case IDCANCEL:
            EndDialog(hwnd, IDCANCEL);
            break;
        }
        break;
    default:
        return FALSE;
    }
    
    return TRUE;
}

int WINAPI WinMain(
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR lpCmdLine,
    _In_ int nShowCmd
)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    
    HWND hWnd = CreateDialogParamW(hInstance, MAKEINTRESOURCEW(IDD_MAIN), nullptr, amp;DialogProc, 0);
    
    if (!hWnd)
    {
        MessageBoxW(nullptr, L"Dialog Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hWnd, nShowCmd);
    UpdateWindow(hWnd);
    
    MSG msg;
    while (GetMessageW(amp;msg, hWnd, 0, 0))
    {
        TranslateMessage(amp;msg);
        DispatchMessageW(amp;msg);
    }
    
    return msg.wParam;
}
 

Ресурс.rc

 // Microsoft Visual C   generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (United States) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""winres.h"""
END

3 TEXTINCLUDE 
BEGIN
    "rn"
    ""
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_MAIN, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 302
        TOPMARGIN, 7
        BOTTOMMARGIN, 169
    END
END
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_MAIN DIALOGEX 0, 0, 309, 176
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Test"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LISTBOX         IDC_LIST2,48,30,235,56,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
    GROUPBOX        "Static",IDC_STATIC,146,92,48,40
    PUSHBUTTON      "Button1",IDC_BUTTON1,215,127,50,14
END


/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//

IDD_MAIN AFX_DIALOG_LAYOUT
BEGIN
    0
END

#endif    // English (United States) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
 

ресурс.ч

 //{{NO_DEPENDENCIES}}
// Microsoft Visual C   generated include file.
// Used by Resource.rc
//
#define IDD_MAIN                        103
#define IDC_LIST2                       1005
#define IDC_BUTTON1                     1006

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        105
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1007
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

 

Комментарии:

1. EndDialog не влияет на диалог, созданный с CreateDialogParamW помощью (внутренне он только публикуется WM_NULL ). WM_CLOSE вы должны получить, если нажмете на кнопку закрытия или atl f4. и вы выбираете DS_MODALFRAME — он не может быть изменен

2. @RbMm, спасибо тебе! DS_FIXEDSYS исправлено изменение размера. А как насчет закрытия? Что я должен использовать, чтобы исправить это?

3. Похоже, вы не вызываете WndProc по умолчанию для WM_DESTROY сообщения. Ваше default дело возвращается FALSE для WM_DESTROY , которое сообщает системе, что вы обработали сообщение.

4. @AdrianMole — в DialogProc никогда не нужно вызывать WndProc по умолчанию

5. @nop — А как насчет закрытия? вместо EndDialog этого позвоните DestroyWindow , случай WM_CLOSE вы можете удалить вообще. PostQuitMessage(0); звонок от WM_NCDESTROY

Ответ №1:

Проблема в том, что вы передаете hWnd в качестве параметра GetMessage() . Это приводит GetMessage() к получению сообщений только для окна. Но WM_QUIT отправляется не в ваше окно, а в вашу нить. Поскольку GetMessage() сообщение никогда не извлекается WM_QUIT , цикл сообщений никогда не завершается.

Правильный подход состоит в том, чтобы пройти nullptr вместо hWnd этого .

Комментарии:

1. да, но все же один момент здесь — while (GetMessageW(amp;msg, hWnd, 0, 0)) неверный результат проверки. должно быть while (0 < GetMessageW(amp;msg, hWnd, 0, 0)) , потому, что api возвращает -1 ошибку. если использовать вторую форму — это также прервет цикл — потому что -1 возвращается после DestroyWindow вызова и hWnd больше недействителен

2. Видеть Опасности фильтрации оконных сообщений и Когда GetMessage вернет -1?