【问题标题】:Calling TransparentBlt in MASM在 MASM 中调用 TransparentBlt
【发布时间】:2017-06-14 01:37:42
【问题描述】:

我正在尝试在 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 表示主要字符的坐标,默认值 (500, 478) 是我的窗口大小。 它工作得非常好,但有一天我在搜索时发现了透明Blt,我对它展示的结果很着迷。然后我试着把它放在我的项目上,只是 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)吗?我对这个几乎是 PNG 的功能感到非常兴奋......

【问题讨论】:

  • 如果您正在寻找类似“PNG”的支持 - 即 alpha 通道支持 - 为什么不使用也是 GDI 一部分的 AlphaBlend API。它比TransparentBlt(本质上)必须在内部制作掩码位图产生更好的效果。
  • @ChrisBecke,我在MSDN 搜索了这个AlphaBlend,我意识到它对于我想要的来说太复杂了。我知道它可能比 TransparentBlt(efficiency, blablabla) 更好,但我只需要一些容易看到、理解和解释的东西。
  • 我认为它一点也不复杂。最大的问题只是工具之一:您需要给它一个 4 通道位图,并且没有很多绘图工具支持使用 ARGB 编写 bmp。

标签: windows winapi bitmap transparency masm


【解决方案1】:

您可能传递了错误的维度。

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

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

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

这里要注意的是BitBlt 从不进行任何调整大小。源矩形和目标矩形可以有不同的原点,它们可以从不同的坐标开始),它们总是有相同的大小(即,源和目标始终具有相同的宽度和高度)。

如果您想在 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 函数的返回值,否则您将不知道它们是否失败。通常,它们会在失败时返回FALSE (== 0)。 有时(查看 MSDN 文档以了解这是否属实),GetLastError 函数可以在另一个函数返回 FALSE 后立即调用以获取有关为什么的更多信息> 功能失败。您的代码不会检查任何的返回值,因此您不知道函数是否失败,因此也不知道从哪里开始调试。

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

【讨论】:

  • 感谢大解释!使用“调试”方式,我能够看到问题所在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
  • 2021-03-02
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 2015-06-06
  • 1970-01-01
相关资源
最近更新 更多