01. CAD双缓冲绘图
# CAD
1. 什么时候绘制
1. WM_PAINT时绘制,MFC中是CMFCApplication1View::OnDraw时绘制
2. 在哪里绘制
1. DC
SDK |
MFC |
绘制区域 |
BeginPaint |
CPaintDC |
无效区 |
GetDC |
CClientDC |
客户区 |
GetWindowDC |
CWindowDC |
整个窗口 |
CreateCompatibleDC |
CDC |
内存 |
3. 如何绘制
1. InvalidateRect(hWnd, nullptr, TRUE);如果调用时传TRUE清除背景,就会导致闪烁。
2. 捕获鼠标SetCapture, ReleaseCapture
3. SDK用MoveToEx, MoveToEx绘制直线
4. 双缓冲步骤
SDK例子:
case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RECT rect = {}; GetClientRect(hWnd, &rect); auto nWidth = rect.right - rect.left; auto nHeight = rect.bottom - rect.top; HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hBitMap = CreateCompatibleBitmap(hdc, nWidth, nHeight); SelectObject(hdcMem, hBitMap); FillRect(hdcMem, &rect, (HBRUSH)(RGB(255, 255, 255) + 1)); for (auto &pts : vec) { MoveToEx(hdcMem, pts.first.x, pts.first.y, nullptr); LineTo(hdcMem, pts.second.x, pts.second.y); } MoveToEx(hdcMem, ptBeg.x, ptBeg.y, nullptr); LineTo(hdcMem, ptEnd.x, ptEnd.y); BitBlt(hdc, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); DeleteObject(hBitMap); DeleteDC(hdcMem); EndPaint(hWnd, &ps); break; }
MFC例子:
void CMFCApplication1View::OnDraw(CDC *pDC) { CMFCApplication1Doc *pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; CRect rcClient; GetClientRect(&rcClient); CDC dcMem; dcMem.CreateCompatibleDC(pDC); CBitmap bmpMem; bmpMem.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); dcMem.SelectObject(&bmpMem); dcMem.FillSolidRect(rcClient, RGB(255, 255, 255)); auto pos = m_lstLines.GetHeadPosition(); while (pos) { auto line = m_lstLines.GetNext(pos); dcMem.MoveTo(line.first); dcMem.LineTo(line.second); } dcMem.MoveTo(m_ptBegin); dcMem.LineTo(m_ptEnd); pDC->BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY); }