Создание двух окон в одном приложении

0

Я изучаю C++ и у меня есть некоторые вопросы. Некоторые исследования в msdn мне не помогли. Я хочу создать два окна в одном приложении. Одно окно - диалог с опциями и другой для графического вывода. Вот код, который я использую. Но у меня есть некоторые проблемы:

  • Второе окно (для графического) не реагирует на нажатия кнопки "Закрыть", "Минимум", "Значок".
  • Ящики сообщений, когда они появляются, не находятся в фокусе и не реагируют на какие-либо щелчки мыши, но в это время основное окно работает нормально.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
{   
    InitCommonControls();   

    if(FAILED(DialogWindow_OnCreate(hInstance)))
            return 1;

    if(FAILED(GraphicWindow_OnCreate(hInstance)))
            return 1;

    MSG msg;
    memset(&msg, 0, sizeof(MSG));
    while(msg.message != WM_QUIT)
    {
            while(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
            {       
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);      
            }

            OnUpdate();
    }

    GraphicWindow_OnClose();        

    return 0;
}

Создание главного окна (Dialog):

 HRESULT DialogWindow_OnCreate(HINSTANCE hInst)
    {
        g_hDialogWindow = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogWindow_WndProc);

        if(!g_hDialogWindow)
            return E_NOTIMPL;

        UpdateWindow(g_hDialogWindow);

        return S_OK;
    }

Главное окно proc (Диалог):

INT_PTR CALLBACK DialogWindow_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);     

    switch (message)
    {
    case WM_INITDIALOG:
        {           
            g_hDialogWindow = hWnd;

            // Some init actions ...

            return (INT_PTR)TRUE;
        }   
    case WM_COMMAND:        
        int wmId, wmEvent;
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        switch(wmEvent)
        {
        case NULL: // Menu used
            {
                switch(wmId)
                {
                case IDC_BTN_1:
                    {
                        DialogWindow_OnBtn1();
                        MessageBoxA(NULL, "Some message", "Some title", MB_OK);
                        return (INT_PTR)TRUE;
                    } break;
                case IDC_BTN_2:
                    {
                        DialogWindow_OnBtn2();
                        return (INT_PTR)TRUE;
                    } break;

                // ...

                    case IDCANCEL:
                    {
                        // Close window
                        DefWindowProc(hWnd, WM_CLOSE, wParam, lParam);
                    } break;
                    case IDOK:
                    {
                        // Close window
                    DefWindowProc(hWnd, WM_CLOSE, wParam, lParam);
                    } break;
                }
            }
        }
    case WM_CLOSE:
        DefWindowProc(hWnd, message, wParam, lParam);
        return (INT_PTR)TRUE;
        break;
    case WM_DESTROY:        
        PostQuitMessage(0);
        return (INT_PTR)TRUE;
        break;  
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;      
    }

return (INT_PTR)FALSE;
}

Создание второго окна (графика):

HRESULT GraphicWindow_OnCreate(HINSTANCE hInst)
{
    HWND g_hGraphicWindow = NULL;

    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style              = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = GraphicWindow_WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInst;
    wcex.hIcon              = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP_ICO));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = 0;
    wcex.lpszClassName  = _T("MyApp");
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 

    if(!RegisterClassEx(&wcex))
    {
        DWORD dwError = GetLastError();
        if(dwError != ERROR_CLASS_ALREADY_EXISTS)
        {
            MessageBoxA(NULL, "GraphicWindow: RegisterClass() failed!", "Error", MB_OK | MB_ICONERROR);
            return HRESULT_FROM_WIN32(dwError);            
        }
    }

    // Set window initial size, but it might be changed later
    int nDefaultWidth = 320;
    int nDefaultHeight = 240;
    RECT rc;
    SetRect(&rc, 0, 0, nDefaultWidth, nDefaultHeight);
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);    

    // Create the window
    g_hGraphicWindow = CreateWindowA("MyApp", "GraphicWindow", WS_OVERLAPPEDWINDOW,
                      CW_USEDEFAULT, CW_USEDEFAULT, (rc.right - rc.left), (rc.bottom - rc.top), 0,
                      0, hInst, 0);
    if(!g_hGraphicWindow)
    {
        DWORD dwError = GetLastError();
        MessageBoxA(NULL, "GraphicWindow: CreateWindow() failed!", "Error", MB_OK | MB_ICONERROR);
        return HRESULT_FROM_WIN32(dwError);
    }

    UpdateWindow(g_hGraphicWindow); 

    return S_OK;
}

