Win32 MFC OnPaint调整大小和重绘处理

时间:2018-08-06 05:58:56

标签: c++ windows winapi mfc win32gui

每次我调整图纸大小时如何处理此问题似乎都不正确。 我认为我每次调整窗口大小时都需要调用Invalidate(),但是每次移动或调整窗口大小时,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();
}

调整大小之前:

调整大小后:

3 个答案:

答案 0 :(得分:1)

当您开始绘画并使用CPaintDC时,调用基类再试一次并可能再次擦除背景是没有意义的。

会发生什么。

  1. 您创建的CPaintDC文件
  2. BeginPaint被调用并发送WM_ERASEBKGND
  3. 您绘画自己的东西。
  4. 您将基类和新的CPaintDC称为BeginPaint
  5. 因为EndPaint未被调用,所以绘画区域未被验证。因此,执行BeginPaint,并再次调用WM_ERASEBKGND
  6. 最后,调用CPaintDC的析构函数并验证了工作区。

如果您开始使用CPaintDC / BeginPaint,请不要调用OnPaint基类函数!

答案 1 :(得分:0)

我不知道这是否是最佳解决方案。

  1. 在绘画代码中,绘画之前,用背景色填充整个工作区:

      dc.FillSolidRect(&rect, ...);
    

    删除CDialogEx::OnPaint()

  2. 添加一个OnEraseBkgnd处理程序:

      BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
        //...
        ON_WM_ERASEBKGND()
      END_MESSAGE_MAP()
    
      //...
    
      BOOL OnEraseBkgnd(CDC * pDC)
      {
        RedrawWindow();
        return TRUE;
      }
    
  3. 如果对话框闪烁,请使用MFC的CMemDC(未记录)。

答案 2 :(得分:-1)

这可以解决我的问题

步骤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 );
}
}

STEP: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:EndPaint()