C++ MFC:将位图绘制到 CFrame 中

Posted

技术标签:

【中文标题】C++ MFC:将位图绘制到 CFrame 中【英文标题】:C++ MFC: Draw a bitmap into a CFrame 【发布时间】:2014-06-13 17:07:10 【问题描述】:

我正在尝试将位图(存储为字节数组)绘制到窗口。

典型程序如下:

在 OnPaint() 处理程序中获取设备上下文。

CPaintDC dc(this);

从中创建兼容的设备上下文,

CDC pMemDC->CreateCompatibleDC(&dc);

创建一个与客户区大小相同的兼容位图 (GetClientRect(&WinRect))。

CBitmap pNewBitmap->CreateCompatibleBitmap(&dc, WinRect.Width(), WinRect.Height());

现在,如果窗口客户端的大小与位图的大小完全相同,我可以简单地调用 pNewBitmap->SetBitmapBits 以将我的数组“输入”到位图中。

在后面加上BitBlt,位图就会出现在窗口上。

dc->BitBlt(0, 0, WinRect.Width(), WinRect.Height(), pMemDC, 0, 0, SRCCOPY);

如果您希望窗口大小独立于图像大小而变化,那么首先您必须确保pNewBitmap 是正确的大小(客户矩形),但现在您不能简单地将数组推入位图中。

在这种情况下,我找到了一个解决方案,方法是重复上述过程来创建一个与图像精确大小的位图,这样我就可以将我的位“推入”其中,然后将BitBlt 放入更大的客户端-大小的位图,然后将BitBlt'ed 到窗口中。

还有其他方法可以做到这一点吗?实际代码如下。

void CAnimateWnd::OnPaint() 

    CPaintDC dc(this); // device context for painting

    DrawScene(&dc);

    // Do not call CWnd::OnPaint() for painting messages


void CAnimateWnd::DrawScene(CDC *pDrawDC)

    CRect WinRect;
    GetClientRect(&WinRect);

    if (pNewBitmap == NULL)
    
        pMemDC = new CDC();
        pMemDC->CreateCompatibleDC(pDrawDC);
        pNewBitmap = new CBitmap();
        pNewBitmap->CreateCompatibleBitmap(pDrawDC, WinRect.Width(), WinRect.Height());
        pMemDC->SelectObject(pNewBitmap);
    

    CRect BMPRect;
    GetBitmapDrawSize(&BMPRect);
    if (BMPRect != NULL)
    
        if (!(BMPRect.Width() >= WinRect.Width() && BMPRect.Height() >= WinRect.Height()))
        
            //The bitmap is smaller than the window, so fill the window with the background color.
            CBrush BackBrush(BackGndColor);
            CPen BackPen(PS_SOLID, 1, BackGndColor);
            pMemDC->SelectObject(&BackBrush);
            pMemDC->SelectObject(&BackPen);
            pMemDC->Rectangle(&WinRect);
            BackBrush.DeleteObject();
            BackPen.DeleteObject();
        
    

    OverrideAndDrawInHere(pMemDC, resize);
    pDrawDC->BitBlt(0,0,WinRect.right,WinRect.bottom,pMemDC,0,0,SRCCOPY);


template <class T>
void ImageWindow<T>::OverrideAndDrawInHere(CDC *pDC, int resize)

    if (this->sourceImage == NULL) return;

    CRect clientRect;
    GetClientRect(&clientRect);

    if (this->dispBMP == NULL)
    
        this->dispDC = new CDC();
        this->dispDC->CreateCompatibleDC(pDC);
        this->dispBMP = new CBitmap();
        this->dispBMP->CreateCompatibleBitmap(pDC, this->sourceImage->GetWidth(), this->sourceImage->GetHeight());
        this->dispDC->SelectObject(this->dispBMP);
    

    this->dispBMP->SetBitmapBits(this->sourceImage->GetArea() * 4, this->translatedImage);
    pDC->BitBlt(0, 0, this->sourceImage->GetWidth(), this->sourceImage->GetHeight(), this->dispDC, 0, 0, SRCCOPY);

【问题讨论】:

【参考方案1】:

如果您想将位图绘制到与源图像大小不同的窗口,请尝试StretchBlt,而不是使用 BitBlt:

来自 MSDN:

将位图从源矩形复制到目标矩形, 必要时拉伸或压缩位图以适应 目标矩形的尺寸。

如果您希望获得与所展示的结果相同的结果,那么您可能正在以最好的方式做到这一点。您可以使用 FillRect 之类的东西直接绘制到 Frame(或处理 OnEraseBkgnd),然后 BitBlt 原始大小的图像,但您可能会得到一些闪烁,这是您的双缓冲解决方案解决的问题。

【讨论】:

问题是绘制一个比窗口小的位图,没有拉伸它,仍然用纯色填充颜色绘制窗口的其余部分。

以上是关于C++ MFC:将位图绘制到 CFrame 中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中绘制纹理/位图的区域?

c++:如何使用 sdl 将位图加载到 opengl 中的多维数据集中?

将位图 (bmp) 转换为具有透明度的 png (Windows c++)

C++如何把位图保存到数组中

在 MFC 中重绘时闪烁

位图未在 Win32 C++ 中绘制