Создание изменяемого размера CMFCPropertySheet с помощью динамических макетов

Я видел этот вопрос, но ссылка в ответе больше не действительна.

Я также нашел то, что я пытался и не работает, и это.

Моя задача должна быть простой. У меня есть несколько страниц на CMFCPropertySheet и я хочу воспользоваться новыми функциями динамического изменения размера в IDE. Поэтому я установил изменение размеров элементов управления и, увы, при показе на листе нет возможности изменить размер листа / страниц.

Попытка вышеуказанных ресурсов не удалась.

Заголовок для CMyPropertySheet:

https://pastebin.com/k8yjhZh7

Источник для CMyPropertySheet:

https://pastebin.com/kxexFPbU

Для тестирования я просто создал диалоговое приложение, добавил страницу и назначил ее этому листу.

Я просто хочу поддержать динамическое изменение размеров с помощью страниц свойств / страниц. Чего мне не хватает и нужен ли этот код на самом деле больше?

3 ответа

Решение

Для немодального окна свойств:
Посмотрите эту ссылку SO Изменение размера немодального окна свойств


Для модального листа свойств:
Как реализовать лист свойств с изменяемым размером
https://www.codeproject.com/Tips/214744/How-to-implement-a-resizable-property-sheet-class

добавлять WS_THICKFRAME стиль окна свойств окна.

int CALLBACK XmnPropSheetCallback(HWND hWnd, UINT message, LPARAM lParam)
{
    extern int CALLBACK AfxPropSheetCallback(HWND, UINT message, LPARAM lParam);
    // XMN: Call MFC's callback
    int nRes = AfxPropSheetCallback(hWnd, message, lParam);

    switch(message)
    {
    case PSCB_PRECREATE:
        // Set our own window styles
        ((LPDLGTEMPLATE)lParam)->style |= (DS_3DLOOK | DS_SETFONT
            | WS_THICKFRAME | WS_SYSMENU | WS_POPUP | WS_VISIBLE | WS_CAPTION);
        break;
    }
    return nRes;
}

INT_PTR CMyPropertySheet::DoModal()
{
    // Hook into property sheet creation code
    m_psh.dwFlags |= PSH_USECALLBACK;
    m_psh.pfnCallback = XmnPropSheetCallback;

    return CMFCPropertySheet::DoModal();
}

PS, оригинальная статья немного старая. Это использует m_psh получить доступ к параметрам листа свойств.

Для изменения размера:

void CMyPropertySheet::OnSize(UINT nType, int cx, int cy)
{
    CPropertySheet::OnSize(nType, cx, cy);

    if(!GetActivePage()) return;
    if(!GetTabControl()) return;

    if(nType == SIZE_MINIMIZED)
        return;

    int dx = cx - save_rc.Width();
    int dy = cy - save_rc.Height();

    int count = 0;
    for(CWnd *child = GetWindow(GW_CHILD); child; child = child->GetWindow(GW_HWNDNEXT))
        count++;

    HDWP hDWP = ::BeginDeferWindowPos(count);

    for(CWnd *child = GetWindow(GW_CHILD); child; child = child->GetWindow(GW_HWNDNEXT))
    {
        bool move = false;
        //override***
        //If you add child controls manually, you want to move not resize
        //if(child == &static_control)
            //move = true;

        CRect r;
        child->GetWindowRect(&r);
        ScreenToClient(&r);

        if(move || child->SendMessage(WM_GETDLGCODE) & DLGC_BUTTON)
        {
            //move the main buttons and the child controls
            r.left += dx;
            r.top += dy;
            ::DeferWindowPos(hDWP, child->m_hWnd, 0, r.left, r.top, 0, 0,
                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
        }
        else
        {
            //this must be a child window, resize it
            r.right += dx;
            r.bottom += dy;
            ::DeferWindowPos(hDWP, child->m_hWnd, 0, 0, 0, r.Width(), r.Height(),
                SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
        }
    }

    ::EndDeferWindowPos(hDWP);
    GetClientRect(&save_rc);
    Invalidate(TRUE);
}

BOOL CMyPropertySheet::OnInitDialog()
{
    CPropertySheet::OnInitDialog();
    GetClientRect(&save_rc);
    GetClientRect(&minimum_rc);
    return TRUE;
}

Вот альтернативный ответ, который я придумал. Мне пришло в голову, что нет никаких оснований вообще не использовать новые функции динамического макета. Просто указатель динамического макета NULL начать с.

Если вы добавите следующий закрытый метод в свой класс производных свойств:

void CResizingMFCPropertySheet::SetupDynamicLayout()
{
    EnableDynamicLayout(TRUE);
    auto pManager = GetDynamicLayout();
    if (pManager != nullptr)
    {
        pManager->Create(this);

        // The navigation control only needs to be stretched vertically
        pManager->AddItem(m_pNavigationControl->GetSafeHwnd(),
            CMFCDynamicLayout::MoveNone(), CMFCDynamicLayout::SizeVertical(100));

        // The resize control needs to be moved 100% in both directions
        pManager->AddItem(m_lblResize.GetSafeHwnd(),
            CMFCDynamicLayout::MoveHorizontalAndVertical(100, 100), CMFCDynamicLayout::SizeNone());

        for (CWnd *child = GetWindow(GW_CHILD); child; child = child->GetWindow(GW_HWNDNEXT))
        {
            if (child->GetSafeHwnd() != m_lblResize.GetSafeHwnd() &&
                child->GetSafeHwnd() != m_pNavigationControl->GetSafeHwnd())
            {
                // All buttons need to be moved 100% in all directions
                if (child->SendMessage(WM_GETDLGCODE) & DLGC_BUTTON)
                {
                    pManager->AddItem(child->GetSafeHwnd(),
                        CMFCDynamicLayout::MoveHorizontalAndVertical(100, 100), CMFCDynamicLayout::SizeNone());
                }
                else // This will be the main tab control which needs to be stretched in both directions
                {
                    pManager->AddItem(child->GetSafeHwnd(),
                        CMFCDynamicLayout::MoveNone(), CMFCDynamicLayout::SizeHorizontalAndVertical(100, 100));
                }
            }
        }
    }
}

И позвони из OnInitDialog тогда вам не нужно никаких OnSize обработчик событий и никакого ручного рисования любого вида.

На всякий случай, если вам подходит CPropertySheet вместо CMFCPropertySheet, рассмотрите возможность использования ResizableLib. Включает в себя класс CResizableSheet который реализует изменяемый размер версии CPropertySheet.

Другие вопросы по тегам