c++ MFC:绘制位图到CFrame

C++ MFC: Draw a bitmap into a CFrame

本文关键字:CFrame 位图 绘制 MFC c++      更新时间:2023-10-16

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

典型步骤如下:

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

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

从MSDN:

将位图从源矩形复制到目标矩形,拉伸或压缩位图(如果需要)以适应目标矩形的尺寸。

如果你想要和你展示的结果一样,那么你可能是在用最好的方法。你可以使用像FillRect这样的东西直接绘制到帧(或处理OnEraseBkgnd),然后对原始大小的图像进行BitBlt,但你可能会得到一些闪烁,这是你的双缓冲解决方案。