2015-09-07 2 views
-1

Ну, просто мне нужно создать сетку прямоугольника и заполнить любой выбранный случай этой сетки при щелчке пользователя. таким образом я сохраняю параметры (цвет, положение ..). Проблема в том, что когда я пытаюсь заполнить случай при событии клика, я не могу никаких изменений, возможно, потому что изменился контекст устройства, даже если я использую метод GetDC(). Итак, есть ли способ сохранить созданный в OnDraw() метод exmaple и использовать его где-то в другой функции, я пытался использовать 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 позволяет сохранять и восстанавливать состояние (кисть, шрифт и т. Д.) Определенного дескриптора постоянного тока, но это не пересекает другие ручки.

Ничего из этого не может сделать MFC, и вы не можете. Вам необходимо перенастроить новую ручку DC для ваших нужд.

+0

Итак, если я понимаю вас, я должен выполнить всю работу над функцией рисования каждый раз, когда мне нужно обновить контекст. –

+0

Я хотел подтвердить свой ответ, поэтому потребовалось некоторое время, но да, вы должны перенастроить свой DC каждый и каждый раз, и это то, что вы обычно делаете в 'OnDraw'. – Amit

0

Ручка от GetDC должна быть выпущена ReleaseDC. См. GetDC

Или используйте CClientDC dc(this), который имеет автоматическую очистку, его использование аналогично, например Draw(&dc,...);.

Что касается вашего основного вопроса, вы можете сохранить рисунок на растровом изображении. Растровое изображение можно сохранить.

определяют:

CBitmap m_bitmap; 
CDC m_memdc; 

инициализации растровой и постоянного тока:

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); 
    } 
} 
Смежные вопросы