Графическое окно proc:

LRESULT CALLBACK GraphicWindow_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam); 

    switch (message)
    {
    case WM_KEYDOWN:
    {
        switch(wParam)
        {
        case VK_RETURN:         
            // Some actions ...         
            break;              
        case VK_ESCAPE:         
            // Some actions ...             
            break;  
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;    
    case WM_CLOSE:      
        ShowWindow(hWnd, SW_HIDE);      
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);        
    }

    return 0;
}

Где моя проблема? Помоги мне, пожалуйста.

  • 0
    Похоже, вы хотите MDI, но я не уверен, что то, что вы просите, возможно. Модальный диалог блокирует все взаимодействие с приложением.
  • 2
    Слишком много кода. Научитесь сузить проблему до конкретного блока кода, а затем опубликовать достаточно кода, чтобы воспроизвести проблему.
Показать ещё 7 комментариев
Теги:
winapi

2 ответа

2
Лучший ответ

У меня есть следующие комментарии:

  1. Не вызывайте DefWindowProc в процедуре диалога. Это может быть главной проблемой. См. Этот пример в MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644996.aspx#modeless_box
  2. Ваш цикл сообщений несколько фиктивный. Об этом позже.
  3. Вы не должны называть функции ANSI. Удалите все суффиксы A Вам нужно будет префикс строковых литералов с L чтобы указать широкие строки. Например, L"foo".
  4. Вы должны, по-видимому, передать дескриптор главного окна как hWndParent когда вы вызываете CreateDialog. В противном случае модельный dailog будет неактивен, поэтому у него есть собственная кнопка на панели задач и не всегда будет отображаться поверх главного окна.
  5. Вы должны передать дескриптор главного окна как hWnd при вызове MessageBox.

Более подробно в цикле сообщений вы не следуете правилам, изложенным в документации для CreateDialog, в котором говорится:

Для поддержки навигации на клавиатуре и других функций диалогового окна цикл сообщения для диалогового окна должен вызвать функцию IsDialogMessage.

Таким образом, ваш цикл сообщений должен быть:

while(GetMessage(&msg, NULL, 0, 0))
{
    if(!IsDialogMessage(g_hDialogWindow, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

Также обратите внимание, что я переключился на цикл GetMessage. Я не думаю, что вам нужно запустить горячий цикл для ваших нужд. Использование GetMessage позволяет основному потоку вашего приложения получать процессор и блокировать, если он неактивен.

  • 0
    Я очень благодарен за вашу помощь, но это не решает проблему. Проблема разочаровывается только тогда, когда я удаляю функцию CreateDialog (). и программа создает только одно окно. Я буду изучать MSDN, а затем опубликовать здесь ответ.
  • 0
    Ну, ты все равно должен сделать то, что я сказал здесь. В любом случае, когда вы можете опубликовать SSCCE, мы можем отладить это.
Показать ещё 1 комментарий
0

В вашей процедуре диалога не используйте DefWindowProc.

См. Диалоговое окно Обработка сообщений по умолчанию.

  • 0
    Спасибо, но я уже нашел его и хотел опубликовать ответ, но не смог, из-за моей репутации. Это решает все мои проблемы!
  • 0
    Все работает нормально, даже с PeekMessage () и ANSI func. ! Большое спасибо всем!
Показать ещё 11 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню