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

Вниз

Получение handle-а активного компонента (вне рабочей формы)   Найти похожие ветки 

 
Delphi5.01 ©   (2006-05-05 13:16) [0]

Доброе время суток,
У меня возник вот такой вопрос, как можно вставить текст в компонент который на данный момент активен. Речь идет не только о компонентах рабочей формы но например если на данный момент активно приложение MS Word то текст должен вставляться на место курсора и т.д.
В интернете уже искал, похожей задачи к сожалению не нашел, может не правильно поиск давал? Помню были API функции для работы с буфером, типа копирования и вставки но для начала нужно как то получить handle компонента который на данный момент активен.
Заранее благодарю всех за уделенное время и желание помочь


 
доп_инф   (2006-05-05 13:59) [1]

Хотел бы уточнить что я знаю функцию которая возвращает handle активного окна GetForegroundWindow но как я догадываюсь теперь, продеться проверить все его дочерние окна, так как все компоненты, в том числе все edit, reachedit и т.д. на самом деле являются "окнами".


 
ANB ©   (2006-05-05 17:27) [2]

1) Если ты кликнешь по своей кнопке, то активное приложение им быть перестанет
2) keybd_event печатает именно на активном окне. Так же, как на клавиатуре. писать много.


 
VEZ   (2006-05-05 18:26) [3]

Оффтопик, но MS Office и вообще все продукты майкрософт не используют стандартные компоненты винды, интересно почему:).


 
доп_инф   (2006-05-05 21:55) [4]

Спасибо но вставку я буду делать на шорткатах, и с помощью хуков, так что мое окно вообще не будет активным а будет работать в фоновом режиме.
Есть подозрения что нужно будет найти активное окно и потом в нем среди чайлд виндоу найти активное (должно соответствовать окну где находиться курсор).
Что вы думаете насчет такого размышления?


 
Мефисто   (2006-05-05 22:03) [5]

Фиг знает :) А WinSight32 в поставке с дельфей чего говорит? Сделай два простых тестовых приложения, поэксперементируй с ними, поизучай какие сообщения пролетают. Может в теории сколько-то поможет.


 
Delphi5.01 ©   (2006-05-05 23:15) [6]

Типа думаю надо тему в раздел Win32 переносить, вот что я раскопал пока :-)

procedure TForm1.findActiveWindow();
 var
   activeHWND: HWND;
   activeThreadID: DWORD;
   GUIThreadInfo: tagGUITHREADINFO;
begin
 activeHWND := GetForegroundWindow;
 GetWindowThreadProcessId(activeHWND, activeThreadID);
 GetGUIThreadInfo(activeThreadID, GUIThreadInfo);
 ShowWindow(GUIThreadInfo.hwndActive, SW_HIDE)
 ShowMessage(inttostr(GUIThreadInfo.hwndActive));
end;

Думаю я не правильно получаю activeThreadID :-(
Вся дока вот здесь по теме:
1) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/getguithreadinfo.asp
2) http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowstructures/guithreadinfo.asp

Что думаешь Мефисто?


 
Delphi5.01 ©   (2006-05-05 23:22) [7]

procedure TForm1.findActiveWindow();
 var
   activeHWND: HWND;
   activeThreadID: DWORD;
   GUIThreadInfo: tagGUITHREADINFO;
   i: integer;
begin
 activeHWND := GetForegroundWindow;
 GetWindowThreadProcessId(activeHWND, activeThreadID);
 GetGUIThreadInfo(activeThreadID, GUIThreadInfo);
 ShowWindow(GUIThreadInfo.hwndActive, SW_HIDE);

 for i:=0 to Form1.ComponentCount-1 do begin
   if (GUIThreadInfo.hwndActive = (Form1.Components[i] as TWinControl).Handle) then
     ShowMessage((Form1.Components[i] as TWinControl).Name);
 end;
end;


Выше приведенный пример доказывает что не правильно определяется activeThreadID, так как в противном случае данная функция должна отобразить имя компонента (button-а) на нажатие которого вызывается данная функция (он и является активным)


 
Delphi5.01 ©   (2006-05-05 23:28) [8]

