Форум: "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