C++ mfc位图读取一个完全黑色的位图
我想使用位图读取当前视图窗口,对其进行一些更改,然后将位图输出回视图。程序应该读取一个白色窗口,并在此背景下绘制一个正方形。然而,我在最后一个窗口中看到的图像是黑色背景中的正方形C++ mfc位图读取一个完全黑色的位图,c++,bitmap,mfc,C++,Bitmap,Mfc,我想使用位图读取当前视图窗口,对其进行一些更改,然后将位图输出回视图。程序应该读取一个白色窗口,并在此背景下绘制一个正方形。然而,我在最后一个窗口中看到的图像是黑色背景中的正方形 void CScribbleView::OnLButtonDown(UINT, CPoint point) { //CClientDC dc(this); //OnPrepareDC(&dc); HBITMAP initialMap; RECT t; BITMAP bm
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
现在,新的程序没有显示任何内容;它的白色背景与我最初使用的相同。这两个DC之间有什么区别?如何解决我的问题?这些WinAPI函数都需要清理:
::CetDC
,::CreateCompatibleDC
,::CreateCompatibleBitmap
。请参阅其中每一项的文档。如果没有清理,您的程序可能会很快使用其10000 GDI资源限制并崩溃
如果您使用这些WinAPI函数的MFC版本,则不必担心清理问题(您仍应查看文档以确保)。这是双缓冲的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);
}
好的,createCompatibleBitmap函数似乎不会创建包含客户端窗口中相同图像的位图。相反,它只是创建一个与客户端窗口大小相同的图像,所有像素颜色初始化为零(黑色)。无论如何,读取当前视图窗口是个坏主意。你到底想实现什么?说来话长。我正在做一个画画程序,就像画画一样。现在我正在画矩形。最初,当我按下并拖动鼠标时,我会在OnMouseMove函数中绘制一个新的矩形。然而,这就留下了一堆落后的矩形。因此,我决定在按下鼠标时将客户端视图保存在位图中。在OnMouseMove函数中,我只需在保存的视图上绘制,覆盖在拖动操作中创建的上一个矩形上。最好是将整个图形绘制到屏幕外的缓冲区中,然后将该缓冲区返回到视图窗口。是的,这就是我试图回答的问题,在CDC或CCC内部使用HDC通常是一个坏主意吗?例如,矩形(m_memdc.m_hDC,100100200200),这不是问题。您还可以依次使用
m_memdc.Rectangle(100100200200)
,这将调用核心WinAPI函数,即::Rectangle(m_memdc.m_hDC,100100200200)
//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);
}