Проблема в том, что вы отправляете сообщение в элемент управления Scintilla, у которого есть адрес буфера StringBuilder в lParam, но элемент управления Scintilla в Notepad ++ находится в другом адресном пространстве, поэтому адрес в сообщении окна, которое он получает, может не быть написано. Стандартные сообщения, такие как WM_GETTEXT и WM_SETTEXT обрабатываются таким образом, что для вас выполняется необходимое сопоставление адресов, но этого не происходит для специальных сообщений, используемых элементом управления Scintilla. Для получения дополнительной информации ищите маршаллинг.
К сожалению, поддержка WM_GETTEXTLENGTH и WM_GETTEXT прекращается из элемента управления Scintilla, и в документации рекомендуется использовать специальные сообщения SCI_XXX . Блокнот ++ уже не работает с WM_GETTEXT , поэтому вам нужно использовать SCI_GETTEXTLENGTH (2183) и SCI_GETTEXT (2182) и выполнять маршалинг самостоятельно.
Предупреждение: На самом деле опасно отправлять сообщение SCI_GETTEXT из другого приложения без специальной обработки адреса буфера - Notepad ++ скопирует данные в буфер, но так как адрес сам по себе недопустим адресное пространство, которое может немедленно вызвать нарушение доступа или (что еще хуже) может незаметно перезаписать внутренние данные.
Вы можете использовать VirtualAllocEx () и ReadProcessMemory (), чтобы использовать буфер с адресом, используемым в Notepad ++. Я собрал быструю программу Delphi, которая работает для меня, важный код такой:
procedure TForm1.Button1Click(Sender: TObject);
const
VMFLAGS = PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE;
var
Wnd: HWND;
Len: integer;
ProcessId, BytesRead: Cardinal;
ProcessHandle: THandle;
MemPtr: PChar;
s: string;
begin
Wnd := $30488;
Len := SendMessage(Wnd, 2183, 0, 0);
if Len > 0 then begin
GetWindowThreadProcessId(Wnd, @ProcessId);
ProcessHandle := OpenProcess(VMFLAGS, FALSE, ProcessId);
MemPtr := VirtualAllocEx(ProcessHandle, nil, Len + 1,
MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
if MemPtr <> nil then try
SendMessage(Wnd, 2182, Len + 1, integer(MemPtr));
SetLength(s, Len + 1);
ReadProcessMemory(ProcessHandle, MemPtr, @s[1], Len + 1, BytesRead);
SetLength(s, BytesRead);
Memo1.Lines.Text := s;
finally
VirtualFreeEx(ProcessId, MemPtr, Len + 1, MEM_RELEASE);
end;
end;
end;
Это более ранняя версия Delphi, использующая версию API-функций Ansi; вероятно, вы бы использовали SendMessageW и буфер WideChar, но общая идея должна быть ясной.