Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];

Вниз

RichEdit20A. Как взять текст?   Найти похожие ветки 

 
DmitrichJ   (2007-05-21 02:18) [0]

Привет, мастера. Собственно и весь вопрос. Как взять текст данного класса из чужого окна? Хэндлы окна и объекта имеются.
Спасибо.


 
Rouse_ ©   (2007-05-21 09:35) [1]

unit MainUnit;

interface

uses
 Windows, Messages, Graphics, Controls, Forms, ComCtrls,
 StdCtrls, Classes, SysUtils, Dialogs;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   Button1: TButton;
   Memo1: TMemo;
   Edit2: TEdit;
   procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure Button1Click(Sender: TObject);
 end;

var
 Form1: TForm1;

implementation

uses RichEdit;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
{$DEFINE DEBUG_FIND}
var
 MainWindowHandle, RichEditWHandle: THandle;
 ProcessID : Cardinal;
 ProcessHandle : THandle;
 StructTextEx: TGetTextEx;
 StructTextLength: TGetTextLengthEx;
 PStructTextLength, PStructTextEx, PTextBuffer: Pointer;
 BytesWriten, RichEditTextLength: DWORD;
 TextBuffer: array of Char;
begin

 {$IFDEF DEBUG_FIND}
   // Заполняем данные для отладки
   // В качестве примера работаем с WordPad-ом
   Edit1.Text := "Document - WordPad";
   Edit2.Text := "RICHEDIT50W";
 {$ENDIF}

 // Ищем окно
 MainWindowHandle := FindWindow(nil , PChar(Edit1.Text));
 if MainWindowHandle = 0 then RaiseLastOSError;
 RichEditWHandle := FindWindowEx(MainWindowHandle, 0, PChar(Edit2.Text), nil);
 if RichEditWHandle = 0 then RaiseLastOSError;

 // Узнаем ID процесса
 GetWindowThreadProcessId(MainWindowHandle, @ProcessID);
 if ProcessID = 0 then RaiseLastOSError;

 // Открываем процесс
 ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, True, ProcessID);
 if ProcessHandle = 0 then RaiseLastOSError;
 try

   // Выделяем в нем память под структуру TGetTextLengthEx
   PStructTextLength := VirtualAllocEx(ProcessHandle, nil,
     SizeOf(TGetTextLengthEx), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
   if PStructTextLength = nil then RaiseLastOSError;
   try

     // Подготавливаем структуру...
     StructTextLength.flags := GTL_NUMBYTES or GTL_USECRLF;
     StructTextLength.codepage := CP_ACP;

     // ...и пишем ее в память процесса
     if not WriteProcessMemory(ProcessHandle, PStructTextLength,
       @StructTextLength, SizeOf(TGetTextLengthEx),
       BytesWriten) then RaiseLastOSError;
     if BytesWriten <> SizeOf(TGetTextLengthEx) then RaiseLastOSError;

     // Отправляем сообщение удаленному RichEdit,
     // чтобы узнать необходимый размер буффера
     RichEditTextLength := SendMessage(RichEditWHandle,
       EM_GETTEXTLENGTHEX , Integer(PStructTextLength), 0);

   finally
     // Освобождаем выделенную под TGetTextLengthEx память
     VirtualFreeEx(ProcessHandle, PStructTextLength, 0, MEM_RELEASE);
   end;

   // Выделяем память под структуру TGetTextEx
   PStructTextEx := VirtualAllocEx(ProcessHandle, nil,
     SizeOf(TGetTextEx), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
   if PStructTextEx = nil then RaiseLastOSError;
   try

     // Подготавливаем структуру...
     ZeroMemory(@StructTextEx, SizeOf(TGetTextEx));
     StructTextEx.flags := GT_USECRLF;
     StructTextEx.cb := RichEditTextLength;

     // ...и пишем ее в память процесса
     if not WriteProcessMemory(ProcessHandle, PStructTextEx,
       @StructTextEx, SizeOf(TGetTextEx),
       BytesWriten) then RaiseLastOSError;
     if BytesWriten <> SizeOf(TGetTextEx) then RaiseLastOSError;

     // Выделяем память под текстовый буффер
     PTextBuffer := VirtualAllocEx(ProcessHandle, nil,
     RichEditTextLength, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
     if PTextBuffer = nil then RaiseLastOSError;
     try

       // отправляем сообщение
       SendMessage(RichEditWHandle, EM_GETTEXTEX, Integer(PStructTextEx),
         Integer(PTextBuffer));

       // Читаем, то, что у нас скопировалось
       SetLength(TextBuffer, RichEditTextLength);
       if not ReadProcessMemory(ProcessHandle, PTextBuffer, @TextBuffer[0],
         RichEditTextLength, BytesWriten) then RaiseLastOSError;

       Memo1.Text := String(TextBuffer);

     finally
       // Освобождаем выделенную под тестовый буффер память
       VirtualFreeEx(ProcessHandle, PTextBuffer, 0, MEM_RELEASE);
     end;

   finally
     // Освобождаем выделенную под TGetTextEx память
     VirtualFreeEx(ProcessHandle, PStructTextEx, 0, MEM_RELEASE);
   end;

 finally
   // Закрываем процесс
   CloseHandle(ProcessHandle);
 end;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 ReleaseCapture;
 SendMessage(Handle, WM_SYSCOMMAND, SC_MOVE or HTCAPTION, 0);
end;

end.


 
Leonid Troyanovsky ©   (2007-05-21 10:04) [2]


> DmitrichJ   (21.05.07 02:18)

> Привет, мастера. Собственно и весь вопрос. Как взять текст
> данного класса из чужого окна? Хэндлы окна и объекта имеются.

А что возвращает SendMessage with WM_GETTEXT?

--
Regards, LVT.


 
DmitrichJ   (2007-05-21 11:12) [3]

Leonid Troyanovsky, пустую строчку, хотя я в этом пока только начинаю разбераться.
Rouse_, спасибо. Надеюсь заработает.


 
Leonid Troyanovsky ©   (2007-05-21 11:30) [4]


> DmitrichJ   (21.05.07 11:12) [3]

> Leonid Troyanovsky, пустую строчку, хотя я в этом пока только
> начинаю разбераться.

Добро пожаловать в "Начинающие".

SendMessage, воо-ще-то, возвращает LRESULT.
И, еще, как идентифицирован RICHEDIT (хендл, класс), показывай.

--
Regards, LVT.


 
DmitrichJ   (2007-05-21 11:56) [5]

var
Form,obj,h:HWND;
...
Form:=FindWindow(nil, "Нужное мне окно");
 if Form<>0 then begin
   ShowMessage("Окно есть!");
   h:=FindWindowEx(form, 0, "RichEdit20A", nil);
   if h<>0 then begin
     ShowMessage("Класс найден");

???????????????????????

   end;
 end else ShowMessage("Нет окна =(");


 
DmitrichJ   (2007-05-21 12:00) [6]

Rouse_, проблема с выделением памяти. PStructTextLength = nil  !!!


 
Rouse_ ©   (2007-05-21 12:10) [7]


> Rouse_, проблема с выделением памяти. PStructTextLength
> = nil  !!!

А RaiseLastOSError что говорит?


 
DmitrichJ   (2007-05-21 12:19) [8]

Project Projext1.exe raised exception class EOSError with message "System Error. Code 6: Неверный дескриптор"...


 
Rouse_ ©   (2007-05-21 12:35) [9]

Система у тебя какая?


 
DmitrichJ   (2007-05-21 12:37) [10]

XP SP2


 
Leonid Troyanovsky ©   (2007-05-21 12:43) [11]


> DmitrichJ   (21.05.07 11:56) [5]

> ???????????????????????

Ну, и здесь-то чего?

--
Regards, LVT.


 
DmitrichJ   (2007-05-21 12:43) [12]

Сейчас почему-то пишет A call to an OS function failed


 
DmitrichJ   (2007-05-21 12:45) [13]

Leonid Troyanovsky, здесь сейчас пользуюсь примером, но работать не хочет.
Вот в этом месте    
// Выделяем в нем память под структуру TGetTextLengthEx
  PStructTextLength := VirtualAllocEx(ProcessHandle, nil,
    SizeOf(TGetTextLengthEx), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
  if PStructTextLength = nil then RaiseLastOSError;


 
Rouse_ ©   (2007-05-21 12:56) [14]

Если GetLastError возвращает ERROR_INVALID_HANDLE значит ProcessHandle кривой... Что-то ты видать там поправил.


 
Leonid Troyanovsky ©   (2007-05-21 13:03) [15]


> DmitrichJ   (21.05.07 12:45) [13]

> // Выделяем в нем память под структуру TGetTextLengthEx

А д.б.
{
var
 buf: array [0..255] of Char;
}

ShowMessage(Format("%d %s", [SendMessage(h, WM_GETTEXT, SizeOf(buf), LParam(@buf)), buf]));

--
Regards, LVT.


 
DmitrichJ   (2007-05-21 13:32) [16]

Не могу разобраться=(


 
Rouse_ ©   (2007-05-21 13:51) [17]

Кстати мне почему-то казалось, что для RICHEDIT система не делает проецируемый файл. Разве под 3.1 он уже существовал?


 
Leonid Troyanovsky ©   (2007-05-21 15:37) [18]


> Rouse_ ©   (21.05.07 13:51) [17]

> Кстати мне почему-то казалось, что для RICHEDIT система
> не делает проецируемый файл. Разве под 3.1 он уже существовал?


Она делает для WM_GETTEXT. А для, скажем, EM_ - уже не будет.
Вот например, для Wordpad (w2k3):

var
  buf: array [0..255] of Char;
  h : HWND;
begin
  h := FindWindow("WordpadClass", nil);
  h := FindWindowEx(h, 0, "RICHEDIT50W", nil);
  ShowMessage(Format("%d %s", [SendMessage(h, WM_GETTEXT, SizeOf(buf), LParam(@buf)), buf]));
end;

все получается.

--
Regards, LVT.


 
DmitrichJ   (2007-05-22 12:53) [19]

Хм... действительно работает.... круть.... А то в начале пример, столько писанины, а толку? Толька я не провверил, надеюсь, можно больше 255 символов?


 
DmitrichJ   (2007-05-22 12:59) [20]

А если в чужоп окне 2 RichEdit20A? По каким параметрам можно найти нужное?


 
Rouse_ ©   (2007-05-22 13:24) [21]


> А то в начале пример, столько писанины, а толку?

Первый пример делает тоже самое, только через EM_


 
Leonid Troyanovsky ©   (2007-05-22 14:49) [22]


> DmitrichJ   (22.05.07 12:53) [19]

>  надеюсь, можно больше 255 символов?

Хоть 64К.
Ну, а если больше, то подход такой, как в [1]
для EM_GETSELEXT, EM_STREAMOUT.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-05-22 14:51) [23]


> DmitrichJ   (22.05.07 12:59) [20]

> А если в чужоп окне 2 RichEdit20A? По каким параметрам можно
> найти нужное?

Например, по z-order. Или по координатам.

--
Regards, LVT.


 
DmitrichJ   (2007-05-22 15:29) [24]

64К, мне за уши. А как по координатам? Или вообще как узнать какие классы есть в чужом окне. Штудирую инет в доль и поперёк, но как-то всё не то.


 
Leonid Troyanovsky ©   (2007-05-22 15:41) [25]


> DmitrichJ   (22.05.07 15:29) [24]

> А как по координатам? Или вообще как узнать
> какие классы есть в чужом окне.

EnumChildWindows, GetClassName, GetWindowRect

--
Regards, LVT.


 
DmitrichJ   (2007-05-22 15:49) [26]

Последний вопрос. в чужом окне есть кнопка "Button". Можно ли отследить её надатие в хуке?


 
Leonid Troyanovsky ©   (2007-05-22 18:06) [27]


> DmitrichJ   (22.05.07 15:49) [26]

> Последний вопрос. в чужом окне есть кнопка "Button". Можно
> ли отследить её надатие в хуке?

Окна класса "BUTTON" получают сообщения BM_*, например, BM_CLICK. Идентифицировать кнопку можно, например, GetDlgCtrlId.

--
Regards, LVT.


 
DmitrichJ   (2007-05-22 19:42) [28]

Кнопку индентифицировал, но отследить нажатие не получается =(


 
Leonid Troyanovsky ©   (2007-05-22 19:59) [29]


> DmitrichJ   (22.05.07 19:42) [28]

> Кнопку индентифицировал, но отследить нажатие не получается

У тебя ошибка в 17 строке.

--
Regards, LVT.


 
DmitrichJ   (2007-05-22 22:04) [30]

?
Где у меня? Я пример Rouse_ не использую.


 
Leonid Troyanovsky ©   (2007-05-22 23:41) [31]


> DmitrichJ   (22.05.07 22:04) [30]

> Где у меня? Я пример Rouse_ не использую.

У уважаемого Rouse_ © с этим, как раз, нормально.

--
Regards, LVT.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.042 c
2-1194958126
Ega23
2007-11-13 15:48
2007.12.09
Приведение Boolean к Integer


2-1194789862
SveTTT
2007-11-11 17:04
2007.12.09
Переменная в переменную


6-1152330319
Yuron
2006-07-08 07:45
2007.12.09
Браузер на Indy


15-1194738002
Kostafey
2007-11-11 02:40
2007.12.09
С днем рождения ! 11 ноября


15-1194890026
Wu Wei
2007-11-12 20:53
2007.12.09
О закрытии веток





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский