Прикрепление дочернего окна к родительскому окну

Мне нужно, чтобы мои 6 элементов управления (дочерние окна главного окна) увеличивались, когда пользователь изменяет размер главного окна (перетаскивая углы). Я думал, что смогу добиться этого, используя функцию MoveWindow для изменения пропорций каждого дочернего элемента в функции WM_SIZE или WM_SIZING главного окна. Это сделало сборку отладки странной (несколько окон, изображение окна, застрявшего после выхода и т. д.). Сборка Release работала нормально, но дочерние окна не изменились, когда я изменил размер главного окна.

Я нашел http://msdn.microsoft.com/en-us/library/ms632598%28v=VS.85%29.aspx#creating_enumerating_etc использовал другой метод для этого: путем перечисления всех дочерних окон и функции обратного вызова enum, обрабатывающей изменение размера окна. через уникальный идентификатор, присвоенный каждому ребенку. Попробовав это сам, это не повлияло на элементы управления, когда размер главного окна изменился.

Почему это не работает?

В операторе переключения основных окон:

case WM_SIZING:
        GetClientRect(hwnd, &hwndRect);
        EnumChildWindows(hwnd, EnumChildProc, (LPARAM)&hwndRect);
        break;

Функция обратного вызова дочернего перечислителя:

BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
    LPRECT hwndRect = (LPRECT)lParam;
    switch(GetWindowLong(hwndChild, GWL_ID))
    {
        case ID_CHILD_LLABEL:
            MoveWindow(hwndChild, 0, 0, (hwndRect->right - hwndRect->left) - 30, 20,     false);
            break;
        case ID_CHILD_LDIR:
            MoveWindow(hwndChild, 12, 20, (hwndRect->right - hwndRect->left) - 40, 20,     false);
            break;
        case ID_CHILD_LLIST:
            MoveWindow(hwndChild, 12, 40, (hwndRect->right - hwndRect->left) - 40,         (hwndRect->bottom - hwndRect->top) - 238, false);
            break;
    }
}

person Greg Treleaven    schedule 21.02.2011    source источник
comment
Есть ли какая-то причина, по которой вы не используете один из многих фреймворков, которые делают такие вещи за вас?   -  person David Heffernan    schedule 21.02.2011


Ответы (1)


Из статьи MSDN о WM_SIZE: " Если функция SetScrollPos или MoveWindow вызывается для дочернего окна в результате сообщения WM_SIZE, параметр bRedraw или bRepaint должен быть отличен от нуля, чтобы вызвать перерисовку окна». Я подозреваю, что дочерние элементы управления перемещаются, они просто не перекрашиваются.

Возможно, также стоит проверить, что ваши случаи переключения действительно срабатывают.

Редактировать: я пропустил очевидное. Вы отвечаете на WM_SIZING, который указывает, что размер окна вот-вот изменится (но еще не изменился). WM_SIZE указывает, что размер изменился. Если вы хотите использовать WM_SIZING, вам нужно использовать прямоугольник, переданный в lParam, а не результаты GetClientRect. К сожалению, прямоугольник WM_SIZING является прямоугольником окна, а не клиентской области, и находится в координатах экрана. Если вам действительно не нужно отображать элементы управления с измененным размером, пока пользователь все еще выполняет изменение размера, было бы намного проще просто обработать сообщение WM_SIZE.

person Jon    schedule 21.02.2011
comment
Я использовал функцию InvalidateRect() для перерисовки окна, и ничего не произошло. Я попытался переместить мое окно MoveWindow() с помощью EnumChildWindows(), и на этот раз все дочерние окна вспыхнули, поскольку их размер изменился. У меня все еще есть проблема с тем, что элементы управления не становятся больше, но, по крайней мере, я знаю, что это не достигло кода обратного вызова перечислителя. Изменение false на true для аргумента BRedraw/paint не повлияло на это. Отличается ли перерисовка от перерисовки? Если они одинаковые, то это не решило проблему. - person Greg Treleaven; 22.02.2011
comment
@Greg Обновил мой ответ. Вы используете неправильный прямоугольник для расчета новых размеров элементов управления. - person Jon; 22.02.2011