C++ MFC : Draw a bitmap into a CFrame

标签 c++ mfc bitblt

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

典型程序如下:

在 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 放入窗口中。

还有其他方法吗?实际代码如下。

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

最佳答案

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

来自 MSDN:

Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap if necessary to fit the dimensions of the destination rectangle.

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

关于C++ MFC : Draw a bitmap into a CFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24210514/

相关文章:

c++ - 使用 Boost::asio 接收压缩数据

c++ - 如何组合两个整数 vector

c++ - 为什么 std::distance 打印出 `-` ?

c++ - ffmpeg 问题

winapi - 在 OnPaint 中闪烁

c# - 在 C# 中使用 BitBlt 捕获的屏幕截图在 Windows 10 上生成黑色图像

c++ - 如何避免与 VSConstants.S_OK 字段命名冲突?

c++ - CArray 的析构函数大约需要 30 秒才能运行

image - BitBlt 性能

objective-c - Objective-C/Cocoa 中的 BitBlt() 等价物