当 PC 使用缩放文本时,恢复的对话框正在裁剪控件

Posted

技术标签:

【中文标题】当 PC 使用缩放文本时,恢复的对话框正在裁剪控件【英文标题】:Restored dialog is cropping the controls when PC is using scaled text 【发布时间】:2019-12-02 23:21:10 【问题描述】:

我有这个基类用于调整对话框大小并记住它们的窗口状态。

BOOL CResizingDialog::OnInitDialog()

    CDialogEx::OnInitDialog();

    // Save Initial window size to m_rcInit
    GetWindowRect(&m_rcInit);

    //if (!m_bOnlyStorePosition && !m_bDoNotShowResizeIcon)
        //InitialiseResizeIcon(m_bmpResize, m_lblResize, this);

    RestoreWindowPosition(m_strWindowID, this, true);

    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE



void CResizingDialog::OnGetMinMaxInfo(MINMAXINFO* lpMMI)

    // Set the minimum window size to initial size.
    lpMMI->ptMinTrackSize.x = m_rcInit.Width();
    lpMMI->ptMinTrackSize.y = m_rcInit.Height();

    CDialogEx::OnGetMinMaxInfo(lpMMI);



void CResizingDialog::RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState)

    int     max_x, max_y;
    RECT    rtWindow;

    if (pWindow == nullptr)
        return;

    // Only restore if there is a previously saved position
    if ((rtWindow.top = AfxGetApp()->GetProfileInt(strWindow, _T("Top"), -1)) != -1 &&
        (rtWindow.left = AfxGetApp()->GetProfileInt(strWindow, _T("Left"), -1)) != -1 &&
        (rtWindow.bottom = AfxGetApp()->GetProfileInt(strWindow, _T("Bottom"), -1)) != -1 &&
        (rtWindow.right = AfxGetApp()->GetProfileInt(strWindow, _T("Right"), -1)))
    
        max_x = rtWindow.right - rtWindow.left;
        max_y = rtWindow.bottom - rtWindow.top;

        // Get a handle to the monitor
        HMONITOR hMonitor = ::MonitorFromPoint(
            CPoint(rtWindow.left, rtWindow.top), MONITOR_DEFAULTTONEAREST);

        // Get the monitor info
        MONITORINFO monInfo;

        monInfo.cbSize = sizeof(MONITORINFO);
        if (::GetMonitorInfo(hMonitor, &monInfo) == 0)
            AfxMessageBox(_T("GetMonitorInfo failed"));
        else
        
            // Adjust for work area
            rtWindow.left += monInfo.rcWork.left - monInfo.rcMonitor.left;
            rtWindow.top += monInfo.rcWork.top - monInfo.rcMonitor.top;

            // Ensure top left point is on screen
            if (CRect(monInfo.rcWork).PtInRect(CPoint(rtWindow.left, rtWindow.top)) == FALSE)
            
                rtWindow.left = monInfo.rcWork.left;
                rtWindow.top = monInfo.rcWork.top;
            

            rtWindow.right = rtWindow.left + max_x;
            rtWindow.bottom = rtWindow.top + max_y;

            // Restore window size
            pWindow->MoveWindow(&rtWindow, FALSE);
        

        if (bOverrideState)
        
            // Let us override by restoring the window state
            int iState = AfxGetApp()->GetProfileInt(strWindow, _T("ShowCmd"), SW_SHOWNORMAL);
            pWindow->ShowWindow(iState);
        
    

有时我所做的只是记住窗口位置。好吧,一位用户向我报告了这个问题:

如您所见,窗口已裁剪控件。我没有检查用户的 PC,但由于某种原因,窗口(不可调整大小)已经裁剪了控件。

更新

我已经能够复制该问题。我在我的 Windows 10 PC 上使用高清(不是超高清)。如果我将操作系统的 文本缩放 设置为 150%,我可以看到这个问题。

我的 MFC 项目是使用 DPI Per Monitor 设置编译的,所以应该没问题。它失败并使用对话框的原始大小而不是对话框的“缩放”大小。

我做了更多的测试,似乎只是这一个窗口不正常。这是对话资源:

