Community
    • Login

    Notepad++, Scintilla, SendMessages and Delphi

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    5 Posts 3 Posters 966 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Sun BrightS
      Sun Bright
      last edited by

      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

      EkopalypseE 1 Reply Last reply Reply Quote 0
      • EkopalypseE
        Ekopalypse @Sun Bright
        last edited by

        @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?

        1 Reply Last reply Reply Quote 1
        • Sun BrightS
          Sun Bright
          last edited by

          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.

          EkopalypseE 1 Reply Last reply Reply Quote 0
          • EkopalypseE
            Ekopalypse @Sun Bright
            last edited by

            @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.

            1 Reply Last reply Reply Quote 1
            • PeterJonesP
              PeterJones
              last edited by

              @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.

              1 Reply Last reply Reply Quote 2
              • First post
                Last post
              The Community of users of the Notepad++ text editor.
              Powered by NodeBB | Contributors