Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.012 c
2-1242909774
Индеец
2009-05-21 16:42
2009.07.12
TJclSimpleXMLElem и CDATA


15-1241808946
TUser
2009-05-08 22:55
2009.07.12
Играем в ассемблер


15-1242127932
snake-as
2009-05-12 15:32
2009.07.12
Приложение клиент-сервер


2-1242837940
Dr.Andrew
2009-05-20 20:45
2009.07.12
Как строку short *s=(short*)buffer можно перевести на делфи?


4-1212599714
Alex
2008-06-04 21:15
2009.07.12
Как расположить форму по центру экрана?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский