Jump to content
Sign in to follow this  
Greenhorn

DllStructSetData issue

Recommended Posts

Greenhorn

Hi Folks,

I have a problem with DllStructSetData(), it says after a few correct settings that the Array is out of range, but I don't understand why !

The loop seems to be OK, but it although throws an error after a few cycles ...

I've marked the "critical section" like this:

;*********** Here's the problem ****************
     For $y = 0 To $ulBitmapHeight
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($stBits, 1, 0x000000FF,  $x + ($y * $ulBitmapWidth)); oO ???
         Next
     Next
;***********************************************

#Region                 Alpha Blending a Bitmap

;    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. 

#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global Const $tagBITMAPINFOHEADER = 'dword Size;' & _
                                    'long Width;' & _
                                    'long Height;' & _
                                    'ushort Planes;' & _
                                    'ushort BitCount;' & _
                                    'dword Compression;' & _
                                    'dword SizeImage;' & _
                                    'long XPelsPerMeter;' & _
                                    'long YPelsPerMeter;' & _
                                    'dword ClrUsed;' & _
                                    'dword ClrImportant;'

Global Const $tagPAINTSTRUCT    =   'hwnd hDC;' & _
                                    'int  fErase;' & _
                                    'long rcPaint[4];' & _
                                    'int  fRestore;' & _
                                    'int  fIncUpdate;' & _
                                    'byte rgbReserved[32]'
Global $NULL = Ptr (0)
Global Const $DIB_RGB_COLORS = 0
; Blending
Global Const $AC_SRC_OVER   = 0x00
Global Const $AC_SRC_ALPHA   = 0x01

Global Const $BI_RGB    = 0

; Fensterstile
Global Const $WS_EX_COMPOSITED = 0x2000000  ; Gegen "Flackern"

; Nachricht zum Zeichnen abfangen.
GUIRegisterMsg ($WM_PAINT, 'MY_WM_PAINT')

; Das übliche ...
$hWnd = GUICreate ('AlphaBlend - Demo', 400, 350, -1, -1, _
                    $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED)
GUISetBkColor (0xFFFFFF, $hWnd)

GUISetState (@SW_SHOW)


While True
    
    Switch GUIGetMsg ()
        Case -3
            ExitLoop
    EndSwitch
WEnd


Func MY_WM_PAINT ($hWnd, $msg, $lParam, $wParam)
    
     Local $hDC, $ps, $lpPs

    ; Zeichenstruktur erzeugen
     $ps   = DllStructCreate ($tagPAINTSTRUCT)
     $lpPs = DllStructGetPtr ($ps)
     
    ; Gerätekontext wird in WM_PAINT von BeginPaint zurückgegeben
     $hDC = BeginPaint ($hWnd, $lpPs)
     
     DrawAlphaBlend ($hWnd, $hDC)
    
    ; Am Ende von WM_PAINT muss der Gerätekontext
    ; mit EndPaint wieder freigegeben werden !
     EndPaint ($hWnd, $lpPs)
     Return

EndFunc

Func DrawAlphaBlend ($hWnd, $hdcwnd)