procedure TForm1.findActiveWindow();
 var
   activeHWND: HWND;
   activeThreadID: DWORD;
   GUIThreadInfo: tagGUITHREADINFO;
begin
 activeHWND := GetForegroundWindow;
 GetWindowThreadProcessId(activeHWND, activeThreadID);
 if GetGUIThreadInfo(activeThreadID, GUIThreadInfo) then
   ShowMessage("Success") else
   ShowMessage("Failure");
end;


Результат как и ожидалось Failure :-( что делать, кто посоветует?


 
Мефисто   (2006-05-06 00:49) [9]

GetWindowThreadProcessId  - получение ID потока некоего процесса, вроде сразу не то.

GetForegroundWindow - возвращает хендл активного окна (конкретно то, что подразумевается под формой).


 
Leonid Troyanovsky ©   (2006-05-06 01:05) [10]


> Delphi5.01 ©   (05.05.06 23:28) [8]


>  GetWindowThreadProcessId(activeHWND, activeThreadID);

activeThreadID := GetWindowThreadProcessId(activeHWND, nil);

> Результат как и ожидалось Failure :-( что делать, кто посоветует?

GetLastError? В смысле, Win32Check.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2006-05-06 01:32) [11]


> доп_инф   (05.05.06 21:55) [4]

> в нем среди чайлд виндоу найти активное (должно соответствовать
> окну где находиться курсор).


AttachThreadInput & GetFocus.

Пример я недавно, IMHO, приводил.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2006-05-06 01:43) [12]


> Delphi5.01 ©   (05.05.06 13:16)  

>  может не правильно поиск давал? Помню были API функции
> для работы с буфером, типа копирования и вставки но для


Про буфер можно забыть, это для юзера.
Вставлять текст можно, например, путем WM_SETTEXT.

Только, например, для Word это может и не пройти.
Возможно, что для него это EM_SETSEL (который, в отличии
от WM_SETTEXT, должен посылаться из потока, принадлежащего
целевому приложению). И, скорее всего, путем SendMessageW.

Ну, а, вообще-то, с такими монстрами как Word, IE & etc давно уж
положено общаться через COM.

--
Regards, LVT.


 
Delphi5.01 ©   (2006-05-06 03:42) [13]

Вот рабочий вариант программы, но как всегда возникли проблемы с продуктами MS, например данный код не работает для полей IE
При получении активного контрола в IE процедура получает handle всей странички (а не отдельного edit-а)

procedure TForm1.findActiveWindow();
 var
   Wnd: HWnd;
   GuiInfo:TGUIThreadInfo;
begin
 Wnd:= GetForegroundWindow;
 GuiInfo.cbSize:=SizeOf(TGUIThreadInfo);
 GetGUIThreadInfo(GetWindowThreadProcessId(Wnd),GuiInfo);
 Edit1.CopyToClipboard;
 //ShowWindow(GuiInfo.hwndFocus, SW_HIDE);
 //SendMessage(GuiInfo.hwndFocus, WM_SETTEXT, 0, integer(pChar(Edit1.Text)));
 //PostMessage(GuiInfo.hwndFocus, WM_PASTE, 0, 0);
 Application.ProcessMessages;
end;

Вот рабочий пример но для IE нужно работать через IShellWindows, IWebbrowser2 и т.д. Но получаеться что, для простой вставки нужно разбирать довольно обемную документацию :-(
http://www.swissdelphicenter.ch/torry/showcode.php?id=1732

Что вы посоветуюете почитать на счет работы с IE через OLE, только пожалйста не давайте документацию на MSDN или похожую сухую доку. Желательно с примером и в пошагвом режиме :-)

Заранее благодарю :-)


 
Delphi5.01 ©   (2006-05-06 08:26) [14]

