Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Посыл к чужим приложениям


Автор: Chydik 13.6.2009, 11:25
Надо из чужого приложения из компоненты RichViewEdit скопировать текст.

Дескриптор получаю, но нет риакции на WM_GETTEXT,EM_GETTEXTEX.

Вот код:
Код

com :=  FindWindowEx(targetWnd,0,'TRichViewEdit',nil);
len:=SendMessage(com,EM_GETTEXTLENGTHEX, GTL_DEFAULT,0);
SetLength (txt, len);
RichEdit1.Text:=inttostr(len);
PostMessage(com,EM_GETTEXTEX, 0 , integer(PChar(txt)));

C сообщениями тольк начал разбираться.
Мож что не так делаю.

Есль кто знает помогите.

Автор: Keeper89 13.6.2009, 12:42
Я уже отвечал на подобный вопрос вот в http://forum.vingrad.ru/forum/topic-261954.html теме, да и на форуме думаю вы уже не первый с таким вопросом.
Если у вас есть что-то "специфическое" в реализации, выкладывайте, например опишите программу, из которой берете текст.

Автор: Chydik 13.6.2009, 13:39
Не наезжать на кривизну кода прост покуд експерементирую с дескрипторами и сообщениями. smile 

Код

function Find(s: string): hWnd;
var
  Wnd: hWnd;
  buff: array[0..127] of Char;
begin
  Find := 0;
  Wnd := GetWindow(Form1.Handle, gw_HWndFirst);
  while Wnd <> 0 do
  begin
    if (Wnd <> Application.Handle) and
      IsWindowVisible(Wnd) and
      (GetWindow(Wnd, gw_Owner) = 0) and
      (GetWindowText(Wnd, buff, sizeof(buff)) <> 0) then
    begin
      GetWindowText(Wnd, buff, sizeof(buff));
      if Copy(buff,1,Length(s))= s then
      begin
        Find := Wnd;
        Break;
      end;
    end;
    Wnd := GetWindow(Wnd, gw_hWndNext);
  end;
end;


function GetCaptionAtPoint(CrPos: TPoint): string;
 var
   textlength: Integer;
   Text: PChar;
   Handle: HWND;
 begin
   Result := 'Empty';
   Handle := WindowFromPoint(CrPos);
   if Handle = 0 then Exit;
   textlength := SendMessage(Handle, WM_GETTEXTLENGTH, 0, 0);
   if textlength <> 0 then
   begin
     getmem(Text, textlength + 1);
     SendMessage(Handle,WM_GETTEXT, textlength + 1, Integer(Text));
     Result := Text;
     freemem(Text);
   end;

 end;

procedure TForm1.Button5Click(Sender: TObject);
var
   targetWnd,TheChildHandle,com: HWND;
   pr,editpt:TPoint;
   l:TRect;
   txt,xaxaxa:string;
   len:integer;

 begin

