Jump to content
Sign in to follow this  
Malkey

GDI+ Gradient Background Utility.

Recommended Posts

Malkey

99% of the work and creative inspiration is smashly's.

This post explains all.

http://www.autoitscript.com/forum/index.ph...st&p=577128

If you wish to have a gradient, then this utility (example/script) is an interactive parameter selector for Func _GDIPlus_CreateLineBrushFromRect() .

You can select the two colours to be used, and, the Linear Gradient Mode (Horiz, Vert, Forward Diagonal, and Backwards Diagonal). :

You can enter you own blend factors and blend factors' positions arrays.

You can toggle Gamma Correction on/off. Sometimes, the Gamma Correction improves the graphics.

To get you thinking a little outside of the box, try this. Put (copy)

0.00, 1.0, 0.0, 1.0, 0.0, 1.00 into the input box for Color Factors , and

0.00, 0.2, 0.40, 0.60, 0.8,1.00 into the input box for Color Positions..

Note - The individual percentage values are separated by commas in each input box, and,

each input box must have an equal number of corresponding percentage values.

The minimum number of individual percentage values in each input box is two.

0 and 1 in each input box works well also.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <Misc.au3>
#include <WinAPI.au3>

Global $ApW = 600, $ApH = 400
Global $iColor[2] = ["0xFFFF00", "0x0000FF"], $Label[2], $Button[3], $Input[2]
Global $aFactors[4] = [0.0, 0.4, 0.6, 1.0], $aPositions[4] = [0.0, 0.3, 0.7, 1.0]
Global $Direction = 0, $bGammaCorrection = False

$hGui = GUICreate("Gradient", $ApW, $ApH)
$Pic = GUICtrlCreatePic("", 0, 0, $ApW, $ApH)
GUICtrlSetState(-1, $GUI_DISABLE)

$Combo = GUICtrlCreateCombo("", 5, 70, 120, 20, 0x0003)
GUICtrlSetData(-1, "Horizontal|Vertical|Forward Diagonal|Backward Diagonal", "Horizontal")
$Button[0] = GUICtrlCreateButton("Select 1st Color", 5, 5, 100, 25)
$Label[0] = GUICtrlCreateLabel($iColor[0], 110, 5, 60, 25, 0x301)
GUICtrlSetBkColor(-1, $iColor[0])
GUICtrlSetColor(-1, $iColor[1])

$Button[2] = GUICtrlCreateButton("Change Color Factors --->" & @CRLF & "        and" & @CRLF & _
        @CRLF & "Change Color Positions ->", 230, 6, 135, 58, 0x2000); $BS_MULTILINE = 0x2000
$Input[0] = GUICtrlCreateInput("0.00, 0.40, 0.60, 1.00", 370, 5, 225, 25)
GUICtrlSetFont(-1, 10, 700)
;$Button[3] = GUICtrlCreateButton(" and   Color Positions", 245, 37, 120, 25)
$Input[1] = GUICtrlCreateInput("0.00, 0.40, 0.60, 1.00", 370, 36, 225, 25)
GUICtrlSetFont(-1, 10, 700)
$checkCN = GUICtrlCreateCheckbox("Gamma Correction is Off", 230, 70, 150, 25)

$Button[1] = GUICtrlCreateButton("Select 2nd Color", 5, 35, 100, 25)
$Label[1] = GUICtrlCreateLabel($iColor[1], 110, 35, 60, 25, 0x301)
GUICtrlSetBkColor(-1, $iColor[1])
GUICtrlSetColor(-1, $iColor[0])

GUISetState(@SW_SHOW, $hGui)

PicSetGradient($Pic, $ApW, $ApH, $aFactors, $aPositions, $iColor[0], $iColor[1], $Direction)

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            _Quit()
        Case $Button[0]  ; Select 1st Color
            Local $SC = SetColor(0)
            If $SC Then PicSetGradient($Pic, $ApW, $ApH, $aFactors, $aPositions, $iColor[0], $iColor[1], $Direction)
        Case $Button[1]  ; Select 2nd Color 
            Local $SC = SetColor(1)
            If $SC Then PicSetGradient($Pic, $ApW, $ApH, $aFactors, $aPositions, $iColor[0], $iColor[1], $Direction)
        Case $Button[2]   ; Change Color Factors and Positions 
            Local $aFacts = FillArray(GUICtrlRead($Input[0]))
            Local $aPosits = FillArray(GUICtrlRead($Input[1]))
            If IsArray($aFacts) And IsArray($aPosits) Then
                If UBound($aFacts) = UBound($aPosits) Then
                    $aFactors = $aFacts
                    $aPositions = $aPosits
                    PicSetGradient($Pic, $ApW, $ApH, $aFactors, $aPositions, $iColor[0], $iColor[1], $Direction)
                Else
                    MsgBox(0, "Error", "Number of entries in each input box must be equal.", 3)
                EndIf
            EndIf
        Case $checkCN
            $bGammaCorrection = Not $bGammaCorrection
            If $bGammaCorrection = False Then
                GUICtrlSetData($checkCN, "Gamma Correction is Off.")
            Else
                GUICtrlSetData($checkCN, "Gamma Correction is On.")
            EndIf
            PicSetGradient($Pic, $ApW, $ApH, $aFactors, $aPositions, $iColor[0], $iColor[1], $Direction)
        Case $Combo
            Switch GUICtrlRead($Combo)
                Case "Horizontal"
                    $Direction = 0x00000000
                Case "Vertical"
                    $Direction = 0x00000001
                Case "Forward Diagonal"
                    $Direction = 0x00000002
                Case "Backward Diagonal"
                    $Direction = 0x00000003
            EndSwitch
            PicSetGradient($Pic, $ApW, $ApH, $aFactors, $aPositions, $iColor[0], $iColor[1], $Direction)
    EndSwitch