; http://msdn.microsoft.com/en-us/library/ms532295(VS.85).aspx
     Local $hdc;          handle of the DC we will create
     Local $hbitmap;      bitmap handle
     Local $bf   = DllStructCreate ($tagBLENDFUNCTION); structure for alpha blending
     Local $bmi = DllStructCreate ($tagBITMAPINFO); bitmap header
     Local $pvBits = DllStructCreate ('ptr pvBits') ;   pointer to DIB section
     Local $ulWindowWidth, $ulWindowHeight;   window width/height
     Local $ulBitmapWidth, $ulBitmapHeight;   bitmap width/height
     Local $rt;          used for getting window dimensions
     Local $x, $y;        stepping variables
     Local $ubAlpha;        used for doing transparent gradient
     Local $ubRed
     Local $ubGreen
     Local $ubBlue
     Local $fAlphaFactor;   used to do premultiply
    
    
   ; get window dimensions
     $rt = _WinAPI_GetClientRect ($hWnd)
     $rtLeft    = DllStructGetData ($rt, "Left")
     $rtTop  = DllStructGetData ($rt, "Top")
     $rtRight   = DllStructGetData ($rt, "Right")
     $rtBottom  = DllStructGetData ($rt, "Bottom")

   ; calculate window width/height
     $ulWindowWidth  = $rtRight  - $rtLeft
     $ulWindowHeight = $rtBottom - $rtTop

   ; make sure we have at least some window size
     If ((Not $ulWindowWidth) Or (Not $ulWindowHeight)) Then _
         Return
         
   ; divide the window into 3 horizontal areas
     $ulWindowHeight = $ulWindowHeight / 3

   ; create a DC for our bitmap -- the source DC for AlphaBlend
     $hdc = _WinAPI_CreateCompatibleDC ($hdcwnd)

     $ulBitmapWidth  = $ulWindowWidth  - ($ulWindowWidth  / 5) * 2
     $ulBitmapHeight = $ulWindowHeight - ($ulWindowHeight / 5) * 2


   ; 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.
     DllStructSetData ($bmi, 'Size' ,      DllStructGetSize (DllStructCreate ($tagBITMAPINFOHEADER)))
     DllStructSetData ($bmi, 'Width',      $ulBitmapWidth)
     DllStructSetData ($bmi, 'Height',    $ulBitmapHeight)
     DllStructSetData ($bmi, 'Planes',    1)
     DllStructSetData ($bmi, 'BitCount',    32 );  four 8-bit components
     DllStructSetData ($bmi, 'Compression', $BI_RGB)
     DllStructSetData ($bmi, 'SizeImage',   $ulBitmapWidth * $ulBitmapHeight * 4)

   ; create our DIB section and select the bitmap into the DC
     $hbitmap = CreateDIBSection ($hdc, DllStructGetPtr ($bmi), $DIB_RGB_COLORS, DllStructGetPtr ($pvBits), $NULL, 0x0)
     _WinAPI_SelectObject ($hdc, $hbitmap)

    $stBits = DllStructCreate ('uint[' & DllStructGetData ($bmi, 'Width') _ 
                                       * DllStructGetData ($bmi, 'Height') & ']', DllStructGetPtr ($pvBits))

   ; in top window area, constant alpha = 50%, but no source alpha
   ; the color format for each pixel is 0xaarrggbb
   ; set all pixels to blue and set source alpha to zero
    
;*********** Here's the problem ****************
     For $y = 0 To $ulBitmapHeight
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($stBits, 1, 0x000000FF,  $x + ($y * $ulBitmapWidth)); oO ???
         Next
     Next
;***********************************************
    
     DllStructSetData ($bf, 'Op'    , $AC_SRC_OVER)
     DllStructSetData ($bf, 'Flags' , 0)
     DllStructSetData ($bf, 'Alpha' , 0x7F);  half of 0xff = 50% transparency
     DllStructSetData ($bf, 'Format', 0);   ignore source alpha channel

     If (Not AlphaBlend ($hdcwnd, $ulWindowWidth / 5, $ulWindowHeight / 5, _
                         $ulBitmapWidth, $ulBitmapHeight, _
                         $hdc, 0, 0, $ulBitmapWidth, $ulBitmapHeight, $bf)) Then _
         Return;     // alpha blend failed
    
   ; do cleanup
     _WinAPI_DeleteObject ($hbitmap)
     _WinAPI_DeleteDC ($hdc)


EndFunc


;***********************************************************************
;*      The funky Funcs ...

Func AlphaBlend ($hdcDest, $nXOriginDest, $nYOriginDest, $nWidthDest, $nHeightDest, _
                         $hdcSrc,  $nXOriginSrc,  $nYOriginSrc,  $nWidthSrc,  $nHeightSrc, ByRef $blendFunction )
    
    Local $aRes = DllCall ('msimg32.dll', 'int', 'AlphaBlend', _
                                                'ptr', $hdcDest,      _ ;  // handle to destination DC
                                                'int', $nXOriginDest, _ ;  // x-coord of upper-left corner
                                                'int', $nYOriginDest, _ ;  // y-coord of upper-left corner
                                                'int', $nWidthDest,   _ ;  // destination width
                                                'int', $nHeightDest,  _ ;  // destination height
                                                'ptr', $hdcSrc,    _ ;  // handle to source DC
                                                'int', $nXOriginSrc,  _ ;  // x-coord of upper-left corner
                                                'int', $nYOriginSrc,  _ ;  // y-coord of upper-left corner
                                                'int', $nWidthSrc,  _ ;  // source width
                                                'int', $nHeightSrc,   _ ;  // source height
                                                'ptr', $blendFunction)  ;  // alpha-blending function
    Return $aRes[0]

