Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

Edit Control Background Color


  • Please log in to reply
23 replies to this topic
xpace
  • Members
  • 9 posts
  • Last active: Feb 20 2013 06:46 PM
  • Joined: 17 Dec 2010
No suggestions?

I realize this is pretty complex stuff, esp. since it involves DllCall.
But I suspect the problem I have with calling this function twice (it lags badly and nearly times out) is most likely a simple oversight on my part.

xpace
  • Members
  • 9 posts
  • Last active: Feb 20 2013 06:46 PM
  • Joined: 17 Dec 2010
Over a week now and this thread gets buried under other threads.
:( Can anybody help? Please?

Edit:
I finally figured some basics of how DllCall works. And a Goggle search for "SetBkColor" lead me here: MSDN Library After a couple hours of trying to interpret some things on the MSDN Library (a lot of which is over my head) I figured that I needed to add a SetTextColor function.

A bit of trial and error later and I got this code to change the background and foreground colors!
; Example: The following is a working script that demonstrates how to subclass a GUI window by
; redirecting its WindowProc to a new WindowProc in the script. In this case, the background
; color and foreground color of a text control is changed to specified custom colors.

TextBackgroundColor := 0xFFBBBB  ; A custom color in BGR format.
TextForegroundColor := 0x0000FF  ; A custom color in BGR format.
TextBackgroundBrush := DllCall("CreateSolidBrush", UInt, TextBackgroundColor)

Gui, Add, Text, HwndMyTextHwnd, Here is some text that is given`na custom background color
    ,`nand a custom foreground color.
Gui +LastFound
GuiHwnd := WinExist()

WindowProcNew := RegisterCallback("WindowProc", ""  ; Specifies "" to avoid fast-mode for subclassing.
    , 4, MyTextHwnd)  ; Must specify exact ParamCount when EventInfo parameter is present.
WindowProcOld := DllCall("SetWindowLong", UInt, GuiHwnd, Int, -4  ; -4 is GWL_WNDPROC
    , Int, WindowProcNew, UInt)  ; Return value must be set to UInt vs. Int.

Gui Show
return

WindowProc(hwnd, uMsg, wParam, lParam)
{
    Critical
    global TextBackgroundColor, TextBackgroundBrush, WindowProcOld, TextForegroundColor
    if (uMsg = 0x138 && lParam = A_EventInfo)  ; 0x138 is WM_CTLCOLORSTATIC.
    {
        DllCall("SetBkColor", UInt, wParam, UInt, TextBackgroundColor)
        DllCall("SetTextColor", UInt, wParam, UInt, TextForegroundColor)
        return TextBackgroundBrush  ; Return the HBRUSH to notify the OS that we altered the HDC.
    }
    ; Otherwise (since above didn't return), pass all unhandled events to the original WindowProc.
    return DllCall("CallWindowProcA", UInt, WindowProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
}

GuiClose:
ExitApp
So, I managed to solve one of my problems. But I still can't figured out how to change the background & foreground text on more than one line of text by calling this function more than once. Doing so still locks up the script.

Could my problem be that the original script left out something important?

This article on CreateSolidBrush says that:

After it is finished using the brush, the program should use DeleteObject to delete the brush and free up system resources.

And this article says something similar.

I'm afraid that if I want to use this more than once, I might need to rewrite the script to replace the use of CreateSolidBrush with something else. I suspect I may end up having to use the ExtTextOut function instead. Unfortunately, defining the font to use must be unnecessarily complicated because I can't figure that out.

I wonder if this Multicolor Text Strings with Managed Code article on a C# program could help with that?

xpace
  • Members
  • 9 posts
  • Last active: Feb 20 2013 06:46 PM
  • Joined: 17 Dec 2010
Hmm... Nobody with the knowledge to help me has read this thread yet?

Anyway, I've been experimenting around with variations to see if I can get this background/forground text color change script to process more than one line of text.

First, I tried to have the code called in a subroutine:
Gui, Add, Text, HwndMyTextHwnd, Here is some text that is given`na custom background color

Gosub ColorMe

Gui, Add, Text, HwndMyTextHwnd, and a custom foreground color.

Gosub ColorMe

Gui Show
return


ColorMe:
Gui +LastFound 
GuiHwnd := WinExist()

TextBackgroundColor := 0xFFFFFF  ; A custom color in BGR format.
TextForegroundColor := 0x0000FF  ; A custom color in BGR format.
TextBackgroundBrush := DllCall("CreateSolidBrush", UInt, TextBackgroundColor) 

WindowProcNew := RegisterCallback("WindowProc", ""  ; Specifies "" to avoid fast-mode for subclassing.
    , 4, MyTextHwnd)  ; Must specify exact ParamCount when EventInfo parameter is present.
WindowProcOld := DllCall("SetWindowLong", UInt, GuiHwnd, Int, -4  ; -4 is GWL_WNDPROC
    , Int, WindowProcNew, UInt)  ; Return value must be set to UInt vs. Int.

return


WindowProc(hwnd, uMsg, wParam, lParam)
{
    Critical
    global TextBackgroundColor, TextBackgroundBrush, WindowProcOld, TextForegroundColor
    if (uMsg = 0x138 && lParam = A_EventInfo)  ; 0x138 is WM_CTLCOLORSTATIC.
    {
        DllCall("SetBkColor", UInt, wParam, UInt, TextBackgroundColor)
        DllCall("SetTextColor", UInt, wParam, UInt, TextForegroundColor)
        return TextBackgroundBrush  ; Return the HBRUSH to notify the OS that we altered the HDC.
    }
    ; Otherwise (since above didn't return), pass all unhandled events to the original WindowProc.
    return DllCall("CallWindowProcA", UInt, WindowProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
}

GuiClose:
ExitApp
That was another failure. It still locked up.

Then I tried a variation where part of the code was rewritten so it was not an exact duplicate. (Changed the variable and fuction names slightly.)
TextBackgroundColor := 0xFFBBBB  ; A custom color in BGR format.
TextForegroundColor := 0x0000FF  ; A custom color in BGR format.
TextBackgroundBrush := DllCall("CreateSolidBrush", UInt, TextBackgroundColor)

Gui, Add, Text, HwndMyTextHwnd, Here is some text that is given`na custom background color

Gui +LastFound
GuiHwnd := WinExist()

WindowProcNew := RegisterCallback("WindowProc", ""  ; Specifies "" to avoid fast-mode for subclassing. 
    , 4, MyTextHwnd)  ; Must specify exact ParamCount when EventInfo parameter is present. 
WindowProcOld := DllCall("SetWindowLong", UInt, GuiHwnd, Int, -4  ; -4 is GWL_WNDPROC 
    , Int, WindowProcNew, UInt)  ; Return value must be set to UInt vs. Int. 

Gui, Add, Text, HwndAddedTextHwnd, and a custom foreground color.

Gui +LastFound 
GuiHwnd_more := WinExist() 

WindowProcNew_more := RegisterCallback("WindowProc", ""  ; Specifies "" to avoid fast-mode for subclassing. 
    , 4, AddedTextHwnd)  ; Must specify exact ParamCount when EventInfo parameter is present. 
WindowProcOld := DllCall("SetWindowLong", UInt, GuiHwnd_more, Int, -4  ; -4 is GWL_WNDPROC 
    , Int, WindowProcNew_more, UInt)  ; Return value must be set to UInt vs. Int.

Gui Show
return

WindowProc(hwnd, uMsg, wParam, lParam)
{
    Critical
    global TextBackgroundColor, TextBackgroundBrush, WindowProcOld, TextForegroundColor
    if (uMsg = 0x138 && lParam = A_EventInfo)  ; 0x138 is WM_CTLCOLORSTATIC.
    {
        DllCall("SetBkColor", UInt, wParam, UInt, TextBackgroundColor)
        DllCall("SetTextColor", UInt, wParam, UInt, TextForegroundColor)
        return TextBackgroundBrush  ; Return the HBRUSH to notify the OS that we altered the HDC.
    }
    ; Otherwise (since above didn't return), pass all unhandled events to the original WindowProc.
    return DllCall("CallWindowProcA", UInt, WindowProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
}

GuiClose:
ExitApp
Nope. Another failure, another lock-up.
I'm running out of ideas here. And I really wanted to finish my project...

Sjc1000
  • Members
  • 572 posts
  • Last active: Mar 11 2017 11:41 AM
  • Joined: 06 Feb 2012
Um.. Is this to hard
Gui, Color, , Red
Gui, Add, Edit, w300 -Background
Gui, Add, Edit, w300
Gui, Show

Sjc1000 - Insert inspirational quote here!

PLEASE find me on the IRC if you have questions. I'm never on the forum anymore.

 


tomoe_uehara
  • Members
  • 2166 posts
  • Last active: Jun 11 2015 05:33 PM
  • Joined: 05 Sep 2009
Actually, what are you trying to achieve? If you provide a screenshot of what you're trying to achieve, it will be easier for us to understand.

jNizM
  • Members
  • 928 posts
  • Last active: Jan 12 2018 09:23 AM
  • Joined: 01 Aug 2012
wont with ReadOnly:
Gui, Color, , Red
Gui, Add, Edit, w300 -Background
Gui, Add, Edit, w300
Gui, Add, Edit, w300 ReadOnly
Gui, Show

[AHK] 1.1.27.04 x64 Unicode | [WIN] 10 Pro (Version 1709)
My GitHub Profile | Donations are appreciated if I could help you

sturmprophet
  • Members
  • 4 posts
  • Last active: Nov 01 2019 10:41 PM
  • Joined: 26 May 2014

You need to subclass the control. There is an example shown in AHK Doc under RegisterCallback() that shows how to subclass a Text control.
I have minimally adapted it for Edit control.
 

Spoiler

Edit: Line feed inserted before Gui+LastFound .. Thanks to Slanter


Is there a way to change the background color for a disabled editcontrol?

jNizM
  • Members
  • 928 posts
  • Last active: Jan 12 2018 09:23 AM
  • Joined: 01 Aug 2012
#Warn
#SingleInstance Force

global BkColor   := 0x5F67FA    ; Background Color | BGR (BLUE - GREEN - RED)
global TxColor   := 0xFFFFFF    ; Text Color       | BGR (BLUE - GREEN - RED)

OnMessage(0x0138, "WM_CTLCOLOR")    ; WM_CTLCOLORSTATIC
;OnMessage(0x0133, "WM_CTLCOLOR")    ; WM_CTLCOLOREDIT

Gui, Add, Edit, w100,          ReadWrite
Gui, Add, Edit, w100 ReadOnly, ReadOnly
Gui, Add, Edit, w100,          ReadWrite
Gui, Add, Edit, w100 ReadOnly, ReadOnly
Gui, Show
Gui, +LastFound
WinSet, Redraw
return

WM_CTLCOLOR(wParam, lParam, hwnd)
{
    static hBrush := ""
    if (hBrush = "")
        SetEnv, hBrush, % DllCall("Gdi32.dll\CreateSolidBrush", "UInt", BkColor, "UPtr")

    WinGetClass, Class, ahk_id %lParam%

    if (Class = "Edit")
    {
        DllCall("gdi32.dll\SetTextColor", "Ptr", wParam, "UInt", TxColor)
        , DllCall("gdi32.dll\SetBkColor", "Ptr", wParam, "UInt", BkColor)
        , DllCall("gdi32.dll\SetBkMode", "Ptr", wParam, "Int", 2)
        return hBrush
    }
    if (Class = "Static")
        DllCall("gdi32.dll\SetTextColor", "Ptr", wParam, "UInt", TxColor)
}

[AHK] 1.1.27.04 x64 Unicode | [WIN] 10 Pro (Version 1709)
My GitHub Profile | Donations are appreciated if I could help you

sturmprophet
  • Members
  • 4 posts
  • Last active: Nov 01 2019 10:41 PM
  • Joined: 26 May 2014
Spoiler


Damn, sry for the late reply. I've completly lost this topic sad.png

jNizM, unfortunatly i do really need the 'Disabled' option for an editcontrol in that particular case. Using your code only recolors the background color for an disabled, readonly editcontrol. (Ofcurse even this is better than nothing ^^)
But maybe you also know a way to get this working with the 'disabled' option active.

Thanks in advance!