[Solved] problem with CColor() only in Unicode builds?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

[Solved] problem with CColor() only in Unicode builds?

19 Jan 2016, 15:46

Hey all,
I've been using CColor() (see below) to color controls for years, back with basic and in at least one other script in _L but it was with the ansi build... Now i'm trying to use it in the Unicode build (32-bit or 64-bit) and I get weird effects:
CColorUnicodeProblem.png
CColorUnicodeProblem.png (15.9 KiB) Viewed 1547 times
As you can see, when the cell has focus in the unicode build, the red background color is "whited out" except for the border... with the Ansi build it works as I want... Any ideas?
Thanks
- joel

Code: Select all

/*
   Function:   CColor
            Set text and background color for some Gui controls.
            Supported types: Edit, Text, ListBox, ComboBox, DropDownList, CheckBox, RadioButton, ListView, TreeView, RichEdit
   
   Parameters:   
      Hwnd      -  Handle of the control.
      Background  -  Background color. HTML color name or 6-digit RGB value. Optional.
      Foreground  -  Foreground color. HTML color name or 6-digit RGB value. Optional.
    
   Remarks:
      You need to redraw the window for changes to take effect. For some controls, it may be needed to explicitelly specify
      foreground color ("cRed") when creating control, otherwise text will stay black.

      On tha first call for a specific control class the function registers itself as message handler for WM_CTLCOLOR
      message of appropriate class.

      Buttons are always drawn with the default system colors. Drawing buttons requires several different brushes-face, highlight and shadow
      but the WM_CTLCOLORBTN message allows only one brush to be returned. To provide a custom appearance for push buttons, use an owner-drawn button.

   About:
      o Version 1.0 by majkinetor.
      o Original code by (de)nick, See: <http://www.autohotkey.com/forum/topic238864.html>.
      o Licenced under BSD <http://creativecommons.org/licenses/BSD/>.
 */
CColor(Hwnd, Background="", Foreground="") {
   return CColor_(Background, Foreground, "", Hwnd+0)
}

