Jump to content

_ChooseColor() but better


argumentum
 Share

Go to solution Solved by argumentum,

Recommended Posts

..I'm coding the High Contrast theme editor and using the _ChooseColor() I wandered why it does not keep the the custom colors I've added.
Found that adding a static declaration would do it. But why stop there. Why not keep going, So I put this together that is non code braking ( backwards compatible ), to replace the one in <Misc.au3>
 

Spoiler
_ChooseColor_mod_Example()
Func _ChooseColor_mod_Example()
    Local $aCustColors[17]
    $aCustColors[1] = 0xFF0000
    $aCustColors[16] = 0x0000FF
    $aCustColors = _ChooseColor_mod(2, "0x00ff00", 2, 0, $aCustColors)
    ConsoleWrite(@CRLF & $aCustColors[0] & @CRLF & @CRLF)
    ConsoleWrite(@CRLF & _ChooseColor_mod(2, $aCustColors[0], 2, 0, $aCustColors)[0] & @CRLF & @CRLF)
    ConsoleWrite(@CRLF & _ChooseColor_mod(2, "0x00ff00", 2) & @CRLF & @CRLF) ; just as default behaviour
    ConsoleWrite(@CRLF & _ChooseColor_mod(2, "0x00ff00", 2, 0, 'reset as is neither "Default" nor "Array[17]"') & @CRLF & @CRLF) ; just as default behaviour
EndFunc   ;==>_ChooseColor_mod_Example

; #FUNCTION# ====================================================================================================================
; Name ..........: _ChooseColor_mod
; Description ...:
; Syntax ........: _ChooseColor_mod([$iReturnType = 0[, $iColorRef = 0[, $iRefType = 0[, $hWndOwnder = 0[, $vCustColors = Default]]]]])
; Parameters ....: $iReturnType         - [optional] an integer value. Default is 0. See remarks for values.
;                  $iColorRef           - [optional] an integer value. Default is 0.
;                  $iRefType            - [optional] an integer value. Default is 0. See remarks for values.
;                  $hWndOwnder          - [optional] a handle to the parent window. Default is 0.
;                  $vCustColors         - [optional] an array of colors to show as custom values. See remarks for values.
; Return values .: Success - Hex value of the selected color
;                  Failure - $vCustomColors is returned if set, otherwise, -1 is returned. Also sets @error:
;                  | -2 -       User initialized $tagCustcolors via $vCustColors.
;                  | -3 -       User canceled or invalid dll struct.
;                  | -4 -       Invalid $iReturnType value.
;                  | Other -    Error returned from Dll call.
; Author ........: Gary Frost (gafrost)
; Modified ......: argumentum
; Remarks .......: $iReturnType can be 0 (RGB COLORREF), 1 (Hex BGR), or 2 (Hex RGB).
;                  $iRefType can be 0 (ColorRef), 1 (BGR Hex), or 2 (RGB Hex).
;                  $vCustColors is a zero based array[17] where:
;                     index 0 hold the color returned by the function.
;                     index 1 to 16 are the colors to use in Custom colors in RGB.
;                     One can pass the array with array[0] = -2 to initialize the custom colors without loading the interface.
;                     When $vCustColors is used, it returns the modified array. ( not the color as integer ).
;                     Anything other than Default or a proper array, will clear $tagCustcolors ( holder of the custom colors ).
;                     When $vCustColors is omited or Default, $tagCustcolors is kept ( hence, no need for the array to keep custom colors ).
; Related .......: Same Func from <Misc.au3>
; Link ..........: https://www.autoitscript.com/forum/topic/200985-_choosecolor-but-better/
; Example .......: YES
; ===============================================================================================================================
Func _ChooseColor_mod($iReturnType = 0, $iColorRef = 0, $iRefType = 0, $hWndOwnder = 0, $vCustColors = Default) ; basic code from Misc.au3 ; https://www.autoitscript.com/forum/topic/200985-_choosecolor-but-better/

    ; added here for independance of #include <Misc.au3>
    Local Static $tagCHOOSECOLOR = "dword Size;hwnd hWndOwnder;handle hInstance;dword rgbResult;ptr CustColors;dword Flags;lparam lCustData;" & _
            "ptr lpfnHook;ptr lpTemplateName"
    Local Static $__MISCCONSTANT_CC_ANYCOLOR = 0x0100
    Local Static $__MISCCONSTANT_CC_FULLOPEN = 0x0002
    Local Static $__MISCCONSTANT_CC_RGBINIT = 0x0001
    ; added here for independance of #include <Misc.au3>


    Local $vReturn, $bCustColors = False, $tagCustcolors = "dword[16]"
    Local $tChoose = DllStructCreate($tagCHOOSECOLOR)
    Local Static $tCc = DllStructCreate($tagCustcolors) ; added Static (mod.), to keep $tagCustcolors changes by user when called again.

    If $vCustColors == Default Then
        ; nothing
    ElseIf UBound($vCustColors) = 17 Then
        $bCustColors = True
        For $n = 1 To 16
            DllStructSetData($tCc, 1, $vCustColors[$n], $n)
        Next
    Else
        $tCc = DllStructCreate($tagCustcolors) ; reset, just in case you'd want to have it default again
    EndIf

    If $iRefType = 1 Then ; BGR hex color to colorref
        $iColorRef = Int($iColorRef)
    ElseIf $iRefType = 2 Then ; RGB hex color to colorref
        $iColorRef = Hex(String($iColorRef), 6)
        $iColorRef = '0x' & StringMid($iColorRef, 5, 2) & StringMid($iColorRef, 3, 2) & StringMid($iColorRef, 1, 2)
    EndIf

    DllStructSetData($tChoose, "Size", DllStructGetSize($tChoose))
    DllStructSetData($tChoose, "hWndOwnder", $hWndOwnder)
    DllStructSetData($tChoose, "rgbResult", $iColorRef)
    DllStructSetData($tChoose, "CustColors", DllStructGetPtr($tCc))
    DllStructSetData($tChoose, "Flags", BitOR($__MISCCONSTANT_CC_ANYCOLOR, $__MISCCONSTANT_CC_FULLOPEN, $__MISCCONSTANT_CC_RGBINIT))

    Local $aResult = DllCall("comdlg32.dll", "bool", "ChooseColor", "struct*", $tChoose)
    If @error Then
        If Not $bCustColors Then
            Return SetError(@error, @extended, -1)
        Else
            $vCustColors[0] = -1
            Return SetError(@error, @extended, $vCustColors)
        EndIf
    EndIf

    If $bCustColors Then ; this here is better than at the end,
        For $n = 1 To 16 ;  that way you'll get the custom colors anyway.
            $vCustColors[$n] = DllStructGetData($tCc, 1, $n)
        Next
        If $vCustColors[0] = -2 Then Return $vCustColors
    EndIf

    If $aResult[0] = 0 Then ; Return SetError(-3, -3, -1) ; user selected cancel or struct settings incorrect
        If Not $bCustColors Then
            Return SetError(-3, -3, -1)
        Else
            $vCustColors[0] = -1
            Return SetError(-3, -3, $vCustColors)
        EndIf
    EndIf

    Local $sColor_picked = DllStructGetData($tChoose, "rgbResult")

    If $iReturnType = 1 Then ; return Hex BGR Color
        $vReturn = '0x' & Hex(String($sColor_picked), 6)
    ElseIf $iReturnType = 2 Then ; return Hex RGB Color
        $sColor_picked = Hex(String($sColor_picked), 6)
        $vReturn = '0x' & StringMid($sColor_picked, 5, 2) & StringMid($sColor_picked, 3, 2) & StringMid($sColor_picked, 1, 2)
    ElseIf $iReturnType = 0 Then ; return RGB COLORREF
        $vReturn = $sColor_picked
    Else
        $vReturn = -1
        SetError(-4, -4)
    EndIf
    If Not $bCustColors Then Return $vReturn
    $vCustColors[0] = $vReturn
    Return $vCustColors
EndFunc   ;==>_ChooseColor_mod

 

Hopefully will replace the default one in the next release;) 

Better use the new code down this post.

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

I like it! Two (minor) nitpicks:

1. $iCustColors is really a boolean, should be used and named as such ;) (Dyslexia is a b***h with 0's and 1's, so I never remember which is True) 
2. Include a header to let us know what the possible results of the function are... I guessed a bit in generating this

