DOBON.NET DOBON.NETプログラミング掲示板過去ログ

画像とかテーブルのようなコントロールの場合に選択したら

環境/言語:[vb.net NET Framework4.0]
分類:[.NET]

いつもお世話になっております。

vb.net で HTML EDITORを開発中ですが、
その中でどうしても解決ができない部分がありまして助けて頂きたいと思います。

現在デザインモードを使っている WebBrowser1コントロールが1個ありますが、
そこで書いたテキストについては以下のCODEでテキストを選択したときに
HTMLソースが正常に見られます。

Dim selectionObject As MSHTML.IHTMLSelectionObject = WebBrowser1.Document.DomDocument.selection
Dim txtRange As MSHTML.IHTMLTxtRange = DirectCast(selectionObject.createRange(), MSHTML.IHTMLTxtRange)
MsgBox(txtRange.htmlText)

しかし、画像とかテーブルのようなコントロールの場合、選択すると
エラーが出ます。上記CODEはどうやらテキスト部分にしかHTMLソースが取れないようです。

どうしたら画像とかテーブルのようなコントロールの場合に選択したら
HTMLソースが見られるようになりますでしょうか?

すみませんが、よろしくお願いします。
■No30065に返信(takahasiさんの記事)
> Dim selectionObject As MSHTML.IHTMLSelectionObject = WebBrowser1.Document.DomDocument.selection
> Dim txtRange As MSHTML.IHTMLTxtRange = DirectCast(selectionObject.createRange(), MSHTML.IHTMLTxtRange)

createRange メソッドの戻り値が IHTMLTxtRange オブジェクトとは限りません。
画像等の場合は、IHTMLControlRange のコレクションを返します。

http://msdn.microsoft.com/en-us/library/ie/aa768846.aspx
》 Creates [a TextRange object] from the current text selection,
》 or [a controlRange collection] from a control selection.


戻り値が txtRange になるか controlRange になるかは、
selectionObject.type で判断できます。

http://msdn.microsoft.com/en-us/library/ie/aa768848.aspx
》Possible Values
》 "Text" : Specifies a text selection.
》 "Control" : Specifies a control selection, which enables dimension controls allowing the selected object to be resized.
早速の返事本当にありがとうございます。

以下のようにテキストかコントロールかを確認するために
以下のCODEができました。ありがとうございます。

しかし、

Dim doc As MSHTML.IHTMLDocument2 = DirectCast(Me.WebBrowser1.Document.DomDocument, MSHTML.IHTMLDocument2)
'Dim selectionObject As MSHTML.IHTMLSelectionObject = doc.selection

If selectionObject.type = "Control" Then
MsgBox(selectionObject.type.ToString)
End If

選択したのがcontrolであることがわかった上でそのcontrolの
HTMLソースを見る方法がいくらやってもできませんでした。

考えたのはまず、
そのCONTOLを1回選択状態(選択すると反転表示になることです。)
参考画像(http://subhand.net/download/001.gif)を
参考してくれたらうれしいです。

たとえハイパーリンクを設定するとき、.execCommand("CreateLink", false, 0))を使うと選択したCONTROLにリンクがかけます。その後、HTMLソースが
出ます。CODEは以下になります。

Dim dd = doc.execCommand("CreateLink", false, 0)
Dim txtRange2As MSHTML.IHTMLTxtRange = DirectCast(doc.selection.createRange(), MSHTML.IHTMLTxtRange)
MsgBox(txtRange2.htmlText)

ですので、doc.execCommand("CreateLink", false, 0)
<-この動きのように選択したCONTROLをまず選択範囲として指定できる
ようにするのがわかりません。これさえできればた解決でると思います。

よろしくお願い致します。




■No30066に返信(魔界の仮面弁士さんの記事)
> ■No30065に返信(takahasiさんの記事)
>>Dim selectionObject As MSHTML.IHTMLSelectionObject = WebBrowser1.Document.DomDocument.selection
>>Dim txtRange As MSHTML.IHTMLTxtRange = DirectCast(selectionObject.createRange(), MSHTML.IHTMLTxtRange)
>
> createRange メソッドの戻り値が IHTMLTxtRange オブジェクトとは限りません。
> 画像等の場合は、IHTMLControlRange のコレクションを返します。
>
> http://msdn.microsoft.com/en-us/library/ie/aa768846.aspx
> 》 Creates [a TextRange object] from the current text selection,
> 》 or [a controlRange collection] from a control selection.
>
>
> 戻り値が txtRange になるか controlRange になるかは、
> selectionObject.type で判断できます。
>
> http://msdn.microsoft.com/en-us/library/ie/aa768848.aspx
> 》Possible Values
> 》 "Text" : Specifies a text selection.
> 》 "Control" : Specifies a control selection, which enables dimension controls allowing the selected object to be resized.
■No30067に返信(takahasiさんの記事)
> 選択したのがcontrolであることがわかった上でそのcontrolの
> HTMLソースを見る方法がいくらやってもできませんでした。

