在 MASM 中调用 TransparentBlt

Calling TransparentBlt in MASM

我正在尝试用 Masm 制作游戏(我的老师是这么说的),但我在使用 TransparentBlt() 函数时遇到了一些问题。 我为我的游戏做了一个基础,我使用的是 BitBlt,就像这样:

invoke SelectObject,memDC,hPerson ;// selecting the Handler of my bitmap
mov hFImage, eax ;// putting the result in hFImage(using in other locals)
invoke BitBlt,hDC,0,0,500,478,memDC,coordX,coordY,SRCCOPY ;// drawing

其中 coordX 和 coordY 表示坐标 os 主要字符和默认值 (500, 478) 是我的 window 的大小。 它工作得非常好,但有一天我在搜索时发现了 TransparentBlt,我对它的演示结果着迷。然后我试着把它放在我的项目中,只是 VUSH!这是怎么回事?我的角色刚刚消失了...

invoke SelectObject,memDC,hPerson ;// same
mov hFImage, eax ;// same
RGB_b 0,160,192 ;// it puts the RGB of background on ebx
invoke TransparentBlt,hDC,0,0,500,478,memDC,coordX,coordY, 59, 30, ebx

如果您想知道,59 和 30 是我的位图的宽度和高度。

有人能告诉我如何使用 TransparentBlt(不仅仅是 MSDN)吗?我对这个 almost PNG 函数感到非常兴奋...

您传递的尺寸可能有误。

从概念上讲,BitBlt 是一个非常简单的函数。您可以将其简单地视为 "blitting"(复制)像素块从一个设备上下文到另一个设备上下文。所以,它需要以下参数:

  1. 源设备上下文
  2. 目标设备环境
  3. 源矩形的原点(左上角)。
  4. 目标矩形的原点(左上角)。
  5. 尺寸(宽度和高度)。

它也需要一个光栅操作代码,但你传递的是 SRCCOPY,这正是我上面描述的意思:将像素块从一个设备上下文复制到另一个设备上下文。您可以使用 BitBlt 做一些更有趣的事情,但我们会忽略它。

这里要注意的是 BitBlt 从不调整大小。源和目标矩形可以有不同的origins,它们可以从不同的坐标开始),它们总是有相同的sizes,源和目标始终具有相同的宽度和高度)。

如果您想在 blit 位图时对位图进行 调整大小(拉伸或压缩),有一个函数可以做到这一点:StretchBltStretchBlt 基本上只是能够拉伸的 BitBlt 的一个版本。它可以放大或缩小源图像的大小,因此源图像和目标图像需要 单独的 尺寸。

这和TransparentBlt有什么关系?嗯,TransparentBlt支持调整大小。它基本上是 StretchBlt 的扩展版本,支持有限形式的透明度。*

所以进度基本上是这样的:

  • BitBlt是基本功能。
  • StretchBlt 在此基础上添加了 调整大小 源图像绘制到目标上的能力。
  • TransparentBlt 在此基础上添加了使源图像中的特定颜色在绘制到目标图像时透明的功能。

我认为这种概念上的理解很重要,因为它可以帮助您弄清楚应该如何使用函数。

它也有助于回答您的问题。如果您想使用 TransparentBlt 作为 BitBlt 的透明等价物,那么您不需要任何拉伸,因此您需要为源传递与目标完全相同的维度。

换句话说,调用TransparentBlt如下:

invoke TransparentBlt, hDC, 0, 0, 500, 478, memDC, coordX, coordY, 500, 478, ebx

最后一点:您确实需要检查 Windows API 函数的 return 值,否则您将不知道它们是否失败。通常,他们会在失败时 return FALSE (== 0)。 有时(查看 MSDN 文档以查看是否属实),可以在另一个函数 returned FALSE 后立即调用 GetLastError 函数获取有关为什么 函数失败的更多信息。您的代码不检查 return 值的 any,因此您不知道函数是否失败,因此没有好的方法知道从哪里开始调试。

__
* 从技术上讲,您可以用 TransparentBlt 做的所有事情都可以用 StretchBlt 使用最后一个参数(光栅操作代码)来完成。而且,事实上,在 Windows 98/2000 之前,在 TransparentBlt 功能存在之前,必须这样做。甚至在 Windows 98 上,你也经常想用老式的方式来避免 TransparentBlt,因为 TransparentBlt 有漏洞。现在那些日子已经过去了,每个人都使用 TransparentBlt 因为它更简单。