WEnd

Func FillArray($sData)
    Local $aDataSplit
    $aDataSplit = StringSplit(StringStripWS($sData, 8), ",")
    If $aDataSplit[0] < 2 Then
        MsgBox(0, "Error", "Must have at lease two (2) entries in input box", 2)
        Return 1
    Else
        Local $aRetArray[$aDataSplit[0]]
        For $x = 0 To UBound($aRetArray) - 1
            $aRetArray[$x] = $aDataSplit[$x + 1]
        Next
        Return $aRetArray
    EndIf
EndFunc   ;==>FillArray

Func SetColor($iD)
    Local $Clr
    $Clr = _ChooseColor(2, 0, 2, $hGui)
    If $Clr <> -1 Then
        $iColor[$iD] = $Clr
        If $iD Then
            GUICtrlSetColor($Label[$iD], $iColor[0])
            GUICtrlSetColor($Label[0], $iColor[1])
        Else
            GUICtrlSetColor($Label[$iD], $iColor[1])
            GUICtrlSetColor($Label[1], $iColor[0])
        EndIf
        GUICtrlSetData($Label[$iD], $iColor[$iD])
        GUICtrlSetBkColor($Label[$iD], $iColor[$iD])
        Return 1
    EndIf
    Return 0
EndFunc   ;==>SetColor

Func PicSetGradient($cID, $iW, $iH, $aFactors, $aPositions, $iClr1, $iClr2, $iDirection)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0
    Local $hWnd, $iC1, $iC2, $hBitmap, $hImage, $hGraphic, $hBrushLin, $hbmp, $aBmp
    $hWnd = GUICtrlGetHandle($cID)
    $iC1 = StringReplace($iClr1, "0x", "0xFF")
    $iC2 = StringReplace($iClr2, "0x", "0xFF")
    $hBitmap = _WinAPI_CreateBitmap($iW, $iH, 1, 32)
    _GDIPlus_Startup()
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    $hBrushLin = _GDIPlus_CreateLineBrushFromRect(0, 0, $iW, $iH, $aFactors, $aPositions, $iC1, $iC2, $iDirection)
    GDIPlus_SetLineGammaCorrection($hBrushLin, $bGammaCorrection)
    _GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iW, $iH, $hBrushLin)
    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    $aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
    If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_BrushDispose($hBrushLin)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hbmp)
    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()
    For $i = $Combo To $Label[1]
        GUICtrlSetState($i, $GUI_SHOW)
    Next
EndFunc   ;==>PicSetGradient

Func _Quit()
    Exit
EndFunc   ;==>_Quit

