解决绘图闪烁问题--双缓冲技术
一、缓冲技术原理:为了解决窗口刷新频率过快所带来的闪烁问题,利用双缓冲技术进行绘图。所谓双缓冲技术,就是将资源加载到内存,然后复制内存数据到设备DC(这个比较快),避免了直接在设备DC上绘图(这个比较慢)。
二、列子示例:
1 void CDlgDrawSignature::OnPaint() 2 { 3 CPaintDC dc(this); // device context for painting 4 // TODO: 在此处添加消息处理程序代码 5 // 不为绘图消息调用 CDialogEx::OnPaint() 6 7 CRect ctrlRect; 8 this->GetClientRect(&ctrlRect);//获取尺寸 9 10 11 CDC dcMemory; 12 dcMemory.CreateCompatibleDC(&dc);//创建内存DC 13 14 15 CBitmap *pOldMapMemory; 16 CBitmap mapMemory; 17 mapMemory.CreateCompatibleBitmap(&dc, ctrlRect.Width(), ctrlRect.Height());//创建控件DC的兼容位图。其实就是与控件DC大小相同的一块区域 18 pOldMapMemory = dcMemory.SelectObject(&mapMemory);//加载兼容位图,只有制定了“桌布”尺寸之后,你才能在内存DC上面绘图 19 20 dcMemory.FillRect(&ctrlRect,&CBrush(RGB(255,255,255))); 21 DrawButton(&dcMemory);//在内存DC上绘图 22 23 dc.BitBlt(0, 0, ctrlRect.Width(), ctrlRect.Height(), &dcMemory, 0, 0, SRCCOPY);//将内存DC上的内容复制到控件DC上 24 dcMemory.SelectObject(pOldMapMemory);//还原原来的内存DC 25 ::DeleteObject(mapMemory);//删除兼容位图资源 26 ::DeleteDC(dcMemory);//删除内存DC 27 ReleaseDC(&dc);//释放控件DC 28 } 29 30 void CDlgDrawSignature::DrawButton(CDC* pDc) 31 { 32 //画黑色标题栏 33 CBrush brush(RGB(0,0,0)); 34 pDc->FillRect(&m_rcHit,&brush); 35 36 CPoint point; 37 GetCursorPos(&point); 38 ScreenToClient(&point); 39 if (m_rcClose.PtInRect(point)) 40 { 41 //红色关闭按钮背景 42 CBrush brushRed(RGB(255,0,0)); 43 pDc->FillRect(&m_rcClose,&brushRed); 44 } 45 46 //画白色关闭的X 47 CPen pen(PS_SOLID,2,RGB(255,255,255)); 48 CPen* penOld = pDc->SelectObject(&pen); 49 pDc->MoveTo(CPoint(m_rcClose.left+4,m_rcClose.top+4)); 50 pDc->LineTo(CPoint(m_rcClose.right-4,m_rcClose.bottom-4)); 51 pDc->MoveTo(CPoint(m_rcClose.right-4,m_rcClose.top+4)); 52 pDc->LineTo(CPoint(m_rcClose.left+4,m_rcClose.bottom-4)); 53 pDc->SelectObject(penOld); 54 55 //绘画保存按钮 56 CPen penBorder(PS_SOLID,1,RGB(0,0,0)); 57 penOld = pDc->SelectObject(&penBorder); 58 pDc->Rectangle(&m_rcSave); 59 pDc->SelectObject(penOld); 60 if (m_rcSave.PtInRect(point)) 61 { 62 CBrush brushBlue(RGB(65,105,255)); 63 pDc->FillRect(&m_rcSave,&brushBlue); 64 m_bSave = TRUE; 65 } 66 else 67 { 68 m_bSave = FALSE; 69 } 70 //设置字体 71 CFont font; 72 font.CreateFont( 18, // nHeight 73 0, // nWidth 74 0, // nEscapement 75 0, // nOrientation 76 FW_NORMAL, // nWeight 77 FALSE, // bItalic 78 FALSE, // bUnderline 79 0, // cStrikeOut 80 ANSI_CHARSET, // nCharSet 81 OUT_DEFAULT_PRECIS, // nOutPrecision 82 CLIP_DEFAULT_PRECIS, // nClipPrecision 83 DEFAULT_QUALITY, // nQuality 84 DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily 85 _T("宋体")); 86 87 CFont* pFont = pDc->SelectObject(&font); 88 pDc->SetBkMode(TRANSPARENT); 89 pDc->DrawText("保 存",&m_rcSave,DT_SINGLELINE|DT_CENTER|DT_VCENTER); 90 91 92 //绘画清除按钮 93 penOld = pDc->SelectObject(&penBorder); 94 pDc->Rectangle(&m_rcClear); 95 pDc->SelectObject(penOld); 96 if (m_rcClear.PtInRect(point)) 97 { 98 CBrush brushBlue1(RGB(65,105,255)); 99 pDc->FillRect(&m_rcClear,&brushBlue1); 100 m_bClear = TRUE; 101 } 102 else 103 { 104 m_bClear = FALSE; 105 } 106 107 pDc->DrawText("清 除",&m_rcClear,DT_SINGLELINE|DT_CENTER|DT_VCENTER); 108 109 pDc->SelectObject(pFont); 110 }