Вот только что сообразил что приме на выше указанной страничке не подходит, так как он работает с компонентом WebBrowser1: TWebBrowser; который находиться на рабочей форме а не на внешней программе :-(
...
FillInGMXForms(Web, iDoc1, Webbrowser1.Document, "user@gmx.net", "pswd");
...


 
Delphi5.01 ©   (2006-05-06 09:38) [15]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, OleCtrls,
 mshtml, activeX, Shdocvw_tlb;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   procedure findActiveWindow();
   procedure hotykey(var msg:TMessage); message WM_HOTKEY;
 end;

var
 Form1: TForm1;
 id,id2:Integer;

implementation

{$R *.dfm}

type
 TObjectFromLResult = function(LRESULT: lResult; const IID: TIID; WPARAM: wParam; out pObject): HRESULT; stdcall;

function GetIEFromHWND(WHandle: HWND; var IE: IWebbrowser2): HRESULT;
var
 hInst: HWND;
 lRes: Cardinal;
 MSG: Integer;
 pDoc: IHTMLDocument2;
 ObjectFromLresult: TObjectFromLresult;
begin
 hInst := LoadLibrary("Oleacc.dll");
 @ObjectFromLresult := GetProcAddress(hInst, "ObjectFromLresult");
 if @ObjectFromLresult <> nil then begin
   try
     MSG := RegisterWindowMessage("WM_HTML_GETOBJECT");
     SendMessageTimeOut(WHandle, MSG, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes);
     Result := ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc);
     if Result = S_OK then
       (pDoc.parentWindow as IServiceprovider).QueryService(IWebbrowserApp, IWebbrowser2, IE);
   finally
     FreeLibrary(hInst);
   end;
 end;
end;

procedure TForm1.findActiveWindow();
 var
   Wnd: HWnd;
   GuiInfo:TGUIThreadInfo;
   IE: iwebbrowser2;
   x: Olevariant;
begin
 Wnd := GetForegroundWindow;
 GuiInfo.cbSize:=SizeOf(TGUIThreadInfo);
 GetGUIThreadInfo(GetWindowThreadProcessId(Wnd),GuiInfo);
 GetIEFromHWnd(GuiInfo.hwndFocus, IE);
 IE.Navigate("http://google.com", x, x, x, x);
end;

procedure TForm1.hotykey(var msg:TMessage);
var
 IDoc1: IHTMLDocument2;
 Web: ShDocVW_TLB.IWebBrowser2;
begin
   if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=ord("Q")) then begin
       findActiveWindow();
       //ShowMessage("Ctrl + Q wurde gedr&#252;ckt !");
   end;

   if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=ord("R")) then begin
       ShowMessage("Ctrl + R wurde gedr&#252;ckt !");
   end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   id:=GlobalAddAtom("hotkey");
   RegisterHotKey(handle,id,mod_control,ord("Q"));

   id2:=GlobalAddAtom("hotkey2");
   RegisterHotKey(handle,id2,mod_control,ord("R"));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   UnRegisterHotKey(handle,id);
   UnRegisterHotKey(handle,id2);
end;

Вот рабочи вариант который перенаправляет активную страничку браузера на адресс google.com, браузер в этот момент должен иметь фокус. Надо заметить что при разработке была использованна утилита SypXX от MS. Теперь осталось малое, найти нужный филд в iwebbrowser2 и сменить значение :-)


 
почти_что_решение   (2006-05-06 10:21) [16]

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, OleCtrls,
 mshtml, activeX, Shdocvw_tlb;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   Memo1: TMemo;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   procedure findActiveWindow();
   procedure hotykey(var msg:TMessage); message WM_HOTKEY;
 end;

var
 Form1: TForm1;
 id,id2:Integer;

implementation

{$R *.dfm}

type
 TObjectFromLResult = function(LRESULT: lResult; const IID: TIID; WPARAM: wParam; out pObject): HRESULT; stdcall;

function GetIEFromHWND(WHandle: HWND; var IE: IWebbrowser2): HRESULT;
var
 hInst: HWND;
 lRes: Cardinal;
 MSG: Integer;
 pDoc: IHTMLDocument2;
 ObjectFromLresult: TObjectFromLresult;
