AHK text control color word

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

AHK text control color word

05 Dec 2020, 20:24

Hello, is it possible to change the color of just one word in an AHK GUi text control? Thanks.
User avatar
mikeyww
Posts: 27169
Joined: 09 Sep 2014, 18:38

Re: AHK text control color word

05 Dec 2020, 21:31

Code: Select all

string = This is one sentence.
color := {one: "Blue", This: "Red"}
Gui, Font, s10
Loop % (word := StrSplit(string, A_Space)).Count() {
 wordNum := A_Index, textColor := "Black"
 For thisWord, thisColor in color
  textColor := word[wordNum] = thisWord ? thisColor : textColor
 Gui, Add, Text, x+4 y5 c%textColor%, % word[A_Index]
}
Gui, Show,, Words
Return

GuiEscape:
GuiClose:
ExitApp
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: AHK text control color word

06 Dec 2020, 06:03

Thanks very much for the code, mikeyww. That an interesting idea. It's not strictly one control, though. I have some text that I display and then later want to change the colour of one word. It might be doable. I'll need to calculate the width of a space so the layout won't change when I rebuild the string. Wrapping is going to be another issue, but you've given me an idea to work with. Thanks again.
teadrinker
Posts: 4364
Joined: 29 Mar 2015, 09:41
Contact:

Re: AHK text control color word

06 Dec 2020, 07:03

Code: Select all

html =
(
<style>
   body {
      font-family: calibri;
      font-size: 28px;
   }
   .red {
      color: red;
   }
   .blue {
      color: blue;
   }
</style>
<body>
   <span class="red">Hello, </span>
   <span class="blue">World!</span><br>
   <span class="red">I love </span>
   <span class="blue">AutoHotkey!</span>
</body>
)

Gui, -DPIScale
Gui, Margin, 0, 0
Gui, Add, ActiveX, vText w300 h100, htmlfile
Text.write(html)
Gui, Show
Return

GuiClose:
   ExitApp
User avatar
mikeyww
Posts: 27169
Joined: 09 Sep 2014, 18:38

Re: AHK text control color word

06 Dec 2020, 08:38

I know, I cheated. :) I love @teadrinker's answer!
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: AHK text control color word

06 Dec 2020, 13:41

RTF control is another option its similar to a edit control if thats what you are looking for.
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: AHK text control color word

06 Dec 2020, 19:50

Thanks, teadrinker, thats' fantastic. I was able to get your code working in my project. One problem I've noticed is with fontsize. The same size for regular text controls gives larger text than the activex control despite using -dpiscale. I can make it larger but then the descenders start disappearing as the vertical height is created using the height of a regular text control. Does anyone know how to get a uniform size?

This is for a fill in the gap type exercise. I'm showing the regular text control and then hiding it and showing the activex control - they both have the almost the same text except for the gap in the first and the colored answer in the second.
User avatar
mikeyww
Posts: 27169
Joined: 09 Sep 2014, 18:38

Re: AHK text control color word

06 Dec 2020, 19:55

I guess it depends what you mean by "uniform size". Using points actually does get you a uniform size (at least in principle, in HTML), but I'm not sure whether it would have a desired effect, or an opposite one, in AHK or your application! Maybe worth trying to see.

Points = pixels * 72 / dpi

Code: Select all

   body {
      font-family: calibri;
      font-size: 12pt;
   }
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: AHK text control color word

06 Dec 2020, 20:02

Of course! I never use pixels when writing web pages. Thanks mikeyww for pointing that out (half a pun intended). I tried your idea and it worked. The difference now is almost negligible. I really appreciate the time you and teadrinker must have taken with this. Thanks again.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: AHK text control color word

07 Dec 2020, 02:47

With one gui text control and GDIP.

Code: Select all

;***************************************************************************************************
#Include <My Altered Gdip Lib>  ;<------       Replace with your copy of GDIP
;***************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
Token := Gdip_Startup()
OnExit, GuiClose
Needle := {"interesting":"0xFF00FFFF","Work":"0xFFFF0000","calculate":"0xFFFF00FF","Wrapping":"0xFFE4BD0F","cheated.":"0xFFFF0000","answer!":"0xFFF5098E","RTF":"0xFF880000","another":"0xFFFFFFFF","edit":"0xFFE923BF"}
text1 =
(Join
	Thanks very much for the code, mikeyww. That an interesting idea. It's not strictly one control, though. I have some text that I display and then 
	 `n later want to change the colour of one word. It might be doable. I'll need to calculate the width of a space so the layout won't change when I 
	 `n rebuild the string. Wrapping is going to be another issue, but you've given me an idea to work with. Thanks again.
)
text2 :="I know, I cheated. :) I love @teadrinker's answer!"
text3 := "RTF control is another option `n its similar to a edit control if thats what you are looking for."
Gui,1:+AlwaysOnTop
Gui,1:Color,335588
Gui,1:Margin,30,50

BackgroundColor := 0xFF000000, Width:=900, Height:=50
Gui,1:Add,Text,xm ym w%Width% h%Height% 0xE hwndCtrlHWND
AddText(Needle, Hwnd := CtrlHWND, Text1  ,DefaultColor:="0xFFFFFFFF",Font:="Arial",FontSize:="s12 Bold",Width,Height,BackgroundColor)

