Windows 在MASM中调用TransparentBlt

Windows 在MASM中调用TransparentBlt,windows,winapi,bitmap,transparency,masm,Windows,Winapi,Bitmap,Transparency,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,hD

我正在尝试用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,主字符和默认值(500478)是我的窗口大小。 它的工作真的很好,但有一天我在搜索时发现了TransparentBlt,我对它的演示结果很着迷。然后我试着把它放在我的项目上,然后嘘!发生什么事?我的角色消失了

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是我的位图的宽度和高度


有人能告诉我如何使用透明语言吗?我对这个近乎PNG的函数非常兴奋…

您可能传递了错误的维度

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

  • 源设备上下文
  • 目标设备上下文
  • 源矩形的原点(左上角)
  • 目标矩形的原点(左上角)
  • 尺寸(宽度和高度)
  • 它还需要一个光栅操作代码,但您要传递的是
    SRCCOPY
    ,这正是我上面描述的意思:将一块像素从一个设备上下文复制到另一个设备上下文。你可以用
    BitBlt
    做一些更有趣的事情,但我们忽略了这一点

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

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

    这与透明度有什么关系?嗯,
    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文档以确定这是否正确),可以在另一个函数返回
    FALSE
    后立即调用
    GetLastError
    函数,以获取有关函数失败原因的其他信息。您的代码不检查任何返回值,因此您不知道函数是否失败,因此无法知道从何处开始调试

    __

    *从技术上讲,您可以使用
    TransparentBlt
    执行的所有操作都可以通过
    StretchBlt
    使用最后一个参数光栅操作代码来完成。事实上,在Windows 98/2000之前,
    TransparentBlt
    功能还没有出现之前,就必须这样做。即使在Windows 98上,您也经常希望使用老式的方法来执行此操作,避免使用
    TransparentBlt
    ,因为
    TransparentBlt
    中存在漏洞。现在,那些日子已经过去了,每个人都只使用
    TransparentBlt
    ,因为它更简单。

    如果您正在寻找类似“PNG”的支持,即alpha通道支持,为什么不使用也是GDI一部分的
    AlphaBlend
    API呢。它产生的效果远远好于TransparentBlt,TransparentBlt(本质上)必须在内部制作遮罩位图。@chrisbeck,我在上搜索了这个
    AlphaBlend
    ,我意识到它太复杂了,无法满足我的需要。我知道这可能比透明的要好,但我只需要一些容易看、理解和解释的东西。我不认为这很复杂。最大的问题只是一个工具:你需要给它一个4通道位图,没有很多绘画工具支持用ARGB写bmp。谢谢你的解释!使用“调试”的方式,我能够看到哪里出了问题。