Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.12.09;
Скачать: CL | DM;

Вниз

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 вся ветка

Текущий архив: 2007.12.09;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.025 c
2-1194962162
Malik
2007-11-13 16:56
2007.12.09
ShellAPI парадокс и ничего более??


2-1195110089
VladSot
2007-11-15 10:01
2007.12.09
Вопрос по TListView


2-1194871765
СержК
2007-11-12 15:49
2007.12.09
Есть ли для TreeView что-то вроде AfterScrol


15-1194461905
vasIZmax
2007-11-07 21:58
2007.12.09
Взялись бы ли вы за проект, который просто обречен на провал&amp;#133


3-1185537092
Nemec
2007-07-27 15:51
2007.12.09
компоненты TIBQuery и IBUpdateSQL1