CColor_(Wp, Lp, Msg, Hwnd) {
   static
   static WM_CTLCOLOREDIT=0x0133, WM_CTLCOLORLISTBOX=0x134, WM_CTLCOLORSTATIC=0x0138
        ,LVM_SETBKCOLOR=0x1001, LVM_SETTEXTCOLOR=0x1024, LVM_SETTEXTBKCOLOR=0x1026, TVM_SETTEXTCOLOR=0x111E, TVM_SETBKCOLOR=0x111D
        ,BS_CHECKBOX=2, BS_RADIOBUTTON=8, ES_READONLY=0x800
        ,CLR_NONE=-1, CSILVER=0xC0C0C0, CGRAY=0x808080, CWHITE=0xFFFFFF, CMAROON=0x80, CRED=0x0FF, CPURPLE=0x800080, CFUCHSIA=0xFF00FF, CGREEN=0x8000, CLIME=0xFF00, COLIVE=0x8080, CYELLOW=0xFFFF, CNAVY=0x800000, CBLUE=0xFF0000, CTEAL=0x808000, CAQUA=0xFFFF00
         ,CLASSES := "Button,ComboBox,Edit,ListBox,Static,RICHEDIT50W,SysListView32,SysTreeView32"
   
   If (Msg = "") {     
      if !adrSetTextColor
         adrSetTextColor   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetTextColor")
         ,adrSetBkColor   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetBkColor")
         ,adrSetBkMode   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetBkMode")
   
      ;Set the colors (RGB -> BGR)
      BG := !Wp ? "" : C%Wp% != "" ? C%Wp% : "0x" SubStr(WP,5,2) SubStr(WP,3,2) SubStr(WP,1,2)
      FG := !Lp ? "" : C%Lp% != "" ? C%Lp% : "0x" SubStr(LP,5,2) SubStr(LP,3,2) SubStr(LP,1,2)

     ;Activate message handling with OnMessage() on the first call for a class
      WinGetClass, class, ahk_id %Hwnd%
      If class not in %CLASSES%
         return A_ThisFunc "> Unsupported control class: " class

      ControlGet, style, Style, , , ahk_id %Hwnd%
      if (class = "Edit") && (Style & ES_READONLY)
         class := "Static"
   
      if (class = "Button")
         if (style & BS_RADIOBUTTON) || (style & BS_CHECKBOX)
             class := "Static"
         else return A_ThisFunc "> Unsupported control class: " class
      
      if (class = "ComboBox") {
         VarSetCapacity(CBBINFO, 52, 0), NumPut(52, CBBINFO), DllCall("GetComboBoxInfo", "UInt", Hwnd, "UInt", &CBBINFO)
         hwnd := NumGet(CBBINFO, 48)      ;hwndList
         %hwnd%BG := BG, %hwnd%FG := FG, %hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : -1

         IfEqual, CTLCOLORLISTBOX,,SetEnv, CTLCOLORLISTBOX, % OnMessage(WM_CTLCOLORLISTBOX, A_ThisFunc)

         If NumGet(CBBINFO,44)   ;hwndEdit
            Hwnd :=  Numget(CBBINFO,44), class := "Edit"
      }

      if class in SysListView32,SysTreeView32
      {
         m := class="SysListView32" ? "LVM" : "TVM"
         SendMessage, %m%_SETBKCOLOR, ,BG, ,ahk_id %Hwnd%
         SendMessage, %m%_SETTEXTCOLOR, ,FG, ,ahk_id %Hwnd%
         SendMessage, %m%_SETTEXTBKCOLOR, ,CLR_NONE, ,ahk_id %Hwnd%
         return
      }

      if (class = "RICHEDIT50W")
         return f := "RichEdit_SetBgColor", %f%(Hwnd, -BG)

      if (!CTLCOLOR%Class%)
         CTLCOLOR%Class% := OnMessage(WM_CTLCOLOR%Class%, A_ThisFunc)

      return %Hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : CLR_NONE,  %Hwnd%BG := BG,  %Hwnd%FG := FG
   }
 
 ; Message handler
   critical               ;its OK, always in new thread.

   Hwnd := Lp + 0, hDC := Wp + 0
   If (%Hwnd%) {
      DllCall(adrSetBkMode, "uint", hDC, "int", 1)
      if (%Hwnd%FG)
         DllCall(adrSetTextColor, "UInt", hDC, "UInt", %Hwnd%FG)
      if (%Hwnd%BG)
         DllCall(adrSetBkColor, "UInt", hDC, "UInt", %Hwnd%BG)
      return (%Hwnd%)
   }
}
Last edited by gwarble on 19 Jan 2016, 19:29, edited 1 time in total.
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
just me
Posts: 9478
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: problem with CColor() only in Unicode builds?

19 Jan 2016, 16:23

GetProcAddress expects the function name as an ANSI string:

Code: Select all

adrSetTextColor   := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "Gdi32.dll", "UPtr"), "AStr", "SetTextColor", "UPtr")
But I'm wondering why there is some red at all.
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: problem with CColor() only in Unicode builds?

19 Jan 2016, 16:29

awesome, and fast, that did it, thank you!
I'm not sure why there is any red at all, but there is that border when in focus and full/expected bgcolor when not in focus

Fixed (for unicode 32-bit at least):

Code: Select all

/*
   Function:   CColor
            Set text and background color for some Gui controls.
            Supported types: Edit, Text, ListBox, ComboBox, DropDownList, CheckBox, RadioButton, ListView, TreeView, RichEdit
   
   Parameters:   
      Hwnd      -  Handle of the control.
      Background  -  Background color. HTML color name or 6-digit RGB value. Optional.
      Foreground  -  Foreground color. HTML color name or 6-digit RGB value. Optional.
    
   Remarks:
      You need to redraw the window for changes to take effect. For some controls, it may be needed to explicitelly specify
      foreground color ("cRed") when creating control, otherwise text will stay black.

      On tha first call for a specific control class the function registers itself as message handler for WM_CTLCOLOR
      message of appropriate class.

      Buttons are always drawn with the default system colors. Drawing buttons requires several different brushes-face, highlight and shadow
      but the WM_CTLCOLORBTN message allows only one brush to be returned. To provide a custom appearance for push buttons, use an owner-drawn button.

   About:
      o Version 1.0 by majkinetor.
      o Original code by (de)nick, See: <http://www.autohotkey.com/forum/topic238864.html>.
      o Licenced under BSD <http://creativecommons.org/licenses/BSD/>.
 */