未検証ですが、controlRange コレクションに含まれる各要素の
outerHTML/innerHTML あたりから取得できないでしょうか?
色々教えてくれて有難うございます。

色々やってみましたが出来ませんでした。
ドリムウィバーとかホームビルダーを見ると編集モードで画像を
選択するとソースの部分でその選択したHTML ソースが反転表示されるのを
見てたぶん方法があると思いながらしも方法が見つからず悩んでいます。






■No30068に返信(魔界の仮面弁士さんの記事)
> ■No30067に返信(takahasiさんの記事)
>>選択したのがcontrolであることがわかった上でそのcontrolの
>>HTMLソースを見る方法がいくらやってもできませんでした。
>
> 未検証ですが、controlRange コレクションに含まれる各要素の
> outerHTML/innerHTML あたりから取得できないでしょうか?
■No30069に返信(takahasiさんの記事)
> 色々やってみましたが出来ませんでした。

「色々やった」との事ですが、具体的にはどの段階で
どのような問題が発生しているのでしょうか。


(1) コレクションから取得した個々の要素から、該当する html ソースを
 得ることができないのでしょうか。

(2) それとも、そもそもコレクションから要素を列挙するところで
 エラーになってしまうということでしょうか。

(3) あるいは、コントロールは取得でき、そこからHTMLソースらしきものも
 得られたが、それが望んでいる結果では無かったという意味でしょうか。


> ドリムウィバーとかホームビルダーを見ると
すみません。私はどちらのソフトも見たことが無いので、
ちょっと想像が付きません。誰か分かる人にお任せします。(逃)
有難うございました。忙しい中有難うございました。


では、どなたか手伝ってください。
簡単に言いますとWEBブラウザコントロールのデザインモードから
テキスト以外の部分(いわゆるコントロール)を選択した場合、その選択した
コントロールのHTMLソースを取得したいことです。

テキストの場合、選択したテキストは一番最初の質問に書いてあるCODEで
HTMLソースが取得できましたが、他の画像の部分とかテーブルとかは
出来ませんでした。

皆様よろしくお願い致します。








■No30072に返信(魔界の仮面弁士さんの記事)
> ■No30069に返信(takahasiさんの記事)
>>色々やってみましたが出来ませんでした。
>
> 「色々やった」との事ですが、具体的にはどの段階で
> どのような問題が発生しているのでしょうか。
>
>
> (1) コレクションから取得した個々の要素から、該当する html ソースを
>  得ることができないのでしょうか。
>
> (2) それとも、そもそもコレクションから要素を列挙するところで
>  エラーになってしまうということでしょうか。
>
> (3) あるいは、コントロールは取得でき、そこからHTMLソースらしきものも
>  得られたが、それが望んでいる結果では無かったという意味でしょうか。
>
>
>>ドリムウィバーとかホームビルダーを見ると
> すみません。私はどちらのソフトも見たことが無いので、
> ちょっと想像が付きません。誰か分かる人にお任せします。(逃)
2012/03/10(Sat) 12:36:39 編集(投稿者)

■No30077に返信(takahasi さんの記事)
> では、どなたか手伝ってください。

ホームビルダー(ホームページビルダー?)や
ドリムウィバー(ドリームウィーバー, Dreamweaver?)の事は
両ソフトを見たことが無いので分かりませんが、最初の質問で、
takahasi さんが何をやりたいのか、までは理解しているつもりです。

WebBrowser のデザインモードで、<table> や <image> 全体を選択したときに、
選択範囲の HTML ソースを得ようとしているのですよね?


その実現のためにどのような手順が必要であるかは提示しているつもりなのですが、
実際にそれを実装するに当たり、どの段階で躓いてしまったのかがハッキリしません。


まず、IHTMLTxtRange からの取得はできているのですよね。
そして、IHTMLSelectionObject.type での "Text" / "Control" / "None" の
判定までは出来ているのですよね。

