日記帳
本ページはプロモーションが含まれています
カテゴリー
Links
blog(ブログ)マスター
アンドロイドの巣
ゼロから始めるベランダ菜園
タイトル
2024年11月
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

TWebBrowser.HWNDを取得する方法 (メモ: その1)

カテゴリー: General
2011-10-19
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でいいようです。

構造
 
ClassName  

- Shell Embedding ← GetClassName(WebBrowser1.Handle)

-- Shell DocObject View 不明

--- Internet Explorer_Server ← 操作画面
解説URL

ページを表示するとコンテンツに応じて 上の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);
で回避することができる。




ブログ内 関連記事: TWebBrowser.HWNDを取得する方法 (メモ: その1)


ブログ内 関連記事: TWebBrowser.HWNDを取得する方法 (メモ: その1)

PR

[PR]