EndFunc

Func CreateDIBSection ($hdc, $pbmi, $iUsage, $ppvBits, $hSection, $dwOffset)

    Local $aRes = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', _
                                            'ptr',   $hdc,    _; // handle to DC
                                            'ptr',   $pbmi,  _; // bitmap data
                                            'uint',  $iUsage,   _; // data type indicator
                                            'ptr*',  $ppvBits,  _; // bit values
                                            'ptr',   $hSection, _; // handle to file mapping object
                                            'dword', $dwOffset ) ; // offset to bitmap bit values
    Return $aRes[0]
    
EndFunc


Func BeginPaint($hWnd, $lpPaint)
    
    Local $aResult = DllCall('user32.dll', 'hwnd', 'BeginPaint', 'hwnd', $hWnd, 'ptr', $lpPaint)
    Return $aResult[0]
    
EndFunc

Func EndPaint($hWnd, $lpPaint)
    
    Local $aResult = DllCall('user32.dll', 'int', 'EndPaint', 'hwnd', $hWnd, 'ptr', $lpPaint)
    Return $aResult[0]
    
EndFunc


#EndRegion
;***************************************************************************

Thanks a lot for audience/patience ...

Greetz

Greenhorn

Edited by Greenhorn

Share this post


Link to post
Share on other sites
PsaltyDS

Hi Folks,

I have a problem with DllStructSetData(), it says after a few correct settings that the Array is out of range, but I don't understand why !

The loop seems to be OK, but it although throws an error after a few cycles ...

I've marked the "critical section" like this:

;*********** Here's the problem ****************
     For $y = 0 To $ulBitmapHeight
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($stBits, 1, 0x000000FF,  $x + ($y * $ulBitmapWidth)); oO ???
         Next
     Next
;***********************************************

; ... <snip>

    $stBits = DllStructCreate ('uint[' & DllStructGetData ($bmi, 'Width') _ 
                                       * DllStructGetData ($bmi, 'Height') & ']', DllStructGetPtr ($pvBits))

 ; in top window area, constant alpha = 50%, but no source alpha
 ; the color format for each pixel is 0xaarrggbb
 ; set all pixels to blue and set source alpha to zero
    
;*********** Here's the problem ****************
     For $y = 0 To $ulBitmapHeight
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($stBits, 1, 0x000000FF,  $x + ($y * $ulBitmapWidth)); oO ???
         Next
     Next
;***********************************************

; ... <snip>

Thanks a lot for audience/patience ...

Greetz

Greenhorn

So you created the array with size = DllStructGetData($bmi, 'Width') * DllStructGetData($bmi, 'Height'). What did that come out to? Are you checking it?

Then you access the array at index = $x + ($y * $ulBitmapWidth). What did that come out to? Are you checking it?

Put some error handling in your function to check how those values are coming out.

:mellow:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
Greenhorn

So you created the array with size = DllStructGetData($bmi, 'Width') * DllStructGetData($bmi, 'Height'). What did that come out to? Are you checking it?

Then you access the array at index = $x + ($y * $ulBitmapWidth). What did that come out to? Are you checking it?

Put some error handling in your function to check how those values are coming out.

:(

I forgot to copy back the "- 1" in the first For/Next loop, sorry. (my test script is a desaster in the moment ... ) :)

But even then it will fail ...

So, I set in the double-loop the bit values for every pixel, right ?

