Notepad++, Scintilla, SendMessages and Delphi



  • Hello, I am having problems managing Scintilla in n ++ via messages. I use delphi. And sorry for my English, I used Google Translate.!!

    I get handle skinntills through FindWindow and FindWindowEx.
    I am trying to pass the replacement string like this:
    str: = ‘qwerty’ # 0;
    sendmessage (hwndScintilla, 2170,0, lparam (pchar (str)));

    2170 is SCI_REPLACESEL. I do not include header files, so I just use numbers instead of constants.

    But instead of the passed string, this appears:

    https://yadi.sk/i/-Vp5G2gdTIngLA
    Moreover, each time you restart n ++ and my program, “this” is always different.

    And messages returning numbers work fine:
    sendmessage (hwndScintilla, 2143,0,0)
    2143 is SCI_GETSELECTIONSTART.

    How do I pass a replacement string in Scintilla?

    Documentation from here: https://www.scintilla.org/ScintillaDoc.html#SCI_REPLACESEL
    Constants here: http://freesourcecode.net/cprojects/106750/sourcecode/Scintilla.h



  • @Sun-Bright

    do you develop a plugin?
    If so you do get the window handles of notepad and scintilla editor1 and editor2 via the setInfo callback.
    Depending on how you use FindWindow api it might not return the handle you expect as npp itself is using
    already three scintilla windows. Plugins might use additional windows as well.

    I don’t know enough about delphi but scintilla expects to receive a byte string NOT a unicode string.
    Is this your case?



  • No, I just want to send commands from my program to npp, without using dll. But it seems that this will be impossible, because from the address space of my program, the scintilla will not be able to get data in the address space of npp.
    From Delphi I transmit a string of bytes, not Unicode.
    Thank you for answer.



  • @Sun-Bright

    that is correct, if you want to access scintilla from another process you have to get access
    to the process memory of npp. See Read-/WriteProcessMemory functions and friends.



  • @Sun-Bright said in Notepad++, Scintilla, SendMessages and Delphi:

    But it seems that this will be impossible, because from the address space of my program, the scintilla will not be able to get data in the address space of npp.

    You can actually send strings back and forth, even from another process. I’m starting to do it in my developing perl-driving-npp module. I don’t know how to do it in delphi, but the commands involved are VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, and VirtualFreeEx. (Oh, I misinterpreted @Ekopalypse’s response; he was saying the same thing. But now I’ve linked to the official win32 api for you. :-) )

    They may be called something else in Delphi. (For example, in the perl wrapper Win32::GuiTest I am using for issuing the SendMessage to NPP, they call those AllocateVirtualBuffer, WriteToVirtualBuffer, ReadFromVirtualBuffer, and FreeVirtualBuffer.

    For commands that want to get or send a single string, like NPPM_DOOPEN for sending a string via LPARAM, or NPPM_GETFULLPATHFROMBUFFERID for reading a string via LPARAM, I use the following sequences successfully.

    # $obj->SendMessage_getUcs2le( $message_id, $wparam ):
    #   issues a SendMessage, and grabs a string up to 1024 bytes, and
    #   converts them from UCS-2 LE into up to 512 perl characters
    #   (includes the memory allocation necessary for cross-application communication)
    #   RETURN: the Perl string
    sub SendMessage_getUcs2le {
        my $self = shift; croak "no object sent" unless defined $self;
        my $msgid = shift; croak "no message id sent" unless defined $msgid;
        my $wparam = shift || 0;
    
        my $buf_uc2le = Win32::GuiTest::AllocateVirtualBuffer( $self->hwnd, 1024 );   # 1024 byte string maximum
        Win32::GuiTest::WriteToVirtualBuffer( $buf_uc2le, "\0"x1024 );                # pre-populate
        my $rslt = $self->SendMessage( $msgid, $wparam, $buf_uc2le->{ptr});
        #diag "SendMessage_getStr(@{[$self->hwnd]}, $msgid, $wparam, @{[explain $buf_uc2le]} ) = $rslt";
        my $rbuf = Win32::GuiTest::ReadFromVirtualBuffer( $buf_uc2le, 1024 );
        Win32::GuiTest::FreeVirtualBuffer( $buf_uc2le );
        return substr Encode::decode('ucs2-le', $rbuf), 0, $rslt;   # return the valid characters from the raw string
    }
    
    # $obj->SendMessage_sendStrAsUcs2le( $message_id, $wparam , $lparam_string ):
    #   issues a SendMessage, sending a string (encoded as UCS-2 LE)
    sub SendMessage_sendStrAsUcs2le {
        my $self = shift; croak "no object sent" unless defined $self;
        my $msgid = shift; croak "no message id sent" unless defined $msgid;
        my $wparam = shift; croak "no wparam sent" unless defined $wparam;
        my $lparam_string = shift; croak "no lparam string sent" unless defined $lparam_string;
    
        # convert string to UCS-2 LE
        my $ucs2le = Encode::encode('ucs2-le', $lparam_string);
    
        # copy string into virtual buffer
        my $buf_str = Win32::GuiTest::AllocateVirtualBuffer( $self->hwnd, length($ucs2le) );
        Win32::GuiTest::WriteToVirtualBuffer( $buf_str, $ucs2le );
    
        # send the message with the string ptr as the lparam
        my $rslt = Win32::GuiTest::SendMessage($self->hwnd, $msgid, $wparam, $buf_str->{ptr});
    
        # clear virtual buffer
        Win32::GuiTest::FreeVirtualBuffer( $buf_str );
    
        # return
        return $rslt;
    
    }
    

    (And yes, I successfully use those same sequences for talking with the NPP hwnd and the Scintilla hwnds.)

    Similar sequences, but using Delphi syntax and function names, should work for those commands.

    I’m actually still working on getting the more complicated messages (which want WPARAM as a TCHAR** rather than just a TCHAR*), but the above wrappers work for all the single-string LPARAM messages.


Log in to reply