あとは、"Text" 時における IHTMLTxtRange に対する処理の代わりに、
"Control" 時における IHTMLControlRange の処理を追加していく段階ですが、
先の回答で示した手順の中での不明点が分からないため、手伝おうにも、
以前の回答に対する補足説明をすることも、参考資料の URL を示すことも、
コーディングミス等を指摘することもできない状況です。


この点については、No30072 でも、
> 具体的にはどの段階でどのような問題が発生しているのでしょうか
とお聞きしていますが、これについては回答を頂けていません。

一応、『色々やってみましたが出来ませんでした。』という一文は頂きましたが、
何に困っているのかの状況説明にはなっていないため、なかなか先に進めません。

どこが分からないのかを説明するのは難しいとは思いますが、
「回答にあった○○という用語について調べてみたが、有用な情報が得られなかった」
「文章を読んではみたが、その中の……の部分の意味がわからなかった」
「なんとなくはわかるが、どのようにコーディングするのか思いつかない」
「自分なりにコーディングはしてみたが、これだと求める物とは違う結果になる」
などなど、より具体的な形で説明いただけると、何を補足すれば良いのか、
どの部分のサンプルコードを書けばよいのか、こちらとしても回答しやすくなります。


ということで、内容をもう少し掘り下げて再度お聞きします。
つまづいているのは、どの段階でしょうか?

No30066
> createRange メソッドの戻り値が IHTMLTxtRange オブジェクトとは限りません。
> 画像等の場合は、IHTMLControlRange のコレクションを返します。
> 戻り値が txtRange になるか controlRange になるかは、
> selectionObject.type で判断できます。

No30068
> 未検証ですが、controlRange コレクションに含まれる各要素の
> outerHTML/innerHTML あたりから取得できないでしょうか?


(1) 今回の処理では、IHTMLSelectionObject.type での条件分岐が必要です。
 No30067 を見る限り、この点は理解していただけていると思っていましたが、
 提示いただいたコードは、条件分岐する部分のコードしか無いようです。
 何のために条件分岐が必要になっているかは、認識いただけていますか?

(2) その条件によって、createRange から返される型が異なるわけですが、
 それぞれの IHTMLTxtRange / IHTMLControlRange を取り出すことは
 できていますか? (No30067 のコードでは、肝心なこの部分が書かれていません)

(3) 先の回答で、IHTMLControlRange はコレクションであると書いていますが、
 それをループ処理して、各要素を取り出すことはできていますか?
 (ループと言っても、通常は、一つの要素しか含まれないのですけれども)

(4) 取り出した要素の outerHTML / innerHTML プロパティを使うことで
 それぞれのソースを取得できます。(No30068 では未検証と書いていますが、
 その後、実際にこれでソースを取得可能な事を確認しています)
2012/03/12(Mon) 10:31:19 編集(投稿者)
2012/03/10(Sat) 17:48:22 編集(投稿者)
2012/03/10(Sat) 14:59:58 編集(投稿者)

お忙しいところお返事有難うございます。

> (1) 今回の処理では、IHTMLSelectionObject.type での条件分岐が必要です。
>  No30067 を見る限り、この点は理解していただけていると思っていましたが、
>  提示いただいたコードは、条件分岐する部分のコードしか無いようです。
>  何のために条件分岐が必要になっているかは、認識いただけていますか?

  ←はい。テキストかコントロールかを区別する必要があるからです。
>


> (2) その条件によって、createRange から返される型が異なるわけですが、
>  それぞれの IHTMLTxtRange / IHTMLControlRange を取り出すことは
>  できていますか? (No30067 のコードでは、肝心なこの部分が書かれていません)
  ←下記にCODEが書いてあります。


>
> (3) 先の回答で、IHTMLControlRange はコレクションであると書いていますが、
>  それをループ処理して、各要素を取り出すことはできていますか?
>  (ループと言っても、通常は、一つの要素しか含まれないのですけれども)
>
  ←指定したコントロールのみのHTMLソースが必要なのでループ処理は
   要らないと思っています。


> (4) 取り出した要素の outerHTML / innerHTML プロパティを使うことで
>  それぞれのソースを取得できます。(No30068 では未検証と書いていますが、
>  その後、実際にこれでソースを取得可能な事を確認しています)

  ←これがよくわからない部分です。どうCODINGするばソースの取得が可能でしょうか?

 

Dim doc As MSHTML.IHTMLDocument2 = DirectCast(Me.WebBrowser1.Document.DomDocument, MSHTML.IHTMLDocument2)
Dim selectionObject As MSHTML.IHTMLSelectionObject = doc.selection