Doing this by scanning each bitmap line in $y and setting the values in the array with $x, which I have to multiplicate with the length of one line in the bitmap, because, for example, if the bitmap has a size of 250x150 pixels, pixel 0, 1 is at array index 251 ($x=1 + ($y=1 *$ulBitmapWidth), pixel 0, 2 is at array index 501($x=1 + ($y=2 *$ulBitmapWidth), right ?

I did the error handling, the size of the struct is 67200 bytes, the same like $ulBitmapWidth * $ulBitmapHeight * 4(bytes), so it's OK ... *brooding*

...

EDIT:

Always after the 13th setting commes the error ... :mellow:

If I read out the values in the loop it's no error, but the script also fails ...

;*********** Here's the problem ****************
     For $y = 0 To $ulBitmapHeight - 1
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($stBits, 1, 0x000000FF, $x + ($y * $ulBitmapWidth)); oO ???
            ;DllStructGetData ($stBits, 1, $x + ($y * $ulBitmapWidth)); oO ???
             if @error then ConsoleWrite ('Index : '&$x + ($y * $ulBitmapWidth)&'; Error : '&@error&@crlf)
         Next
     Next
;***********************************************

Greetz

Greenhorn

Edited by Greenhorn

Share this post


Link to post
Share on other sites
PsaltyDS

I forgot to copy back the "- 1" in the first For/Next loop, sorry. (my test script is a desaster in the moment ... ) ;)

But even then it will fail ...

So, I set in the double-loop the bit values for every pixel, right ?

Doing this by scanning each bitmap line in $y and setting the values in the array with $x, which I have to multiplicate with the length of one line in the bitmap, because, for example, if the bitmap has a size of 250x150 pixels, pixel 0, 1 is at array index 251 ($x=1 + ($y=1 *$ulBitmapWidth), pixel 0, 2 is at array index 501($x=1 + ($y=2 *$ulBitmapWidth), right ?

Careful how you do that. Pixel numbering is 0-based (there is a pixel at 0,0). AutoIt arrays are 0-based, which is why so many For/Next loops have that -1 in there. But DLL struct arrays are 1-based. There is no DLL struct array element at [0]. So pixel 0,0 is at [1]. That's $x=0 and $y=0, so index = $x + 1 + ($y * $ulBitmapWidth). Pixel 0,1 is at 251 like you indicated.

I did the error handling, the size of the struct is 67200 bytes, the same like $ulBitmapWidth * $ulBitmapHeight * 4(bytes), so it's OK ... *brooding*

...

EDIT:

Always after the 13th setting commes the error ... :(

If I read out the values in the loop it's no error, but the script also fails ...

;*********** Here's the problem ****************
     For $y = 0 To $ulBitmapHeight - 1
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($stBits, 1, 0x000000FF, $x + ($y * $ulBitmapWidth)); oO ???
    ;DllStructGetData ($stBits, 1, $x + ($y * $ulBitmapWidth)); oO ???
             if @error then ConsoleWrite ('Index : '&$x + ($y * $ulBitmapWidth)&'; Error : '&@error&@crlf)
         Next
     Next
;***********************************************

Greetz

Greenhorn

I meant more like a temporary debug breakpoint:
; ... <snip>

$iArraySize = DllStructGetData($bmi, 'Width') * DllStructGetData($bmi, 'Height')
$stBits = DllStructCreate('uint[' & $iArraySize & ']', DllStructGetPtr($pvBits))

; in top window area, constant alpha = 50%, but no source alpha
; the color format for each pixel is 0xaarrggbb
; set all pixels to blue and set source alpha to zero

;*********** Here's the problem ****************
For $y = 0 To $ulBitmapHeight
    For $x = 1 To $ulBitmapWidth
        $iPixelIndex = $x + ($y * $ulBitmapWidth)
        If ($iPixelIndex > 0) And ($iPixelIndex <= $iArraySize) Then
            DllStructSetData($stBits, 1, 0x000000FF, $iPixelIndex)
        Else
            MsgBox(16, "Debug", "Error!  Array index out of bounds:" & @CRLF & _
                    "DllStructGetData($bmi, 'Width') = " & DllStructGetData($bmi, 'Width') & @CRLF & _
                    "DllStructGetData($bmi, 'Height') = " & DllStructGetData($bmi, 'Height') & @CRLF & _
                    "Calculated $iArraySize = " & $iArraySize & @CRLF & _
                    "$x = " & $x & "  $y = " & $y & @CRLF & _
                    "$ulBitmapWidth = " & $ulBitmapWidth & @CRLF & _
                    "Calculated $iPixelIndex = " & $iPixelIndex)
            Exit
        EndIf
    Next
Next
;***********************************************

; ... <snip>

Checking the value of $iPixelIndex will slow it down, so you may not want that in there permanently, but it should pop the MsgBox() with diagnostic info before it crashes for that particular problem.

:)

P.S. I just notice you do your loop with "For $x = 1 To $ulBitmapWidth", which is correct, but above that you have "For $y = 0 To $ulBitmapHeight". Shouldn't that be "For $y = 0 To $ulBitmapHeight - 1"?

:mellow:

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
Malkey

If what you are doing is journey based, a learning exercise, good luck. Looks like headache material. May you have lots of enthusiastic perseverance.

If you want to accomplish a task by any means, the functions from gdiplus.dll are better suited to manipulate 0xAARRGGBB color format.

Example:-

#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GuiConstants.au3>
#include <WindowsConstants.au3>

Global $GuiSizeX = 500, $GuiSizeY = 500

$hGui = GUICreate("GDIPlus Example", $GuiSizeX, $GuiSizeY)
GUISetState()

_GDIPlus_Startup()
; Create Double Buffer, so doesn't need to be repainted on PAINT-Event
$hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGui)
$hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
;End Double Buffer add-in 1 of 3

;Graphics here
_GDIPlus_GraphicsClear($hGraphic, 0xFFFFFFFF)  ; White background 
$hBrush3 = _GDIPlus_BrushCreateSolid(0xFF0000FF) ; 100% opaque Blue, 0% transparency - Alpha channel FF
$hBrush2 = _GDIPlus_BrushCreateSolid(0xA00000FF) ; [(0xA0/0xFF)*100] % opaque, [(0xff-0xA0/0xFF)*100] % transparency
$hBrush1 = _GDIPlus_BrushCreateSolid(0x500000FF) ;
_GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $GuiSizeX, $GuiSizeY / 3, $hBrush1) ; Top third of window
_GDIPlus_GraphicsFillRect($hGraphic, 0, $GuiSizeY / 3, $GuiSizeX, $GuiSizeY / 3, $hBrush2) ; Middle third of GUI
_GDIPlus_GraphicsFillRect($hGraphic, 0, $GuiSizeY * 2 / 3 - 1, $GuiSizeX, $GuiSizeY / 3 + 1, $hBrush3)
;End of graphics

; Double Buffer
GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
GUIRegisterMsg(0x85, "MY_PAINT") ; $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
_GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
;End Double Buffer add-on 2 of 3

;To save GUI image, un-comment the next two lines.
;_GDIPlus_ImageSaveToFile($hBMPBuff, @DesktopDir & "\TestWrite1.png")
;ShellExecute(@DesktopDir & "\TestWrite1.png")

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            _GDIPlus_BrushDispose($hBrush1)
            _GDIPlus_BrushDispose($hBrush2)
            _GDIPlus_BrushDispose($hBrush3)
            _GDIPlus_GraphicsDispose($hGraphic)
            _GDIPlus_GraphicsDispose($hGraphicGUI)
            _WinAPI_DeleteObject($hBMPBuff)
            _GDIPlus_Shutdown()
            Exit
    EndSwitch
WEnd

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME)) ; , $RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

