SetWindowText and Edit controls Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

SetWindowText and Edit controls

14 Oct 2017, 02:36

The proper way to set the text of Edit controls is to use WM_SETTEXT.

However I tested SetWindowText on the Edit control on Notepad, and although it didn't set the text, when I subsequently did GetWindowText, it returned the text that I had set with SetWindowText. Where is this text being stored?

Note: when I manually change the visible text, it does not affect the Get/SetWindowText text.
Note: when I reload the script, it does not affect the Get/SetWindowText text.
Note: when I apply Get/SetWindowText text to an internal AHK GUI window it does get/set the text. (The MSDN articles for the 2 functions say you can use them on internal windows but you are not supposed to use them on external windows.)

This is potentially useful, if an Edit control can have in effect two separate buffers for storing text consistently. You can store additional information there.

Code: Select all

q::
WinGet, hWnd, ID, A
ControlGet, hWnd, Hwnd,, Static1, A
ControlGet, hWnd, Hwnd,, Edit1, A

vChars := DllCall("user32\GetWindowTextLength", Ptr,hWnd) + 1
VarSetCapacity(vText, vChars*2, 0)
DllCall("user32\GetWindowText", Ptr,hWnd, Str,vText, Int,vChars)
MsgBox, % vText

vText := "hello"
DllCall("user32\SetWindowText", Ptr,hWnd, Str,vText)

;needed for Static controls
WinSet, Redraw,, % "ahk_id " hWnd
return

w::
Gui, New, +HwndhGui, MyWinTitle
Gui, Add, Edit
Gui, Show
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: SetWindowText and Edit controls

14 Oct 2017, 08:06

Cheers just me, I thought if anyone knew, it might be you. Haha in the article they actually call this second text buffer simply a 'special place'. It's great to have some confirmation of the existence of a second buffer. I'd actually saved this article before, but it's far more meaningful this time.

I'll mark this is as solved, although any further details beyond a 'special place' would be welcome. Not that I'm expecting any.

Since Edit controls have two text storage locations, you can store 'secret' text in any Edit control you like. Curiously enough though, if the Edit control belongs to your process, AFAIK you would need a workaround, which is what I have done in the two functions below.

I would use this text buffer as a handy place to store text, when communicating between scripts. I might use the Edit control's text itself, but AutoHotkey can change that text, e.g. when you want to list variables, so to store it in a 'special place' is safer.

Code: Select all

q:: ;Edit control - set 'special place' text
ControlGet, hCtl, Hwnd,, Edit1, A
WinGet, vPID, PID, % "ahk_id " hCtl
vText := "hello " vPID
JEE_EditSetTextSpecialPlace(hCtl, vText)
return

w:: ;Edit control - get 'special place' text
ControlGet, hCtl, Hwnd,, Edit1, A
MsgBox, % JEE_EditGetTextSpecialPlace(hCtl)
return

;==================================================

;q:: ;AutoHotkey main window - set 'special place' text
DetectHiddenWindows, On
ControlGet, hCtl, Hwnd,, Edit1, % "ahk_id " A_ScriptHwnd
WinGet, vPID, PID, % "ahk_id " hCtl
vText := "hello " vPID
JEE_EditSetTextSpecialPlace(hCtl, vText)
return

;w:: ;AutoHotkey main window - get 'special place' text
DetectHiddenWindows, On
ControlGet, hCtl, Hwnd,, Edit1, % "ahk_id " A_ScriptHwnd
MsgBox, % JEE_EditGetTextSpecialPlace(hCtl)
return

;==================================================

;The secret life of GetWindowText – The Old New Thing
;https://blogs.msdn.microsoft.com/oldnewthing/20030821-00/?p=42833

JEE_EditGetTextSpecialPlace(hCtl)
{
	static vScriptPID := DllCall("kernel32\GetCurrentProcessId", UInt)
	DllCall("user32\GetWindowThreadProcessId", Ptr,hCtl, UIntP,vPID, UInt)
	if !(vPID = vScriptPID)
	{
		vChars := DllCall("user32\GetWindowTextLength", Ptr,hCtl) + 1
		VarSetCapacity(vText, vChars*2, 0)
		DllCall("user32\GetWindowText", Ptr,hCtl, Str,vText, Int,vChars)
		return vText
	}
	vScript .= "vChars := DllCall(" Chr(34) "user32\GetWindowTextLength" Chr(34) ", Ptr," hCtl ") + 1"
	vScript .= "`r`n" "VarSetCapacity(vText, vChars*2, 0)"
	vScript .= "`r`n" "DllCall(" Chr(34) "user32\GetWindowText" Chr(34) ", Ptr," hCtl ", Str,vText, Int,vChars)"
	vScript .= "`r`n" "FileAppend, % vText, *"

	oShell := ComObjCreate("WScript.Shell")
	oExec := oShell.Exec(Chr(34) A_AhkPath Chr(34) " /ErrorStdOut *")
	oExec.StdIn.Write(vScript)
	oExec.StdIn.Close()
	vStdOut := oExec.StdOut.ReadAll()
	oShell := oExec := ""
	return vStdOut
}

;==================================================

JEE_EditSetTextSpecialPlace(hCtl, vText)
{
	static vScriptPID := DllCall("kernel32\GetCurrentProcessId", UInt)
	DllCall("user32\GetWindowThreadProcessId", Ptr,hCtl, UIntP,vPID, UInt)
	if !(vPID = vScriptPID)
	{
		DllCall("user32\SetWindowText", Ptr,hCtl, Str,vText)
		return
	}
	vText := StrReplace(vText, "``", "````")
	vText := StrReplace(vText, "`r", "``r")
	vText := StrReplace(vText, "`n", "``n")
	if !!SubStr(1,0) ;vIsV1
		vText := StrReplace(vText, Chr(34), Chr(34) Chr(34))
	else
		vText := StrReplace(vText, Chr(34), "``" Chr(34))
	vScript := "DllCall(" Chr(34) "user32\SetWindowText" Chr(34) ", Ptr," hCtl ", Str," Chr(34) vText Chr(34) ")"

	oShell := ComObjCreate("WScript.Shell")
	oExec := oShell.Exec(Chr(34) A_AhkPath Chr(34) " /ErrorStdOut *")
	oExec.StdIn.Write(vScript)
	oExec.StdIn.Close()
	oShell := oExec := ""
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
just me
Posts: 9458
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: SetWindowText and Edit controls

14 Oct 2017, 10:01

FYI:
SetTitleMatchMode wrote:Fast|Slow

One of the following words to specify how the WinText and ExcludeText parameters should be matched:

Fast: This is the default behavior. Performance may be substantially better than Slow, but certain types of controls are not detected. For instance, text is typically detected within Static and Button controls, but not Edit controls, unless they are owned by the script.

Slow: Can be much slower, but works with all controls which respond to the WM_GETTEXT message.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: SetWindowText and Edit controls

14 Oct 2017, 10:57

Thank you, I'm not sure if you had a specific point in mind, because there are quite a few conclusions you can draw from this.
- Fast mode would detect text in an Edit control's 'special place'.
- Fast mode uses GetWindowText, which is mainly used for getting the text of window titles, but which can also get the text from some controls.
- Slow mode uses WM_GETTEXT, which is used for getting the text of Edit controls and several/many other controls.

I almost never use WinText / TextExclude, I did for #32770 windows, but then when ahk_exe was added, I didn't really need them any more.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 314 guests