If selectionObject.type = "Control" Then

MsgBox("controです。")

Else

Dim txtRange As MSHTML.IHTMLTxtRange = DirectCast(selectionObject.createRange(), MSHTML.IHTMLTxtRange)
MsgBox(txtRange.htmlText)
End If



MsgBox("controです。")
←この部分にCONTROLをクリックした時 HTML取得をするCODEが
書けません。

魔界の仮面弁士様からの(4)番の質問でHTML取得ができたというお話は
これのことであれば嬉しいです。

教えていただけますでしょうか?

よろしくお願い致します。



■No30078に返信(魔界の仮面弁士さんの記事)
> 2012/03/10(Sat) 12:36:39 編集(投稿者)
>
> ■No30077に返信(takahasi さんの記事)
>>では、どなたか手伝ってください。
>
> ホームビルダー(ホームページビルダー?)や
> ドリムウィバー(ドリームウィーバー, Dreamweaver?)の事は
> 両ソフトを見たことが無いので分かりませんが、最初の質問で、
> takahasi さんが何をやりたいのか、までは理解しているつもりです。
>
> WebBrowser のデザインモードで、<table> や <image> 全体を選択したときに、
> 選択範囲の HTML ソースを得ようとしているのですよね?
>
>
> その実現のためにどのような手順が必要であるかは提示しているつもりなのですが、
> 実際にそれを実装するに当たり、どの段階で躓いてしまったのかがハッキリしません。
>
>
> まず、IHTMLTxtRange からの取得はできているのですよね。
> そして、IHTMLSelectionObject.type での "Text" / "Control" / "None" の
> 判定までは出来ているのですよね。
>
> あとは、"Text" 時における IHTMLTxtRange に対する処理の代わりに、
> "Control" 時における IHTMLControlRange の処理を追加していく段階ですが、
> 先の回答で示した手順の中での不明点が分からないため、手伝おうにも、
> 以前の回答に対する補足説明をすることも、参考資料の URL を示すことも、
> コーディングミス等を指摘することもできない状況です。
>
>
> この点については、No30072 でも、
>>具体的にはどの段階でどのような問題が発生しているのでしょうか
> とお聞きしていますが、これについては回答を頂けていません。
>
> 一応、『色々やってみましたが出来ませんでした。』という一文は頂きましたが、
> 何に困っているのかの状況説明にはなっていないため、なかなか先に進めません。
>
> どこが分からないのかを説明するのは難しいとは思いますが、
> 「回答にあった○○という用語について調べてみたが、有用な情報が得られなかった」
> 「文章を読んではみたが、その中の……の部分の意味がわからなかった」
> 「なんとなくはわかるが、どのようにコーディングするのか思いつかない」
> 「自分なりにコーディングはしてみたが、これだと求める物とは違う結果になる」
> などなど、より具体的な形で説明いただけると、何を補足すれば良いのか、
> どの部分のサンプルコードを書けばよいのか、こちらとしても回答しやすくなります。
>
>
> ということで、内容をもう少し掘り下げて再度お聞きします。
> つまづいているのは、どの段階でしょうか?
>
> No30066
>>createRange メソッドの戻り値が IHTMLTxtRange オブジェクトとは限りません。
>>画像等の場合は、IHTMLControlRange のコレクションを返します。
>>戻り値が txtRange になるか controlRange になるかは、
>>selectionObject.type で判断できます。
>
> No30068
>>未検証ですが、controlRange コレクションに含まれる各要素の
>>outerHTML/innerHTML あたりから取得できないでしょうか?
>
>
> (1) 今回の処理では、IHTMLSelectionObject.type での条件分岐が必要です。
>  No30067 を見る限り、この点は理解していただけていると思っていましたが、
>  提示いただいたコードは、条件分岐する部分のコードしか無いようです。
>  何のために条件分岐が必要になっているかは、認識いただけていますか?
>
> (2) その条件によって、createRange から返される型が異なるわけですが、
>  それぞれの IHTMLTxtRange / IHTMLControlRange を取り出すことは
>  できていますか? (No30067 のコードでは、肝心なこの部分が書かれていません)
>
> (3) 先の回答で、IHTMLControlRange はコレクションであると書いていますが、
>  それをループ処理して、各要素を取り出すことはできていますか?
>  (ループと言っても、通常は、一つの要素しか含まれないのですけれども)
>
> (4) 取り出した要素の outerHTML / innerHTML プロパティを使うことで
>  それぞれのソースを取得できます。(No30068 では未検証と書いていますが、
>  その後、実際にこれでソースを取得可能な事を確認しています)
■No30080に返信(takahasi さんの記事)
>>(1) 今回の処理では、IHTMLSelectionObject.type での条件分岐が必要です。
>> No30067 を見る限り、この点は理解していただけていると思っていましたが、
>> 提示いただいたコードは、条件分岐する部分のコードしか無いようです。
>> 何のために条件分岐が必要になっているかは、認識いただけていますか?
>   ←はい。テキストかコントロールかを区別する必要があるからです。