CColor(Hwnd, Background="", Foreground="") {
   return CColor_(Background, Foreground, "", Hwnd+0)
}

CColor_(Wp, Lp, Msg, Hwnd) {
   static
   static WM_CTLCOLOREDIT=0x0133, WM_CTLCOLORLISTBOX=0x134, WM_CTLCOLORSTATIC=0x0138
        ,LVM_SETBKCOLOR=0x1001, LVM_SETTEXTCOLOR=0x1024, LVM_SETTEXTBKCOLOR=0x1026, TVM_SETTEXTCOLOR=0x111E, TVM_SETBKCOLOR=0x111D
        ,BS_CHECKBOX=2, BS_RADIOBUTTON=8, ES_READONLY=0x800
        ,CLR_NONE=-1, CSILVER=0xC0C0C0, CGRAY=0x808080, CWHITE=0xFFFFFF, CMAROON=0x80, CRED=0x0FF, CPURPLE=0x800080, CFUCHSIA=0xFF00FF, CGREEN=0x8000, CLIME=0xFF00, COLIVE=0x8080, CYELLOW=0xFFFF, CNAVY=0x800000, CBLUE=0xFF0000, CTEAL=0x808000, CAQUA=0xFFFF00
         ,CLASSES := "Button,ComboBox,Edit,ListBox,Static,RICHEDIT50W,SysListView32,SysTreeView32"
   
   If (Msg = "") {     
      if !adrSetTextColor
         adrSetTextColor := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "Gdi32.dll", "UPtr"), "AStr", "SetTextColor", "UPtr")
         ,adrSetBkColor  := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "Gdi32.dll", "UPtr"), "AStr", "SetBkColor", "UPtr")
         ,adrSetBkMode   := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "Gdi32.dll", "UPtr"), "AStr", "SetBkMode", "UPtr")
;         adrSetTextColor   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetTextColor")
;         ,adrSetBkColor   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetBkColor")
;         ,adrSetBkMode   := DllCall("GetProcAddress", "uint", DllCall("GetModuleHandle", "str", "Gdi32.dll"), "str", "SetBkMode")
   
      ;Set the colors (RGB -> BGR)
      BG := !Wp ? "" : C%Wp% != "" ? C%Wp% : "0x" SubStr(WP,5,2) SubStr(WP,3,2) SubStr(WP,1,2)
      FG := !Lp ? "" : C%Lp% != "" ? C%Lp% : "0x" SubStr(LP,5,2) SubStr(LP,3,2) SubStr(LP,1,2)

     ;Activate message handling with OnMessage() on the first call for a class
      WinGetClass, class, ahk_id %Hwnd%
      If class not in %CLASSES%
         return A_ThisFunc "> Unsupported control class: " class

      ControlGet, style, Style, , , ahk_id %Hwnd%
      if (class = "Edit") && (Style & ES_READONLY)
         class := "Static"
   
      if (class = "Button")
         if (style & BS_RADIOBUTTON) || (style & BS_CHECKBOX)
             class := "Static"
         else return A_ThisFunc "> Unsupported control class: " class
      
      if (class = "ComboBox") {
         VarSetCapacity(CBBINFO, 52, 0), NumPut(52, CBBINFO), DllCall("GetComboBoxInfo", "UInt", Hwnd, "UInt", &CBBINFO)
         hwnd := NumGet(CBBINFO, 48)      ;hwndList
         %hwnd%BG := BG, %hwnd%FG := FG, %hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : -1

         IfEqual, CTLCOLORLISTBOX,,SetEnv, CTLCOLORLISTBOX, % OnMessage(WM_CTLCOLORLISTBOX, A_ThisFunc)

         If NumGet(CBBINFO,44)   ;hwndEdit
            Hwnd :=  Numget(CBBINFO,44), class := "Edit"
      }

      if class in SysListView32,SysTreeView32
      {
         m := class="SysListView32" ? "LVM" : "TVM"
         SendMessage, %m%_SETBKCOLOR, ,BG, ,ahk_id %Hwnd%
         SendMessage, %m%_SETTEXTCOLOR, ,FG, ,ahk_id %Hwnd%
         SendMessage, %m%_SETTEXTBKCOLOR, ,CLR_NONE, ,ahk_id %Hwnd%
         return
      }

      if (class = "RICHEDIT50W")
         return f := "RichEdit_SetBgColor", %f%(Hwnd, -BG)

      if (!CTLCOLOR%Class%)
         CTLCOLOR%Class% := OnMessage(WM_CTLCOLOR%Class%, A_ThisFunc)

      return %Hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : CLR_NONE,  %Hwnd%BG := BG,  %Hwnd%FG := FG
   }
 
 ; Message handler
   critical               ;its OK, always in new thread.

   Hwnd := Lp + 0, hDC := Wp + 0
   If (%Hwnd%) {
      DllCall(adrSetBkMode, "uint", hDC, "int", 1)
      if (%Hwnd%FG)
         DllCall(adrSetTextColor, "UInt", hDC, "UInt", %Hwnd%FG)
      if (%Hwnd%BG)
         DllCall(adrSetBkColor, "UInt", hDC, "UInt", %Hwnd%BG)
      return (%Hwnd%)
   }
}
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
just me
Posts: 9478
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Solved] problem with CColor() only in Unicode builds?

