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

Вниз

Получение 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.013 c
3-1145514966
vishnia
2006-04-20 10:36
2006.06.11
Индексы в Access


9-1131219429
Bogdan1024
2005-11-05 22:37
2006.06.11
DoCollision


15-1145593459
pavel_guzhanov
2006-04-21 08:24
2006.06.11
Получил вот такое письмо


6-1139248031
justy
2006-02-06 20:47
2006.06.11
передать голос по сети


2-1148299061
Hitkliff
2006-05-22 15:57
2006.06.11
Снова веббраузер!!!





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