65.9K
CodeProject 正在变化。 阅读更多。
Home

替换现有位图的一部分

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.77/5 (32投票s)

2006年7月28日

CPOL

3分钟阅读

viewsIcon

57769

downloadIcon

541

将一个位图复制到另一个位图的一部分。

Sample Image - bitmaptest_screenshot.png

引言

有时,你需要在代码中实现一些功能,而这需要大量的研究,通常与实现代码所需的最终行数不成比例。操作位图就是其中之一。 对于我们大多数人来说,进行GDI操作是我们能想到的最令人不快(和神秘)的编码任务之一。

在当前开发过程中,我决定动态更改CImageList的内容。 所谓 "动态",是指构建位图,然后在现有图像列表中替换给定的图像。 我知道 - 这简直是疯狂。 好吧,没有伟大的想法不受惩罚,我的也不例外。 在弄清楚如何做之后,情况阻止了我实际使用该代码。 但是,这并不意味着您(观众)不能从我的经验中受益。

这里的核心思想是获取现有的位图,并用另一个(更小的?)位图替换该位图的一部分,这就是本文所描述的内容。 您对生成的位图的处理方式仅受您的想象力限制。 以下是对演示应用程序中执行所有相关工作的函数的描述。

如何实现 - 部分替换现有位图

首先,我们必须建立一些参数。由于演示使用大小静态且已知的图像,因此我们使它非常简单。我们的小位图的宽度和高度为20x20。“目标”位图为60x20。

    int nWidth       = 20; 
    int nHeight      = 20;
    int nTargetWidth = 60;

接下来,我们确定要在目标位图上复制选定的源位图的位置。

    int nCoordX      = m_nSection * 20;
    int nCoordY      = 0; 

在这里,我们调用一个对话框函数来检索适当的(并且已经加载的)位图。

    CBitmap* pBmpSource = GetSourceBitmap(nImgNumb);

然后,我们要定义并初始化一些必要的对象。 由于我们将使用设备上下文,因此我们需要源和目标位图的CBitmap指针,以及设备上下文对象。

    CBitmap* pOldTargetBmp = NULL;
    CBitmap* pOldSourceBmp = NULL;
    CDC      targetDC;
    CDC      sourceDC;
    CDC*     pDC = this->GetDC();

现在到了有趣的部分。 我们需要创建一个可以在其上渲染位图的设备上下文。

    targetDC.CreateCompatibleDC(pDC);
    sourceDC.CreateCompatibleDC(pDC);

然后,我们将目标位图选择到目标DC中,并将源位图选择到源DC中。

    pOldTargetBmp = targetDC.SelectObject(&m_BmpTarget);
    pOldSourceBmp = sourceDC.SelectObject(pBmpSource);

这就是魔力发生的地方。 我们使用BitBlt将源DC的内容复制到指定坐标处的目标DC中。 请记住,我们在函数顶部为前四个参数设置了值。

    targetDC.BitBlt(nCoordX, nCoordY, nTargetWidth, nHeight, &sourceDC, 
                    0, 0, SRCCOPY);

现在我们已经完成了使用设备上下文需要做的一切,我们可以释放资源并进行清理。

    sourceDC.SelectObject(pOldSourceBmp);
    targetDC.SelectObject(pOldTargetBmp);

    sourceDC.DeleteDC();
    targetDC.DeleteDC();

    ReleaseDC(pDC);

最后一步是将对话框上的位图控件设置为使用我们的新位图。

    m_ctrlTargetImage.SetBitmap(HBITMAP(m_BmpTarget));

有了它 - 在少于20行代码中将位图复制到另一个位图(当然,不包括让我们到达这里的代码)。

如果您有任何问题,我将尽力回答,但我不是询问深奥的位图处理理论的最佳人选。 您最好在CodeProject上的MFC / VC ++论坛中提问。

旧版编译器

演示项目是用VS2005创建的,但是您应该能够将所需的代码直接复制/粘贴到使用VC5到VS2003的任何项目中,而不会出现任何问题。 如果您确实遇到问题,您应该完全有能力弄清楚如何解决它们。 毕竟,你是一名程序员,对吧?

致谢

非常感谢PJ Arends和Christian Graus对代码工作的协助。

我使用PJ的位图调试实用程序,以确保一切都按应有的方式工作。

另一个值得一提的是Chris Richardson,他指出了有关发布DC的遗漏。

更新

  • 07/31/2006 - 更正了一些拼写错误,并更新了代码和文章主体,以反映缺少对ReleaseDC的调用。
  • 07/28/2006 - 原始文章
© . All rights reserved.