BackgroundColor := 0xFFFFFF00, Width:=700, Height:=30
Gui,1:Add,Text,xm w%Width% h%Height% 0xE hwndCtrlHWND
AddText(Needle, Hwnd := CtrlHWND, Text2  ,DefaultColor:="0xFF000000",Font:="Arial",FontSize:="s26 Bold",Width,Height,BackgroundColor)

BackgroundColor := "0xFFFFFFFF", Width:=800, Height:=50
Gui,1:Add,Text,xm w%Width% h%Height% 0xE hwndCtrlHWND
AddText(Needle, Hwnd := CtrlHWND, Text1  ,DefaultColor:="0xFF000000",Font:="Segoe UI",FontSize:="s10 Bold",Width,Height,BackgroundColor)

BackgroundColor := 0xFF00FF00, Width:=700, Height:=50
Gui,1:Add,Text,xm w%Width% h%Height% 0xE hwndCtrlHWND
AddText(Needle, Hwnd := CtrlHWND, Text3  ,DefaultColor:="0xFF000000",Font:="Arial",FontSize:="s20 Bold",Width,Height,BackgroundColor)

Gui,1:Show,,(:  -_-     Multi Color Text Controls     -_-  :)
return
GuiClose:
GuiContextMenu:
*ESC::
	Gdip_Shutdown(Token)
	ExitApp

AddText(Needle,Hwnd,String,DefaultColor:="0xFF235689",Font:="Arial",FontSize:="s12 Bold",w:=50,h:= 50,BackgroundColor:=""){
	pBitmap:=Gdip_CreateBitmap( w , h ), G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
	if(BackgroundColor)
		Brush := Gdip_BrushCreateSolid( BackgroundColor ), Gdip_FillRectangle(G, Brush, -1, -1, w+2, h+2), Gdip_DeleteBrush( Brush )
	Arr := StrSplit(String," "), Position := 0, Y:=0 
	Loop,% Arr.Length(){
		Gui,FakeGui:Font,%FontSize%, % Font
		Gui,FakeGui:Add,Text,hwndtemphwnd,% Arr[A_Index]
		GuiControlGet,pos,FakeGui:pos,% temphwnd
		Gui,FakeGui:Destroy
		if(Arr[A_Index]="`n")
			Arr[A_Index] := "", Y+=PosH//2.5, Position:=0
		Brush := Gdip_BrushCreateSolid( (Needle.HasKey(Arr[A_Index]))?(Needle[Arr[A_Index]]):(DefaultColor) )
		Position+= StrSplit( Gdip_TextToGraphics( G , Arr[A_Index] , FontSize " c" Brush " Left NoWrap x" Position " y" Y , Font , PosW+5, PosH  ),"|","|"  )[3]
		Gdip_DeleteBrush( Brush )
	}
	Gdip_DeleteGraphics( G ), hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap), Gdip_DisposeImage(pBitmap), SetImage( Hwnd , hBitmap ), DeleteObject(hBitmap)
}

Spoiler
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: AHK text control color word

07 Jan 2022, 21:53

Thanks very much for the alternative, HellBent. I've tried many times in the past to get Gdip to work but whenever I've included it I got an error message saying it could not be opened. I finally figured out that I have to include the complete path to Gdip even when it is in the same folder:

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
SetBatchLines, -1

#include myfileinthesamedirectory.ahk ; no error
#Include Gdip_All.ahk ;Gives an error message
#Include %A_ScriptDir%\Gdip_All.ahk ;works!

After playing around with the code I've found that one advantage of using Gdip is that is possible to make the background of the text transparent. I can't find a way to do that with the html approach. The disadvantage though is working out how to wrap the text when dealing with multiple lines. I'm going to keep looking at your method and try to find a way to deal with wrapping. Thanks again.
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: AHK text control color word

20 Nov 2023, 02:06

I'm still trying to find a method for changing the color of a single word in a text control. Can the RichEdit class be used for a text control or is it only for an edit control? The Rich Edit demo is amazing but are there any examples of how to change the color of a single word. Thanks.
User avatar
PuzzledGreatly
Posts: 1303
Joined: 29 Sep 2013, 22:18

Re: AHK text control color word

21 Nov 2023, 23:50

I'm now trying to use a modified version of Hellbent's example:

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
;#Warn  ; Recommended for catching common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
SetBatchLines, -1
#SingleInstance force

;***************************************************************************************************
#Include D:\AHK Files\GdIp_All.ahk
;***************************************************************************************************

Token := Gdip_Startup()
OnExit, GuiClose
answer := "another"
Needle := {(answer):"0xFF0196fd"}

txt := "RTF control is another option it's similar to an edit control if that's` what you are looking for."
Gui,Game:New, -Caption +HwndWise -dpiscale +E0x02000000 +E0x00080000
Gui,Game:+AlwaysOnTop
Gui,Game:Color,335588
Gui,Game:Margin,40,40
Gui,Game:font, s44, Arial

