2016-06-17 16 views
1

Ich möchte ein Bitmap verwenden, um die aktuelle Ansicht Fenster zu lesen, machen einige Änderungen daran und geben die Bitmap auf die Ansicht zurück. Das Programm soll ein weißes Fenster lesen und vor diesem Hintergrund ein Quadrat zeichnen. Das Bild, das ich im letzten Fenster sehe, ist jedoch ein Quadrat in einem schwarzen Hintergrund.mfc Bitmap liest eine vollständig schwarze Bitmap

void CScribbleView::OnLButtonDown(UINT, CPoint point) 
{ 
    //CClientDC dc(this); 
    //OnPrepareDC(&dc); 
    HBITMAP initialMap; 
    RECT t; 
    BITMAP bmpScreen; 
    GetClientRect(&t); 
    initialMap = CreateCompatibleBitmap(GetDC()->m_hDC,t.right-t.left,t.bottom-t.top);   
    HDC tempDC = CreateCompatibleDC(GetDC()->m_hDC); 
    SelectObject(tempDC,initialMap); 
    SelectObject(tempDC,getStockObject(BLACK_PEN); 
    SelectObject(tempDC,GetStockObject(WHITE_BRUSH)); 
    Rectangle(tempDC,100,100,200,200); 
    BitBlt(GetDC()->m_hDC,clientR.left,clientR.top,clientR.right-clientR.left,t.bottom-clientR.top,tempDC,0,0,SRCCOPY); 
} 

Dies ist die Ausgabe:

ich, dass die Bitmap vermuten nicht richtig von meiner ursprünglichen DC gelesen wurde. Also entschied ich mich später, eine andere Methode zum Abrufen von DC, den CClientDC, anstelle von GetClientDC() -> m_hDC zu verwenden.

void CScribbleView::OnLButtonDown(UINT, CPoint point) 
{ 
    CClientDC dc(this); 
    OnPrepareDC(&dc); 
    HBITMAP initialMap; 
    RECT t; 
    BITMAP bmpScreen; 
    GetClientRect(&t); 
    initialMap = CreateCompatibleBitmap(dc.m_hDC,t.right-t.left,t.bottom-t.top);   
    HDC tempDC = CreateCompatibleDC(dc.m_hDC); 
    SelectObject(tempDC,initialMap); 
    SelectObject(tempDC,getStockObject(BLACK_PEN); 
    SelectObject(tempDC,GetStockObject(WHITE_BRUSH)); 
    Rectangle(tempDC,100,100,200,200); 
    BitBlt(dc.m_hDC,clientR.left,clientR.top,clientR.right-clientR.left,t.bottom-clientR.top,tempDC,0,0,SRCCOPY); 
} 

Jetzt zeigt das neue Programm nichts; Es ist der gleiche weiße Hintergrund, mit dem ich ursprünglich angefangen hatte. Was ist der Unterschied zwischen diesen beiden DC's und wie kann ich mein Problem beheben?

+0

Okay, scheint es, dass CreateCompatibleBitmap Funktion keine Bitmap erstellen, die das gleiche Bild enthalten, das in dem Client-Fenster ist. Stattdessen wird nur ein Bild erstellt, das der Größe des Clientfensters entspricht, bei dem alle Pixelfarben auf Null initialisiert sind (was schwarz ist). – varimax

+0

Das aktuelle Ansichtsfenster zu lesen ist sowieso eine schlechte Idee. Was versuchst du eigentlich zu erreichen? –

+0

Es ist eine lange Geschichte. Ich mache ein Zeichenprogramm wie Paint. Im Moment arbeite ich daran, Rechtecke zu zeichnen. Ursprünglich, wenn ich meine Maus drücke und ziehe, würde ich ein neues Rechteck in der OnMouseMove-Funktion zeichnen. Dies hinterlässt jedoch eine Reihe von verzögerten Rechtecken. Also entschied ich mich, die Client-Ansicht in einer Bitmap zu speichern, sobald die Maus gedrückt wird. In der OnMouseMove-Funktion würde ich einfach über die Ansicht, die ich gespeichert hatte, zeichnen und das vorherige Rechteck abdecken, das beim Ziehen erstellt wurde. – varimax

Antwort

1

Diese WinAPI-Funktionen müssen alle bereinigt werden: ::CetDC, ::CreateCompatibleDC, ::CreateCompatibleBitmap. Siehe Dokumentation für jede von ihnen. Ohne Bereinigung könnte Ihr Programm schnell seine Ressourcengrenze von 10.000 GDI verwenden und abstürzen.

Sie müssen über Bereinigung keine Sorge, wenn Sie die MFC-Version dieser WinAPI-Funktionen verwenden (Sie sollten immer noch die Dokumentation sehen sicher zu machen). Dies ist MFC-Beispiel für die Doppelpufferung:

void foo::OnLButtonDown(UINT nFlags, CPoint point) 
{ 
    CWnd::OnLButtonDown(nFlags, point); 

    CClientDC dc(this); 

    CRect rect; 
    GetClientRect(&rect); 

    //create memory dc 
    CDC memdc; 
    memdc.CreateCompatibleDC(&dc); 
    CBitmap bitmap; 
    bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); 
    memdc.SelectObject(bitmap); 

    //some random drawings: 
    memdc.SelectObject(GetStockObject(BLACK_PEN)); 
    memdc.SelectObject(GetStockObject(GRAY_BRUSH)); 
    memdc.Rectangle(10, 10, 100, 100); 

    //draw memory DC to destination DC 
    dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memdc, 0, 0, SRCCOPY); 
}; 

Ihr Ziel ist wahrscheinlich, Bildschirmpuffer zu zeichnen, wie in Kommentaren vorgeschlagen. In diesem Fall erklären Sie memdc und bitmap als Mitglied Daten:

//declare member data 
CDC m_memdc; 
CBitmap m_bitmap; 
CRect m_rect; 
CPoint m_point; 

void foo::initialize_once() 
{ 
    ASSERT(IsWindow(m_hWnd)); 
    GetClientRect(&m_rect); 
    //create memdc 
    m_memdc.CreateCompatibleDC(0); 
    CBitmap bitmap; 
    bitmap.CreateCompatibleBitmap(&m_memdc, m_rect.Width(), m_rect.Height()); 
    m_memdc.SelectObject(bitmap); 
    //initialize memdc background color 
    m_memdc.FillSolidRect(m_rect, RGB(255,255,255)); 
} 

void foo::OnLButtonDown(UINT nFlags, CPoint point) 
{ 
    __super::OnLButtonDown(nFlags, point); 
    m_point = point; 
    m_memdc.MoveTo(point); 
}; 

void OnMouseMove(UINT nFlags, CPoint point) 
{ 
    __super::OnMouseMove(nFlags, point); 
    if (!(nFlags & MK_LBUTTON)) return; 
    m_point = point; 
    m_memdc.LineTo(point); 
    CClientDC dc(this); 
    dc.BitBlt(0, 0, m_rect.Width(), m_rect.Height(), &m_memdc, 0, 0, SRCCOPY); 
} 
+0

Vielen Dank, dass für mich gearbeitet hat !! – varimax

+0

Noch eine Frage, ist es eine schlechte Idee, im Allgemeinen die HDC innerhalb CDC oder CClientDC zu benutzen? Zum Beispiel, Rechteck (m_memdc.m_hDC, 100, 100, 200, 200). – varimax

+0

Das ist kein Problem. Sie können auch 'm_memdc.Rectangle (100,100,200,200)' verwenden, was wiederum die Kern-WinAPI-Funktion aufruft, die ':: Rectangle (m_memdc.m_hDC, 100,100,200,200)' ist –