Win32 API Дочернее окно не появляется в родительской области - PullRequest
0 голосов
/ 19 марта 2020

Я пытаюсь написать простое приложение в Win32 API. Цель состоит в том, чтобы создать родительское окно с синим фоном и дочерним окном (видимым как маленький красный квадрат) внутри него.

Я определяю родителя и дочернего элемента windows:

    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMEPRACTICE3));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 255));
    wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GAMEPRACTICE3);
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    RegisterClassEx(&wcex);
    HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE | WS_BORDER,
        0,0, 400, 600, HWND_DESKTOP, nullptr, hInstance, nullptr);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    // Child window

    WNDCLASSEX wc;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.lpszClassName = childClass;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.hInstance = hInst;
    wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
    wc.lpfnWndProc = WndProc;

    RegisterClassEx(&wc);


    HWND hwnd_child = CreateWindow(childClass, NULL,
        WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        0, 0, 32, 32,
        hWnd, 0, hInst, 0);

    ShowWindow(hwnd_child, nCmdShow);
    UpdateWindow(hwnd_child);

Когда я запускаю приложение, я получаю следующий вывод:

enter image description here

Кажется, что дочернее окно вообще не отображается. Я пытался найти похожие проблемы на Inte rnet, но пока ни одно из решений не помогло мне.

Исходный код:


#include "stdafx.h"
#include "GamePractice3.h"

#define MAX_LOADSTRING 100

HINSTANCE hInst;                               
WCHAR szTitle[MAX_LOADSTRING];              
WCHAR szWindowClass[MAX_LOADSTRING];        
WCHAR childClass[MAX_LOADSTRING];
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_GAMEPRACTICE3, szWindowClass, MAX_LOADSTRING);


    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMEPRACTICE3));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 255));
    wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GAMEPRACTICE3);
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    RegisterClassEx(&wcex);

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GAMEPRACTICE3));

    MSG msg;

    hInst = hInstance; 

    HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE | WS_BORDER,
        0,0, 400, 600, HWND_DESKTOP, nullptr, hInstance, nullptr);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);


    WNDCLASSEX wc;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.lpszClassName = childClass;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.hInstance = hInst;
    wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
    wc.lpfnWndProc = WndProc;

    RegisterClassEx(&wc);

    HWND hwnd_child = CreateWindow(childClass, NULL,
        WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        0, 0, 32, 32,
        hWnd, 0, hInst, 0);


    ShowWindow(hwnd_child, nCmdShow);
    UpdateWindow(hwnd_child);

    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}


Любая помощь будет принята:).

Ответы [ 2 ]

0 голосов
/ 20 марта 2020

Для Дочернее окно не отображается в родительской области * Проблема 1002 *, в дополнение к ответу @ daniel_p:

  1. WS_OVERLAPPEDWINDOW стиль не имеет значения Вот. Этот стиль дает окну строку заголовка, меню окна, границу размеров и кнопки минимизации и максимизации.
  2. Необходима проверка ошибок . Вы обнаружите, что регистр класса дочернего окна завершился неудачно и вернет 0.

  3. Укажите допустимую строку с нулем в конце для имени класса. Имя класса NULL является одним из факторов, вызывающих сбой RegisterClassEx.

  4. Инициализация WNDCLASSEX struct like: WNDCLASSEX wc = {0}; Без инициализации некоторое значение, которое вы не установите явно позже, будет значением мусора. Это еще один фактор, вызывающий сбой RegisterClassEx. Или вы можете установить каждое значение явно.

В следующих редакциях ваш код будет работать:

    WCHAR childClass[MAX_LOADSTRING] = L"Child Window";
// ...
            WNDCLASSEX wc = {0};

Пример проверки ошибок RegisterClassEx функция:

DWORD errCode = 0;

ATOM childClassId = RegisterClassEx(&wc);
if (!childClassId)
{
    errCode = GetLastError();
    MessageBox(NULL, L"RegisterClassEx failed!", L"Error", MB_ICONERROR | MB_OKCANCEL);
    return 0;
}
0 голосов
/ 19 марта 2020

Мне удалось решить проблему.

  • Я удалил WS_OVERLAPPEDWINDOW из создания дочернего окна
  • Я добавил отдельную оконную процедуру для дочернего окна с DefWindowPro c
  • Я создал строку для childClass и загрузил ее (LoadStringW)
  • Я инициализировал все 11 полей структуры WNDCLASSEXW (не уверен, если это необходимо)

Надеюсь, это поможет .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...