我正在创建一个简单的 Win32/MFC 应用程序,它有一个主窗口和一个AnimateWindow()
用于显示(向上滑动)和隐藏(向下滑动)窗口的子窗口。当以 100% dpi 缩放运行应用程序时,一切正常。
我已经重写WM_ERASEBKGND
以呈现随机红色,以展示效果。随着窗口在动画的每个“步骤”上向下滑动(隐藏),背景的“更新矩形”被重新绘制,正是子窗口消失的位置,并且背景再次变得可见。
但是,当通过 Windows 设置更改 dpi 缩放(在本例中为 125%)时,会重新绘制不正确的区域。看起来好像传入的区域OnEraseBkgnd()
仍在使用 100% dpi 缩放大小,但位置也关闭了:似乎左上角的 x/y 位置是在屏幕空间而不是客户端中传递的-空间。因此,重绘区域看起来会有所不同,具体取决于窗口在屏幕上的位置。
白色区域是子窗口实际放置的位置,也是背景重绘实际发生的位置。
我已经在 Win10(1803 和 1809)和 Win8.1 上确认了这种影响这是操作系统中的错误,还是我可以做些什么来避免这个问题 - 除了不使用AnimateWindow()
?ShowWindow()
(带SW_SHOW
或SW_HIDE
)工作得很好,顺便说一句。
更新:添加了完整的源代码以重现该问题。根本不使用 dpi-aware manifest 时会出现此问题,但使用时也会出现此问题<gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>
class CDialogTestApp : public CWinApp
{
virtual BOOL InitInstance();
};
CDialogTestApp theApp;
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg() : CDialogEx(IDD_ABOUTBOX) {}
};
class CDialogTestDlg : public CDialogEx
{
public:
CDialogTestDlg(CWnd* pParent = nullptr) : CDialogEx(IDD_DIALOGTEST_DIALOG, pParent) {}
protected:
virtual BOOL OnInitDialog();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP()
private:
CAboutDlg mDialog;
};
BEGIN_MESSAGE_MAP(CDialogTestDlg, CDialogEx)
ON_WM_ERASEBKGND()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
BOOL CDialogTestApp::InitInstance()
{
CWinApp::InitInstance();
CDialogTestDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
return FALSE;
}
BOOL CDialogTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
mDialog.Create(IDD_ABOUTBOX, this);
return TRUE;
}
BOOL CDialogTestDlg::OnEraseBkgnd(CDC* pDC)
{
COLORREF color = RGB(rand() & 255, 20, 40);
CRect rect;
GetClipBox(pDC->m_hDC, &rect); // retrieve the update-rectangle
CBrush brush(color);
FillRect(pDC->m_hDC, &rect, (HBRUSH)brush.m_hObject);
return TRUE;
}
void CDialogTestDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
if (mDialog.IsWindowVisible())
{
mDialog.AnimateWindow(200, AW_HIDE | AW_SLIDE | AW_VER_POSITIVE);
}
else
{
mDialog.SetWindowPos(&CWnd::wndTop, 0, 50, 0, 0, SWP_NOSIZE);
mDialog.AnimateWindow(200, AW_ACTIVATE | AW_SLIDE | AW_VER_NEGATIVE);
}
CDialogEx::OnLButtonUp(nFlags, point);
}