; #FUNCTION# ====================================================================================================================
; Name ..........: _ChooseColor_mod
; Description ...: 
; Syntax ........: _ChooseColor_mod([$iReturnType = 0[, $iColorRef = 0[, $iRefType = 0[, $hWndOwnder = 0[, $vCustColors = Default]]]]])
; Parameters ....: $iReturnType         - [optional] an integer value. Default is 0. See remarks for values.
;                  $iColorRef           - [optional] an integer value. Default is 0.
;                  $iRefType            - [optional] an integer value. Default is 0. See remarks for values.
;                  $hWndOwnder          - [optional] a handle to the parent window. Default is 0.
;                  $vCustColors         - [optional] an array of colors to show as custom values. Default is Default.
; Return values .: Success - Hex value of the selected color
;                  Failure - $vCustomColors is returned if set, otherwise, -1 is returned. Also sets @error: 
;                  | -3 -       User canceled or invalid dll struct. 
;                  | -4 -       Invalid $iReturnType value.
;                  | Other -    Error returned from Dll call.
; Author ........: argumentum
; Modified ......: 
; Remarks .......: $iReturnType can be 0 (RGB COLORREF), 1 (Hex BGR), or 2 (Hex RGB).
;~                 $iRefType can be 0 (ColorRef), 1 (BGR Hex), or 2 (RGB Hex).
; Related .......: 
; Link ..........: https://www.autoitscript.com/forum/topic/200985-_choosecolor-but-better/
; Example .......:
; ===============================================================================================================================

 

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Link to comment
Share on other sites

  • 5 months later...
  • Solution

ok, this, I believe is a good approach and fixes the lies in the description from the prior incarnation :) 

#include <AutoItConstants.au3>; For $UBOUND_*
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <WindowsConstants.au3>

Example()

Func Example()
    Local $hGUI, $idCOLORREF, $idBGR, $idRGB, $idMemo, $idRGBwA1, $idRGBwA2, $idClear

    $hGUI = GUICreate("_ChooseColor() Example", 400, 300)
    $idMemo = GUICtrlCreateEdit("", 2, 55, 396, 200, BitOR($WS_VSCROLL, $WS_HSCROLL))
    GUICtrlSetFont($idMemo, 10, 400, 0, "Courier New")
    $idCOLORREF = GUICtrlCreateButton("COLORREF", 40, 10, 80, 40)
    $idBGR = GUICtrlCreateButton("BGR", 130, 10, 80, 40)
    $idRGB = GUICtrlCreateButton("RGB", 220, 10, 80, 40)
    $idClear = GUICtrlCreateButton("Clear", 310, 10, 60, 40)
    $idRGBwA1 = GUICtrlCreateButton("RGB + custom #1", 80, 260, 100, 40)
    $idRGBwA2 = GUICtrlCreateButton("RGB + custom #2", 210, 260, 100, 40)
    GUISetState(@SW_SHOW)

    Local $aCustColors1[17]
    $aCustColors1[0] = -9  ; init. the custom colors
    $aCustColors1[3] = 0xFF0000 ; if you would like to,
    $aCustColors1[16] = 0x0000FF ; without having to load the interface.
    _ChooseColor_Mod_2($aCustColors1)

    Local $aCustColors2[17]
    $aCustColors2[2] = 0x0000FF
    $aCustColors2[15] = 0xFF0000

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                GUIDelete()
                ExitLoop
            Case $idClear
                GUICtrlSetState($idClear, $GUI_DISABLE)
                _ChooseColor_Mod_2(-10)
                Sleep(200) ; some feedback to show something was done  =)
                GUICtrlSetState($idClear, $GUI_ENABLE)
            Case $idCOLORREF
                _ShowChoice($hGUI, $idMemo, 0, _ChooseColor_Mod_2(0, 255, 0, $hGUI), "COLORREF color of your choice: ")
            Case $idBGR
                _ShowChoice($hGUI, $idMemo, 1, _ChooseColor_Mod_2(2, 0x808000, 1, $hGUI), "BGR Hex color of your choice: ")
            Case $idRGB
                _ShowChoice($hGUI, $idMemo, 2, _ChooseColor_Mod_2(2, 0x0080C0, 2, $hGUI), "RGB Hex color of your choice: ")
            Case $idRGBwA1
                $aCustColors1[0] = 2 ; this is the "ReturnType"
                $aCustColors1 = _ChooseColor_Mod_2($aCustColors1, 0x0080C0, 2, $hGUI) ; to update the saved custom colors back to the array
                _ShowChoice($hGUI, $idMemo, 2, $aCustColors1[0], "RGB Hex color of your choice ( #1 ): ")
            Case $idRGBwA2
                $aCustColors2[0] = 2
                _ShowChoice($hGUI, $idMemo, 2, _ChooseColor_Mod_2($aCustColors2, 0x0080C0, 2, $hGUI)[0], "RGB Hex color of your choice ( #2 ): ")
        EndSwitch
    WEnd
