Jump to content
Sign in to follow this  

Button Background Gradient

Recommended Posts



Can someone take a look at this for me? I've attempted to combine Yashied icon extract function with a gradient function which I believe was designed by a few different people.

I have success and a very neat affect. My problem is the program crashes with no explanation if you create more than 6 buttons. I think this script could be useful for a lot of people if we could get it working.

#include <GDIPlus.au3>
#include <Array.au3>
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <ButtonConstants.au3>
#include <Winapi.au3>
#include <Process.au3>
#include <StaticConstants.au3>
#include <GuiConstants.au3>
#include <Constants.au3>
#include <GuiMenu.au3>
Global $aFactors[4] = [0.0, 0.6, 0.8, 1.0], $aPositions[4] = [0.0, 0.6, 0.8, 1.0]
Global $bGammaCorrection = False

    Opt("GUIOnEventMode", 1) ; Change to OnEvent mode 
    Global $gw=@DesktopWidth,$gh=44
    $taskbar=GUICreate("taskbar", $gw, $gh,0,@DesktopHeight-44,$WS_POPUP, $WS_EX_TOOLWINDOW);,$WS_EX_LAYERED)
$iPid = Run("notepad.exe")
Sleep(100); allow notepad to create window

                $a = _ProcessGetIcon("notepad.exe")
                $left =10
                for $i=1 to 6
                SetIcon($b,$a, 0, 56, 40, $aFactors, $aPositions, "0x111111", "0x999999", 2,2)
MsgBox(0,"","Nothing, just pausing script")
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
        Local $aRetArray[$aDataSplit[0]]
        For $x = 0 To UBound($aRetArray) - 1
            $aRetArray[$x] = $aDataSplit[$x + 1]
        Return $aRetArray
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])
            GUICtrlSetColor($Label[$iD], $iColor[1])
            GUICtrlSetColor($Label[1], $iColor[0])
        GUICtrlSetData($Label[$iD], $iColor[$iD])
        GUICtrlSetBkColor($Label[$iD], $iColor[$iD])
        Return 1
    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)
    $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])

EndFunc  ;==>PicSetGradient
func SetIcon($controlID, $sIcon, $iIndex, $iWidth, $iHeight, $aFactors, $aPositions, $iClr1, $iClr2, $iDirection, $pressed)
    const $STM_SETIMAGE = 0x0172
    local $tIcon, $tID, $hDC, $hBackDC, $hBackSv, $hBitmap, $hImage, $hIcon, $hBkIcon

    $tIcon = DllStructCreate('hwnd')
    $tID = DllStructCreate('hwnd')
    $hIcon = DllCall('user32.dll', 'int', 'PrivateExtractIcons', 'str', $sIcon, 'int', $iIndex, 'int', 32, 'int', 32, 'ptr', DllStructGetPtr($tIcon), 'ptr', DllStructGetPtr($tID), 'int', 1, 'int', 0)
    if (@error) or ($hIcon[0] = 0) then
        return SetError(1, 0, 0)
    $hIcon = DllStructGetData($tIcon, 1)
    $tIcon = 0
    $tID = 0

    $hDC = _WinAPI_GetDC(0)
    $hBackDC = _WinAPI_CreateCompatibleDC($hDC)
    Local Const $IMAGE_BITMAP = 0
    Local $hWnd, $iC1, $iC2, $hBitmap, $hImage, $hGraphic, $hBrushLin, $hbmp, $aBmp
    $hWnd = GUICtrlGetHandle($controlID)
    $iC1 = StringReplace($iClr1, "0x", "0xFF")
    $iC2 = StringReplace($iClr2, "0x", "0xFF")
    $hBitmap = _WinAPI_CreateBitmap($iWidth+$pressed, $iHeight+$pressed, 1, 32)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    $hBrushLin = _GDIPlus_CreateLineBrushFromRect(0, 0, $iWidth, $iHeight, $aFactors, $aPositions, $iC1, $iC2, $iDirection)
    GDIPlus_SetLineGammaCorrection($hBrushLin, $bGammaCorrection)
    _GDIPlus_GraphicsFillRect($hGraphic, 0, 0, $iWidth, $iHeight, $hBrushLin)
    $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    Local $w=$iWidth-32, $h=$iHeight-32
   ;$hBitmap = _WinAPI_CreateSolidBitmap(0, $iBackground, $iWidth, $iHeight)
    $hBackSv = _WinAPI_SelectObject($hBackDC, $hbmp)
   If $hIcon <> 0 Then _WinAPI_DrawIconEx($hBackDC, $w/2, $h/2, $hIcon, 0, 0, 0, 0, $DI_NORMAL)
    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    Local $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