そもそも、何故区別する必要があるのか……それは、
「createRange メソッドの戻り値が異なるから」でしたよね。

IHTMLSelectionObject 自体に HTML ソースを得る機能が無いことは
うすうす気づいておられるかと思います。重要なのは createRange です。
(実際、Text モードのときは、createRange されていましたよね)

Text モードの時には、createRange から IHTMLSelectionObject を得て、
Control なら、createRange から IHTMLControlRange を得ねばなりません。
★これが、今回の処理で重要な点(その壱)です★


――しかし No30067 のコードでは、「区別」するところまでしか実装されて
おらず、本題の IHTMLControlRange を得る部分が抜けています。
(IHTMLControlRange がどのようなものであるか、確認されましたか?)


もしかして、 No30066 の回答の前半部分に書いた、
>> createRange メソッドの戻り値が IHTMLTxtRange オブジェクトとは限りません。
>> 画像等の場合は、IHTMLControlRange のコレクションを返します。
の部分が読み落とされてしまっていたのでしょうか。


>   ←下記にCODEが書いてあります。
未選択の場合の条件分岐が足りない気もしますが、それはとりあえず置いといて:

まずは IHTMLControlRange のための変数を用意してみてください。
IHTMLControlRange を受け取る手順は、No30066 の前半部分に記しています。
(すなわち、Text モードと同様に「createRange」が必要だということです)


>>(3) 先の回答で、IHTMLControlRange はコレクションであると書いていますが、
>> それをループ処理して、各要素を取り出すことはできていますか?

No30066 にて、MSDN Library の内容を引用しつつ短く触れているのですが、
IHTMLTxtRange がオブジェクト [a TextRange object] であるのに対して
IHTMLControlRange はコレクション [a controlRange collection] です。

この違いには気が付いておられましたでしょうか。
★コレクションであるというのも、今回の処理で重要な点(その弐)です★


IHTMLControlRange には、選択された要素群が格納されています。
具体的には、選択した画像やテーブルやセルやインラインフレーム等です。
ですから IHTMLControlRange を取得したあとに行うべき作業は、
コレクションからその要素を抜き出してやるためのコーディングです。

コレクションから要素を取り出す方法は、IHTMLControlRange の
メンバー一覧を調べていただければ、直ぐにわかるかと思います。


>>(4) 取り出した要素の outerHTML / innerHTML プロパティを使うこと
>   ←これがよくわからない部分です。どうCODINGするばソースの取得が可能でしょうか?
要素の取り出しまでが行われているのあれば、この部分はとても単純な処理です。
先のコレクションから取り出した要素は、<table> や <image> そのものなのですが、
正しくコーディングされていれば、それを IHTMLElement 型で取得できているはずです。
これは、innerText / outerText / innerHTML / outerHTML プロパティを含んでいます。
★IHTMLElement の outerHTML プロパティの呼び出しが、最後の重要箇所(その参)です★



>> (ループと言っても、通常は、一つの要素しか含まれないのですけれども)
>   ←指定したコントロールのみのHTMLソースが必要なのでループ処理は
>    要らないと思っています。

そうとは限りません。
たとえば、MultipleSelection モードを True にした状態では、
Ctrl キーを押しながらクリックすることで、場所の離れた複数の要素を
選択状態にすることができるからです。

もっとも、MultipleSelection の初期値は False なわけですから、
意図的に複数選択モードに移行させるか、または IHTMLControlRange に
要素を直接追加するなどしない限りは、要素数は通常 1 固定です。

ですから、常に 1 個しか含まれないということを確実に保証できるなら、
ループ処理を省いてしまい、コレクション内の 0 番目の先頭要素を
固定的に取り出す方法でも大丈夫だとは思います。

DOBON.NET | プログラミング道 | プログラミング掲示板