flashのハンドルを取得してみよう。
執筆:2011.10.19
編集:2011.10.19
TWebBrowser.HWNDを取得する方法 (
メモ: その2)
flashのハンドルを取得してみよう。
【方法1】 : Tag名からリストアップする
var
H : THandle;
i : Integer;
v_Doccument, v_elems , v_attr : Variant;
s : string;
begin
v_Doccument := WebBrowser1.Document;
if VarIsClear(v_Doccument)
or
('Internet Explorer_Server'
<> GetClassNameText(GetWindowHandleFromIDispatch(v_Doccument)))
then
begin
Exit;
end;
v_elems := v_Doccument.getElementsByTagName('OBJECT');
if Not VarIsClear(v_elems)
and (v_elems.length > 0) then
begin
s := 'count: '+IntToStr(v_elems.length) + sLineBreak;
for i := 0 to v_elems.length -1 do
begin
v_attr := v_elems.Item(i).getAttribute('CLASSID');
if Not VarIsClear(v_attr)
and (VarToStr(v_attr)
= 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000')
then
begin
s := s + v_attr + sLineBreak;
H := GetWindowHandleFromIDispatch(v_elems.Item(i));
s := s + ' HWND: ' + IntToStr(H) + sLineBreak + sLineBreak;
end;
end;
ShowMessage(s);
end;
end;
|
【方法2】 : 子Windowから探す
flashオブジェクトが htmlの
最上位に貼り付けられている場合の例です。
※iframeなどに入っている場合は、下位階層まで追いかける必要があります。
※単一のflashが htmlに張り付いている場合。
function SearchFlashHandle(p_hwnd : HWND) : HWND;
var
c_hwnd : HWND;
begin
Result := 0;
c_hwnd := GetWindow(p_hwnd, GW_CHILD );
while (c_hwnd > 0) do
begin
// ClassName[MacromediaFlashPlayerActiveX]
if (Pos('MacromediaFlashPlayerActiveX',
GetClassNameText(c_hwnd)) = 1) then
begin
Result := c_hwnd;
break;
end;
c_hwnd := GetWindow(c_hwnd, GW_HWNDNEXT );
end;
end; |
使用例 : SetFocusする。
h := GetWindowHandleFromIDispatch(WebBrowser1.Document);
flash_handle := SearchFlashHandle(h);
if (flash_handle > 0) then
Windows.SetFocus(flash_handle);
|
GetWindowHandleFromIDispatch関数については、
TWebBrowser.HWNDを取得する方法 (
メモ:
その1)
に書いてあります。
TWebBrowserで、どうしても入力フォーカスを当てたい際に役に立ちます。
flash以外の他のオブジェクトも同様に応用することができます。
さようなら Delphi
レッツゴー ドットネット
それいけ ドットネット
それいけ C#
TWebBrowser.HWNDを取得する方法 (
メモ:
その1)
執筆:2011.10.17
編集:2011.10.17
今日は、
C#へレッツゴー
さぁ Delphiなんか捨てて みんなドットネットへ Go !!
それいけ ドットネット推進派 の 禁断のDelphiネタです。
次期Windows8 の 「
Windows Developer Preview版」が無償公開 されていますが
もう みなさんは、お使いですか?
※OSのアンインストール機能がないそうなので、インス トールは気をつけてください
Visual Studio 11 Expressの同梱版もあり すごいお試し版OSです。
“Win RunTime(WinRT)”と呼ばれる新しいAPIが追加され
新しいデスクトップ“Metro”では、新しい“Metro”対応のアプリケーション(“Metro style apps”)
なんていうものが必要になるそうです。
キット古い開発環境とアプリを市場から強制排除したいのでしょうね。
もう、Visual Studio意外に開発環境の選択の余地がないって感じになってきましたね。
ということで、 ほらほら、 みんなドットネットへ Go !!
では、本題です。
TWebBrowser.HWNDへのアクセスは不正なエラーに なります。
WebBrowser1.Handleでいいようです。
構造
ページを表示するとコンテンツに応じて 上の3つが、階層構造で多様につながる。
iframeなどの要素があると多重構造になるようです。
※ コードを参考にする場合は、自己責任で参考にされてください。
※ 十分なテストが必要です。
※ 将来的に、仕様などの変更で利用できなくなることも考えられます。
【TWebBrowser.HWNDは、無効なプロパティ】
(MSDN 文書番号: 244310):
※要約 子WindowをたどっていくとHandleを取得することができます。
※ TWebBrowser.HWND
|
Web ブラウザの Window ハンドルへのアクセスを提供します。 |
※ Delphiでは、TWebBrowser.HWNDは使えません。 |
コード |
WebBrowser1.HWND; |
実行結果 |
デバッガ例外通知
プロジェクト は例外クラス EOleException (メッセージ 'エラーを特定できません')を送出しました。 |
【HTML要素からhandleを取得する方法。】
ハンドルを 直接要求する方法
|
|
// [エラー] : E2010 'System.TGUID' と 'Ole2.TGUID' には互換性がありません
const // From Ole2.pas
IID_IOleWindow: TGUID = (
D1:$00000114;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
function GetWindowHandleFromIDispatch(disp: IDispatch) : HWND;
var
h : hwnd;
Res : HRESULT;
oWin : IOleWindow; // Unit ActiveX.pas
begin
// example: GetWindowHandleFromIDispatch(WebBrowser1.Document)
Result := 0;
Res := disp.QueryInterface(IID_IOleWindow, oWin);
if Succeeded(Res) then
begin
Res := OWin.GetWindow(h);
if (SUCCEEDED(Res)) then
Result := h;
end;
end;
|
使
い
方
|
// Class : Internet Explorer_Server
h := GetHTMLObjectWindowHandle(WebBrowser1.Document);
if (h > 0) then
Windows.SetFocus(h); |
(参考)正 規のhtml要素のfocusの使い方
|
|
// HtmlElement から直接呼び出す場合
// HtmlElement.focus();
var
v : Variant;
begin
v_Doccument := WebBrowser1.Document;
if Not VarIsClear(v_Doccument) then
v_Doccument.focus();
|
|
var
v_Doccument, v_elems : Variant;
begin
v_Doccument := WebBrowser1.Document;
if VarIsClear(v_Doccument) then exit;
v_elems := v_Doccument.getElementsByName('ここにhtml要素の名前');
if Not VarIsClear(v_elems)
and (v_elems.length > 0) then
v_elems.Item(0).focus();
|
擬似キー入力を送るコード:Function Key
var
H : THandle;
begin
h := GetWindowHandleFromIDispatch(WebBrowser1.Document);
Windows.PostMessage(H , WM_KEYDOWN, VK_F1 , 0);
|
擬似キー入力を送るコード:通常文字
var
H : THandle;
begin
h := GetWindowHandleFromIDispatch(WebBrowser1.Document);
Windows.PostMessage(H , WM_CHAR, Byte('a') , 0);
end;
|
ALT+F4(終了)を呼びたい場合は
WM_SYSKEYDOWN を使います
Windows.PostMessage(TargetHandle ,
WM_SYSKEYDOWN , wParam, lParam); |
|
wParam
|
lParam
|
VK_F4 + ALT |
VK_F4
|
1 shl 29 |
VK_F1
IEのF1(ヘルプ)の呼び出しは、反応しないのでわかりません。
Firefox系の他のブラウザでは反応します。
テキストボックスに文字列をいれるだけなら、
普通にgetElementsByNameやgetElementByIdなどで
要素にアクセスして代入した方が安全に入力できます。
普通にテキストボックスに入力する方法
( 応用例:ログインIDなどの自動入力 )
例
v_elems.Item(0).innerText := 'abc';
|
|
.innerText |
|
.innerHTML |
コンボボックス
(selectタグのoption要素)
|
e.options[e.selectedIndex].text
e.options[e.selectedIndex].value
|
使い方は、基本的にJavaScriptと同じ。
【一番上のShell DocObject View の HWND 取得方法】
GetWindow(WebBrowser1.Handle, GW_CHILD )
※ ClassNameで、確認した方がいい 、 GW_HWNDNEXT
Navigateでフォルダを指定した場合、エクスプローラーが内蔵されるので注意。 SysListView32などが現れる。
function GetWebBrowser_Root_ShellDocObject_Handle(AWebBrowser : TWebBrowser) : hwnd;
// Shell DocObject View
var
h : hwnd;
begin
h := GetWindow(AWebBrowser.Handle, GW_CHILD );
while (h > 0) do
begin
if (Pos('Shell DocObject View', GetClassNameText(h)) = 1) then
begin
Result := h;
Break;
end;
h := GetWindow(h, GW_HWNDNEXT );
end;
end;
|
function GetWebBrowser_Root_IE_Server_Handle(AWebBrowser : TWebBrowser) : hwnd;
// Internet Explorer_Server
var
h : hwnd;
h_child : hwnd;
begin
h := GetWindow(AWebBrowser.Handle, GW_CHILD );
while (h > 0) do
begin
if (Pos('Shell DocObject View', GetClassNameText(h)) = 1) then
begin
h_child := GetWindow(h, GW_CHILD );
while (h_child > 0) do
begin
if (Pos('Internet Explorer_Server',
GetClassNameText(h_child)) = 1) then
begin
Result := h_child;
break;
end;
h_child := GetWindow(h_child, GW_HWNDNEXT );
end;
if (Result > 0) then
Break;
end;
h := GetWindow(h, GW_HWNDNEXT );
end;
end;
|
【場所から取得する方法】
・ ChildWindowFromPoint関数を使用します。
ついでに、それいけみんなドットネットなので
C#で、ハンドルにメッセージを送る方法は
知らないので
[System.Runtime.InteropServices.DllImport("user32.dll")]
private extern static System.Boolean PostMessage(
System.IntPtr hWnd,
System.UInt32 Msg,
System.Int32 wParam,
System.Int32 lParam);
で回避することができる。