Share this post


Link to post
Share on other sites
Greenhorn

Thanks to both of you for taking notice and giving advice !

Also thx to Malkey, I've seen this script before in my searches for CreateDIBSection(). But I want to get even this function to run.

It seems I got solved the problems with the Bitmap-Bits pointer.

All return values seem to be OK, but no bitmap is drawn. :mellow:

#Region                 Alpha Blending a Bitmap

;    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. 

#include <WindowsConstants.au3>
#include <WinAPI.au3>

Global Const $tagBITMAPINFOHEADER = 'dword Size;' & _
                                    'long Width;' & _
                                    'long Height;' & _
                                    'ushort Planes;' & _
                                    'ushort BitCount;' & _
                                    'dword Compression;' & _
                                    'dword SizeImage;' & _
                                    'long XPelsPerMeter;' & _
                                    'long YPelsPerMeter;' & _
                                    'dword ClrUsed;' & _
                                    'dword ClrImportant;'

Global Const $tagPAINTSTRUCT    =   'hwnd hDC;' & _
                                    'int  fErase;' & _
                                    'long rcPaint[4];' & _
                                    'int  fRestore;' & _
                                    'int  fIncUpdate;' & _
                                    'byte rgbReserved[32]'
Global $NULL = Ptr (0)
Global Const $DIB_RGB_COLORS = 0
; Blending
Global Const $AC_SRC_OVER    = 0x00
Global Const $AC_SRC_ALPHA   = 0x01