;==== GDIPlus_CreateLineBrushFromRect === Malkey's function
;Description - Creates a LinearGradientBrush object from a set of boundary points and boundary colors.
; $aFactors - If non-array, default array will be used.
;           Pointer to an array of real numbers that specify blend factors. Each number in the array
;           specifies a percentage of the ending color and should be in the range from 0.0 through 1.0.
;$aPositions - If non-array, default array will be used.
;            Pointer to an array of real numbers that specify blend factors' positions. Each number in the array
;            indicates a percentage of the distance between the starting boundary and the ending boundary
;            and is in the range from 0.0 through 1.0, where 0.0 indicates the starting boundary of the
;            gradient and 1.0 indicates the ending boundary. There must be at least two positions
;            specified: the first position, which is always 0.0, and the last position, which is always
;            1.0. Otherwise, the behavior is undefined. A blend position between 0.0 and 1.0 indicates a
;            line, parallel to the boundary lines, that is a certain fraction of the distance from the
;            starting boundary to the ending boundary. For example, a blend position of 0.7 indicates
;            the line that is 70 percent of the distance from the starting boundary to the ending boundary.
;            The color is constant on lines that are parallel to the boundary lines.
; $iArgb1    - First Top color in 0xAARRGGBB format
; $iArgb2    - Second color in 0xAARRGGBB format
; $LinearGradientMode -  LinearGradientModeHorizontal       = 0x00000000,
;                        LinearGradientModeVertical         = 0x00000001,
;                        LinearGradientModeForwardDiagonal  = 0x00000002,
;                        LinearGradientModeBackwardDiagonal = 0x00000003
; $WrapMode  - WrapModeTile       = 0,
;              WrapModeTileFlipX  = 1,
;              WrapModeTileFlipY  = 2,
;              WrapModeTileFlipXY = 3,
;              WrapModeClamp      = 4
; GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect, ARGB color1, ARGB color2,
;             LinearGradientMode mode, GpWrapMode wrapMode, GpLineGradient **lineGradient)
; Reference:  http://msdn.microsoft.com/en-us/library/ms534043(VS.85).aspx
;
Func _GDIPlus_CreateLineBrushFromRect($iX, $iY, $iWidth, $iHeight, $aFactors, $aPositions, _
        $iArgb1 = 0xFF0000FF, $iArgb2 = 0xFFFF0000, $LinearGradientMode = 0x00000001, $WrapMode = 0)

    Local $tRect, $pRect, $aRet, $tFactors, $pFactors, $tPositions, $pPositions, $iCount

    If $iArgb1 = Default Then $iArgb1 = 0xFF0000FF
    If $iArgb2 = Default Then $iArgb2 = 0xFFFF0000
    If $LinearGradientMode = -1 Or $LinearGradientMode = Default Then $LinearGradientMode = 0x00000001
    If $WrapMode = -1 Or $LinearGradientMode = Default Then $WrapMode = 1

    $tRect = DllStructCreate("float X;float Y;float Width;float Height")
    $pRect = DllStructGetPtr($tRect)
    DllStructSetData($tRect, "X", $iX)
    DllStructSetData($tRect, "Y", $iY)
    DllStructSetData($tRect, "Width", $iWidth)
    DllStructSetData($tRect, "Height", $iHeight)

    ;Note: Withn _GDIPlus_Startup(), $ghGDIPDll is defined
    $aRet = DllCall($ghGDIPDll, "int", "GdipCreateLineBrushFromRect", "ptr", $pRect, "int", $iArgb1, _
            "int", $iArgb2, "int", $LinearGradientMode, "int", $WrapMode, "int*", 0)

    If IsArray($aFactors) = 0 Then Dim $aFactors[4] = [0.0, 0.4, 0.6, 1.0]
    If IsArray($aPositions) = 0 Then Dim $aPositions[4] = [0.0, 0.3, 0.7, 1.0]

    $iCount = UBound($aPositions)
    $tFactors = DllStructCreate("float[" & $iCount & "]")
    $pFactors = DllStructGetPtr($tFactors)
    For $iI = 0 To $iCount - 1
        DllStructSetData($tFactors, 1, $aFactors[$iI], $iI + 1)
    Next
    $tPositions = DllStructCreate("float[" & $iCount & "]")
    $pPositions = DllStructGetPtr($tPositions)
    For $iI = 0 To $iCount - 1
        DllStructSetData($tPositions, 1, $aPositions[$iI], $iI + 1)
    Next

    $hStatus = DllCall($ghGDIPDll, "int", "GdipSetLineBlend", "hwnd", $aRet[6], _
            "ptr", $pFactors, "ptr", $pPositions, "int", $iCount)
    Return $aRet[6] ; Handle of Line Brush
EndFunc   ;==>_GDIPlus_CreateLineBrushFromRect

;===========================================================
; Description:  Specifies whether gamma correction is enabled for this linear gradient brush.
; Parameters
; $hBrush             - [in] Pointer to the LinearGradientBrush object.
; $useGammaCorrection - [in] Boolean value that specifies whether gamma correction occurs
;                           during rendering. TRUE specifies that gamma correction is enabled,
;                           and FALSE specifies that gamma correction is not enabled. By default,
;                           gamma correction is disabled during construction of a
;                           LinearGradientBrush object.
;GdipSetLineGammaCorrection(GpLineGradient *brush, BOOL useGammaCorrection)
;
Func GDIPlus_SetLineGammaCorrection($hBrush, $useGammaCorrection = True)
    Local $aResult  
    $aResult = DllCall($ghGDIPDll, "int", "GdipSetLineGammaCorrection", "hwnd", $hBrush, "int", $useGammaCorrection)
    Return $aResult[0]
EndFunc   ;==>GDIPlus_SetLineGammaCorrection