IDD_DIALOG_OUR_CHRISTIAN_LIFE_AND_MINISTRY_STUDENTS DIALOGEX 0, 0, 385, 298
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Apply Yourself to the Field Ministry"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    GROUPBOX        "Main hall",IDC_STATIC,7,7,257,93
    LTEXT           "Student:",IDC_STATIC_STUDENT_MH,29,16,29,8
    LTEXT           "Study #",IDC_STATIC_STUDY_MH,117,16,27,8
    LTEXT           "Assistant:",IDC_STATIC_ASSIST_MH,154,16,33,8,0,WS_EX_RIGHT
    LTEXT           "#1",IDC_STATIC,15,29,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN2_MH_STUDENT,29,26,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN2_MH_STUDENT_STUDY,117,26,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN2_MH_ASSIST,154,26,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM1_MH,"MfcButton",WS_TABSTOP,242,26,15,15
    LTEXT           "#2",IDC_STATIC,15,46,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN3_MH_STUDENT,29,43,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN3_MH_STUDENT_STUDY,117,43,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN3_MH_ASSIST,154,43,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM2_MH,"MfcButton",WS_TABSTOP,242,43,15,15
    LTEXT           "#3",IDC_STATIC,15,62,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN4_MH_STUDENT,29,60,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN4_MH_STUDENT_STUDY,117,60,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN4_MH_ASSIST,154,60,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM3_MH,"MfcButton",WS_TABSTOP,242,60,15,15
    LTEXT           "#4",IDC_STATIC,15,80,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN5_MH_STUDENT,29,78,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN5_MH_STUDENT_STUDY,117,78,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN5_MH_ASSIST,154,78,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM4_MH,"MfcButton",WS_TABSTOP,241,78,15,15
    GROUPBOX        "Auxiliary Clas-s-room 1",IDC_STATIC,7,102,257,93
    LTEXT           "Student:",IDC_STATIC_STUDENT_C1,30,111,29,8
    LTEXT           "Study #",IDC_STATIC_STUDY_C1,117,111,27,8
    LTEXT           "Assistant:",IDC_STATIC_ASSIST_C1,154,111,33,8,0,WS_EX_RIGHT
    LTEXT           "#1",IDC_STATIC,15,124,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN2_C1_STUDENT,29,121,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN2_C1_STUDENT_STUDY,117,121,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN2_C1_ASSIST,154,121,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM1_C1,"MfcButton",WS_TABSTOP,242,121,15,15
    LTEXT           "#2",IDC_STATIC,15,142,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN3_C1_STUDENT,29,139,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN3_C1_STUDENT_STUDY,117,139,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN3_C1_ASSIST,154,139,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM2_C1,"MfcButton",WS_TABSTOP,242,139,15,15
    LTEXT           "#3",IDC_STATIC,15,158,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN4_C1_STUDENT,29,157,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN4_C1_STUDENT_STUDY,117,157,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN4_C1_ASSIST,154,157,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM3_C1,"MfcButton",WS_TABSTOP,242,157,15,15
    LTEXT           "#4",IDC_STATIC,15,176,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN5_C1_STUDENT,29,175,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN5_C1_STUDENT_STUDY,117,175,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN5_C1_ASSIST,154,175,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM4_C1,"MfcButton",WS_TABSTOP,241,175,15,15
    GROUPBOX        "Auxiliary Clas-s-room 2",IDC_STATIC,7,198,257,93
    LTEXT           "Student:",IDC_STATIC_STUDENT_C2,30,208,29,8
    LTEXT           "Study #",IDC_STATIC_STUDY_C2,117,207,27,8
    LTEXT           "Assistant:",IDC_STATIC_ASSIST_C2,154,208,33,8,0,WS_EX_RIGHT
    LTEXT           "#1",IDC_STATIC,16,222,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN2_C2_STUDENT,29,219,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN2_C2_STUDENT_STUDY,117,219,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN2_C2_ASSIST,154,219,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM1_C2,"MfcButton",WS_TABSTOP,242,219,15,15
    LTEXT           "#2",IDC_STATIC,16,239,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN3_C2_STUDENT,29,237,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN3_C2_STUDENT_STUDY,117,237,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN3_C2_ASSIST,154,237,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM2_C2,"MfcButton",WS_TABSTOP,242,237,15,15
    LTEXT           "#3",IDC_STATIC,16,255,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN4_C2_STUDENT,29,254,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN4_C2_STUDENT_STUDY,117,254,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN4_C2_ASSIST,154,254,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM3_C2,"MfcButton",WS_TABSTOP,242,254,15,15
    LTEXT           "#4",IDC_STATIC,15,272,10,8
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN5_C2_STUDENT,29,272,84,14,ES_AUTOHSCROLL | ES_READONLY
    COMBOBOX        IDC_COMBO_OCLM_AYFM_ASSIGN5_C2_STUDENT_STUDY,117,272,26,133,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_EDIT_OCLM_AYFM_ASSIGN5_C2_ASSIST,154,272,84,14,ES_AUTOHSCROLL | ES_READONLY
    CONTROL         "",IDC_MFCBUTTON_ITEM4_C2,"MfcButton",WS_TABSTOP,241,272,15,15
    EDITTEXT        IDC_EDIT_INFO,270,7,108,243,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_VSCROLL
    DEFPUSHBUTTON   "OK",IDOK,270,255,108,14
    PUSHBUTTON      "Cancel",IDCANCEL,270,274,108,14