//WinExec(PChar(('"'+PPath+'\tmaker.exe" ')+'"'+FileListBox1.fileName+'"'),sw_ShowNormal);
    targetWnd :=Find('tMaker');
    if targetWnd <> 0 then
     begin
      Form1.Caption:='1';
       BringWindowToTop(targetWnd);
        GetWindowRect(targetWnd,l);
         PostKeyExHWND(targetWnd, VK_F10, [], False);
         pr.X:=l.Left+200;
         pr.Y:=l.Top+200;
          TheChildHandle :=WindowFromPoint(pr);
           sleep(1000);
           pr.X:=l.Left+200;
           pr.Y:=l.Top+200;
         TheChildHandle :=WindowFromPoint(pr);
           PostKeyExHWND(TheChildHandle, VK_TAB, [], False);
           PostKeyExHWND(TheChildHandle, VK_TAB, [], False);
           PostKeyExHWND(TheChildHandle, VK_TAB, [], False);
           PostKeyExHWND(TheChildHandle, VK_TAB, [], False);
         GetWindowRect(TheChildHandle,l);

            Editpt.X:=l.Left+20;
            Editpt.Y:=l.Top+111;
            Edit1.Text:=GetCaptionAtPoint(Editpt);

        Editpt.X:=l.Left+270;
        Editpt.Y:=l.Top+65;
        Edit2.Text:=GetCaptionAtPoint(Editpt);
        Editpt.X:=l.Left+270;
        Editpt.Y:=l.Top+5; 
        com :=  WindowFromPoint(Editpt); Editpt.X:=l.Left+100;
        Editpt.Y:=l.Top+350;

        PostMessage(com,WM_LBUTTONDBLCLK, 10, 10);
        PostKeyExHWND(TheChildHandle, VK_RIGHT, [], False);
        PostKeyExHWND(TheChildHandle, VK_RIGHT, [], False);
        PostKeyExHWND(TheChildHandle, VK_RIGHT, [], False);
        PostKeyExHWND(TheChildHandle, VK_RIGHT, [], False);
        PostKeyExHWND(TheChildHandle, VK_RETURN, [], False);

        com :=  FindWindowEx(targetWnd,0,'TRichViewEdit',nil);
        len:=SendMessage(com,EM_GETTEXTLENGTHEX, GTL_NUMBYTES,0);
        SetLength (txt, len);
        RichEdit1.Text:=inttostr(len);
        PostMessage(com,EM_GETTEXTEX, 0 , integer(PChar(txt)));
        RichEdit1.Text:=RichEdit1.Text+txt;
  end;
 end;



Есть программка tMaker для создания тестов и srt (сами тесты).
Надо Выдрать из тестов Автора, Название теста, и Описание.
С автором и названием разобрался(хоть и черезчур криво, но пашет), а вот описание из TRichViewEdit никак не могу выдрать(в ручную енто будет вешалка т.к. тестов просто тьма).

Сперва использовал поиск дескрипторов по позициям покуд не разобрался как получать название классов.


http://depositfiles.com/files/s53roj3x3

