Форум: "WinAPI";
Текущий архив: 2009.07.12;
Скачать: [xml.tar.bz2];
ВнизEM_GETLINE Найти похожие ветки
← →
ЗапомниСынок (2008-06-04 15:06) [0]Почему функция
function GetRichEditLine(hRichEdit : HWND; Index : LongWord) : String;
var
Buffer : array[0..$FF] of Char;
begin
FillChar(Buffer, 4, $FF);
SendMessage(hRichEdit, EM_GETLINE, Index, LParam(@Buffer));
Result:= Buffer;
end;
Исправно возвращает строку из RichEdit своего приложения, но не хочет возвращать из чужого.
← →
MBo © (2008-06-04 15:39) [1]потому что указатель на строку - в чужом адресном пространстве
нужно внедряться в процесс - см., например, книгу Рихтера
← →
Olegz77 © (2008-06-04 15:48) [2]
> FillChar(Buffer, 4, $FF);
1. Че за ботва???
В начало буфера надо записать слово (два байта!), содержащее размер принимающего буфера. У тебя он - 256 байт, а не 65535 !!! Т.е.
FillChar(Buffer, SizeOf(Buffer), 0);
Buffer[0] := #255;
Buffer[1] := #0;
последний байт надо оставить для завершающего нуля, он туда автоматом не записывается.
2. Из какого такого RichEdit ты пытаешся получить строку? Может там не стандартный RichEdit, а какой-то свой контрол, которому на EM_GETLINE плевать ?
← →
ЗапомниСынок (2008-06-04 16:53) [3]2 Olegz77
FillChar(Buffer, 4, $FF);
В различных источниках указано где 2 байта, где 4 байта, в справке Delphi сказано 2 байта.
Но сколько писать два или 4 в данном случае не имеет значения, хоть весь буфер могу заполнить $FF. Сами понимаете. что если работает в своем приложении, то к ошибке отношения не имеет.
RichEdit обычный, тестовая форма с RichEdit-ом.
2 Mbo
Вообще то Windows заботится о передаче данных из процесса в процесс для стандартных сообщений. Я считал EM_GETLINE именно таким. Когда у меня не получилось я, разумеется, первым делом проверил эту версию, выделил память при помощи VirtualAllocEx, WriteProcessMemory... Не помогло.
← →
guav © (2008-06-04 17:49) [4]> [3] ЗапомниСынок (04.06.08 16:53)
> Вообще то Windows заботится о передаче данных из процесса
> в процесс для стандартных сообщений. Я считал EM_GETLINE
> именно таким.
Стандартные это меньше WM_USER, EM_GETLINE таковым не является.
← →
ЗапомниСынок (2008-06-04 19:22) [5]Ну хорошо, вот такая функция возвращает аналогичный результат:
function GetRichEditItem(hWindow : HWND; Index : Integer) : String;
var
Buffer : array[0..255] of Char;
ProcessId : DWORD;
Process : THandle;
Ptr : Pointer;
BytesRead : Cardinal;
Size : Word;
begin
Result := "";
GetWindowThreadProcessId(hWindow, @ProcessId);
Process := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, False, ProcessId);
Ptr := VirtualAllocEx(Process, nil, 4096, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
try
Size := $FFFF;
WriteProcessMemory(Process, Ptr, @Size, SizeOf(Word), BytesRead);
SendMessage(hWindow, EM_GETLINE, Index, LParam(Ptr));
ReadProcessMemory(Process, Ptr, @Buffer[0], SizeOf(Buffer), BytesRead);
finally
VirtualFreeEx(Process, Ptr, 0, MEM_RELEASE);
CloseHandle(Process);
end;
Result := Buffer;
end;
← →
ЗапомниСынок (2008-06-04 19:27) [6]Кстати, если уж на то пошло:
EM_GETLINE = $00C4;
WM_USER = $0400;
Для сравнения LVM_GETITEM, где такой подход действительно требуется:
LVM_GETITEM = $1005
← →
Игорь Шевченко © (2008-06-04 23:55) [7]
> Исправно возвращает строку из RichEdit своего приложения,
> но не хочет возвращать из чужого.
Сдается мне, что EM_GETLINE по-разному работает для Edit и RichEdit
guav © (04.06.08 17:49) [4]
> Стандартные это меньше WM_USER, EM_GETLINE таковым не является.
EM_GETLINE "таковым является", для которго предусмотрена передача данных между процессами.
← →
ЗапомниСынок (2008-06-05 07:50) [8]2 Игорь Шевченко
Это я тоже проверил, бросил на форму TRichEdit, TMemo и TEdit, результат один и тот же. Все сведения, которые я нашел в интернете и в королевстве в частности, говорят о том что первый вариант должен работать. Я, мягко говоря, в недоумении.
← →
ЗапомниСынок (2008-06-05 14:19) [9]Забавно, вот что написано в справке Delphi по EM_GETLINE:
...
lpch
Value of lParam. Points to the buffer that receives a copy of the line. The first word of the buffer specifies the maximum number of characters that can be copied to the buffer.
Т.е. первые два байта просто максимальный размер буфера.
Тем не менее при использовании в рамках одного приложения вот такой вариант:
FillChar(Buffer, SizeOf(Buffer), $FF);
SendMessage(hRichEdit, $00C4, {EM_GETLINE} Index, LParam(@Buffer));
работает нормально, а при попытке вытащить данные из чужого приложения приходится писать
FillChar(Buffer, SizeOf(Buffer), 0);
Buffer[0] := #$FF;
SendMessage(hRichEdit, $00C4, {EM_GETLINE} Index, LParam(@Buffer));
Очевидно, разруливая указатели в разных адресных пространствах, система каким-то образом отслеживает и сравнивает действительные и указанные размеры буферов.
← →
Olegz77 © (2008-06-05 14:35) [10]> ЗапомниСынок
А с чего ты вообще решил заполнять весь буфер $FF-ами ?
← →
Игорь Шевченко © (2008-06-05 14:50) [11]ЗапомниСынок (05.06.08 14:19) [9]
>
> Очевидно, разруливая указатели в разных адресных пространствах,
> система каким-то образом отслеживает и сравнивает действительные
> и указанные размеры буферов.
Система, как ты понимаешь, создает разделяемую область памяти, в противном случае передать данные посредством сообщений из разных процессов она просто не сможет.
Весьма вероятно, что для совместимости с Windows 3.x размер буфера $FFFF является каким-то запретным. Мало ли. Ты попробуй другой размер поставить, $1000 например
← →
ЗапомниСынок (2008-06-05 15:23) [12]2 Olegz77 © (05.06.08 14:35) [10]
Да я собственно ничего не решил, прочитав в одном месте про два байта, а в другом про 4 байта (видимо различная интерпретация термина "слово") решил забить все 4 байта, проверил локально - работает. Когда не смог считать из другого приложения. удивился
2 Игорь Шевченко
Пробовал, дело похоже не в константе, а в размере буфера. Выделил буфер 0..$FF, если записать 2048 - работает, 4096 - уже нет.
← →
Olegz77 © (2008-06-05 15:36) [13]Я чего-то не понимаю. У тебя размер буфера 256 байт. Этот размер надо представить в виде двух байт (слово - это два байта). Так почему ты записываешь его как $FF,$FF (2 байта) или $FF,$FF,$FF,$FF (4 байта) ??? Бред какой-то.
Чтобы не парится сделай так:
var
Buffer : array[0..$FF] of Char;
BufferSize: Word absolute Buffer;
begin
FillChar(Buffer, SizeOf(Buffer), 0);
BufferSize := SizeOf(Buffer);
// и т.д.
Это гарантированно запишет тебе правильный размер буфера в начало.
← →
Игорь Шевченко © (2008-06-05 15:44) [14]
> Пробовал, дело похоже не в константе, а в размере буфера.
> Выделил буфер 0..$FF, если записать 2048 - работает, 4096
> - уже нет.
Ну и последние 2048-256 байт пишутся, соответственно, в стек, круша все данные ? :)
Я вполне допускаю, что в коде обработки сообщений (именно межпроцессного взаимодействия) стоит вызов проверки, можно ли записать в переданный буфер.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2009.07.12;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.004 c