END

我想知道是不是我在CResizingDialog 中的代码可能有缺陷?但后来我读了这个answer。这意味着由于我正在为 DPI 感知监视器进行编译,因此 MFC 项目应该开箱即用。那么为什么我最终得到的窗口大小没有补偿缩放设置呢?

我可以验证嵌入式清单也具有此 DPI 设置(为简洁起见,我剪掉了一些信息):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings>
            <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
        </windowsSettings>
    </application>
</assembly>

更新

问题与RestoreWindowPosition 有关。假设我上次存储的位置是在我使用 100% 字体缩放时。现在我使用 150% 的字体缩放。注册表中保存的窗口尺寸用于 100% 缩放。因此它被裁剪了。

同样,如果我删除我的恢复代码,并使用 150% 的缩放文本并关闭窗口,则注册表中的大小现在为 150%。因此,如果我恢复为 100% 缩放,则大小是错误的。

我不确定如何继续。我保存窗口位置的代码在这里:

void CResizingDialog::SaveWindowPosition(CString strWindow, CWnd* pWindow)

    WINDOWPLACEMENT wp;

    if (pWindow == nullptr)
        return;

    pWindow->GetWindowPlacement(&wp);

    // Commit to registry
    AfxGetApp()->WriteProfileInt(strWindow, _T("Top"), wp.rcNormalPosition.top);
    AfxGetApp()->WriteProfileInt(strWindow, _T("Left"), wp.rcNormalPosition.left);
    AfxGetApp()->WriteProfileInt(strWindow, _T("Bottom"), wp.rcNormalPosition.bottom);
    AfxGetApp()->WriteProfileInt(strWindow, _T("Right"), wp.rcNormalPosition.right);
    AfxGetApp()->WriteProfileInt(strWindow, _T("ShowCmd"), wp.showCmd);

显然,它保存的值取决于活动缩放。 #confused - 头痛。

更新

基于 cmets,我尝试进行一些更改以存储标准化的位置,然后对其进行缩放。但这并不完全正确。

代码如下:

void CResizingDialog::RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState)

    int     max_x, max_y;
    RECT    rtWindow;

    if (pWindow == nullptr)
        return;

    // Only restore if there is a previously saved position
    if ((rtWindow.top = AfxGetApp()->GetProfileInt(strWindow, _T("TopDPI"), -1)) != -1 &&
        (rtWindow.left = AfxGetApp()->GetProfileInt(strWindow, _T("LeftDPI"), -1)) != -1 &&
        (rtWindow.bottom = AfxGetApp()->GetProfileInt(strWindow, _T("BottomDPI"), -1)) != -1 &&
        (rtWindow.right = AfxGetApp()->GetProfileInt(strWindow, _T("RightDPI"), -1)))
    
        CDC* screen = GetDC();
        if (screen != nullptr)
        
            double dpi = static_cast<double>(screen->GetDeviceCaps(LOGPIXELSX));

            // 100% Scaled Text using 96 DPI
            double dScaleFactor = dpi / 96.0;

            rtWindow.top *= dScaleFactor;
            rtWindow.left *= dScaleFactor;
            rtWindow.bottom *= dScaleFactor;
            rtWindow.right *= dScaleFactor;

            ReleaseDC(screen);
        

        max_x = rtWindow.right - rtWindow.left;
        max_y = rtWindow.bottom - rtWindow.top;

        // Get a handle to the monitor
        HMONITOR hMonitor = ::MonitorFromPoint(
            CPoint(rtWindow.left, rtWindow.top), MONITOR_DEFAULTTONEAREST);

        // Get the monitor info
        MONITORINFO monInfo;

        monInfo.cbSize = sizeof(MONITORINFO);
        if (::GetMonitorInfo(hMonitor, &monInfo) == 0)
            AfxMessageBox(_T("GetMonitorInfo failed"));
        else
        
            // Adjust for work area
            rtWindow.left += monInfo.rcWork.left - monInfo.rcMonitor.left;
            rtWindow.top += monInfo.rcWork.top - monInfo.rcMonitor.top;

            // Ensure top left point is on screen
            if (CRect(monInfo.rcWork).PtInRect(CPoint(rtWindow.left, rtWindow.top)) == FALSE)
            
                rtWindow.left = monInfo.rcWork.left;
                rtWindow.top = monInfo.rcWork.top;
            

            rtWindow.right = rtWindow.left + max_x;
            rtWindow.bottom = rtWindow.top + max_y;

            // Restore window size
            pWindow->MoveWindow(&rtWindow, FALSE);
        

        if (bOverrideState)
        
            // Let us override by restoring the window state
            int iState = AfxGetApp()->GetProfileInt(strWindow, _T("ShowCmd"), SW_SHOWNORMAL);
            pWindow->ShowWindow(iState);
        
    