Gui,Game:Add,Text,vcue -background w500, % txt
Gui,Game:Add,Text,0xE hwndCtrlHWND vdue -background w500, % txt
Guicontrolget, cue, game:pos

AddText(Needle, CtrlHWND, txt  ,"0xFF000000","Arial","s44",cuew,cueh)

Gui,Game:Show,,Text test

return
GuiClose:
GuiContextMenu:
*ESC::
	Gdip_Shutdown(Token)
	ExitApp
	
AddText(Needle,Hwnd,String,DefaultColor:="0xFF235689",Font:="Arial",FontSize:="s12 Bold",w:=50,h:= 50,BackgroundColor:="")
{
	pBitmap:=Gdip_CreateBitmap( w , h ), G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
	if(BackgroundColor)
		Brush := Gdip_BrushCreateSolid( BackgroundColor ), Gdip_FillRectangle(G, Brush, -1, -1, w+2, h+2), Gdip_DeleteBrush( Brush )
	
	msgbox, 4096, FontSize, % fontsize
	
	arr := [], testx := 0, Position := 0, Y:=0 
	
	loop, parse, string, % A_space
	{
		agap := tempx := 0 ? "" : A_space
		Gui,addtext:Font,%FontSize%, % Font
		Gui,addtext:add, text, hwndtemp x%testx%, % agap A_loopField
		Guicontrolget, pos, addtext:pos, % temp
	
		if (testx + posw >= w)
		Arr.push("`n", A_loopField), testx := 0
		else
		Arr.push(A_loopField), testx := testx + posw	
	}

	msgbox, 4096, FontSize, % fontsize
	Loop,% Arr.Length()
	{
		Gui,FakeGui:Font,%FontSize%, % Font
		Gui,FakeGui:Add,Text,hwndfake,% Arr[A_Index]
		GuiControlGet,pos,FakeGui:pos,% fake
		Gui,FakeGui:Destroy
		if(Arr[A_Index]="`n")
			Arr[A_Index] := "", Y+=PosH//2.5, Position:=0
		Brush := Gdip_BrushCreateSolid( (Needle.HasKey(Arr[A_Index]))?(Needle[Arr[A_Index]]):(DefaultColor) )
		Position+= StrSplit( Gdip_TextToGraphics( G , Arr[A_Index] , FontSize " c" Brush " Left NoWrap x" Position " y" Y , Font , PosW+5, PosH  ),"|","|"  )[3]
		Gdip_DeleteBrush( Brush )
	}
	Gdip_DeleteGraphics( G ), hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap), Gdip_DisposeImage(pBitmap), SetImg( Hwnd , hBitmap ), DeleteObject(hBitmap)
}	

; AddText(Needle,Hwnd,String,DefaultColor:="0xFF235689",Font:="Arial",FontSize:="s12 Bold",w:=50,h:= 50,BackgroundColor:="")
; {
	; pBitmap:=Gdip_CreateBitmap( w , h ), G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
	
	; if(BackgroundColor)
	; Brush := Gdip_BrushCreateSolid( BackgroundColor ), Gdip_FillRectangle(G, Brush, -1, -1, w+2, h+2), Gdip_DeleteBrush( Brush )
	
	; Arr := StrSplit(String," "), Position := 0, Y:=0 
	; msgbox, 4096, Arr, % Astr(Arr)
	
	; Loop,% Arr.Length(){
		; Gui,FakeGui:Font,%FontSize%, % Font
		; Gui,FakeGui:Add,Text,hwndtemphwnd,% Arr[A_Index]
		; GuiControlGet,pos,FakeGui:pos,% temphwnd
		; Gui,FakeGui:Destroy
		; if(Arr[A_Index]="`n")
			; Arr[A_Index] := "", Y+=PosH//2.5, Position:=0
		; Brush := Gdip_BrushCreateSolid( (Needle.HasKey(Arr[A_Index]))?(Needle[Arr[A_Index]]):(DefaultColor) )
		; Position+= StrSplit( Gdip_TextToGraphics( G , Arr[A_Index] , FontSize " c" Brush " Left NoWrap x" Position " y" Y , Font , PosW+5, PosH  ),"|","|"  )[3]
		; Gdip_DeleteBrush( Brush )
	; }
	; Gdip_DeleteGraphics( G ), hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap), Gdip_DisposeImage(pBitmap), SetImg( Hwnd , hBitmap ), DeleteObject(hBitmap)
; }

Astr(a,ax:="`n",i:="")
{
	static k, v
	str := ""
	for k,v in a 
	if k is digit
	str .= v ax
	else
	str .= A_index = a.count() ? k ":" v : k ":" v ax

	if Regexmatch(i, "\d|U")
	sort, str, D%ax%
	if instr(i, ":")
	str := strReplace(str,":"), str := Regexreplace(str, "(\bzoc\d)\d*\?","$1?",,1)
	return str
}
I can't figure out why the the regular text control and the bitmap text control are displaying differently. The bitmap's font seems a different size and letters are missing:

Display Test.png
Display Test.png (30.95 KiB) Viewed 581 times

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot], Borthar, Descolada, erotoman and 117 guests