Global Const $BI_RGB    = 0

; Fensterstile
Global Const $WS_EX_COMPOSITED = 0x2000000   ; Gegen "Flackern"

; Nachricht zum Zeichnen abfangen.
GUIRegisterMsg ($WM_PAINT, 'MY_WM_PAINT')

; Das übliche ...
$hWnd = GUICreate ('Alpha Blending a Bitmap', 400, 350, -1, -1, _
                    $WS_OVERLAPPEDWINDOW, $WS_EX_COMPOSITED)
GUISetBkColor (0xFFFFFF, $hWnd)

GUISetState (@SW_SHOW)


While True
    
    Switch GUIGetMsg ()
        Case -3
            ExitLoop
    EndSwitch
WEnd


Func MY_WM_PAINT ($hWnd, $msg, $lParam, $wParam)
    
     Local $hDC, $ps, $lpPs

     ; Zeichenstruktur erzeugen
     $ps   = DllStructCreate ($tagPAINTSTRUCT)
     $lpPs = DllStructGetPtr ($ps)
     
     ; Gerätekontext wird in WM_PAINT von BeginPaint zurückgegeben
     $hDC = BeginPaint ($hWnd, $lpPs)
     
     DrawAlphaBlend ($hWnd, $hDC)
    
     ; Am Ende von WM_PAINT muss der Gerätekontext
     ; mit EndPaint wieder freigegeben werden !
     EndPaint ($hWnd, $lpPs)
     Return 0

EndFunc

Func DrawAlphaBlend ($hWnd, $hdcwnd)

    ; http://msdn.microsoft.com/en-us/library/ms532295(VS.85).aspx
     Local $hdc         ; handle of the DC we will create
     Local $hbitmap     ; bitmap handle
     Local $bf     = DllStructCreate ($tagBLENDFUNCTION); structure for alpha blending
     Local $bmi    = DllStructCreate ($tagBITMAPINFO);    bitmap header
     Local $pvBits   ; pointer to DIB section
     Local $ulWindowWidth, $ulWindowHeight  ; window width/height
     Local $ulBitmapWidth, $ulBitmapHeight  ; bitmap width/height
     Local $rt            ; used for getting window dimensions
     Local $x, $y         ; stepping variables
     Local $ubAlpha       ; used for doing transparent gradient
     Local $ubRed
     Local $ubGreen
     Local $ubBlue
     Local $fAlphaFactor  ; used to do premultiply
    
    
    ; get window dimensions
     $rt = _WinAPI_GetClientRect ($hWnd)
     $rtLeft    = DllStructGetData ($rt, "Left")
     $rtTop     = DllStructGetData ($rt, "Top")
     $rtRight   = DllStructGetData ($rt, "Right")
     $rtBottom  = DllStructGetData ($rt, "Bottom")

    ; calculate window width/height
     $ulWindowWidth  = $rtRight  - $rtLeft
     $ulWindowHeight = $rtBottom - $rtTop

    ; make sure we have at least some window size
     If ((Not $ulWindowWidth) Or (Not $ulWindowHeight)) Then _
         Return
         
    ; divide the window into 3 horizontal areas
     $ulWindowHeight = $ulWindowHeight / 3

    ; create a DC for our bitmap -- the source DC for AlphaBlend
     $hdc = _WinAPI_CreateCompatibleDC ($hdcwnd)

     $ulBitmapWidth  = $ulWindowWidth  - ($ulWindowWidth  / 5) * 2
     $ulBitmapHeight = $ulWindowHeight - ($ulWindowHeight / 5) * 2


    ; 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.
     DllStructSetData ($bmi, 'Size' ,       DllStructGetSize (DllStructCreate ($tagBITMAPINFOHEADER)))
     DllStructSetData ($bmi, 'Width',       $ulBitmapWidth)
     DllStructSetData ($bmi, 'Height',      $ulBitmapHeight)
     DllStructSetData ($bmi, 'Planes',      1)
     DllStructSetData ($bmi, 'BitCount',    32) ; four 8-bit components
     DllStructSetData ($bmi, 'Compression', $BI_RGB)
     DllStructSetData ($bmi, 'SizeImage',   $ulBitmapWidth * $ulBitmapHeight * 4)

    ; create our DIB section and select the bitmap into the DC
     $hbitmap = CreateDIBSection ($hdc, DllStructGetPtr ($bmi), $DIB_RGB_COLORS, $pvBits, $NULL, 0x0)
     _WinAPI_SelectObject ($hdc, $hbitmap)

    ; in top window area, constant alpha = 50%, but no source alpha
    ; the color format for each pixel is 0xaarrggbb
    ; set all pixels to blue and set source alpha to zero
     For $y = 0 To $ulBitmapHeight - 1
        For $x = 1 To $ulBitmapWidth
             DllStructSetData ($pvBits, 1, 0x000000FF, $x + ($y * $ulBitmapWidth))
         Next
     Next


     DllStructSetData ($bf, 'Op'    , $AC_SRC_OVER)
     DllStructSetData ($bf, 'Flags' , 0)
     DllStructSetData ($bf, 'Alpha' , 0x7F) ;  half of 0xff = 50% transparency
     DllStructSetData ($bf, 'Format', 0)    ;  ignore source alpha channel

     If (Not AlphaBlend ($hdcwnd, $ulWindowWidth / 5, $ulWindowHeight / 5, _
                         $ulBitmapWidth, $ulBitmapHeight, _
                         $hdc, 0, 0, $ulBitmapWidth, $ulBitmapHeight, $bf)) Then _
         Return ;  alpha blend failed
    
    ; do cleanup
     _WinAPI_DeleteObject ($hbitmap)
     _WinAPI_DeleteDC ($hdc)


EndFunc


;***********************************************************************
;*        The funky Funcs ...

Func AlphaBlend ($hdcDest, $nXOriginDest, $nYOriginDest, $nWidthDest, $nHeightDest, _
                 $hdcSrc,  $nXOriginSrc,  $nYOriginSrc,  $nWidthSrc,  $nHeightSrc, ByRef $blendFunction )
    
    Local $aRes = DllCall ('msimg32.dll', 'int', 'AlphaBlend', _
                                                    'ptr', $hdcDest,      _  ;  // handle to destination DC
                                                    'int', $nXOriginDest, _  ;  // x-coord of upper-left corner
                                                    'int', $nYOriginDest, _  ;  // y-coord of upper-left corner
                                                    'int', $nWidthDest,   _  ;  // destination width
                                                    'int', $nHeightDest,  _  ;  // destination height
                                                    'ptr', $hdcSrc,       _  ;  // handle to source DC
                                                    'int', $nXOriginSrc,  _  ;  // x-coord of upper-left corner
                                                    'int', $nYOriginSrc,  _  ;  // y-coord of upper-left corner
                                                    'int', $nWidthSrc,    _  ;  // source width
                                                    'int', $nHeightSrc,   _  ;  // source height
                                                    'ptr', $blendFunction)   ;  // alpha-blending function
    Return $aRes[0]

EndFunc

Func CreateDIBSection ($hdc, $pbmi, $iUsage, ByRef $ppvBits, $hSection, $dwOffset)

    Local $aRes = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', _
                                                'ptr',   $hdc,      _ ; // handle to DC
                                                'ptr',   $pbmi,     _ ; // bitmap data
                                                'uint',  $iUsage,   _ ; // data type indicator
                                                'ptr*',  $ppvBits,  _ ; // bit values
                                                'ptr',   $hSection, _ ; // handle to file mapping object
                                                'dword', $dwOffset )  ; // offset to bitmap bit values
    Local $cbSize = DllStructGetData (DllStructCreate ($tagBITMAPINFOHEADER, $pbmi), 'SizeImage')
    $ppvBits = DllStructCreate ('uint[' & $cbSize / 4 & ']', $aRes[4])
    Return $aRes[0]
    
EndFunc


Func BeginPaint($hWnd, $lpPaint)
    
    Local $aResult = DllCall('user32.dll', 'hwnd', 'BeginPaint', 'hwnd', $hWnd, 'ptr', $lpPaint)
    Return $aResult[0]
    
EndFunc

Func EndPaint($hWnd, $lpPaint)
    
    Local $aResult = DllCall('user32.dll', 'int', 'EndPaint', 'hwnd', $hWnd, 'ptr', $lpPaint)
    Return $aResult[0]
    
EndFunc


#EndRegion
;***************************************************************************

Does somebody have any suggestions ?

Greetz

Greenhorn

Edited by Greenhorn

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×