begin
 hInst := LoadLibrary("Oleacc.dll");
 @ObjectFromLresult := GetProcAddress(hInst, "ObjectFromLresult");
 if @ObjectFromLresult <> nil then begin
   try
     MSG := RegisterWindowMessage("WM_HTML_GETOBJECT");
     SendMessageTimeOut(WHandle, MSG, 0, 0, SMTO_ABORTIFHUNG, 1000, lRes);
     Result := ObjectFromLresult(lRes, IHTMLDocument2, 0, pDoc);
     if Result = S_OK then
       (pDoc.parentWindow as IServiceprovider).QueryService(IWebbrowserApp, IWebbrowser2, IE);
   finally
     FreeLibrary(hInst);
   end;
 end;
end;

procedure FillInGMXForms(IE: IWebbrowser2);
var
 i: Integer;
 m: Integer;
 ovElements: OleVariant;
 Document: Variant;
begin
 Document := IE.Document;
 //Poisk vsekh form na strnichke
 for m := 0 to Document.forms.Length - 1 do
 begin
   ovElements := Document.forms.Item(m).elements;

   //Perebor vsekh plov v zadannoi forme
   for i := ovElements.Length - 1 downto 0 do
   begin
     try
       if (ovElements.item(i).name = "username") then
         ovElements.item(i).Value := "myTest";
         
       form1.Memo1.Lines.Add(ovElements.item(i).id + ":" + ovElements.item(i).name + ":" +
         ovElements.item(i).tagName + ":" + ovElements.item(i).type);
     except
     end;
   end;
 end;
end;

procedure TForm1.findActiveWindow();
 var
   Wnd: HWnd;
   GuiInfo:TGUIThreadInfo;
   IE: IWebBrowser2;
   x: Olevariant;
begin
 Wnd := GetForegroundWindow;
 GuiInfo.cbSize:=SizeOf(TGUIThreadInfo);
 GetGUIThreadInfo(GetWindowThreadProcessId(Wnd),GuiInfo);
 GetIEFromHWnd(GuiInfo.hwndFocus, IE);
 FillInGMXForms(IE);
end;

procedure TForm1.hotykey(var msg:TMessage);
var
 IDoc1: IHTMLDocument2;
 Web: ShDocVW_TLB.IWebBrowser2;
begin
   if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=ord("Q")) then begin
       findActiveWindow();
       //ShowMessage("Ctrl + Q wurde gedr&#252;ckt !");
   end;

   if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=ord("R")) then begin
       ShowMessage("Ctrl + R wurde gedr&#252;ckt !");
   end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   id:=GlobalAddAtom("hotkey");
   RegisterHotKey(handle,id,mod_control,ord("Q"));

   id2:=GlobalAddAtom("hotkey2");
   RegisterHotKey(handle,id2,mod_control,ord("R"));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   UnRegisterHotKey(handle,id);
   UnRegisterHotKey(handle,id2);
end;

end.

Данный пример полно функциональный, но к сожалению он может находить в IE нужное поле с нужным именем и заполнять. Мне же желательно найти сразу ктивное поле
Надеюсь комуто данный пример поможет, вот дополнительные ссылки которые будут интерестны и конечно в любое время можете мылить :-)

http://www.swissdelphicenter.ch/torry/showcode.php?id=1732
http://msdn.microsoft.com/workshop/author/dhtml/reference/collections/children.asp



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

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

Наверх




Память: 0.54 MB
Время: 0.047 c
2-1148633281
ASW
2006-05-26 12:48
2006.06.11
Работа с группой компонентов


15-1147786895
Andy BitOff
2006-05-16 17:41
2006.06.11
Может кто знает форум ...


1-1146734024
DelphiLexx
2006-05-04 13:13
2006.06.11
Проблема с TSpeedButton ом


3-1144947505
parovoZZ
2006-04-13 20:58
2006.06.11
Вытащить номер ошибки из ADOQuery


11-1127963073
dvk
2005-09-29 07:04
2006.06.11
TKOLPanel.Font.Color не меняется