IEコンポーネント上の全選択方法

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#1 投稿記事 by KICO »

何時も、お世話に成っています。

 実践コードモジュールで、Toshi様の「IE コンポーネントを表示してみる」
 (http://www.activebasic.com/forum/viewtopic.php?t=435)
を使わして頂いてますが、全選択(CTRL+A)が出来ないのですが度の様に
すれば良いのでしょうか?

EM_SETSELを試しましたが駄目でした。
CreateWindowEx()の戻り値がハンドルじゃ無いのでしょうか?


宜しくお願いします。
ゲスト

#2 投稿記事 by ゲスト »

CreateWindowExの戻り値は確かにハンドルですが"AtlAxWin"という特殊なウィンドウクラスのため通常の方法では操作できません
おそらくはiwebbrowser2インターフェースからの操作する事になると思いますが、そちらの方は疎いので明確にはお答えできないです
Toshi
記事: 98
登録日時: 2005年7月19日(火) 19:47
お住まい: 山形県
連絡する:

#3 投稿記事 by Toshi »

あのコードですと、Ctrl+A に限らず多くのショートカット キーが効きません。
なのでいっそ IE コンポーネントにそのあたりの処理を任せるようにしてみます。
これで IE コンポーネントで有効なあらゆるショートカット キーが使えます。

まず必要な宣言を追加します。別なファイルとしてプロジェクトに追加するなどします。 次に MainWnd.sbp を大幅に書き替えます。
AtlAxWinInit の宣言の削除、必要なインターフェイスの取得と解放を行っています。
また TestProject_DestroyObjects の部分は「(プロジェクト名)_DestroyObjects」に書き替えます。 更に IE コンポーネントに処理を渡す為に、メッセージ ループを書き替えます。 API の TranslateAccelerator と同じような感じです。

これで Ctrl+A や Ctrl+F 等の、IE コンポーネントのショートカット キーが使えるようになります。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#4 投稿記事 by イグトランス »

見ていて思ったのですが,そのコードではIWebBrower2インタフェースは使っていないので,IUnknownへのポインタから直接IOleInPlaceActiveObjectをQueryInterfaceして構わないはずです。

もちろん後で使うためにIWebBrower2へのポインタを取っておくという方法も考えられますけどね。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#5 投稿記事 by KICO »

Toshi様、ありがとう御座います。

 実践コードモジュールの「IE コンポーネントを表示してみる」に追加。

 Ver4.24で全選択(CTRL+A)が出来る様に成りました。(凄いですね^_^)
(私は、未だにVer3.13を使用しているのですが、Ver3.13では無理でしょうか?) ですが、今作成しているのはメイン画面ではなくダイアログ ボックスに
ブラウザウィンドウを2つ表示しているのですが、頂いたコードを追加し
Dim hBrowserWnd[1] As HWND
Dim pUnknown[1] As *IUnknown
Dim pWebBrowser2[1] As *IWebBrowser2
Dim pOleInPlaceActiveObject[1] As *IOleInPlaceActiveObject
等の様に変更しましたが有効なショートカット キー等、使用出来ません。
AtlAxGetControl()以降のコードは、Create時のみ有効のなのでしょうか?

 前後に成りましたが、イグトランス (egtra)様、何時もありがとう御座います。


宜しくお願いします。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#6 投稿記事 by KICO »

AtlAxGetControl()以降のコードは、Create時のみ有効のなのでしょうか?
    これは、問題では無いみたいですね。

 モーダルダイアログボックスの場合、メッセージループは”Callback.wbp”のDialogBox()中に
在るのでここに追加したのですがコードを変更する度、書き換えなければならないので
他に方法は無いでしょうか?

 それと、ブラウザウィンドウのハンドルをWindowFromPoint()で取得しているのですが、
他に取得する方法は無いでしょうか?

 ボタンをクリックして一連の作業をする場合、ブラウザウィンドウをクリックしてからでないと
出来ないのと一度アクティブ(?)に成るとフォーカスがエディットボックスに成っていても関係なく
Ctrl+A でブラウザウィンドウに対して全選択に成ってしまいますし、カーソルキーを押した場合も
ブラウザウィンドウの画面がスクロールしてしまいます。(SetFocus()は効きません)

 ブラウザウィンドウを2つ表示しているの場合、どちらに対して指定しているかの判別は、
度の様にすれば良いのでしょうか?


一度に沢山質問しましたが宜しくお願いします。
Toshi
記事: 98
登録日時: 2005年7月19日(火) 19:47
お住まい: 山形県
連絡する:

#7 投稿記事 by Toshi »

(私は、未だにVer3.13を使用しているのですが、Ver3.13では無理でしょうか?)
Ver. 3.13 は COM を扱えないので無理です。
Ver5.xxでは、エラー:「"VarPtr" 無効な識別子です」と成ります。
これは QueryInterface の引数の型が変わった為で、VarPtr() を外すだけでいいはずです。

コード: 全て選択

    pUnknown->QueryInterface(IID_IOleInPlaceActiveObject,pOleInPlaceActiveObject) 
モーダルダイアログボックスの場合、メッセージループは”Callback.wbp”のDialogBox()中に
在るのでここに追加したのですがコードを変更する度、書き換えなければならないので
他に方法は無いでしょうか?
フックを利用すると可能です。こちらのページの手法を参考にしてみてください。
それと、ブラウザウィンドウのハンドルをWindowFromPoint()で取得しているのですが、
他に取得する方法は無いでしょうか?
CreateWindowEx が返したハンドルから子ウィンドウを辿っていき、
クラス名が "Internet Explorer_Server" のウィンドウを見つけるという方法がありますが、面倒です。
ブラウザウィンドウを2つ表示しているの場合、どちらに対して指定しているかの判別は、
度の様にすれば良いのでしょうか?
フックによってメッセージを捕まえたら GetFocus でフォーカスのあるハンドルを取得し、
あらかじめ取得しておいた、上記のウィンドウのハンドル 2 つとそれぞれ比較することで出来ます。
そして一致していた方の pOleInPlaceActiveObject->TranslateAccelerator を呼びます。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#8 投稿記事 by KICO »

Toshi様、ありがとう御座います。
Ver. 3.13 は COM を扱えないので無理です。
 COM を使わず出来ないものかと思って。
と云うのも、例えば下記の様にすればメモ帳の全選択(CTRL+A)が出来る様に、
ブラウザウィンドウに対しても出来ないのかなと思ったのです。
hWnd=FindWindow("Notepad", NULL)
PostMessage(hWnd, WM_COMMAND, 25, 0) ’25はメニュのID
QueryInterface の引数の型が変わった為で、VarPtr() を外すだけでいいはずです。
 Ver5.xxから仕様が変わったのでしたね。(すみません)


 フックの事は過去に何度も教えて頂いたのですが、気が付きませんでした。
ブラウザウィンドウが複数表示してる場合も、どれを指定したか判別が出来る様に成りました。
 しかし、SetFocus()で設定した場合、カーソルキー等で画面はスクロールしますが
ショートカット キー等は、ブラウザウィンドウをクリックしてからでないと使用出来ません。

 ”Internet Explorer_Server”(クラス名)のハンドルは未だ取得できず、試行錯誤しています。
先ずCreateWindowEx()で ”AtlAxWin”(クラス名)のウィンドウを生成し表示すると
次に”Shell DocObject View”(クラス名)のウィンドウが表示し
続いて”Internet Explorer_Server”のウィンドウが表示しますが、
このウィンドウが表示した事が解る関数は無いのでしょうか?
どのタイミングで又、何処でハンドルを取得すれば良いのでしょうか?


宜しくお願いします。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#9 投稿記事 by イグトランス »

AtlAxGetControlして得たブラウザコントロールへのポインタからIOleWindowインタフェースを得られないでしょうか?

コード: 全て選択

Interface IOleWindow
    Inherits IUnknown

    Function GetWindow(ByRef hwnd As HWND) As HRESULT
    Function ContextSensitiveHelp(fEnterMode As BOOL) As HRESULT
End Interface

Dim IID_IOleWindow = [&h00000114, &h0000, &h0000, [&hC0, &h00, &h00, &h00, &h00, &h00, &h00, &h46]] As IID

コード: 全て選択

Dim pOleWindow As *IOleWindow
p->QueryInterface(IID_IOleWindow, pOleWindow) 'pはAtlAxGetControlで得たポインタか、それからQueryInterfaceして得たポインタ
Dim hwnd As HWND
pOleWindow->GetWindow(hwnd)
pOleWindow->Release()
Toshi
記事: 98
登録日時: 2005年7月19日(火) 19:47
お住まい: 山形県
連絡する:

#10 投稿記事 by Toshi »

おそらく IE コンポーネントはメモ帳のようなことは出来ません。(確証は無いですが)
また TranslateAccelerator を呼ばない限りショートカット キーを処理しないらしく、
それを自前でやる(プログラム側でキーボード イベントを捕まえて、それに対応する処理を IE コンポーネントに依頼する)
のにも COM が必要になってしまいます...。
しかし、SetFocus()で設定した場合、カーソルキー等で画面はスクロールしますが
ショートカット キー等は、ブラウザウィンドウをクリックしてからでないと使用出来ません。
SetFocus は Internet Explorer_Server クラスのウィンドウにする必要があります。
このウィンドウが確実に存在するのなら、次の関数に hBrowserWnd を渡すとハンドルを取得出来ます。

コード: 全て選択

Function GetIEHWND(hParent As HWND) As HWND
	Dim hWnd As HWND
	Dim szClassName[255] As Byte
	hWnd=GetWindow(hParent,GW_CHILD)
	If hWnd Then
		GetClassName(hWnd,szClassName,255)
		If lstrcmp(szClassName,"Internet Explorer_Server")=0 Then
			GetIEHWND=hWnd
			Exit Function
		Else
			GetIEHWND=GetIEHWND(hWnd)
			Exit Function
		End If
	End If
	GetIEHWND=NULL
End Function
そして確実に存在することを確かめるにはまた COM を使って色々しなければならないので、
少し無理矢理ですがタイマーなどである程度の時間を待って、戻り値が NULL ではなくなるまで上の関数を呼ぶといった方法があります。

追記:
かぶってしまいました。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#11 投稿記事 by KICO »

イグトランス (egtra)様、ありがとう御座います。
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)

