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