20 Jan 2016, 03:05

Hi gwarble,

this should run with U64, too:

Code: Select all

/*
   Function:   CColor
               Set text and background color for some Gui controls.
               Supported types: Edit, Text, ListBox, ComboBox, DropDownList, CheckBox, RadioButton, ListView, TreeView, RichEdit

   Parameters:
      Hwnd        -  Handle of the control.
      Background  -  Background color. HTML color name or 6-digit RGB value. Optional.
      Foreground  -  Foreground color. HTML color name or 6-digit RGB value. Optional.

   Remarks:
      You need to redraw the window for changes to take effect. For some controls, it may be needed to explicitelly specify
      foreground color ("cRed") when creating control, otherwise text will stay black.

      On tha first call for a specific control class the function registers itself as message handler for WM_CTLCOLOR
      message of appropriate class.

      Buttons are always drawn with the default system colors. Drawing buttons requires several different brushes-face, highlight and shadow
      but the WM_CTLCOLORBTN message allows only one brush to be returned. To provide a custom appearance for push buttons, use an owner-drawn button.

   About:
      o Version 1.0 by majkinetor.
      o Original code by (de)nick, See: <http://www.autohotkey.com/forum/topic238864.html>.
      o Licenced under BSD <http://creativecommons.org/licenses/BSD/>.
*/
CColor(Hwnd, Background := "", Foreground := "") {
   Return CColor_(Background, Foreground, "", Hwnd+0)
}

