Scintilla direct access in external process (notepad++)?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Scintilla direct access in external process (notepad++)?

Post by neogna2 » 18 May 2021, 06:09

The Scintilla control in an external notepad++ window can be accessed from AutoHotkey scripts with SendMessage calls, but Scintilla's manual says another direct access method can be more performant. I can get that direct access working for Scintilla inside AutoHotkey GUIs.
Question: is there a way to use the direct access method from AutoHotkey to control Scintilla in notepad++ and other external processes?

My test code below gives DllCall error 0xC0000005 "access violation". I think because Scintilla's direct function is in notepad++ memory and not AutoHotkey memory. Can we work around that somehow? Some extra DllCall steps with OpenProcess?

Code: Select all

#IfWinActive, ahk_exe notepad++.exe
F1::
;scintilla control handle
ControlGet, CtrlHWND, Hwnd,, Scintilla1, A
;scintilla direct access
;https://www.scintilla.org/ScintillaDoc.html#DirectAccess
;"On Windows, the message-passing scheme used to communicate between the container and Scintilla is mediated "by the "
;"operating system SendMessage function and can lead to bad performance when calling intensively.                    "
;"To avoid this overhead, Scintilla provides messages that allow you to call the Scintilla message function directly."
;https://www.scintilla.org/Steps.html
;"retrieve the pointer to the function and a pointer which must be the first parameter"
;also https://www.autohotkey.com/boards/viewtopic.php?p=335222#p335222
df := DllCall("SendMessage", "Ptr", CtrlHWND, "Int", SCI_GETDIRECTFUNCTION := 2184, "Int", 0, "Int", 0, "UInt")
dp := DllCall("SendMessage", "Ptr", CtrlHWND, "Int", SCI_GETDIRECTPOINTER := 2185, "Int", 0, "Int", 0, "Ptr")
;direct access call to read caret position
;https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/scintilla/include/Scintilla.h#L57
CurrentPos := DllCall(df, "Ptr", dp, "Int", SCI_GETCURRENTPOS := 2008, "Int", wParam := 0, "Int", lParam := 0)
MsgBox % "CtrlHWND=" CtrlHWND
        . "`ndf=" df
        . "`ndp=" dp
        . "`nCurrentPos=" CurrentPos
        . "`nErrorLevel=" ErrorLevel  ; error 0xC0000005 = "access violation"

;For comparison, reading scintilla caret position in notepad++ through SendMessage works
MsgBox % CurrentPos := DllCall("SendMessage", "Ptr", CtrlHWND, "Int", SCI_GETCURRENTPOS := 2008)
ExitApp
#IfWinActive
teadrinker
Posts: 4331
Joined: 29 Mar 2015, 09:41
Contact:

Re: Scintilla direct access in external process (notepad++)?

Post by teadrinker » 18 May 2021, 07:25

Direct access wrote:While faster, this direct calling will cause problems if performed from a different thread to the native thread of the Scintilla window in which case SendMessage(hSciWnd, SCI_*, wParam, lParam) should be used to synchronize with the window's thread.
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Re: Scintilla direct access in external process (notepad++)?

Post by neogna2 » 18 May 2021, 07:48

teadrinker wrote:
18 May 2021, 07:25
Direct access wrote:While faster, this direct calling will cause problems if performed from a different thread to the native thread of the Scintilla window in which case SendMessage(hSciWnd, SCI_*, wParam, lParam) should be used to synchronize with the window's thread.
I'm not sure what to make of the "synchronize with" part of that sentence. Does it mean we can use direct access across threads if we also do some extra "synchronizing" step? Or does it mean that it is impossible to get direct access working to Scintilla in a different process and that the only option in that case is to the use slower, non-direct access SendMessage method?
teadrinker
Posts: 4331
Joined: 29 Mar 2015, 09:41
Contact:

Re: Scintilla direct access in external process (notepad++)?

Post by teadrinker » 18 May 2021, 07:50

I suppose, the second is right.
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Re: Scintilla direct access in external process (notepad++)?

Post by neogna2 » 18 May 2021, 07:56

teadrinker wrote:
18 May 2021, 07:50
I suppose, the second is right.
Ok. I did find some AHK forum posts about calling functions in the memory of external processes and was hoping something like that would work in this case too. This thread for example https://www.autohotkey.com/boards/viewtopic.php?t=5571 But the steps there are too advanced for me to understand at the moment.
teadrinker
Posts: 4331
Joined: 29 Mar 2015, 09:41
Contact:

Re: Scintilla direct access in external process (notepad++)?

Post by teadrinker » 18 May 2021, 07:58

This is a possible way, but performance will be reduced, so this makes no sense.
neogna2
Posts: 591
Joined: 15 Sep 2016, 15:44

Re: Scintilla direct access in external process (notepad++)?

Post by neogna2 » 19 May 2021, 14:50

teadrinker wrote:
18 May 2021, 07:58
This is a possible way, but performance will be reduced, so this makes no sense.
Ok, too bad. For a lot of uses SendMessage control over Scintilla in an external process is fast enough, but not for some repetitive calls to large documents. For example if we want to search and delete thousands of lines that match a pattern in a 20K lines long document all the repeat SendMessages step adds up to slowness. Much faster to read the whole document into AutoHotkey, operate and then replace the Scintilla content in one go. But some fancier Scintilla stuff can't be done that way, like applying a lot of annotations.
teadrinker
Posts: 4331
Joined: 29 Mar 2015, 09:41
Contact:

Re: Scintilla direct access in external process (notepad++)?

Post by teadrinker » 19 May 2021, 15:06

I have no experience with handling such a large text. I only used messages to implement some features in my Notepad++ AHK-editor. For me messages work fast enough.
Post Reply

Return to “Ask for Help (v1)”