"ControlSetText" and "Control, EditPaste" Only Pasting One Letter

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
ViewtifulDom
Posts: 12
Joined: 07 Oct 2017, 23:28

"ControlSetText" and "Control, EditPaste" Only Pasting One Letter

21 Oct 2017, 18:38

I'm trying to create a hotkey that sends a string of text to the current application. Here's what I've tried so far.

Code: Select all

f1:: Send, This is a test.
It works, but I'd like to find a solution that pastes the entire string instantly, rather than type it out.

Code: Select all

f1::
	save_clip = %ClipboardAll%
	Clipboard := "This is also a test."
	Send, {Control down}v{Control up}
	Clipboard = %save_clip%
	return
This also works, but it still discards important data from copied images (e.g., the image's original position when it was copied).

Code: Select all

f1:: Control, EditPaste, This is another test, Scintilla1, ahk_class Notepad++

Code: Select all

f1:: ControlSetText, Scintilla1, This is yet an additional test, ahk_class Notepad++
These methods both only produce the first character in the string, (in this case 'T', ) when used in Notepad++. However, it does seem to work in Notepad without issue.

Nothing seems to work without taking too long or compromising the clipboard contents. If anyone has any insight on a method I haven't discovered yet, or can tell me what I'm doing wrong with the aforementioned methods, it would be greatly appreciated.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: "ControlSetText" and "Control, EditPaste" Only Pasting One Letter

21 Oct 2017, 18:48

I've been working on various functions for getting/setting the text of controls. And Scintilla is one of them, so here's a sneak peek of my functions:

I might replace the JEE_DC functions with DllCall when I'm finished.

Functions such as these that deal with remote buffers in external processes, should be used with caution as they could potentially crash the process.

Code: Select all

q:: ;Scintilla control - get/set text (works with Notepad2 and Notepad++)
ControlGet, hSci, Hwnd,, Scintilla1, A
MsgBox, % JEE_SciGetText(hSci)
JEE_SciSetText(hSci, "hello world")
return

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

;JEE_ScintillaGetText
;options:
;a - read as ANSI
JEE_SciGetText(hCtl, vOpt:="")
{
	vScriptPID := DllCall("kernel32\GetCurrentProcessId", UInt)
	WinGet, vPID, PID, % "ahk_id " hCtl
	if (vPID = vScriptPID)
		vIsLocal := 1, vPIs64 := (A_PtrSize=8)

	SendMessage, 2006, 0, 0,, % "ahk_id " hCtl ;SCI_GETLENGTH := 2006 ;returns size of UTF-8 buffer in bytes (not chars)
	vSize := ErrorLevel+1
	VarSetCapacity(vText, vSize, 0)

	if vIsLocal
		SendMessage, 2182, % vSize, % &vText,, % "ahk_id " hCtl ;SCI_GETTEXT := 2182
	else
	{
		if !hProc := JEE_DCOpenProcess(0x438, 0, vPID)
			return
		if !pBuf := JEE_DCVirtualAllocEx(hProc, 0, vSize, 0x3000, 0x4)
			return
		SendMessage, 2182, % vSize, % pBuf,, % "ahk_id " hCtl ;SCI_GETTEXT := 2182
		JEE_DCReadProcessMemory(hProc, pBuf, &vText, vSize, 0)
		JEE_DCVirtualFreeEx(hProc, pBuf, 0, 0x8000)
		JEE_DCCloseHandle(hProc)
	}
	return StrGet(&vText, InStr(vOpt, "a")?"CP0":"UTF-8")
}

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

;JEE_ScintillaSetText
JEE_SciSetText(hCtl, vText)
{
	vScriptPID := DllCall("kernel32\GetCurrentProcessId", UInt)
	WinGet, vPID, PID, % "ahk_id " hCtl
	if (vPID = vScriptPID)
		vIsLocal := 1, vPIs64 := (A_PtrSize=8)

	vSize := StrPut(vText, "UTF-8")
	vOutput := ""
	VarSetCapacity(vOutput, vSize, 0)
	StrPut(vText, &vOutput, "UTF-8")

	if vIsLocal
		SendMessage, 2181,, % &vOutput,, % "ahk_id " hCtl ;SCI_SETTEXT := 2181
	else
	{
		if !hProc := JEE_DCOpenProcess(0x438, 0, vPID)
			return
		if !pBuf := JEE_DCVirtualAllocEx(hProc, 0, vSize, 0x3000, 0x4)
			return
		JEE_DCWriteProcessMemory(hProc, pBuf, &vOutput, vSize, 0)
		SendMessage, 2181,, % pBuf,, % "ahk_id " hCtl ;SCI_SETTEXT := 2181
		JEE_DCVirtualFreeEx(hProc, pBuf, 0, 0x8000)
		JEE_DCCloseHandle(hProc)
	}
}

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

JEE_DCOpenProcess(vAccess, hInherit, vPID)
{
	return DllCall("kernel32\OpenProcess", UInt,vAccess, Int,hInherit, UInt,vPID, Ptr)
}
JEE_DCVirtualAllocEx(hProc, vAddress, vSize, vAllocType, vProtect)
{
	return DllCall("kernel32\VirtualAllocEx", Ptr,hProc, Ptr,vAddress, UPtr,vSize, UInt,vAllocType, UInt,vProtect, Ptr)
}
JEE_DCWriteProcessMemory(hProc, vBAddress, pBuf, vSize, vWritten)
{
	return DllCall("kernel32\WriteProcessMemory", Ptr,hProc, Ptr,vBAddress, Ptr,pBuf, UPtr,vSize, Ptr,vWritten)
}
JEE_DCReadProcessMemory(hProc, vBAddress, pBuf, vSize, vRead)
{
	return DllCall("kernel32\ReadProcessMemory", Ptr,hProc, Ptr,vBAddress, Ptr,pBuf, UPtr,vSize, Ptr,vRead)
}
JEE_DCVirtualFreeEx(hProc, vAddress, vSize, vFreeType)
{
	return DllCall("kernel32\VirtualFreeEx", Ptr,hProc, Ptr,vAddress, UPtr,vSize, UInt,vFreeType)
}
JEE_DCCloseHandle(hObject) ;e.g. hProc
{
	return DllCall("kernel32\CloseHandle", Ptr,hObject)
}

;==================================================
ControlSetText and Control EditPaste are not guaranteed to work correctly on all controls.

When things happen where only one character is inserted into a control can often be related to Unicode/ANSI issues. I.e. you have an ANSI control, you try to put Unicode text into it, the Unicode text 'abc' in byte form is: a null b null c null. And so the control sees the string a, as ANSI strings terminate at the first null byte.
Last edited by jeeswg on 22 Oct 2017, 01:19, edited 5 times in total.
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: "ControlSetText" and "Control, EditPaste" Only Pasting One Letter

21 Oct 2017, 19:07

Based on your results with ControlSetText, I considered a different, relatively simple approach.

Code: Select all

q:: ;Scintilla control - get text (works with Notepad2 and Notepad++)
ControlGetText, vText, Scintilla1, A
MsgBox, % StrGet(&vText, "UTF-8") ;works with Notepad2
MsgBox, % vText ;works with Notepad++
return

w:: ;Scintilla control - set text (works with Notepad2 and Notepad++)
vText := "hello world"
vSize := StrPut(vText, "UTF-8") + 2
VarSetCapacity(vUtf8, vSize, 0)
StrPut(vText, &vUtf8, "UTF-8")
ControlSetText, Scintilla1, % vUtf8, A
return

e:: ;Scintilla control - edit paste (works with Notepad2 and Notepad++)
vText := "hello world"
vSize := StrPut(vText, "UTF-8") + 2
VarSetCapacity(vUtf8, vSize, 0)
StrPut(vText, &vUtf8, "UTF-8")
Control, EditPaste, % vUtf8, Scintilla1, A
return
[EDIT: It says this is the 1000th thread I've been in.]
Last edited by jeeswg on 21 Oct 2017, 22:28, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
ViewtifulDom
Posts: 12
Joined: 07 Oct 2017, 23:28

Re: "ControlSetText" and "Control, EditPaste" Only Pasting One Letter

21 Oct 2017, 21:23

Thanks jeeswg. Your first post is a little over my head, I've got some more research to do before that will work for me - but it DOES work when I copy and paste it. Your second post, not so much, I couldn't get that one to work, in fact the 'q' command gives me only the first character like my own attempts.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: "ControlSetText" and "Control, EditPaste" Only Pasting One Letter

21 Oct 2017, 22:37

For my JEE_SciGetText / JEE_SciSetText example, the functions are both working in Notepad2/Notepad++.
I've fixed JEE_SciSetText which was truncating some strings.

For the ControlGetText/ControlSetText/EditPaste examples, all three are working in Notepad2/Notepad++.
I added a line for the ControlGetText example which works with Notepad++.

So at least on my end, everything is now working fine. Cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
ViewtifulDom
Posts: 12
Joined: 07 Oct 2017, 23:28

Re: "ControlSetText" and "Control, EditPaste" Only Pasting One Letter

22 Oct 2017, 02:11

So at least on my end, everything is now working fine. Cheers.
My bad, I didn't paste all of it correctly. It worked, and I'm going to study it. Thank you very much!
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: "ControlSetText" and "Control, EditPaste" Only Pasting One Letter

22 Oct 2017, 04:28

For me this works also:

Code: Select all

SCI_GETCODEPAGE := 2137, SCI_GETLENGTH := 2006, WM_GETTEXT := 0xD
; to set the text
$F1::
   text := "This is yet an additional test"
   WinWait, ahk_class Notepad++
   SendMessage, SCI_GETCODEPAGE,,, Scintilla1
   copePage := ErrorLevel
   VarSetCapacity(var, StrPut(text, "cp" . copePage) << (copePage = 1200), 0)
   StrPut(text, &var, "cp" . copePage)
   VarSetCapacity(var, -1)
   ControlSetText, Scintilla1, % var
   Return
; to get the text   
$F2::
   WinWait, ahk_class ahk_class Notepad++
   SendMessage, SCI_GETLENGTH,,, Scintilla1
   length := ErrorLevel + 1
   VarSetCapacity(buff, length << !!A_IsUnicode, 0)
   SendMessage, WM_GETTEXT, length, &buff, Scintilla1
   MsgBox, % text := StrGet(&buff)
   Return

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], RandomBoy and 233 guests