2016-06-17 3 views
1

Я хочу использовать растровое изображение, чтобы прочитать текущее окно просмотра, внести в него некоторые изменения и вывести растровое изображение обратно в представление. Предполагается, что программа читает белое окно и рисует квадрат на этом фоне. Однако изображение, которое я вижу в последнем окне, представляет собой квадрат на черном фоне.mfc 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); 
} 

Это выход:

Я подозреваю, что растровое изображение не было правильно прочитать из моего оригинального DC. Поэтому позже я решил использовать другой способ получения DC, CClientDC, а не GetClientDC() -> m_hDC.

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); 
} 

Теперь новая программа ничего не показывает; это тот же белый фон, с которого я изначально начинался. В чем разница между этими двумя DC и как я могу исправить свою проблему?

+0

Хорошо, кажется, что функция CreateCompatibleBitmap не создает битовый массив, который содержит то же изображение, которое находится в окне клиента. Вместо этого он просто создает изображение, которое является размером окна клиента со всеми цветами пикселей, инициализированными нулем (что является черным). – varimax

+0

Чтение текущего окна просмотра - это плохая идея. Чего вы на самом деле пытаетесь достичь? –

+0

Это долгая история. Я делаю программу рисования, такую ​​как Paint. Сейчас я работаю над рисованием прямоугольников. Первоначально, когда я нажимаю и перетаскиваю мышь, я бы нарисовал новый прямоугольник в функции OnMouseMove. Однако это оставляет кучу отсталых прямоугольников. Поэтому я решил сохранить представление клиента в растровом изображении в момент нажатия мыши. В функции OnMouseMove я просто нарисую верх над просмотром, который я сохранил, прикрывая предыдущий прямоугольник, созданный при перетаскивании. – varimax

ответ

1

Эти функции WinAPI требуют очистки: ::CetDC, ::CreateCompatibleDC, ::CreateCompatibleBitmap. См. Документацию по каждому из них. Без очистки ваша программа может быстро использовать ограничение на 10 000 GDI ресурсов и сбоя.

Вам не нужно беспокоиться об очистке, если вы используете MFC-версию этих функций WinAPI (вы все равно должны видеть документы, чтобы убедиться). Это пример MFC для двойной буферизации:

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); 
}; 

Возможно, ваша цель состоит в том, чтобы нарисовать экранный буфер, как это предлагается в комментариях. В этом случае вы объявляете memdc и bitmap как данные члена:

//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

Спасибо большое, что сработало для меня !! – varimax

+0

Еще один вопрос: это плохая идея в целом использовать HDC внутри CDC или CClientDC? Например, Rectangle (m_memdc.m_hDC, 100, 100, 200, 200). – varimax

+0

Это не проблема. Вы также можете использовать 'm_memdc.Rectangle (100,100,200,200)', в свою очередь это вызовет основную функцию WinAPI, которая является :: :: Rectangle (m_memdc.m_hDC, 100,100,200,200) ' –

Смежные вопросы