AtlAxWinInit()
hBrowserWnd=CreateWindowEx(NULL,"AtlAxWin","http://www.yahoo.co.jp/",
WS_CHILD Or WS_VISIBLE Or WS_VSCROLL Or WS_HSCROLL,
0,0,100,100,hMainWnd,0,GetModuleHandle(NULL),NULL)
AtlAxGetControl(hBrowserWnd,VarPtr(pUnknown))
Dim IID_IWebBrowser2=[&HD30C1661,&HCDAF,&H11D0,[&H8A,&H3E,&H00,&HC0,&H4F,&HC9,&HE2,&H6E]] As GUID
pUnknown->QueryInterface(VarPtr(IID_IWebBrowser2),VarPtr(pWebBrowser2))
Dim IID_IOleInPlaceActiveObject=[&H00000117,&H0000,&H0000,[&HC0,&H00,&H00,&H00,&H00,&H00,&H00,&H46]] As GUID
pWebBrowser2->QueryInterface(VarPtr(IID_IOleInPlaceActiveObject),VarPtr(pOleInPlaceActiveObject))

pWebBrowser2->QueryInterface(VarPtr(IID_IOleWindow), VarPtr(pOleWindow)) 'pはAtlAxGetControlで得たポインタか、それからQueryInterfaceして得たポインタ
Dim hwnd As HWND
pOleWindow->GetWindow((VarPtr(hwnd))
pOleWindow->Release()


pWebBrowser2->Release()
pUnknown->Release()

End Sub
 何処に入れれば良いのか解らないので取り合えず上記の様にしましたが
Internet Explorer_Server クラスのウィンドウハンドルは取得出来ませんでした。
pのポインタ変数はこれで良いのでしょうか?

 Interface中の各Function の機能の解説があるサイトがあれば教えてください。
Refresh()で”更新”出来る等便利で他にも使いたいのですが機能名だけからでは
解らないものが多いので。


宜しくお願いします。
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#12 投稿記事 by KICO »

Toshi様、ありがとう御座います。
おそらく IE コンポーネントはメモ帳のようなことは出来ません。(確証は無いですが)
また TranslateAccelerator を呼ばない限りショートカット キーを処理しないらしく、
それを自前でやる(プログラム側でキーボード イベントを捕まえて、それに対応する処理を IE コンポーネントに依頼する)
のにも COM が必要になってしまいます...。
 IE コンポーネント等はCOM が不可欠なんですね。
色々調べて頂いてありがとう。
SetFocus は Internet Explorer_Server クラスのウィンドウにする必要があります。
 SetFocus で指定したウィンドウハンドルは、Internet Explorer_Server クラスのウィンドウです。
GetIEHWNDで得たハンドルですよね。

今迄、WindowFromPoint で取得していましたがGetIEHWNDを使わして頂きます。(^_^)
 そして確実に存在することを確かめるにはまた COM を使って色々しなければならないので、
少し無理矢理ですがタイマーなどである程度の時間を待って、戻り値が NULL ではなくなるまで上の関数を呼ぶといった方法があります。
 「COM を使用すれば存在することを確かめられる」のが、イグトランス (egtra)様のコードでしょうか?
何処に入れれば良いのか使い方が解ずお聞きしているところです。

 ウィンドウが表示した事が解る関数は無いみたいで、COM で出来ない場合はタイマーを使って取得するしか無いみたいですね。


宜しくお願いします。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#13 投稿記事 by イグトランス »

はい,そういうコードを想定していました。お役に立てず済みません。

ちなみに,そのコードはここを参考にしました。
Obtaining the HWND for the WebBrowser control - Microsoft Support Online
KICO
記事: 57
登録日時: 2005年12月13日(火) 17:42

IEコンポーネント上の全選択方法

#14 投稿記事 by KICO »

イグトランス (egtra)様、ありがとう御座います。
はい,そういうコードを想定していました。お役に立てず済みません。
 いいえ、何時も役に立つ回答を頂いています!(^_^)

 現在は、Toshi様が提案して頂いたタイマーを使ってGetIEHWNDでハンドルを取得していますが、
Internet Explorer_Server クラスのウィンドウが表示した事が解る関数が有れば教えてください。

 フォーカス なのですが、ブラウザウィンドウをクリックしてからでないとショートカット キー等は
使用出来無い為、SetCursorPosでマウスカーソルをブラウザウィンドウに移動しmouse_eventで
クリックしてますが、他に方法は無いでしょうか?
SetFocusだけでは駄目なので、AttachThreadInputを試したのですが上手くいきません。

 それと、ブラウザウィンドウ中のTABによるフォーカス移動が出来ないのですが、度の様にすれば
良いのでしょうか?
宜しくお願いします。
返信する