SCI_REPLACESEL for Notepad++ Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

SCI_REPLACESEL for Notepad++

10 Mar 2019, 14:07

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?
ciao
toralf
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: SCI_REPLACESEL for Notepad++

10 Mar 2019, 14:19

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)
}
ciao
toralf
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: SCI_REPLACESEL for Notepad++

10 Mar 2019, 14:33

- 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.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: SCI_REPLACESEL for Notepad++

11 Mar 2019, 01:39

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
}
ciao
toralf
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: SCI_REPLACESEL for Notepad++

11 Mar 2019, 01:44

Btw Scintilla controls generally use UTF-8. So, I convert strings to UTF-8 before using them with Scintilla controls.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: SCI_REPLACESEL for Notepad++

11 Mar 2019, 01:46

how could i do this?
ciao
toralf
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: SCI_REPLACESEL for Notepad++

11 Mar 2019, 01:55

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")
ciao
toralf
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

05 Jul 2022, 05:31

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
}
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: SCI_REPLACESEL for Notepad++

05 Jul 2022, 11:33

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
ciao
toralf
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

07 Jul 2022, 01:23

Tnank you, toralf.
I'm waiting.
I just used your code with StrPut added. But unfortunately, as I mentioned, it doesn't work
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: SCI_REPLACESEL for Notepad++

21 Jul 2022, 07:17

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)

}
ciao
toralf
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

21 Jul 2022, 07:31

Thanks, toralf, I'll try
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

21 Jul 2022, 08:16

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
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: SCI_REPLACESEL for Notepad++  Topic is solved

21 Jul 2022, 12:14

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
   }
}
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

21 Jul 2022, 12:43

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:

Code: Select all

Борщ
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: SCI_REPLACESEL for Notepad++

21 Jul 2022, 13:05

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.
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

21 Jul 2022, 14:46

All right, it works, thank you
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: SCI_REPLACESEL for Notepad++

22 Jul 2022, 03:15

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.
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

22 Jul 2022, 10:36

Scintilla also "supports" EM_REPLACESEL
Yes, it works for me too
vadus
Posts: 11
Joined: 26 May 2019, 13:02

Re: SCI_REPLACESEL for Notepad++

07 Sep 2022, 06:55

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%
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Draken, Google [Bot], roeleboele and 360 guests