Где лучше всего создать дочерний элемент управления дочерним окном в чистом приложении WinAPI GUI? - PullRequest
0 голосов
/ 10 мая 2019

Я работаю только с приложением WinAPI.Я хочу создать дочернее окно STATIC, которое будет использоваться в качестве «контейнера» для дочерних элементов управления.В примерах, которые я нашел до сих пор, создается окно «контейнера», перехватывающее WM_CREATE в процедуре главного окна.Я предположил, что лучшее место для создания дочерних элементов управления дочерним окном - перехват WM_CREATE для дочернего окна.Чтобы сделать это, мне сначала нужно создать подкласс дочернего окна, чтобы указать на новую оконную процедуру.Дело в том, что окно создается до его подкласса, поэтому WM_CREATE отправляется исходной процедуре, а не моей пользовательской процедуре.Конечно, я могу создать дочерние элементы управления после создания дочернего статического окна в процедуре главного окна, но я не считаю, что это лучший способ сделать это.Какой вариант лучше?

Рабочий пример кода:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
    {
        HWND hContainer = CreateWindow(WC_STATIC, L"Container", WS_CHILD, 0, 0, 100, 50, hWnd, (HMENU)ID_CONTAINER, NULL, NULL);
        WNDPROC wpOldProc = (WNDPROC)SetWindowLongPtr(hContainer, GWLP_WNDPROC, (LONG_PTR)ChildWindowProc);
        HWND hButton = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU)ID_BUTTON, NULL, NULL); // This works well
    }
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

INT_PTR CALLBACK ChildWindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
    {
       // HWND hButton = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU)ID_BUTTON, NULL, NULL); 
       // This point is never reached because the WM_CREATE message is sent before subclassing of the window
    }
    break;
    default:
        break;
    }
    return CallWindowProc(gsHdl.wpTE, hWnd, message, wParam, lParam);
}

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

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

Но я не думаю, что это сильно отличается от приведенного ниже:

HWND hContainer = CreateWindow (WC_STATIC, L "Container", WS_CHILD, 0, 0, 100, 50, hWnd, (HMENU) ID_CONTAINER, NULL, NULL);
if(hContainer)
{
    HWND hButton = CreateWindow (WC_BUTTON, L "Button", WS_CHILD | BS_PUSHBUTTON, 0, 0, 20, 10, hContainer, (HMENU) ID_BUTTON, NULL, NULL);
}

Это также обеспечивает порядок создания и предварительные условия.

Если вам действительно нужно изменить WinProc иЗахват WM_CREATE сообщений в стандартные элементы управления Windows, SetWindowsLongPtr не соответствует вашим требованиям.Вместо этого используйте SetClassLongPtr перед созданием «Контейнера».

0 голосов
/ 10 мая 2019

Основным принципом здесь является разделение задач: окно обычно создает своих дочерних элементов в ответ на свое сообщение WM_CREATE как:

Это гарантирует, что окно "владеет" созданием своих дочерних элементов.Это также гарантирует, что когда родительское окно создается непосредственно по имени класса, все дочерние элементы создаются автоматически.И, наконец, поскольку WM_CREATE отправляется до того, как окно становится видимым / окрашенным, оно гарантирует, что все дочерние окна будут созданы к моменту, когда окно будет впервые нарисовано.

Многие из этих соображений отпадают при использовании дочерних оконокна для организации дочерних окон: - Если вы создаете правильное абстрагированное окно управления, это одно, а если вы просто размещаете некоторые относительно стандартные элементы управления окнами, с которыми вы хотите, чтобы главное окно могло взаимодействовать, то глубокие иерархии раздражаютНавигация, есть некоторые странности в том, как мышь и рисование происходят там, где вы, возможно, захотите расположить контейнер и его дочерние элементы в «неправильном» z-порядке, которого вы не смогли бы достичь, если бы они были строго расположены как дочерние / родительские.

То есть, нет ничего плохого в создании статического окна и использовании возвращенного HWND в качестве родительского окна в последующих строках - особенно если это уменьшает количество классов окна, строк кода / свертки создания- и упрощает отношение родительского окна к его элементам управления.

...