EndFunc   ;==>Example

Func _ShowChoice($hGUI, $idMemo, $iType, $iChoose, $sMessage)
    Local $sCr
    If $iChoose <> -1 Then

        If $iType = 0 Then ; convert COLORREF to RGB for this example
            $sCr = Hex($iChoose, 6)
            GUISetBkColor('0x' & StringMid($sCr, 5, 2) & StringMid($sCr, 3, 2) & StringMid($sCr, 1, 2), $hGUI)
        Else
            GUISetBkColor($iChoose, $hGUI)
        EndIf

        GUICtrlSetData($idMemo, $sMessage & $iChoose & @CRLF, 1)

    Else
        GUICtrlSetData($idMemo, "User Canceled Selction" & @CRLF, 1)
    EndIf
EndFunc   ;==>_ShowChoice





; #FUNCTION# ====================================================================================================================
; Name ..........: _ChooseColor_Mod_2
; Description ...:
; Syntax ........: _ChooseColor_Mod_2([$vReturnType = 0[, $iColorRef = 0[, $iRefType = 0[, $hWndOwnder = 0]]]])
; Parameters ....: $vReturnType         : [optional] an integer value. Default is 0. See remarks for values.
;                  $iColorRef           : [optional] an integer value. Default is 0.
;                  $iRefType            : [optional] an integer value. Default is 0. See remarks for values.
;                  $hWndOwnder          : [optional] a handle to the parent window. Default is 0.
; Return values .: Success - Hex value of the selected color
;                  Failure - $vCustomColors is returned if set, otherwise, -1 is returned. Also sets @error:
;                  | -3       : User canceled or invalid dll struct.
;                  | -4       : Invalid $vReturnType value.
;                  | -5       : Invalid $vReturnType array.
;                  | Other    : Error returned from Dll call.
; Author ........: Gary Frost (gafrost)
; Modified ......: argumentum
; Remarks .......: $vReturnType can be 0 (RGB COLORREF), 1 (Hex BGR), 2 (Hex RGB),
;                        -9 (return saved custom colors),
;                       -10 (return saved custom colors and clear/remove saved custom colors),
;                          or an array ( see remark below ).
;
;                  $iRefType can be 0 (ColorRef), 1 (BGR Hex), or 2 (RGB Hex).
;
;                  $vReturnType can be an array[17] where:
;                     index 0 holds a value of:
;                       0   : COLORREF rgbcolor
;                       1   : BGR hex
;                       2   : RGB hex
;                       -9  : returns the currently saved custom colors as array[17], and by the way, is
;                                           where the return value is placed on return ( when used as array ).
;
;                     index 1 to 16 are the colors to use in Custom colors in RGB.
;
;                     When $vReturnType is an array, it returns the modified array. ( not the color as integer ).
;                       with the selected color in array[0], unless canceled by which no update will occur.
;
;                     Adding int(10) to $vReturnType, when used as an integer, will also clear the saved custom colors.
;
; Related .......: Same Func from <Misc.au3>
; Link ..........: https://www.autoitscript.com/forum/topic/200985-_choosecolor-but-better/
; Example .......: YES
Func _ChooseColor_Mod_2($vReturnType = 0, $iColorRef = 0, $iRefType = 0, $hWndOwnder = 0)
    Local $tagCustcolors = "dword[16]"

    Local $tChoose = DllStructCreate($tagCHOOSECOLOR)

    ; mod. init. start

    Local Static $tCc = DllStructCreate($tagCustcolors) ; keep the colors
    Local $iReturnType, $vReturn

    If $vReturnType = -9 Or $vReturnType = -10 Then ; get $tagCustcolors as array
        Local $a_tCc = __ChooseColor_TagToArray($tCc)
        $a_tCc[0] = -1
        If $vReturnType = -10 Then $tCc = DllStructCreate($tagCustcolors)
        Return $a_tCc
    ElseIf $vReturnType > 9 Then ; re-init./clear $tCc, and continue on a clean slate, just "10 + ReturnType"
        $tCc = DllStructCreate($tagCustcolors) ; ( maybe unnecessary but the user may want to )
        $iReturnType = $vReturnType - 10
    ElseIf IsArray($vReturnType) Then ; user declared Custcolors array
        If UBound($vReturnType, $UBOUND_ROWS) = 17 And UBound($vReturnType, $UBOUND_DIMENSIONS) = 1 Then
            For $n = 1 To 16
                DllStructSetData($tCc, 1, $vReturnType[$n], $n)
            Next
            If $vReturnType[0] = -9 Then ; ..consistent with "-9 = return $tagCustcolors as array"
                $vReturnType[0] = 0 ; set back to default "ReturnType"
                Return $vReturnType
            EndIf
            If $vReturnType[0] > 9 Then $vReturnType[0] -= 10 ; just in case the user mistakenly think it needs to
            $iReturnType = $vReturnType[0]
        Else
            Return SetError(-5, 0, -1) ; unexpected array format
        EndIf
    Else
        $iReturnType = $vReturnType
    EndIf

    If $iReturnType < 0 Or $iReturnType > 2 Then ; unexpected ReturnType
        SetError(-4, -4) ;                      moved here to avoid loading
        If IsArray($vReturnType) Then
            $vReturnType[0] = -1
            Return $vReturnType
        EndIf
        Return -1
    EndIf


    ; mod. init. end

    If $iRefType = 1 Then ; BGR hex color to colorref
        $iColorRef = Int($iColorRef)
    ElseIf $iRefType = 2 Then ; RGB hex color to colorref
        $iColorRef = Hex(String($iColorRef), 6)
        $iColorRef = '0x' & StringMid($iColorRef, 5, 2) & StringMid($iColorRef, 3, 2) & StringMid($iColorRef, 1, 2)
    EndIf

    DllStructSetData($tChoose, "Size", DllStructGetSize($tChoose))
    DllStructSetData($tChoose, "hWndOwnder", $hWndOwnder)
    DllStructSetData($tChoose, "rgbResult", $iColorRef)
    DllStructSetData($tChoose, "CustColors", DllStructGetPtr($tCc))
    DllStructSetData($tChoose, "Flags", BitOR($__MISCCONSTANT_CC_ANYCOLOR, $__MISCCONSTANT_CC_FULLOPEN, $__MISCCONSTANT_CC_RGBINIT))

    Local $aResult = DllCall("comdlg32.dll", "bool", "ChooseColor", "struct*", $tChoose)
    If @error Then
        SetError(@error, @extended)
        If IsArray($vReturnType) Then
            $vReturnType[0] = -1
            Return $vReturnType
        EndIf
        Return -1
    EndIf

    If $aResult[0] = 0 Then
        SetError(-3, -3) ; user selected cancel or struct settings incorrect
        If IsArray($vReturnType) Then
            $vReturnType[0] = -1
            Return $vReturnType
        EndIf
        Return -1
    EndIf

    Local $sColor_picked = DllStructGetData($tChoose, "rgbResult")

    If $iReturnType = 1 Then ; return Hex BGR Color
        $vReturn = '0x' & Hex(String($sColor_picked), 6)
    ElseIf $iReturnType = 2 Then ; return Hex RGB Color
        $sColor_picked = Hex(String($sColor_picked), 6)
        $vReturn = '0x' & StringMid($sColor_picked, 5, 2) & StringMid($sColor_picked, 3, 2) & StringMid($sColor_picked, 1, 2)
    ElseIf $iReturnType = 0 Then ; return RGB COLORREF
        $vReturn = $sColor_picked
    Else
        SetError(-4, -4)
        $vReturn = -1
    EndIf
    If IsArray($vReturnType) Then
        $vReturnType = __ChooseColor_TagToArray($tCc)
        $vReturnType[0] = $vReturn
        Return $vReturnType
    EndIf
    Return $vReturn
EndFunc   ;==>_ChooseColor_Mod_2

Func __ChooseColor_TagToArray(ByRef $tag) ; internal
    Local $aArray[17]
    For $n = 1 To 16
        $aArray[$n] = DllStructGetData($tag, 1, $n)
    Next
    Return $aArray
EndFunc   ;==>__ChooseColor_TagToArray

Edit: I guess the most practical use is to init. the colors and use as usual. The rest of the options, are there for the user's fancy.

Edit 2: This is now part of beta 3.3.15.4

Edited by argumentum
corrected text in the code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
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
 Share

×
×
  • Create New...