【问题标题】:mfc bitmap reads a completely black bitmapmfc 位图读取全黑位图
【发布时间】:2016-06-17 05:20:38
【问题描述】:

我想使用位图来读取当前视图窗口,对其进行一些更改并将位图输出回视图。该程序应该读取一个白色窗口并在此背景下绘制一个正方形。但是,我在最终窗口中看到的图像是黑色背景中的正方形。

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 有什么区别?如何解决我的问题?

【问题讨论】:

  • 好的,createCompatibleBitmap 函数似乎没有创建包含客户端窗口中相同图像的位图。相反,它只是创建一个与客户端窗口大小相同的图像,其中所有像素颜色都初始化为零(即黑色)。
  • 无论如何,阅读当前视图窗口是个坏主意。你到底想达到什么目标?
  • 说来话长。我正在做一个像Paint这样的绘图程序。现在我正在绘制矩形。最初,当我按下并拖动鼠标时,我会在 OnMouseMove 函数中绘制一个新矩形。但是,这会留下一堆滞后的矩形。所以我决定在按下鼠标的那一刻将客户端视图保存在位图中。在 OnMouseMove 函数中,我只会在保存的视图上绘制,覆盖在拖动操作中创建的前一个矩形。
  • 最好将整个绘图放入屏幕外缓冲区,然后将该缓冲区blit 返回到您的视图窗口。
  • 是的,这就是我想要做的

标签: c++ bitmap mfc


【解决方案1】:

这些 WinAPI 函数都需要清理:::CetDC::CreateCompatibleDC::CreateCompatibleBitmap。请参阅每个文档的文档。如果不进行清理,您的程序可能会很快使用其 10,000 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);
}; 

您的目标可能是在屏幕缓冲区上绘制,如 cmets 中所建议的那样。在这种情况下,您将 memdcbitmap 声明为成员数据:

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

【讨论】:

  • 还有一个问题,一般来说,在 CDC 或 CClientDC 中使用 HDC 是不是一个坏主意?例如,矩形(m_memdc.m_hDC,100,100,200,200)。
  • 这不是问题。您也可以依次使用m_memdc.Rectangle(100,100,200,200),这将调用核心WinAPI函数::Rectangle(m_memdc.m_hDC,100,100,200,200)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
  • 2012-12-08
  • 1970-01-01
  • 2014-02-09
相关资源
最近更新 更多