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