替换现有位图的一部分
将一个位图复制到另一个位图的一部分。
引言
有时,你需要在代码中实现一些功能,而这需要大量的研究,通常与实现代码所需的最终行数不成比例。操作位图就是其中之一。 对于我们大多数人来说,进行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 - 原始文章