_GDIPlus_GraphicsDispose    ($hGraphic)
    $hBkIcon = DllCall($ghGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0)
 ;  _GDIPlus_ImageDispose($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])
;   _WinAPI_DeleteObject($hbmp)

    _WinAPI_SelectObject($hBackDC, $hBackSv)
    _WinAPI_ReleaseDC(0, $hDC)

    return SetError(0, 0, 1)
endfunc; SetIcon
Func _Quit()
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)
    $tPositions = DllStructCreate("float[" & $iCount & "]")
    $pPositions = DllStructGetPtr($tPositions)
    For $iI = 0 To $iCount - 1
        DllStructSetData($tPositions, 1, $aPositions[$iI], $iI + 1)

    $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

Func _ProcessGetIcon($vProcess)
    Local $iPID = ProcessExists($vProcess)
    If Not $iPID Then Return SetError(1, 0, -1)
    Local $aProc = DllCall('kernel32.dll', 'hwnd', 'OpenProcess', 'int', BitOR(0x0400, 0x0010), 'int', 0, 'int', $iPID)
    If Not IsArray($aProc) Or Not $aProc[0] Then Return SetError(2, 0, -1)
    Local $vStruct = DllStructCreate('int[1024]')
    Local $hPsapi_Dll = DllOpen('Psapi.dll')
    If $hPsapi_Dll = -1 Then $hPsapi_Dll = DllOpen(@SystemDir & '\Psapi.dll')
    If $hPsapi_Dll = -1 Then $hPsapi_Dll = DllOpen(@WindowsDir & '\Psapi.dll')
    If $hPsapi_Dll = -1 Then Return SetError(3, 0, '')
    DllCall($hPsapi_Dll, 'int', 'EnumProcessModules', _
    'hwnd', $aProc[0], _
    'ptr', DllStructGetPtr($vStruct), _
    'int', DllStructGetSize($vStruct), _
    'int_ptr', 0)
    Local $aRet = DllCall($hPsapi_Dll, 'int', 'GetModuleFileNameEx', _
    'hwnd', $aProc[0], _
    'int', DllStructGetData($vStruct, 1), _
    'str', '', _
    'int', 2048)
    If Not IsArray($aRet) Or StringLen($aRet[3]) = 0 Then Return SetError(4, 0, '')
    Return $aRet[3]

Func processgetstate($process)
        For $i = 1 To $winlistall[0][0]
                If $process = $winlistall[$i][0] and WinActive($winlistall[$i][2]) Then return 1
    Return 0

Share this post

Link to post
Share on other sites

... My problem is the program crashes with no explanation if you create more than 6 buttons. ..

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post

Link to post
Share on other sites

it works for me as well with more than 6 pics

Share this post

Link to post
Share on other sites

Well, I guess I should move this post to the examples forum......I still have the problem. I've tried on a Vista and XP machine. Both get a Windows type error. I have since tried it on a Win 7 build and had success. So I guess it must be my machines which are the problem and not the script.

I will leave this post here for a day or so and see if others have problems...then perhaps will move to examples forum.

Thanks for your time.


Share this post

Link to post
Share on other sites

found it.

I commented out this line in the SetIcon function

; $hBkIcon = DllCall($ghGDIPDll, 'int', 'GdipCreateHICONFromBitmap', 'hWnd', $hImage, 'int*', 0)

it was a remnant that I no longer needed. As a result I think I was attempting to set an image twice to the same handle in the same function and my computer wasn't handling it....

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  


Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.