Как динамически изменить ширину CFormView или высоту в приложении Windows MDI MFC C ++? - PullRequest
0 голосов
/ 30 января 2019

В 1997 году я использовал C ++ для создания программы MDI MFC.

Я создал класс с именем XFormFiew, который расширяет класс MFC CFormView.

В OnInitialUpdate() методе событий яЯ написал несколько кодов для автоматического изменения масштаба изображения.

Раньше большинство разрешений экрана составляло 800х600, но теперь разрешение выше.При автоматическом масштабировании в XFormView я избегаю внесения некоторых изменений во все мои виды.

Код масштабирования изменяет Левый и Нижний, а также ширину и высоту каждого CWnd, содержащегося в активном CFormView

Код следующий

void XFormView::OnInitialUpdate()
    {
    CFormView::OnInitialUpdate();

    pLogFont = new LOGFONT;
    CFont* pDialogFont = GetFont();
    pDialogFont->GetObject(sizeof(LOGFONT),pLogFont);
    pLogFont->lfHeight = MulDiv(pLogFont->lfHeight, Config.GetDstH(), Config.GetSrcH());
    pLogFont->lfWeight = FW_NORMAL;

    pFont = new CFont;
    pFont->CreateFontIndirect(pLogFont);
    SetFont(pFont);

    CWnd* pWnd;
    pWnd = GetWindow(GW_CHILD);
    while (pWnd != NULL)
        {
        ZoomWnd(pWnd);
        pWnd = pWnd->GetWindow(GW_HWNDNEXT);
        }

    // TRY to modify WIDTH and HEIGTH of CFormView    
    ZoomWnd(this);
    }        

void XFormView::ZoomWnd(CWnd* pWnd)
    {
    CRect rect;
    pWnd->GetWindowRect(&rect);
    ScreenToClient(&rect);
    rect.left   = (int)((long)rect.left   * Config.GetDstH() / Config.GetSrcH());
    rect.top    = (int)((long)rect.top    * Config.GetDstV() / Config.GetSrcV());
    rect.right  = (int)((long)rect.right  * Config.GetDstH() / Config.GetSrcH());
    rect.bottom = (int)((long)rect.bottom * Config.GetDstV() / Config.GetSrcV());

    pWnd->MoveWindow(&rect);
    pWnd->SetFont(pFont);
    }

Код работает хорошо, но для некоторых видов вертикальная и горизонтальная полоса прокрутки отсутствуют.

Окно всегда загружается MAXIMIZED.Если я не раскрываю окно, полосы прокрутки всегда отсутствуют.

Если я уменьшу ширину или высоту, полоса прокрутки отобразится, когда ширина или высота достигнет значения, определенного в файле ресурсов RC.

Пример:

IDD_OVFORM DIALOGEX 0, 0, 370, 297

, где 370 - ширина формы, а 297. - высота.

Если я уменьшу ширину дочернего окна, ничего не произойдет, пока ширина не уменьшится до 370. В этот момент горизонтальная полоса прокрутки автоматически

Моя проблема заключается в том, как динамически (не в файле RC) изменять ширину и высоту IDD_OVFORM в соответствии с уровнем масштабирования, чтобы горизонтальная и вертикальная полосы прокрутки отображались правильно?

У меня естьЯ уже пытался изменить эти свойства в методе OnInitialUpdate (), но ничего не работает.

Если я изменил Width и Height в RC Resource FILE, масштабирование будет работать корректно для определенного уровня масштабирования (но не для всех уровней масштабирования).

В Интернете я нахожу несколько решений об удалении полос прокрутки, но не о масштабировании иОтсутствуют полосы прокрутки при использовании MDI MFC Form.

Есть ли кто-нибудь, кто уже нашел решение этой проблемы?

2019-02-12: спасибо Barmak Shemirani за его решение (ВАРИАНТ3) отлично работает.

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Позвоните SetScrollSizes, чтобы показать полосы прокрутки в определенных размерах:

CRect rect;
GetClientRect(rect);

//this multiplication is to make sure the scrollbar is visible
//remove it in actual code.
rect.right *= 2;
rect.bottom *= 2;

SetScrollSizes(MM_TEXT, rect.Size());

