Page 1 of 1
SCI_REPLACESEL for Notepad++
Posted: 10 Mar 2019, 14:07
by toralf
I would like to replace the selction in notepad++ with a text.
Code: Select all
SCI_REPLACESEL(text){ ;2170
; SCI_REPLACESEL(<unused>, const char *text)
; The currently selected text between the anchor and the current position is replaced by the 0 terminated text string. If the anchor and current position are the same, the text is inserted at the caret position. The caret is positioned after the inserted text and the caret is scrolled into view.
DllCall("SendMessage", "Ptr", SCI_HWND(), "UInt", 2170, "Int", 0, "Ptr", &text)
}
Nppm_HWND(Title := "Notepad++"){
return DllCall("FindWindow", "Str", Title, "Int", 0, "Ptr")
}
SCI_HWND(){
ControlGet hSci, Hwnd,, Scintilla1, % "ahk_id" Nppm_HWND()
Return hSci
}
unfortunately this doesn't work.
Any help or hint?
Re: SCI_REPLACESEL for Notepad++
Posted: 10 Mar 2019, 14:19
by toralf
It does work when i send numbers
Code: Select all
SCI_GotoLine(Line){
DllCall("SendMessage", "Ptr", SCI_HWND(), "UInt", 2024 , "Int", Line - 1, "Int", 0)
}
SCI_GOTOPOS(Pos){
DllCall("SendMessage", "Ptr", SCI_HWND(), "UInt", 2025 , "Int", Pos, "Int", 0)
}
Re: SCI_REPLACESEL for Notepad++
Posted: 10 Mar 2019, 14:33
by jeeswg
- I have some Scintilla control functions, here:
GUIs via DllCall: text functions (get/set internal/external control text) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- Sometimes, to put text into external processes, you have to use WriteProcessMemory etc.
Re: SCI_REPLACESEL for Notepad++
Posted: 11 Mar 2019, 01:39
by toralf
I tried to write to memory, but i didn't succeed. A selection gets replaced, but with nothing.
Code: Select all
SCI_REPLACESEL(text){
hNpp := DllCall("FindWindow"
, "Str", "Notepad++"
, "Int", 0
, "Ptr")
ControlGet hSci, Hwnd,, Scintilla1, % "ahk_id" hNpp
NppPID := NPPM_PID()
hProcess := DllCall("OpenProcess"
, "UInt", ( PROCESS_VM_OPERATION := 0x8 | PROCESS_VM_READ := 0x10 | PROCESS_VM_WRITE := 0x20)
, "Int" , false
, "UInt", NppPID
, "Ptr")
BufferSize := StrLen(text) * (A_IsUnicode ? 2 : 1)
nppBufAddress := DllCall("VirtualAllocEx"
, "UInt", hProcess
, "Int" , 0
, "Int" , BufferSize
, "Int" , MEM_COMMIT := 0x1000
, "Int" , PAGE_READWRITE := 0x4
, "Ptr" )
DllCall("kernel32\WriteProcessMemory"
, Ptr,hProcess
, Ptr,nppBufAddress
, Ptr, &text
, UPtr,BufferSize
, Ptr,0)
DllCall("SendMessage", "Ptr", hSci, "UInt", 2170, "Int", 0, "Ptr", nppBufAddress)
DllCall("VirtualFreeEx"
, "Ptr", hProcess
, "Ptr", nppBufAddress
, "UInt", 0
, "UInt", MEM_RELEASE := 0x8000)
DllCall("CloseHandle"
, "Ptr", hProcess)
}
Nppm_PID(TimeOutInSec := 1){
Process, Wait, Notepad++.exe, %TimeOutInSec%
return ErrorLevel ;PID or 0 when timed out
}
Re: SCI_REPLACESEL for Notepad++
Posted: 11 Mar 2019, 01:44
by jeeswg
Btw Scintilla controls generally use UTF-8. So, I convert strings to UTF-8 before using them with Scintilla controls.
Re: SCI_REPLACESEL for Notepad++
Posted: 11 Mar 2019, 01:46
by toralf
how could i do this?
Re: SCI_REPLACESEL for Notepad++
Posted: 11 Mar 2019, 01:55
by toralf
Thanks for the tip. It worked.
Code: Select all
BufferSize := StrPut(Text, "UTF-8")
vOutput := ""
VarSetCapacity(vOutput, BufferSize+1, 0)
StrPut(Text, &vOutput, "UTF-8")
Re: SCI_REPLACESEL for Notepad++
Posted: 05 Jul 2022, 05:31
by vadus
Hi,
@toralf,
When I run this code, only the first letter of the text 't' is inserted. What am I doing wrong?
Code: Select all
SCI_REPLACESEL("test")
Return
SCI_REPLACESEL(text){
hNpp := DllCall("FindWindow"
, "Str", "Notepad++"
, "Int", 0
, "Ptr")
ControlGet hSci, Hwnd,, Scintilla1, % "ahk_id" hNpp
NppPID := NPPM_PID()
hProcess := DllCall("OpenProcess"
, "UInt", ( PROCESS_VM_OPERATION := 0x8 | PROCESS_VM_READ := 0x10 | PROCESS_VM_WRITE := 0x20)
, "Int" , false
, "UInt", NppPID
, "Ptr")
BufferSize := StrPut(Text, "UTF-8")
vOutput := ""
VarSetCapacity(vOutput, BufferSize+1, 0)
StrPut(Text, &vOutput, "UTF-8")
nppBufAddress := DllCall("VirtualAllocEx"
, "UInt", hProcess
, "Int" , 0
, "Int" , BufferSize
, "Int" , MEM_COMMIT := 0x1000
, "Int" , PAGE_READWRITE := 0x4
, "Ptr" )
DllCall("kernel32\WriteProcessMemory"
, Ptr,hProcess
, Ptr,nppBufAddress
, Ptr, &text
, UPtr,BufferSize
, Ptr,0)
DllCall("SendMessage", "Ptr", hSci, "UInt", 2170, "Int", 0, "Ptr", nppBufAddress)
DllCall("VirtualFreeEx"
, "Ptr", hProcess
, "Ptr", nppBufAddress
, "UInt", 0
, "UInt", MEM_RELEASE := 0x8000)
DllCall("CloseHandle"
, "Ptr", hProcess)
}
Nppm_PID(TimeOutInSec := 1){
Process, Wait, Notepad++.exe, %TimeOutInSec%
return ErrorLevel ;PID or 0 when timed out
}
Re: SCI_REPLACESEL for Notepad++
Posted: 05 Jul 2022, 11:33
by toralf
Hello vadus.
Welcome to the AHK Forum. I see this is your first post.
I’ll have to take a look at my current code and compare it. It will take a while, sorry
Re: SCI_REPLACESEL for Notepad++
Posted: 07 Jul 2022, 01:23
by vadus
Tnank you, toralf.
I'm waiting.
I just used your code with StrPut added. But unfortunately, as I mentioned, it doesn't work
Re: SCI_REPLACESEL for Notepad++
Posted: 21 Jul 2022, 07:17
by toralf
Sorry that it took so long.
This code works
Code: Select all
f5: SCI_REPLACESEL("toralf")
SCI_REPLACESEL(text){ ;2170
; SCI_REPLACESEL(<unused>, const char *text)
; The currently selected text between the anchor and the current position is replaced by the 0 terminated text string. If the anchor and current position are the same, the text is inserted at the caret position. The caret is positioned after the inserted text and the caret is scrolled into view.
Output := NPPM_ConvertToUTF8(Text, BufferSize)
hNpp := Nppm_Hwnd()
openProcSuccess := NPPM_OpenBuffer(hProcess, nppBufAddress, BufferSize)
if (WinExist("ahk_id " . hNpp) == 0) OR (openProcSuccess == 0)
return
NPPM_WriteProcessMemory(hProcess, nppBufAddress, Output, BufferSize)
DllCall("SendMessage", "Ptr", SCI_HWND(), "UInt", 2170, "Int", 0, "Ptr", nppBufAddress)
NPPM_CloseBuffer(hProcess, nppBufAddress)
}
Re: SCI_REPLACESEL for Notepad++
Posted: 21 Jul 2022, 07:31
by vadus
Thanks, toralf, I'll try
Re: SCI_REPLACESEL for Notepad++
Posted: 21 Jul 2022, 08:16
by vadus
It's lib from here?
https://github.com/Ixiko/AHK-libs-and-classes-collection/blob/master/libs/g-n/NPPM.ahk
Unfortunately, it doesn't work for me.
Maybe this is a lib for AHK_V2? I have v 1.1.33
Re: SCI_REPLACESEL for Notepad++ Topic is solved
Posted: 21 Jul 2022, 12:14
by teadrinker
Try this:
Code: Select all
ControlGet, hScintilla, hwnd,, Scintilla1, ahk_class Notepad++
if !hScintilla {
MsgBox, Scintilla not found
ExitApp
}
SCI_REPLACESEL(hScintilla, "AutoHotkey")
SCI_REPLACESEL(hScintilla, text) {
WinGet, PID, PID, ahk_id %hScintilla%
size := StrPut(text, "UTF-8")
RB := new RemoteBuffer(PID, size)
VarSetCapacity(buf, size, 0)
StrPut(text, &buf, "UTF-8")
RB.Write(&buf, size)
SendMessage, SCI_REPLACESEL := 2170,, RB.ptr,, ahk_id %hScintilla%
}
class RemoteBuffer
{
__New(PID, size) {
static flags := (PROCESS_VM_OPERATION := 0x8) | (PROCESS_VM_WRITE := 0x20) | (PROCESS_VM_READ := 0x10)
, Params := ["UInt", MEM_COMMIT := 0x1000, "UInt", PAGE_READWRITE := 0x4, "Ptr"]
if !this.hProc := DllCall("OpenProcess", "UInt", flags, "Int", 0, "UInt", PID, "Ptr")
throw Exception("Can't open remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
if !this.ptr := DllCall("VirtualAllocEx", "Ptr", this.hProc, "Ptr", 0, "Ptr", size, Params*) {
DllCall("CloseHandle", "Ptr", this.hProc)
throw Exception("Can't allocate memory in remote process PID = " . PID . "`nA_LastError: " . A_LastError, "RemoteBuffer.__New")
}
}
__Delete() {
DllCall("VirtualFreeEx", "Ptr", this.hProc, "Ptr", this.ptr, "UInt", 0, "UInt", MEM_RELEASE := 0x8000)
DllCall("CloseHandle", "Ptr", this.hProc)
}
Read(ByRef localBuff, size, offset = 0) {
VarSetCapacity(localBuff, size, 0)
if !DllCall("ReadProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", &localBuff, "Ptr", size, "PtrP", bytesRead)
throw Exception("Can't read data from remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Read")
Return bytesRead
}
Write(pData, size, offset = 0) {
if !res := DllCall("WriteProcessMemory", "Ptr", this.hProc, "Ptr", this.ptr + offset, "Ptr", pData, "Ptr", size, "PtrP", bytesWritten)
throw Exception("Can't write data to remote buffer`nA_LastError: " . A_LastError, "RemoteBuffer.Write")
Return bytesWritten
}
}
Re: SCI_REPLACESEL for Notepad++
Posted: 21 Jul 2022, 12:43
by vadus
Great, it works! Thank you, teadrinker.
Just how do I make it work with Cyrillic, ANSI encoding?
Now this code:
Code: Select all
SCI_REPLACESEL(hScintilla, "Борщ")
is inserted:
Re: SCI_REPLACESEL for Notepad++
Posted: 21 Jul 2022, 13:05
by teadrinker
vadus wrote:Just how do I make it work with Cyrillic, ANSI encoding?
Cyrillic is not an encoding, it's just a font group. For me this script works with any text. Ensure you save the script as
UTF-8 with BOM. Scintilla in Notepad++ uses UTF-8 too.
Re: SCI_REPLACESEL for Notepad++
Posted: 21 Jul 2022, 14:46
by vadus
All right, it works, thank you
Re: SCI_REPLACESEL for Notepad++
Posted: 22 Jul 2022, 03:15
by lexikos
Scintilla also "supports" EM_REPLACESEL (although it's "deprecated and discouraged"), which means it "supports" Control EditPaste.
The trick is that unlike real Edit controls, Scintilla requires a UTF-8 string. So this works for me:
Code: Select all
str := "Text to insert"
VarSetCapacity(str8, StrPut(str8, "utf-8"), 1), StrPut(str, &str8, "utf-8")
SetTitleMatchMode 2
Control EditPaste, % str8, Scintilla1, ahk_class Notepad++
But SCI_REPLACESEL will be needed if the Edit control messages are ever actually removed (as the documentation warns).
EM_REPLACESEL is a system-defined message, so the system automatically copies the string between processes. This means it doesn't require RemoteBuffer or anything like it.
Re: SCI_REPLACESEL for Notepad++
Posted: 22 Jul 2022, 10:36
by vadus
Scintilla also "supports" EM_REPLACESEL
Yes, it works for me too
Re: SCI_REPLACESEL for Notepad++
Posted: 07 Sep 2022, 06:55
by vadus
Hi,
Maybe someone will be interested to know how to insert Cyrillic text in an ANSI encoded file using SCI_REPLACESEL
You just need to change UTF-8 to CP1251. The code will look like this:
Code: Select all
SCI_REPLACESEL(hScintilla, text) {
WinGet, PID, PID, ahk_id %hScintilla%
size := StrPut(text, "CP1251")
RB := new RemoteBuffer(PID, size)
VarSetCapacity(buf, size, 0)
StrPut(text, &buf, "CP1251")
RB.Write(&buf, size)
SendMessage, SCI_REPLACESEL := 2170,, RB.ptr,, ahk_id %hScintilla%
}