2015-09-07 31 views
-1

簡而言之,我需要做的是創建一個矩形網格,並在用戶單擊時填充該網格的任何選定案例。因此我保存參數(顏色,位置..)。問題是當我嘗試在點擊事件中填充案例時,我無法做出任何更改,可能是因爲即使使用GetDC()方法更改了設備上下文。那麼是否有任何方法來保存當前在OnDraw()方法中創建的當前實例,並在另一個函數的某個地方使用它,我試圖使用SaveDC()和RestoreDC(),但徒勞無益。MFC如何保存和重用當前設備上下文CDC

下面是我的一些代碼:

void CXThiefManView::OnDraw(CDC* pDC) 
{ 
    CXThiefManDoc* pDoc = GetDocument(); 
    ASSERT_VALID(pDoc); 
    if (!pDoc) 
     return; 
    CRect rcClient; 
    GetClientRect(&rcClient); 
    // Get the background color of the board 
    COLORREF clr = pDoc->GetBoardSpace(-1, -1); 
    // Draw the background first 
    pDC->FillSolidRect(&rcClient, clr); 
    // Create the brush for drawing 
    CBrush br; 
    br.CreateStockObject(HOLLOW_BRUSH); 
    CBrush* pbrOld = pDC->SelectObject(&br); 
    // Draw the squares 
    for (int row = 0; row < pDoc->GetRows(); row++) 
    { 
     for (int col = 0; col < pDoc->GetColumns(); col++) 
     { 
      // Get the color for this board space 
      clr = pDoc->GetBoardSpace(row, col); 
      // Calculate the size and position of this space 
      CRect rcBlock; 
      rcBlock.top = row * pDoc->GetHeight(); 
      rcBlock.left = col * pDoc->GetWidth(); 
      rcBlock.right = rcBlock.left + pDoc->GetWidth(); 
      rcBlock.bottom = rcBlock.top + pDoc->GetHeight(); 
      // Fill in the block with the correct color 
      pDC->FillSolidRect(&rcBlock, clr); 
      // Draw the block outline 
      pDC->Rectangle(&rcBlock); 
     } 
    } 

    saveState = pDC->SaveDC(); 

    DrawItem(pDC, pDoc->GetThiefRow(), pDoc->GetThiefCol(), pDoc->GetThiefColor()); 

} 

void CXThiefManView::OnLButtonDown(UINT nFlags, CPoint point) 
{ 
    // TODO: Add your message handler code here and/or call default 

    CView::OnLButtonDown(nFlags, point); 
    CXThiefManDoc* pDoc = GetDocument(); 

    // the draw item here to fill the case 
    DrawItem(GetDC(), 5, 5, RGB(0, 0, 0)); 
} 
+0

調用'這樣GetDC'會造成討厭的GDI資源泄漏。改用'CClientDC'。我想你想把繪畫保存到位圖上並更新它的圖形? 'SaveDC'和'RestoreDC'是爲了別的。 –

+0

以及如何在許多地方重複使用相同的CClientDC –

+2

您無法保存在WM_PAINT處理程序中檢索到的設備上下文。每次調用[BeginPaint](https://msdn.microsoft.com/en-us/library/dd183362.aspx)時都會重新創建它(這是[CPaintDC](https://msdn.microsoft.com/en -us/library/a48eab8d.aspx)在封面之後)。此設備上下文已設置剪輯到更新區域。更新區域通常可能從'WM_PAINT'消息到下一個消息。此外,即使在被銷燬後,您仍然會將'br'選擇到您的設備上下文中。這是一個懸掛指針的道德等價物。 – IInspectable

回答

0

下的所有這些MFC函數同名的WINAPI函數被調用。在WINAPI中,GetDC返回一個新的設備上下文。 SaveDC & RestoreDC允許您保存和恢復特定DC句柄的狀態(筆刷,字體等),但不會與其他句柄交叉。

MFC沒有辦法做到這一點,你也不能。您必須根據需要重新配置新的DC手柄。

+0

因此,如果我理解你,我必須重新做所有的工作在繪圖函數每次我需要更新上下文 –

+0

我想重新確認我的答案,所以它花了一段時間,但是,你必須重新配置你的DC每個每一次,這就是你通常在'OnDraw'中做的事情。 – Amit

0

手柄從GetDC必須發佈ReleaseDC。請參閱GetDC

或使用CClientDC dc(this)其中有自動清理,它的用法很相似,例如Draw(&dc,...);

至於您的主要問題,您可以將圖形保存在位圖上。位圖可以保存。

定義:

CBitmap m_bitmap; 
CDC m_memdc; 

初始化位圖和DC:

CClientDC dc(this); 
m_bitmap.CreateCompatibleBitmap(&dc, 2000, 1200); 
//this creates a bitmap as big as the screen... 

m_memdc.CreateCompatibleDC(&dc); 
m_memdc.SelectObject(m_bitmap); 
m_memdc.FillSolidRect(0, 0, 2000, 1200, RGB(255, 255, 255)); 
//draw on m_memdc, then draw memdc on to dc 

用法:

void CMyWindow::OnPaint() 
{ 
    CWnd::OnPaint(); 
    CClientDC dc(this); 

    CRect rc; 
    GetClientRect(&rc); 

    dc.BitBlt(0, 0, rc.Width(), rc.Height(), &m_memdc, 0, 0, SRCCOPY); 
} 

void CMyWindow::OnMouseMove(UINT k, CPoint p) 
{ 
    CClientDC dc(this); 

    CRect rc; 
    GetClientRect(&rc); 

    if (k & MK_LBUTTON) 
    { 
     //draw on m_memdc, (instead of drawing on dc) 
     m_memdc.SetPixel(p.x, p.y, RGB(0,0,0)); 
     m_memdc.SetPixel(p.x, p.y+1, RGB(0,0,255)); 

     //when finished drawing, draw m_memdc on to dc 
     dc.BitBlt(0, 0, rc.Width(), rc.Height(), &m_memdc, 0, 0, SRCCOPY); 
    } 
} 
相關問題