void CResizingDialog::SaveWindowPosition(CString strWindow, CWnd* pWindow)

    WINDOWPLACEMENT wp;

    if (pWindow == nullptr)
        return;

    pWindow->GetWindowPlacement(&wp);

    CDC *screen = GetDC();
    if (screen != nullptr)
    
        double dpi = static_cast<double>(screen->GetDeviceCaps(LOGPIXELSX));

        // 100% Scaled Text using 96 DPI
        double dScaleFactor = dpi / 96.0;

        AfxGetApp()->WriteProfileInt(strWindow, _T("TopDPI"), wp.rcNormalPosition.top / dScaleFactor);
        AfxGetApp()->WriteProfileInt(strWindow, _T("LeftDPI"), wp.rcNormalPosition.left / dScaleFactor);
        AfxGetApp()->WriteProfileInt(strWindow, _T("BottomDPI"), wp.rcNormalPosition.bottom / dScaleFactor);
        AfxGetApp()->WriteProfileInt(strWindow, _T("RightDPI"), wp.rcNormalPosition.right / dScaleFactor);
        AfxGetApp()->WriteProfileInt(strWindow, _T("ShowCmd"), wp.showCmd);

        ReleaseDC(screen);
    

当我的电脑 DPI 为 120 时,这里是一个对话框:

好消息是我现在可以看到所有控件。坏消息是它实际上太宽了。我尝试注释掉为工作区域调整它并确保左上角在屏幕上的代码,但这只会减少一点。

我不明白为什么它现在太宽了?它也比应有的高度略高。

【问题讨论】:

我假设你的代码改变了对话框的大小,这应该可以在调试器下重现。我的方法是:首先在 OnInitDialog() 中注释掉您对 RestoreWindowPosition() 的调用 - 然后可能该错误不再出现?第二次在调试器中重现错误,查看设置的窗口大小如何变化。当然你不能改变有效窗口大小,它是根据你的屏幕缩放调整的! 正如我所见,您恢复以前保存的确切窗口大小。我对这个问题的尝试是将尺寸标准化为 100% 屏幕缩放,并在恢复时将其与实际屏幕缩放相乘。在您的情况下(您依赖于 MFC/Windows 标准缩放机制),您应该只更改窗口位置并保留其大小。 使用 API 函数 GetDpiForMonitor(),除以 LOGPIXELSX (=96) 得到缩放为浮点数(您可以只参考 X 值,因为 X 和 Y 缩放始终相同)。然后除以它以归一化为 100% 并乘以它以获得当前屏幕的正确坐标或大小。 对我来说也是(我正在使用另一种方法)......也许是扩展的 SDK?但您也可以在此窗口中对 DC 使用 GetDeviceCaps(hDC, LOGPIXELSX)。 原因是对话框的大小取决于dialogbaseunits,它取决于它的字体。由于字体比例不能通过简单的乘法计算,它们对于应用程序的代码来说似乎是不可预测的,您必须依赖 Windows/MFC 的结果。所以你不应该调整你的对话窗口的大小,而只是重新定位它。 【参考方案1】:

我不知道这是否是最好的方法,但我已经接受了一些 cmets。这给了我 95% 的解决方案。

void CResizingDialog::RestoreWindowPosition(CString strWindow, CWnd* pWindow, bool bOverrideState)

    int     max_x, max_y;
    RECT    rtWindow;

    if (pWindow == nullptr)
        return;

    // Only restore if there is a previously saved position
    if ((rtWindow.top = AfxGetApp()->GetProfileInt(strWindow, _T("Top"), -1)) != -1 &&
        (rtWindow.left = AfxGetApp()->GetProfileInt(strWindow, _T("Left"), -1)) != -1 &&
        (rtWindow.bottom = AfxGetApp()->GetProfileInt(strWindow, _T("Bottom"), -1)) != -1 &&
        (rtWindow.right = AfxGetApp()->GetProfileInt(strWindow, _T("Right"), -1)))
    
        max_x = rtWindow.right - rtWindow.left;
        max_y = rtWindow.bottom - rtWindow.top;

        // Get a handle to the monitor
        HMONITOR hMonitor = ::MonitorFromPoint(
            CPoint(rtWindow.left, rtWindow.top), MONITOR_DEFAULTTONEAREST);

        // Get the monitor info
        MONITORINFO monInfo;

        monInfo.cbSize = sizeof(MONITORINFO);
        if (::GetMonitorInfo(hMonitor, &monInfo) == 0)
            AfxMessageBox(_T("GetMonitorInfo failed"));
        else
        
            // Adjust for work area
            rtWindow.left += monInfo.rcWork.left - monInfo.rcMonitor.left;
            rtWindow.top += monInfo.rcWork.top - monInfo.rcMonitor.top;

            // Ensure top left point is on screen
            if (CRect(monInfo.rcWork).PtInRect(CPoint(rtWindow.left, rtWindow.top)) == FALSE)
            
                rtWindow.left = monInfo.rcWork.left;
                rtWindow.top = monInfo.rcWork.top;
            

            if (m_bOnlyStorePosition)
            
                // We must override the dimensions of the dialog. This is because the user
                // might have text scale in effect.
                CRect rtOrg;
                GetWindowRect(&rtOrg);
                // But we want to show it in the previous place (albeit slightly off position)
                pWindow->MoveWindow(rtWindow.left, rtWindow.top, rtOrg.Width(), rtOrg.Height());
            
            else
            
                rtWindow.right = rtWindow.left + max_x;
                rtWindow.bottom = rtWindow.top + max_y;

                // Restore window size
                pWindow->MoveWindow(&rtWindow, FALSE);
            
        

        if (bOverrideState)
        
            // Let us override by restoring the window state
            int iState = AfxGetApp()->GetProfileInt(strWindow, _T("ShowCmd"), SW_SHOWNORMAL);
            pWindow->ShowWindow(iState);
        
    

主要问题是当我们恢复具有固定大小的窗口时(因为如果用户错误,可以调整大小的窗口)。

所以我添加了一些代码来恢复 X/Y 处的窗口,但具有原生的宽度和高度。然而,MFC 机制做到了,这里的值总是正确的,所以只使用它们是有意义的。

唯一的问题是 x/y 原点没有考虑到文本缩放的变化,但至少他们现在可以移动窗口并且没问题。

如果您能想到我对函数所做的代码调整有什么改进,请告诉我。我希望它对处于这种困境的其他人有用。

【讨论】:

如果您忽略更改对话框大小的部分,您的代码在我看来是合理的。 @Nick 我确实稍微调整了一下。之前的代码提前返回,所以它没有设置宽度和高度。但我已经重新调整它以进行其他测试,仍然可以按摩左上角。工作正常。

以上是关于当 PC 使用缩放文本时,恢复的对话框正在裁剪控件的主要内容,如果未能解决你的问题,请参考以下文章

裁剪 WPF 控件

由于 PC 显示设置的更改,Qt Widget 被部分裁剪

缩放图像以在android中裁剪

SwiftUI - 缩放、缩放和裁剪图像

html 使用croppie jquery-plugin。上传文件,它允许您在中心使用圆圈进行平移和缩放,然后当您单击“保存”时,将裁剪c

使用 DialogBoxIndirect 时,如何在对话框关闭时获取用户输入的文本?