Search code examples
windowswinapibitmaptransparencymasm

Calling TransparentBlt in MASM


I'm trying to make a game in Masm (my teacher said so) and I'm experiencing some problems with the TransparentBlt() function. I made a base for my game and I was using BitBlt, like this:

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

Where coordX and coordY represents the coordinates os the principal character and the default values(500, 478) are the size of my window. It's was working really nice, but some day I was searching and I found the TransparentBlt, I was fascinated with it's demonstrating results. Then I tryied to put it on my project and just VUSH! What's going on? My character just disappeared...

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

In case you're wondering, 59 and 30 are the width and height of my bitmap.

Could some one tell me how to use TransparentBlt (more than just MSDN)? I'm really excited with this almost PNG function...


Solution

  • You are probably passing the wrong dimensions.

    Conceptually, BitBlt is a very simple function. You can think of it as simply "blitting" (copying) a block of pixels from one device context to another. So, it needs the following parameters:

    1. The source device context
    2. The destination device context
    3. The origin (upper-left corner) of the source rectangle.
    4. The origin (upper-left corner) of the destination rectangle.
    5. The dimensions (width and height).

    It also takes a raster-operation code, but you're passing SRCCOPY, which means exactly what I described above: copy a block of pixels from one device context to another. You can do fancier stuff with BitBlt, but we'll ignore that.

    The thing to notice here is that BitBlt never does any resizing. The source and destination rectangles can have different origins (i.e., they can start at different coordinates), they they always have the same sizes (i.e., the source and destination always have the same width and height).

    If you want to do resizing (stretching or compressing) of the bitmap when you blit it, there is a function that can do that: StretchBlt. StretchBlt is basically just a version of BitBlt that is capable of stretching. It can scale the source image up or down in size, so it takes separate dimensions for the source and the destination.

    What does this have to do with TransparentBlt? Well, TransparentBlt also supports resizing. It is basically an extended version of StretchBlt that supports a limited form of transparency.*

    So the progression is basically this:

    • BitBlt is the basic function.
    • StretchBlt builds on this by adding the ability to resize the source image as it is drawn onto the destination.
    • TransparentBlt builds on this by adding the ability to make a particular color in the source image transparent as it is drawn onto the destination.

    I think this conceptual understanding is important, because it helps you keep straight how the functions should be used.

    It also helps answer your question. If you want to use TransparentBlt as a transparent equivalent to BitBlt, then you don't want any stretching, and you therefore need to pass exactly the same dimensions for the source as for the destination.

    In other words, call TransparentBlt as follows:

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

    One final note: you really need to be checking the return values of Windows API functions, otherwise you won't know whether they are failing. Generally, they will return FALSE (== 0) on failure. Sometimes (check the MSDN documentation to see if this is true), the GetLastError function can be called immediately after another function has returned FALSE to get additional information about why the function failed. Your code doesn't check any of the return values, so you have no idea if the functions failed or not, and therefore no good way of knowing where to start debugging.

    __
    * Technically, everything that you can do with TransparentBlt can be done with StretchBlt using that last parameter, the raster-operation code. And, in fact, this is how it had to be done prior to Windows 98/2000, before the TransparentBlt function existed. And even on Windows 98, you often wanted to do it the old-fashioned way, avoiding TransparentBlt, because TransparentBlt had a leak in it. Now that those days are well behind us, everyone just uses TransparentBlt because it is much simpler.