Но это не правильный метод в целом.

Вариант 1:

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

Опция 2:

В свойствах диалога вы также увидитераздел под названием «Динамический макет».Это позволяет масштабировать элементы управления при изменении размера или перемещать их вверх / вниз и влево / вправо.

Опция 3:

Изменение шрифта в шаблоне диалога во время выполнения.Для этого необходимо переопределить CFormView::Create, что в свою очередь вызывает CreateDlg.Эти имена функций должны быть объявлены в точности так, как показано ниже.

Обратите внимание, что шрифт в шаблоне диалога может быть изменен только один раз, до загрузки диалога.

Пример для Visual Studio 2017 (этот кодможет быть несовместимо со старыми версиями MFC)

BOOL XFormView::CreateDlg(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
    CDialogTemplate dlt;
    if(dlt.Load(lpszTemplateName)))
    {
        // set your own font
        dlt.SetFont(L"Arial", 20);

        HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);

        LPCDLGTEMPLATE dlgtemplate = (LPCDLGTEMPLATE)GlobalLock(dlt.m_hTemplate);

        // create a modeless dialog
        BOOL bSuccess = CreateDlgIndirect(dlgtemplate, pParentWnd, hInst);

        GlobalUnlock(dlt.m_hTemplate);
        return bSuccess;
    }

    return CFormView::CreateDlg(lpszTemplateName, pParentWnd);
}

BOOL XFormView::Create
    ( LPCTSTR lpszClassName
    , LPCTSTR lpszWindowName
    , DWORD dwRequestedStyle
    , const RECT& rect
    , CWnd* pParentWnd
    , UINT nID
    , CCreateContext* pContext
    );
{
    ASSERT(pParentWnd != NULL);
    ASSERT(m_lpszTemplateName != NULL);

    m_pCreateContext = pContext;    // save state for later OnCreate

    // call PreCreateWindow to get prefered extended style
    CREATESTRUCT cs; 
    memset(&cs, 0, sizeof(CREATESTRUCT));
    if(dwRequestedStyle == 0)
        dwRequestedStyle = AFX_WS_DEFAULT_VIEW;
    cs.style = dwRequestedStyle;
    if(!PreCreateWindow(cs))
        return FALSE;

    // create a modeless dialog
    if(!CreateDlg(m_lpszTemplateName, pParentWnd))
        return FALSE;

    m_pCreateContext = NULL;

    ModifyStyle(WS_BORDER | WS_CAPTION, cs.style & (WS_BORDER | WS_CAPTION));
    ModifyStyleEx(WS_EX_CLIENTEDGE, cs.dwExStyle & WS_EX_CLIENTEDGE);

    SetDlgCtrlID(nID);

    CRect rectTemplate;
    GetWindowRect(rectTemplate);
    SetScrollSizes(MM_TEXT, rectTemplate.Size());

    // initialize controls etc
    if(!ExecuteDlgInit(m_lpszTemplateName))
        return FALSE;

    // force the size requested
    SetWindowPos(NULL, rect.left, rect.top,
        rect.right - rect.left, rect.bottom - rect.top,
        SWP_NOZORDER | SWP_NOACTIVATE);

    // make visible if requested
    if(dwRequestedStyle & WS_VISIBLE)
        ShowWindow(SW_NORMAL);

    return TRUE;
}

и определение класса в XFormView.h ДОЛЖНО содержать следующие строки

protected:

    BOOL Create
        ( LPCTSTR lpszClassName
        , LPCTSTR lpszWindowName
        , DWORD dwRequestedStyle
        , const RECT& rect
        , CWnd* pParentWnd
        , UINT nID
        , CCreateContext* pContext
        );

    BOOL CreateDlg(LPCTSTR lpszTemplateName, CWnd* pParentWnd);

    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

Объявление OnCreate абсолютно необходимо.

Без этого объявления ничего не происходит !!!

OnCreate объявляется только во включаемом файле, но не определяется в файле CPP.

0 голосов
/ 02 февраля 2019

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

Возможно, вам потребуется затем вызвать SetScrollInfo, чтобы настроить общий размер.

Оба вызова должны быть выполнены в родительском окне CFormView, которое должно быть CChildFrame.

...