Win32 MFC OnPaint 调整大小和重绘处理
Win32 MFC OnPaint Resizing and Redrawing handling
每当我调整我的绘图大小时,如何处理这个问题,我的绘图似乎不正确。
我想我每次调整 window 大小时都需要调用 Invalidate() 但不是每次移动或调整 window 大小时自动调用 WM_PAINT 吗?
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(rect);
if (IsIconic())
{
//CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
for(int ndx(0); ndx < rect.Width() - 150; ndx += 10)
{
dc.MoveTo( rect.left + 50, rect.bottom / 2 );
dc.LineTo( rect.left + 50 + ndx, rect.bottom / 2 );
}
CBrush mybrush(RGB(30,30,30));
dc.FillRect( CRect(rect.left + 10, rect.top + 10, rect.Width() / 4, rect.Height() / 4),&mybrush );
CDialogEx::OnPaint();
}
调整大小前:
调整大小后:
当您开始绘画并使用 CPaintDC
时,调用基础 class 并再次尝试并可能再次擦除背景是没有意义的...
会发生什么。
- 您的
CPaintDC
已创建
调用 BeginPaint
并发送 WM_ERASEBKGND
。
- 你画你的东西。
- 你调用基础 class 和一个新的
CPaintDC
调用 BeginPaint
.
- 因为
EndPaint
未被调用,所以未验证绘画区域。所以 BeginPaint
被执行并且 WM_ERASEBKGND
被再次调用。
- 最后调用
CPaintDC
的析构函数并验证客户区。
如果您开始使用 CPaintDC
/BeginPaint
,请不要调用 OnPaint baseclass 函数!
不知道这个是不是最优解
在您的绘制代码中,在绘制之前,用背景色填充整个客户区:
dc.FillSolidRect(&rect, ...);
移除CDialogEx::OnPaint()
.
添加一个 OnEraseBkgnd
处理程序:
BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
//...
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
//...
BOOL OnEraseBkgnd(CDC * pDC)
{
RedrawWindow();
return TRUE;
}
如果对话框闪烁,请使用 MFC 的 CMemDC(未记录)。
这解决了我的问题
第 1 步:BeginPaint()
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTestDrawDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(rect);
// draw background manually
EraseBkgnd(&dc);
if (IsIconic())
{
//CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
for(int ndx(0); ndx < rect.Width() - 150; ndx += 10)
{
dc.MoveTo( rect.left + 50, rect.bottom / 2 );
dc.LineTo( rect.left + 50 + ndx, rect.bottom / 2 );
}
CBrush mybrush(RGB(30,30,30));
dc.FillRect( CRect(rect.left + 10, rect.top + 10, rect.Width() / 4, rect.Height() / 4),&mybrush );
}
}
步骤:WM_ERASEBACKGND
上的 2 个 RedrawWindow()
BOOL CTestDrawDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
RedrawWindow();
return TRUE;
}
和手动绘制背景
void CTestDrawDlg::EraseBkgnd( CDC * pDC )
{
CRect rect;
GetClientRect(rect);
pDC->FillSolidRect(rect, RGB(255,255,255));
// paint whatever you want in the background
}
第 3 步:结束绘制()
每当我调整我的绘图大小时,如何处理这个问题,我的绘图似乎不正确。 我想我每次调整 window 大小时都需要调用 Invalidate() 但不是每次移动或调整 window 大小时自动调用 WM_PAINT 吗?
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(rect);
if (IsIconic())
{
//CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
for(int ndx(0); ndx < rect.Width() - 150; ndx += 10)
{
dc.MoveTo( rect.left + 50, rect.bottom / 2 );
dc.LineTo( rect.left + 50 + ndx, rect.bottom / 2 );
}
CBrush mybrush(RGB(30,30,30));
dc.FillRect( CRect(rect.left + 10, rect.top + 10, rect.Width() / 4, rect.Height() / 4),&mybrush );
CDialogEx::OnPaint();
}
调整大小前:
调整大小后:
当您开始绘画并使用 CPaintDC
时,调用基础 class 并再次尝试并可能再次擦除背景是没有意义的...
会发生什么。
- 您的
CPaintDC
已创建
调用 BeginPaint
并发送WM_ERASEBKGND
。- 你画你的东西。
- 你调用基础 class 和一个新的
CPaintDC
调用BeginPaint
. - 因为
EndPaint
未被调用,所以未验证绘画区域。所以BeginPaint
被执行并且WM_ERASEBKGND
被再次调用。 - 最后调用
CPaintDC
的析构函数并验证客户区。
如果您开始使用 CPaintDC
/BeginPaint
,请不要调用 OnPaint baseclass 函数!
不知道这个是不是最优解
在您的绘制代码中,在绘制之前,用背景色填充整个客户区:
dc.FillSolidRect(&rect, ...);
移除
CDialogEx::OnPaint()
.添加一个
OnEraseBkgnd
处理程序:BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx) //... ON_WM_ERASEBKGND() END_MESSAGE_MAP() //... BOOL OnEraseBkgnd(CDC * pDC) { RedrawWindow(); return TRUE; }
如果对话框闪烁,请使用 MFC 的 CMemDC(未记录)。
这解决了我的问题
第 1 步:BeginPaint()
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTestDrawDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(rect);
// draw background manually
EraseBkgnd(&dc);
if (IsIconic())
{
//CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
for(int ndx(0); ndx < rect.Width() - 150; ndx += 10)
{
dc.MoveTo( rect.left + 50, rect.bottom / 2 );
dc.LineTo( rect.left + 50 + ndx, rect.bottom / 2 );
}
CBrush mybrush(RGB(30,30,30));
dc.FillRect( CRect(rect.left + 10, rect.top + 10, rect.Width() / 4, rect.Height() / 4),&mybrush );
}
}
步骤:WM_ERASEBACKGND
上的 2 个 RedrawWindow()BOOL CTestDrawDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
RedrawWindow();
return TRUE;
}
和手动绘制背景
void CTestDrawDlg::EraseBkgnd( CDC * pDC )
{
CRect rect;
GetClientRect(rect);
pDC->FillSolidRect(rect, RGB(255,255,255));
// paint whatever you want in the background
}
第 3 步:结束绘制()