CColor_(Wp, Lp, Msg, Hwnd) {
   Static
   Static WM_CTLCOLOREDIT := 0x0133, WM_CTLCOLORLISTBOX := 0x134, WM_CTLCOLORSTATIC := 0x0138
        , LVM_SETBKCOLOR := 0x1001, LVM_SETTEXTCOLOR := 0x1024, LVM_SETTEXTBKCOLOR := 0x1026, TVM_SETTEXTCOLOR := 0x111E
        , TVM_SETBKCOLOR := 0x111D
        , BS_CHECKBOX := 2, BS_RADIOBUTTON := 8, ES_READONLY := 0x800
        , CLR_NONE := -1, CSILVER := 0xC0C0C0, CGRAY := 0x808080, CWHITE := 0xFFFFFF, CMAROON := 0x80, CRED := 0x0FF
        , CPURPLE := 0x800080, CFUCHSIA := 0xFF00FF, CGREEN := 0x8000, CLIME := 0xFF00, COLIVE := 0x8080, CYELLOW := 0xFFFF
        , CNAVY := 0x800000, CBLUE := 0xFF0000, CTEAL := 0x808000, CAQUA := 0xFFFF00
        , CLASSES := "Button,ComboBox,Edit,ListBox,Static,RICHEDIT50W,SysListView32,SysTreeView32"

   If (Msg = "") {
      If !(adrSetTextColor)
         hGdi := DllCall("GetModuleHandle", "Str", "Gdi32.dll", "UPtr")
         , adrSetTextColor := DllCall("GetProcAddress", "Ptr", hGdi, "AStr", "SetTextColor", "UPtr")
         , adrSetBkColor   := DllCall("GetProcAddress", "Ptr", hGdi, "AStr", "SetBkColor", "UPtr")
         , adrSetBkMode    := DllCall("GetProcAddress", "Ptr", hGid, "AStr", "SetBkMode", "UPtr")

      ;Set the colors (RGB -> BGR)
      BG := !Wp ? "" : C%Wp% != "" ? C%Wp% : "0x" SubStr(WP,5,2) SubStr(WP,3,2) SubStr(WP,1,2)
      FG := !Lp ? "" : C%Lp% != "" ? C%Lp% : "0x" SubStr(LP,5,2) SubStr(LP,3,2) SubStr(LP,1,2)

      ;Activate message handling with OnMessage() on the first call for a Class
      WinGetClass, Class, ahk_id %Hwnd%
      If Class not In %CLASSES%
         Return A_ThisFunc "> Unsupported control class: " Class

      ControlGet, Styles, Style, , , ahk_id %Hwnd%
      If (Class = "Edit") && (Style & ES_READONLY)
         Class := "Static"

      If (Class = "Button")
         If (Styles & BS_RADIOBUTTON) || (Styles & BS_CHECKBOX)
            Class := "Static"
         Else
            Return A_ThisFunc "> Unsupported control class: " Class

      If (Class = "ComboBox") {
         VarSetCapacity(CBBINFO, 40 + (A_PtrSize * 3), 0)
         , NumPut(40 + (A_PtrSize * 3), CBBINFO, 0, "UInt")
         , DllCall("GetComboBoxInfo", "Ptr", Hwnd, "Ptr", &CBBINFO)
         , Hwnd := NumGet(CBBINFO, 40 + (A_PtrSize * 2), "UPtr") ; hwndList
         %hwnd%BG := BG, %hwnd%FG := FG, %hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG) : -1

         If !(CTLCOLORLISTBOX)
            CTLCOLORLISTBOX := OnMessage(WM_CTLCOLORLISTBOX, A_ThisFunc)

         If (hEdit := NumGet(CBBINFO, 40 + A_PtrSize, "UPtr")) ; hwndEdit
            Hwnd := hEdit, Class := "Edit"
      }

      If Class In SysListView32,SysTreeView32
      {
         m := Class = "SysListView32" ? "LVM" : "TVM"
         SendMessage, %m%_SETBKCOLOR, , BG, , ahk_id %Hwnd%
         SendMessage, %m%_SETTEXTCOLOR, , FG, , ahk_id %Hwnd%
         SendMessage, %m%_SETTEXTBKCOLOR, , CLR_NONE, , ahk_id %Hwnd%
         Return
      }

      If (Class = "RICHEDIT50W")
         Return f := "RichEdit_SetBgColor", %f%(Hwnd, -BG)

      If (!CTLCOLOR%Class%)
         CTLCOLOR%Class% := OnMessage(WM_CTLCOLOR%Class%, A_ThisFunc)

      Return %Hwnd% := BG ? DllCall("CreateSolidBrush", "UInt", BG, "Ptr") : CLR_NONE,  %Hwnd%BG := BG,  %Hwnd%FG := FG
   }

   ; Message handler
   Critical               ; its OK, always in new thread.
   Hwnd := Lp + 0
   If (%Hwnd%) {
      DllCall(adrSetBkMode, "Ptr", Wp, "int", 1)
      If (%Hwnd%FG)
         DllCall(adrSetTextColor, "Ptr", Wp, "UInt", %Hwnd%FG)
      If (%Hwnd%BG)
         DllCall(adrSetBkColor, "Ptr", Wp, "UInt", %Hwnd%BG)
      Return (%Hwnd%)
   }
}
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [Solved] problem with CColor() only in Unicode builds?

20 Jan 2016, 03:07

Hi,

why you dont link your class just me?
CtlColors - color your controls
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
just me
Posts: 9478
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Solved] problem with CColor() only in Unicode builds?

20 Jan 2016, 04:54

Everybody's free to choose the script she/he wants to use. ;)
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: [Solved] problem with CColor() only in Unicode builds?

20 Jan 2016, 20:40

thank you, and thanks for the class suggestion, i'm always open to better ways to do things, i'll check it out
- joel
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Darkmaster006, mikeyww and 339 guests