Автор: Keeper89 13.6.2009, 15:51
Chydik, залей тест куда-нибудь еще (http://webfile.ru/) или разбей на архивы по 1Мб и загрузи здесь.

Автор: Chydik 13.6.2009, 16:18
Выкладываю!

Автор: Chydik 13.6.2009, 16:25
Второй!

Автор: Chydik 13.6.2009, 16:27
И третий...

Автор: Keeper89 13.6.2009, 16:38
Цитата(Chydik @  13.6.2009,  14:39 Найти цитируемый пост)
Надо Выдрать из тестов Автора, Название теста, и Описание.

Это я так понимаю в свойствах теста?

Каким образом будет "выдираться" информация? Насколько я понял, будет открываться каждый тест и тогда уже копироваться данные...

Автор: Chydik 13.6.2009, 17:01
1.Да в свойствах(F10)

2.Да(, будет открываться каждый тест) прост другого варианта я не вижу.
Непосредственно из тестов выдрать не могу.

Автор: Keeper89 13.6.2009, 20:23
Долго провозился с этим делом, пробовал посылку сообщений, но судя по заявлению автора (http://www.trichview.com/forums/viewtopic.php?t=2639&highlight=wmgettext, http://www.trichview.com/forums/viewtopic.php?t=1358&view=next)
Цитата

Processing of WM_GETTEXT, WM_GETTEXTLENGTH, WM_SETTEXT was disabled for Delphi 2005 and 2006, because it conflicted with VCL implementation. Sorry, I do not plan to restore them. 

они не реализованы.
Вроде бы реализованные сообщения EM_*** тоже у меня не работают.

В итоге получилось сделать через буфер обмена:
Код

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  DescriptionOptionsHandle: THandle;


implementation

{$R *.dfm}

uses ClipBrd;


function IsDescriptionOptions(wnd: THandle): Boolean;
begin
  // Ищем описание в свойствах
  Result := FindWindowEx(wnd, 0, 'TRichViewEdit', nil) <> 0;
end;

function EnumProc(wnd: HWND): BOOL; stdcall;
begin
  Result := True;
  if IsDescriptionOptions(wnd) then
    descriptionOptionsHandle := wnd;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  H, TabsHandle,
  DescriptionHandle: THandle;
begin
  H := FindWindow('TTestForm', Nil);
  if H <> 0 then
  begin
    TabsHandle := FindWindowEx(H, 0, 'TSpTBXTabControl.UnicodeClass', nil);
    if TabsHandle <> 0 then
    begin
      // Определяем целевой таб
      EnumChildWindows(TabsHandle, @EnumProc, 0);
      DescriptionHandle := FindWindowEx(DescriptionOptionsHandle, 0,
                           'TRichViewEdit', nil);
      if DescriptionHandle <> 0 then
      begin
        // Выделяем весь текст и копируем его в буфер обмена
        SendMessage(DescriptionHandle, EM_SETSEL, WPARAM(0), LPARAM(-1));
        SendMessage(DescriptionHandle, WM_COPY, 0, 0);
        Showmessage(Clipboard.asText);
      end
      else
        Showmessage('RichViewEdit не найден!')
    end
    else
      Showmessage('TSpTBXTabControl.UnicodeClass не найден!');
  end
  else
    Showmessage('Окно "Свойства теста" не найдено!');

end;


Добавлено через 2 минуты и 10 секунд
Цитата(Chydik @  13.6.2009,  18:01 Найти цитируемый пост)
1.Да в свойствах(F10)

2.Да(, будет открываться каждый тест) прост другого варианта я не вижу.
Непосредственно из тестов выдрать не могу. 

Я бы рекомендовал этот процесс автоматизировать. Например, запускать по очереди все тесты в программе, запускать окно свойств и брать информацию. Так (без запусков тестирования и открывания окон) работа действительно станет легче.

Автор: Chydik 13.6.2009, 20:42
 smile ОГРОМНОЕ ЧЕЛОВЕЧЕСКОЕ СПАСИБО. smile 
Счас протестю.

Цитата

Я бы рекомендовал этот процесс автоматизировать. Например, запускать по очереди все тесты в программе, запускать окно свойств и брать информацию. Так (без запусков тестирования и открывания окон) работа действительно станет легче.


Я и планирую все енто автоматизовать для ентого и начал разбираться(Будет создан список всех тестов(программно) и по очередно запускаться, а тем временем можно чаю попить smile ).
Или ты имееш ввиду после получения не закрывать прогу, а загружать в нее новый тест?

Автор: Chydik 13.6.2009, 21:31
 smile Все суперски работает еще раз огромное спасибо.

Но тольк одна загвоздка - с буфером. smile 
Если буфер направить в переменную то все ок, но в РичЕдит(На моей форме) не передается даже посредством етой переменной.
Цитата

Access violation at adress 00469 in module 'SrtSave.exe'. Read of Adress 0000033C

Может знаешь в чем может быть проблемма.

Автор: Keeper89 13.6.2009, 23:26
Цитата(Chydik @  13.6.2009,  21:42 Найти цитируемый пост)
smile ОГРОМНОЕ ЧЕЛОВЕЧЕСКОЕ СПАСИБО. smile 

Пожалуйста ;)
Цитата(Chydik @  13.6.2009,  21:42 Найти цитируемый пост)
Или ты имееш ввиду после получения не закрывать прогу, а загружать в нее новый тест? 

Это не обязательно, под полной автоматизацией я имею ввиду указание директории с тестами и нажатие на волшебную кнопку. Как конкретно это будет реализовано - не важно.
Цитата(Chydik @  13.6.2009,  22:31 Найти цитируемый пост)
Если буфер направить в переменную то все ок, но в РичЕдит(На моей форме) не передается даже посредством етой переменной.

Ошибся в функции EnumProc, правильно написать так:
Код

function EnumProc(wnd: HWND; lParam: LongInt): Boolean; stdcall;

теперь спокойно работает
Код

RichEdit1.Text := Clipboard.AsText;

Автор: Chydik 14.6.2009, 00:39
Теперь все просто супер. smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)