Using this method for your gradient, it would add about 25 lines to your script if you are already using GDIPlus, Or about 50 lines if you have to add the GDIPlus graphics.

Edit: Added Default (keyword value) to all conditional expressions for default values in Func _GDIPlus_CreateLineBrushFromRect() for consistency, and:

Removed -1 as a default parameter for $iArgb1 and $iArgb2, 32 bit colour variables.

Edited by Malkey

Share this post


Link to post
Share on other sites
smashly

Nice work Malkey ,

I really do learn a lot from your GDI+ coding efforts. :)

Cheers

Share this post


Link to post
Share on other sites
KaFu

Very nice indeed :), thanks for that script, will be very useful. One point though, if I set a color to 0xFFFFFF (white) the color used is the default color. What I dont quiet get is how it happens. It happens in the _GDIPlus_CreateLineBrushFromRect() function where $iArgb1 and $iArgb2 are checked for default -1. Try this:

MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)
If $iArgb1 = -1 Then $iArgb1 = 0xFF0000FF
If $iArgb2 = -1 Then $iArgb2 = 0xFFFF0000
MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)

Best Regards

Edit: Typo

Edited by KaFu

Share this post


Link to post
Share on other sites
KaFu

Doesn't work either for me.

MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)
    If $iArgb1 = "-1" Then $iArgb1 = 0xFF0000FF
    If $iArgb2 = "-1" Then $iArgb2 = 0xFFFF0000
    If $iArgb1 = 0xFFFFFFFF Then $iArgb1 = 0xFFEEEEEE
    If $iArgb2 = 0xFFFFFFFF Then $iArgb2 = 0xFFEEEEEE   
MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)

The change happens while the check and changes the string to a negative value, it does not happen to 0xFFFFFE. I'm just curious why this happens.

Best Regards

Edit: Hey, where's smashly's comment? This looks like I monologuize :)...

Edited by KaFu

Share this post


Link to post
Share on other sites
smashly

0xFFFFFFFF = -1

0xFFFFFFFE = -2

Yep my comment I submitted I retracted..

As I hit the submit button I realized the above.. doh

Edited by smashly

Share this post


Link to post
Share on other sites
KaFu

Looks like white... but the returned result is not 0xFFFFFE but -2. I'm just curious why this happens. Even

MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)
    If $iArgb1 = 0xFFFFFFFF Then
        $iArgb1 = 0xFFFFFFFE
    elseif $iArgb1 = "-1" Then 
        $iArgb1 = 0xFF0000FF
    EndIf
    If $iArgb2 = 0xFFFFFFFF Then 
        $iArgb2 = 0xFFFFFFFE
    elseif $iArgb2 = "-1" Then 
        $iArgb2 = 0xFFFF0000
    EndIf
    MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)

returns a -2 :).

Share this post


Link to post
Share on other sites
Malkey

Doesn't work either for me.

MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)
    If $iArgb1 = "-1" Then $iArgb1 = 0xFF0000FF
    If $iArgb2 = "-1" Then $iArgb2 = 0xFFFF0000
    If $iArgb1 = 0xFFFFFFFF Then $iArgb1 = 0xFFEEEEEE
    If $iArgb2 = 0xFFFFFFFF Then $iArgb2 = 0xFFEEEEEE   
MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)

The change happens while the check and changes the string to a negative value, it does not happen to 0xFFFFFE. I'm just curious why this happens.

Best Regards

Edit: Hey, where's smashly's comment? This looks like I monologuize :)...

Ops, one can not have -1 as a default when used with 32 bit colours. I will change -1 to Default.

Well picked up. I learnt something new.

Share this post


Link to post
Share on other sites
KaFu

0xFFFFFFFF = -1

0xFFFFFFFE = -2

Yep my comment I submitted I retracted..

As I hit the submit button I realized the above.. doh

THAT make sense to me, your first AND second statement :), thanks.

Best Regards

Share this post


Link to post
Share on other sites
smashly

Looks like white... but the returned result is not 0xFFFFFE but -2. I'm just curious why this happens. Even

MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)
    If $iArgb1 = 0xFFFFFFFF Then
        $iArgb1 = 0xFFFFFFFE
    elseif $iArgb1 = "-1" Then 
        $iArgb1 = 0xFF0000FF
    EndIf
    If $iArgb2 = 0xFFFFFFFF Then 
        $iArgb2 = 0xFFFFFFFE
    elseif $iArgb2 = "-1" Then 
        $iArgb2 = 0xFFFF0000
    EndIf
    MsgBox(64,"Color",$iArgb1 & @crlf & $iArgb2)oÝ÷ Ú·­º¹ìkhnú®¢×«ëh®'«²Ø¨ú+Ê°«wöËaz±½©nzö{0z¶®¶­sd6öç6öÆUw&FRWÓ"fײÄb

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  

×