Форум: "Основная";
Текущий архив: 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ückt !");
end;
if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=ord("R")) then begin
ShowMessage("Ctrl + R wurde gedrü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ückt !");
end;
if (msg.LParamLo=MOD_CONTROL) and (msg.LParamHi=ord("R")) then begin
ShowMessage("Ctrl + R wurde gedrü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