Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

DrawAlphaBlend (correct use of the AlphaBlend API)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DrawAlphaBlend (correct use of the AlphaBlend API)

    Code:
    ' Original MSDN C source code showing how to use the AlphaBlend API
    '
    ' Example translated to PowerBASIC by Patrice Terrier
    ' www.zapsolution.com 
    '
    ' Make sure you use the correct declaration for the AlphaBlend API DECLARE
    ' using ---> bf AS BLENDFUNCTION
    '
    TYPE BLENDFUNCTION
        BlendOp AS BYTE
        BlendFlags AS BYTE
        SourceConstantAlpha AS BYTE
        AlphaFormat AS BYTE
    END TYPE
    '
    %AC_SRC_OVER             = &H00
    %AC_SRC_ALPHA            = &H01
    '
    DECLARE FUNCTION AlphaBlend LIB "MSIMG32.DLL" ALIAS "AlphaBlend" (BYVAL hdcDest AS DWORD, BYVAL nXOriginDest AS LONG, BYVAL nYOriginDest AS LONG, BYVAL nWidthDest AS LONG, BYVAL nHeightDest AS LONG, _
                     BYVAL hdcSrc AS DWORD, BYVAL nXOriginSrc AS LONG, BYVAL nYOriginSrc AS LONG, BYVAL nWidthSrc AS LONG, BYVAL nHeightSrc AS LONG, BYVAL bf AS BLENDFUNCTION) AS LONG
    '
    SUB DrawAlphaBlend (BYVAL hWnd AS LONG, BYVAL hDCwnd AS LONG)
    '
        DIM hdc AS LONG            ' handle of the DC we will create 
        DIM bf AS BLENDFUNCTION    ' structure for alpha blending
        DIM hbitmap AS LONG        ' bitmap handle
        DIM bmi AS BITMAPINFO      ' bitmap header
        DIM pvBits AS DWORD PTR    ' pointer to DIB section
        DIM ulWindowWidth AS LONG, ulWindowHeight AS LONG ' window width/height
        DIM ulBitmapWidth AS LONG, ulBitmapHeight AS LONG ' bitmap width/height
        DIM rt AS RECT             ' used for getting window dimensions
        DIM x AS LONG, y AS LONG   ' stepping variables
        DIM ubAlpha AS BYTE, shubAlpha AS BYTE ' used for doing transparent gradient
        DIM ubRed   AS BYTE, shubRed AS BYTE
        DIM ubGreen AS BYTE, shubGreen AS BYTE
        DIM ubBlue  AS BYTE, shubBlue AS BYTE
        DIM fAlphaFactor AS SINGLE ' used to do premultiply
    '            
      ' get window dimensions
        CALL GetClientRect(hWnd, rt)
    '    
      ' calculate window width/height
        ulWindowWidth = rt.nright - rt.nleft
        ulWindowHeight = rt.nbottom - rt.ntop
    '
      ' make sure we have at least some window size
        IF ulWindowWidth = 0 OR ulWindowHeight = 0 THEN EXIT SUB
    '        
      ' divide the window into 3 horizontal areas
        ulWindowHeight = ulWindowHeight \ 3
    '
      ' create a DC for our bitmap -- the source DC for AlphaBlend 
        hdc = CreateCompatibleDC(hDCwnd)
    '    
      ' zero the memory for the bitmap info
        'ZeroMemory(&bmi, sizeof(BITMAPINFO));
    '
      ' setup bitmap info 
      ' set the bitmap width and height to 60% of the width and height of each of the three horizontal areas. Later on, the blending will occur in the center of each of the three areas.
        bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)
        ulBitmapWidth = ulWindowWidth - (ulWindowWidth / 5) * 2
        bmi.bmiHeader.biWidth = ulBitmapWidth
        ulBitmapHeight = ulWindowHeight - (ulWindowHeight / 5) * 2
        bmi.bmiHeader.biHeight = ulBitmapHeight
        bmi.bmiHeader.biPlanes = 1
        bmi.bmiHeader.biBitCount = 32         ' four 8-bit components
        bmi.bmiHeader.biCompression = %BI_RGB
        bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4
    '
      ' create our DIB section and select the bitmap into the dc
        hbitmap = CreateDIBSection(hdc, bmi, %DIB_RGB_COLORS, BYVAL VARPTR(pvBits), 0, 0)
        CALL SelectObject(hdc, hbitmap)
    '
      ' in top window area, constant alpha = 50%, but no source alpha
      ' the color format for each pixel is &Haarrggbb 
      ' set all pixels to blue and set source alpha to zero
        FOR y = 0 TO ulBitmapHeight - 1
            FOR x = 0 TO ulBitmapWidth - 1
                @pvBits[x + y * ulBitmapWidth] = &H000000ff
            NEXT
        NEXT
    '
        bf.BlendOp = %AC_SRC_OVER
        bf.BlendFlags = 0
        bf.SourceConstantAlpha = &H7F  ' half of &Hff = 50% transparency
        bf.AlphaFormat = 0             ' ignore source alpha channel
    '
        IF AlphaBlend(hDCwnd, (ulWindowWidth\5), (ulWindowHeight\5), _
                      ulBitmapWidth, ulBitmapHeight, _
                      hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, BYVAL VARPTR(bf)) = 0 THEN 
           GOTO ExitDrawAlpha  ' alpha blend failed
        END IF
    '    
      ' in middle window area, constant alpha = 100% (disabled), source 
      ' alpha is 0 in middle of bitmap and opaque in rest of bitmap 
        FORr y = 0 TO ulBitmapHeight - 1
            FOR x = 0 TO ulBitmapWidth - 1
                IF (x > (ulBitmapWidth / 5)) AND (x < (ulBitmapWidth-ulBitmapWidth / 5)) AND _
                   (y > (ulBitmapHeight / 5)) AND (y < (ulBitmapHeight-ulBitmapHeight / 5)) THEN
                  'in middle of bitmap: source alpha = 0 (transparent).
                  ' This means multiply each color component by &H00.
                  ' Thus, after AlphaBlend, we have a, &H00 * r, 
                  ' &H00 * g,and &H00 * b (which is &H00000000)
                  ' for now, set all pixels to red
                   @pvBits[x + y * ulBitmapWidth] = &H00ff0000
                ELSE
                  ' in the rest of bitmap, source alpha = &Hff (opaque) 
                  ' and set all pixels to blue 
                   @pvBits[x + y * ulBitmapWidth] = &Hff0000ff
                END IF
            NEXT
        NEXT
    '    
        bf.BlendOp = %AC_SRC_OVER
        bf.BlendFlags = 0
        bf.AlphaFormat = %AC_SRC_ALPHA  ' use source alpha 
        bf.SourceConstantAlpha = &HFF   ' opaque (disable constant alpha)
    '   
        IF AlphaBlend(hDCwnd, ulWindowWidth / 5, ulWindowHeight / 5 + ulWindowHeight, ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, BYVAL VARPTR(bf)) = 0 THEN 
           GOTO ExitDrawAlpha
        END IF
      ' bottom window area, use constant alpha = 75% and a changing
      ' source alpha. Create a gradient effect using source alpha, and 
      ' then fade it even more with constant alpha
        ubRed   = &H00
        ubGreen = &H00
        ubBlue  = &HFF
    '    
        FOR y = 0 TO ulBitmapHeight - 1
            FOR x = 0 TO ulBitmapWidth - 1
              ' for a simple gradient, base the alpha value on the x 
              ' value of the pixel 
                ubAlpha = x / ulBitmapWidth * 255
              ' calculate the factor by which we multiply each component
                fAlphaFactor = ubAlpha / 255 
              ' multiply each pixel by fAlphaFactor, so each component 
              ' is less than or equal to the alpha value.
                shubAlpha = ubAlpha:                SHIFT LEFT shubAlpha, 24
                shubRed = ubRed * fAlphaFactor:     SHIFT LEFT shubRed, 16
                shubGreen = ubGreen * fAlphaFactor: SHIFT LEFT shubGreen, 8
                shubBlue = ubBlue * fAlphaFactor
                @pvBits[x + y * ulBitmapWidth] = shubAlpha OR _  '&Haa000000
                                                 shubRed   OR _  '&H00rr0000
                                                 shubGreen OR _  '&H0000gg00
                                                 ubBlue          '&H000000bb
            NEXT
        NEXT
    '
        bf.BlendOp = %AC_SRC_OVER
        bf.BlendFlags = 0
        bf.AlphaFormat = %AC_SRC_ALPHA  ' use source alpha 
        bf.SourceConstantAlpha = &HBF   ' use constant alpha, with 
                                        ' 75% opaqueness
    '
        CALL AlphaBlend(hDCwnd, ulWindowWidth/5, _
                   ulWindowHeight/5+2*ulWindowHeight, ulBitmapWidth, _
                   ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, _
                   ulBitmapHeight, BYVAL VARPTR(bf))
    '
    ExitDrawAlpha:
      ' do cleanup
        CALL DeleteObject(hbitmap)
        CALL DeleteDC(hdc)
    '
    END SUB

    ------------------
    Patrice Terrier
    mailto[email protected][email protected]</A>
    www.zapsolution.com
    Addons: WinLIFT (Skin Engine), GDI+ helper (Graphic package), dvBTree (Index manager)
    Patrice Terrier
    www.zapsolution.com
    www.objreader.com
    Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

  • #2
    The declaration for the Alphablend function in Win32Api.inc uses
    BYVAL DWORD because earlier versions of the compiler didn't support
    passing structures by value. However, it can be used if you convert
    the four bytes BLENDFUNCTION structure to a DWORD using CVDWD.

    Note: I have been unable to get the bottom part working properly,
    so I have used different code.

    Code:
    ' ########################################################################################
    ' Alpha Blending a Bitmap
    ' ########################################################################################
    
    ' SED_PBWIN - Use the PBWIN compiler
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "WIN32API.INC"
    
    %AC_SRC_OVER             = &H00
    %AC_SRC_ALPHA            = &H01
    
    ' ========================================================================================
    ' The following code sample divides a window into three horizontal areas. Then it draws an
    ' alpha-blended bitmap in each of the window areas as follows:
    '    * In the top area, constant alpha = 50% but there is no source alpha.
    '    * In the middle area, constant alpha = 100% (disabled) and source alpha is 0
    '      (transparent) in the middle of the bitmap and 0xff (opaque) elsewhere.
    '    * In the bottom area, constant alpha = 75% and source alpha changes.
    ' ========================================================================================
    SUB DrawAlphaBlend (BYVAL hwnd AS LONG, BYVAL hDCwnd AS LONG)
    
       LOCAL hdc AS LONG              ' handle of the DC we will create
       LOCAL bf AS BLENDFUNCTION      ' structure for alpha blending
       LOCAL hbitmap AS LONG          ' bitmap handle
       LOCAL bmi AS BITMAPINFO        ' bitmap header
       LOCAL pvBits AS DWORD PTR      ' pointer to DIB section
       LOCAL ulWindowWidth AS LONG    ' window width
       LOCAL ulWindowHeight AS LONG   ' window height
       LOCAL ulBitmapWidth AS LONG    ' bitmap width
       LOCAL ulBitmapHeight AS LONG   ' bitmap height
       LOCAL rt AS RECT               ' used for getting window LOCALensions
       LOCAL x AS LONG, y AS LONG     ' stepping variables
       LOCAL ubAlpha AS BYTE          ' used for doing transparent gradient
       LOCAL ubRed   AS BYTE
       LOCAL ubGreen AS BYTE
       LOCAL ubBlue  AS BYTE
       LOCAL fAlphaFactor AS SINGLE   ' used to do premultiply
    
       ' get window dimensions
       GetClientRect hwnd, rt
    
       ' calculate window width/height
       ulWindowWidth = rt.nright - rt.nleft
       ulWindowHeight = rt.nbottom - rt.ntop
    
       ' make sure we have at least some window size
       IF ulWindowWidth = 0 OR ulWindowHeight = 0 THEN EXIT SUB
    
       ' divide the window into 3 horizontal areas
       ulWindowHeight = ulWindowHeight \ 3
    
       ' create a DC for our bitmap -- the source DC for AlphaBlend
       hdc = CreateCompatibleDC(hDCwnd)
    
       ' setup bitmap info
       ' set the bitmap width and height to 60% of the width and height of each of
       ' the three horizontal areas. Later on, the blending will occur in the center
       ' of each of the three areas.
       bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER)
       ulBitmapWidth = ulWindowWidth - (ulWindowWidth \ 5) * 2
       bmi.bmiHeader.biWidth = ulBitmapWidth
       ulBitmapHeight = ulWindowHeight - (ulWindowHeight \ 5) * 2
       bmi.bmiHeader.biHeight = ulBitmapHeight
       bmi.bmiHeader.biPlanes = 1
       bmi.bmiHeader.biBitCount = 32         ' four 8-bit components
       bmi.bmiHeader.biCompression = %BI_RGB
       bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4
    
       ' create our DIB section and select the bitmap into the dc
       hbitmap = CreateDIBSection(hdc, bmi, %DIB_RGB_COLORS, BYVAL VARPTR(pvBits), 0, 0)
       SelectObject hdc, hbitmap
    
       ' in top window area, constant alpha = 50%, but no source alpha
       ' the color format for each pixel is &Haarrggbb
       ' set all pixels to blue and set source alpha to zero
       FOR y = 0 TO ulBitmapHeight - 1
          FOR x = 0 TO ulBitmapWidth - 1
             @pvBits[x + y * ulBitmapWidth] = &H000000FF
          NEXT
       NEXT
    
       bf.BlendOp = %AC_SRC_OVER
       bf.BlendFlags = 0
       bf.SourceConstantAlpha = &H7F  ' half of &HFF = 50% transparency
       bf.AlphaFormat = 0             ' ignore source alpha channel
    
       IF ISFALSE AlphaBlend(hDCwnd, (ulWindowWidth\5), (ulWindowHeight\5), _
                             ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, _
                             ulBitmapWidth, ulBitmapHeight, BYVAL CVDWD(bf)) THEN
          DeleteObject hbitmap
          DeleteDC hdc
          EXIT SUB
       END IF
    
       ' in middle window area, constant alpha = 100% (disabled), source
       ' alpha is 0 in middle of bitmap and opaque in rest of bitmap
       FOR y = 0 TO ulBitmapHeight - 1
          FOR x = 0 TO ulBitmapWidth - 1
             IF (x > (ulBitmapWidth \ 5)) AND (x < (ulBitmapWidth-ulBitmapWidth \ 5)) AND _
                (y > (ulBitmapHeight \ 5)) AND (y < (ulBitmapHeight-ulBitmapHeight \ 5)) THEN
                ' in middle of bitmap: source alpha = 0 (transparent).
                ' This means multiply each color component by &H00.
                ' Thus, after AlphaBlend, we have a, &H00 * r,
                ' &H00 * g,and &H00 * b (which is &H00000000)
                ' for now, set all pixels to red
                @pvBits[x + y * ulBitmapWidth] = &H00FF0000
             ELSE
                ' in the rest of bitmap, source alpha = &Hff (opaque)
                ' and set all pixels to blue
                @pvBits[x + y * ulBitmapWidth] = &HFF0000FF
             END IF
          NEXT
       NEXT
    
       bf.BlendOp = %AC_SRC_OVER
       bf.BlendFlags = 0
       bf.AlphaFormat = %AC_SRC_ALPHA  ' use source alpha
       bf.SourceConstantAlpha = &HFF   ' opaque (disable constant alpha)
    
       IF ISFALSE AlphaBlend (hDCwnd, ulWindowWidth \ 5, ulWindowHeight \ 5 + ulWindowHeight, _
                             ulBitmapWidth, ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, _
                             ulBitmapHeight, BYVAL CVDWD(bf)) THEN
          DeleteObject hbitmap
          DeleteDC hdc
          EXIT SUB
       END IF
    
       ' bottom window area, use constant alpha = 75% and a changing
       ' source alpha. Create a gradient effect using source alpha, and
       ' then fade it even more with constant alpha
       ubRed   = &H00
       ubGreen = &H00
       ubBlue  = &HFF
    
       LOCAL f AS SINGLE
    
       FOR y = 0 TO ulBitmapHeight - 1
          FOR x = 0 TO ulBitmapWidth - 1
             ' for a simple gradient, base the alpha value on the x
             ' value of the pixel
             f = x / ulBitmapWidth * 255
             ubAlpha = f
             ' calculate the factor by which we multiply each component
             fAlphaFactor = ubAlpha / &HFF
             f = ubBlue * fAlphaFactor
             ubBlue = f
             @pvBits[x + y * ulBitmapWidth] = ubAlpha OR _            '&Haa000000
                                              ubRed   OR _            '&H00rr0000
                                              ubGreen OR _            '&H0000gg00
                                              ubBlue                  '&H000000bb
          NEXT
       NEXT
    
       bf.BlendOp = %AC_SRC_OVER
       bf.BlendFlags = 0
       bf.AlphaFormat = 0
       bf.SourceConstantAlpha = &HBF   ' use constant alpha, with 75% opaqueness
    
       AlphaBlend hDCwnd, ulWindowWidth \ 5, _
                  ulWindowHeight \ 5 + 2 * ulWindowHeight, ulBitmapWidth, _
                  ulBitmapHeight, hdc, 0, 0, ulBitmapWidth, _
                  ulBitmapHeight, BYVAL CVDWD(bf)
    
       ' do cleanup
       DeleteObject hbitmap
       DeleteDC hdc
    
    END SUB
    ' ========================================================================================
    
    ' ========================================================================================
    ' Main
    ' ========================================================================================
    FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, _
                      BYVAL pszCmdLine AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
    
       LOCAL szAppName AS ASCIIZ * 256
       LOCAL msg       AS tagMsg
       LOCAL hwnd      AS DWORD
       LOCAL wc        AS WNDCLASS
       LOCAL szCaption AS ASCIIZ * 256
    
       szAppName        = "DrawAlphaBlendDemo"
       wc.style         = %CS_HREDRAW OR %CS_VREDRAW
       wc.lpfnWndProc   = CODEPTR(WndProc)
       wc.cbClsExtra    = 0
       wc.cbWndExtra    = 0
       wc.hInstance     = hInstance
       wc.hIcon         = LoadIcon(%NULL, BYVAL %IDI_APPLICATION)
       wc.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)
       wc.hbrBackground = %COLOR_3DFACE + 1
       wc.lpszMenuName  = %NULL
       wc.lpszClassName = VARPTR(szAppName)
    
       IF ISFALSE RegisterClass(wc) THEN
          FUNCTION = %TRUE
          EXIT FUNCTION
       END IF
    
       szCaption = "DrawAlphaBlend Demo"
       hwnd = CreateWindow (szAppName, _             ' window class name
                            szCaption, _             ' window caption
                            %WS_OVERLAPPEDWINDOW, _  ' window style
                            %CW_USEDEFAULT, _        ' initial x position
                            %CW_USEDEFAULT, _        ' initial y position
                            %CW_USEDEFAULT, _        ' initial x size
                            %CW_USEDEFAULT, _        ' initial y size
                            %NULL, _                 ' parent window handle
                            %NULL, _                 ' window menu handle
                            hInstance, _             ' program instance handle
                            %NULL)                   ' creation parameters
    
       ShowWindow hwnd, iCmdShow
       UpdateWindow hwnd
    
       WHILE GetMessage(msg, %NULL, 0, 0)
          IF ISFALSE IsDialogMessage(hwnd, msg) THEN
             TranslateMessage msg
             DispatchMessage msg
          END IF
       WEND
    
       FUNCTION = msg.wParam
    
    END FUNCTION
    ' ========================================================================================
    
    ' ========================================================================================
    ' Main dialog callback.
    ' ========================================================================================
    FUNCTION WndProc (BYVAL hwnd AS DWORD, BYVAL wMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
    
       LOCAL  hdc AS DWORD
       LOCAL  ps  AS PAINTSTRUCT
    
       SELECT CASE wMsg
    
          CASE %WM_COMMAND
             ' -------------------------------------------------------
             ' Messages from controls and menu items are handled here.
             ' -------------------------------------------------------
             SELECT CASE LOWRD(wParam)
    
                CASE %IDOK
                   IF HIWRD(wParam) = %BN_CLICKED THEN
                   END IF
    
                CASE %IDCANCEL
                   IF HIWRD(wParam) = %BN_CLICKED THEN
                      SendMessage hwnd, %WM_CLOSE, wParam, lParam
                      FUNCTION = 0
                      EXIT FUNCTION
                   END IF
    
             END SELECT
    
          CASE %WM_PAINT
             hdc = BeginPaint(hwnd, ps)
             DrawAlphaBlend hwnd, hdc
             EndPaint hwnd, ps
             FUNCTION = 0
             EXIT FUNCTION
    
         CASE %WM_DESTROY
             PostQuitMessage 0
             FUNCTION = 0
             EXIT FUNCTION
    
       END SELECT
    
       FUNCTION = DefWindowProc(hwnd, wMsg, wParam, lParam)
    
    END FUNCTION
    ' ========================================================================================



    [This message has been edited by José Roca (edited May 12, 2007).]
    Forum: http://www.jose.it-berater.org/smfforum/index.php

    Comment

    Working...
    X