MFC 画直线 减少闪烁

最近一个作业,是MFC画直线。主要功能是三个:

1.可以指定线的颜色:红色,绿色和蓝色。

2.有四种画直线的方法。第一种用的是:SetROP2(R2_COPYPEN)

                                 第二种用的是:SetROP2(R2_NOT)

                                 第三种用的是:SetROP2(R2_XORPEN)

                                 第四种用的是:SetROP2(R2_XORPEN)

3.可以指定线的宽度:2pt 4pt 8pt.

 

一开始写程序的时候,没有用memory DC来画,于是在画线的过程中会产生闪烁这个问题。

 

这个程序主要部分有两个:一个是OnPaint()函数,一个是DrawTempLine()函数。

OnPaint()函数主要是将松开鼠标左键后的终点和起始点的那条直接画出来,这个直线当然不会只是一条。因为松开鼠标后,可以继续画其他的直线。

DrawTempLine()函数:主要是将鼠标在移动的过程中产生的线画出来。当鼠标放开之后,只会得到最后那条直线。

 

接下来,就是memDC解决闪烁问题。

当我们添加WM_ERASEBKGND后,在OnPain()函数中用memDC来画直线的话,然后在mousemove这个操作中,RedrawWindow()是不起作用的,而且还会增加闪烁现象。

于是,在DrawTempLine()函数中也用memDC来画直线。

代码贴出来:

 

void CChildView::OnPaint()
{
 CPaintDC dc(this); 

 CRect rect;
 GetClientRect(&rect);
 CDC mDC;
 mDC.CreateCompatibleDC(&dc);

 CBitmap bitmap;
 bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());

 CBitmap *pOldBmp = mDC.SelectObject(&bitmap);
 mDC.FillSolidRect(&rect, RGB(255, 255, 255));
 CPen *pOldPen=NULL;
 
 INT_PTR n = m_lines.GetSize();
 for (int i=0; i<n; i++)
 {
  CPen pen(PS_SOLID, m_lines[i].width , m_lines[i].color);
  mDC.SelectObject(pen);
  mDC.MoveTo(m_lines[i].start);
  mDC.LineTo(m_lines[i].end);
 }
 dc.BitBlt(0, 0, rect.Width(), rect.Height(), &mDC, 0, 0, SRCCOPY);
 mDC.SelectObject(pOldBmp);
 mDC.SelectObject (pOldPen);

 

}

 

 

 

void CChildView::DrawTempLine(CPoint point, BOOL bFirst)
{
 CClientDC dc(this);

 CRect rect;
 GetClientRect(&rect);
 CDC mDC;
 mDC.CreateCompatibleDC(&dc);

 CBitmap bitmap;
 bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());

 CBitmap *pOldBmp = mDC.SelectObject(&bitmap);
 //mDC.FillSolidRect(&rect, dc.GetBkColor ());
 mDC.BitBlt(0, 0, rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);  //这是关键的地方
 //CPen *pOldPen=NULL;

 CPen pen;

 if (m_selMethod == ID_METHOD1)
 {
  pen.CreatePen(PS_SOLID, m_width, m_color);
  mDC.SetROP2(R2_COPYPEN);
 }
 else if (m_selMethod == ID_METHOD2)
 {
  pen.CreatePen(PS_SOLID, m_width, m_color);
  mDC.SetROP2(R2_NOT);
 }
 else if (m_selMethod == ID_METHOD3)
 {
  pen.CreatePen(PS_SOLID, m_width, m_color);
  mDC.SetROP2(R2_XORPEN);
 }
 else if (m_selMethod == ID_METHOD4)
 {
  pen.CreatePen(PS_SOLID, m_width, 0xffffff & ~m_color);
  mDC.SetROP2(R2_XORPEN);
 }

 CPen *pOldPen =mDC.SelectObject(&pen);
 
 if (!bFirst)
 {
  mDC.MoveTo(m_tmpLine.start);
  mDC.LineTo(m_tmpLine.end);
 }

 m_tmpLine.end = point;
 mDC.MoveTo(m_tmpLine.start);
 mDC.LineTo(m_tmpLine.end);

 dc.BitBlt(0, 0, rect.Width(), rect.Height(), &mDC, 0, 0, SRCCOPY);
 mDC.SelectObject(pOldBmp);
 mDC.SelectObject (pOldPen);

}

 

 

在DrawTempLine()函数中。

mDC.BitBlt(0, 0, rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);  //这是关键的地方

按照平时的写程式的方式,会将memDC在放回到dc上面去。

但是在这里,如果DrawTempLine()函数也是先创建一个memDC,在这个上面进行画直线,然后放回到dc上去,在鼠标移动进行画线的时候,客户区上原来已经画好的直线是不会出现的,只会在鼠标放开之后,才会出现。

于是:咱们换个角度去想问题。我在鼠标移动,DrawTempLine的时候,将此时客户区背景以及上面已经有的东西,整个截取下来,当作DrawTempLine()的memDC,在上面进行画直线,画完之后,再讲memDC放回到原来的dc上去。这样的话,就不会出现遮盖原来的直线的问题。而且也不会闪烁了。

 

就这个样子。不好意思,表达能力有限

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值