C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: WebBrowser上でドラッグできないようにしたい


(過去ログ 137 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■80771 / inTopicNo.1)  WebBrowser上でドラッグできないようにしたい
  
□投稿者/ オニオコゼ (1回)-(2016/08/10(Wed) 10:05:54)

分類:[VB.NET/VB2005 以降] 

VB2008 Windows7(32bit)

現在、WebBrowserを使用して、HTML形式の文章を表示する
プログラムを作りました。
これを色々と試しているうちに、おかしな動作を確認しました。

それは、マウス操作をしている時に、
WebBrowser上の画像(srcタグで定義)を何気なくドラッグしたところ、

 ○○は動作を停止しました
 問題が発生したため、プログラムが正しく動作しなくなりました。
 プログラムは閉じられ、解決策がある場合はWindowsから通知されます。

のダイアログが表示されました。

ただし、この現象が全く発生しないPCもあり、原因も分かっておりません。
また、問題の発生しないPCでは、例えばドラッグしたものをデスクトップ上にドロップすると、
ドラッグした画像ファイルがそこに保存されます。

そこで質問なのですが、特に以下の2.が知りたいです。

1.WebBrowserで表示されているHTML上の画像をドラッグした場合、
  どのような形式のデータがドラッグされているのでしょうか?
  (画像データ?画像ファイルのパス?)

2.WebBrowser上のデータを外部にドラッグ&ドロップすることは
  考えていないので、いっそのこと、WebBrowser上ではドラッグ自体が
  できないようにしたいのですが、可能でしょうか?
  (WebBrowser上の選択範囲をクリップボードにコピーできれば十分と思っています。)
  もしその方法があれば、ご教示頂けますよう、宜しくお願い申し上げます。

以上、宜しくお願い申し上げます。
引用返信 編集キー/
■80793 / inTopicNo.2)  Re[1]: WebBrowser上でドラッグできないようにしたい
□投稿者/ WebSurfer (997回)-(2016/08/11(Thu) 12:25:35)
No80771 (オニオコゼ さん) に返信

質問者さんの言う WebBrowser というのは System.Windows.Forms.WebBrowser クラス
のことですか?

であれば、基本 IE と同じ(デフォルトで IE7 相当)なので、表示された img 要素を
ドラッグ&ドロップする機能は IE を使っても WebBrowser コントロールを使っても同
じになるはずです。

なので、

> ただし、この現象が全く発生しないPCもあり、原因も分かっておりません。
> また、問題の発生しないPCでは、例えばドラッグしたものをデスクトップ上にドロップすると、
> ドラッグした画像ファイルがそこに保存されます。

というのは正常な動作、すなわち「この現象が全く発生しないPC」が正常だ思います。

問題が発生する PC には、その PC 固有の問題がありそうな気がします。

で、質問の答えですが、

> 1.WebBrowserで表示されているHTML上の画像をドラッグした場合、
>  どのような形式のデータがドラッグされているのでしょうか?
>  (画像データ?画像ファイルのパス?)

ドロップする場所によるようですが、例えばデスクトップ上にドロップした場合は Temporary
Internet Files から画像ファイルそのものが Desktop フォルダにコピーされます。

Visual Studio 上にドロップすると、例えば .aspx の場合は img 要素が生成されその src 属
性に Temporary Internet Files の画像ファイルへのパスが "file:///C:\Users\..." というよ
うに設定されます。

> 2.WebBrowser上のデータを外部にドラッグ&ドロップすることは
>   考えていないので、いっそのこと、WebBrowser上ではドラッグ自体が
>   できないようにしたいのですが、可能でしょうか?

HTML ソースの作成も質問者さんの管轄範囲であれば、img 要素の onmousedown 属性にスクリプ
トを設定してマウスが効かなくなるようするということでいががです? 具体的な例は以下の記
事を見てください。

Disable Drag and Drop on HTML elements?
http://stackoverflow.com/questions/704564/disable-drag-and-drop-on-html-elements

上記のようなスクリプトを追加しても、右クリックして画像を保存することは可能だと思います。

引用返信 編集キー/
■80796 / inTopicNo.3)  Re[1]: WebBrowser上でドラッグできないようにしたい
□投稿者/ 魔界の仮面弁士 (810回)-(2016/08/11(Thu) 19:35:04)
No80771 (オニオコゼ さん) に返信
> VB2008 Windows7(32bit)
同じ環境が無いため、VB2015/Win10(1607)64bit をベースに回答します。


> 2.WebBrowser上のデータを外部にドラッグ&ドロップすることは
>   考えていないので、いっそのこと、WebBrowser上ではドラッグ自体が
>   できないようにしたいのですが、可能でしょうか?

これでどうでしょう。
選択されたテキストや画像をドラッグすることはできなくなりますが、
範囲選択のためのドラッグ操作は可能にしています。


Private Sub EventCancel(sender As Object, e As EventArgs)
  Dim win = WebBrowser1.Document.Window.DomWindow
  Dim ev = win.event
  ev.cancelBubble = True
  ev.returnValue = False
  System.Runtime.InteropServices.Marshal.ReleaseComObject(ev)
  System.Runtime.InteropServices.Marshal.ReleaseComObject(win)
End Sub

Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
  WebBrowser1.Document.Body.AttachEventHandler("ondragstart", AddressOf ondragstart)
  'WebBrowser1.Document.Body.AttachEventHandler("onselectstart", AddressOf EventCancel)
End Sub


範囲選択も無効化したい場合は、onselectstart イベントもキャンセルすれば OK です。



>   (WebBrowser上の選択範囲をクリップボードにコピーできれば十分と思っています。)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  'WebBrowser1.Document.ExecCommand("SelectAll", False, Type.Missing)
  WebBrowser1.Document.ExecCommand("Copy", False, Type.Missing)
End Sub



> 1.WebBrowserで表示されているHTML上の画像をドラッグした場合、
>   どのような形式のデータがドラッグされているのでしょうか?
>   (画像データ?画像ファイルのパス?)

クリップボードと同様、ドラッグデータには複数形式のデータが含まれます。
https://msdn.microsoft.com/ja-jp/library/windows/desktop/bb776902%28vs.85%29.aspx

試しに、当方の環境で
 WebBrowser1.Navigate("http://www.officedaytime.com/clipmm/")
の画像をドロップしてみたところ、10 種類のデータが使われていました。


(1) CFSTR_UNTRUSTEDDRAGDROP  ("UntrustedDragDrop")
 untrusted すなわち「信頼できないデータが含まれているかもしれない」ことを
 示すデータです。今回は  URLACTION_SHELL_ENHANCED_DRAGDROP_SECURITY を
 意味する &H180Bui という 32bit 値が入っていました。

(2) "msSourceUrl"
 ドロップ元ページの URL を示すデータです。今回は、NUL終端の UTF-16 文字列で
 「http://www.officedaytime.com/clipmm/」が返されました。

(3) CF_HDROP  (&HF)
 存在しているファイルグループの場所を示す DROPFILES 構造体です。
 今回は "C:\Users\…\AppData\Local\Microsoft\Windows\INetCache\IE\V33UQQPV\step1[1].png"
 なパスが 1 つ含まれていました。

(4) CFSTR_INETURLW  ("UniformResourceLocatorW")
 ドロップされたアイテムの URL を示す UTF-16 文字列です。今回は NUL 終端付きの
 「http://www.officedaytime.com/clipmm/img/step1.png」が返されました。

(5) CF_DIB  (&H8)
 デバイス非依存ビットマップを示すバイナリです。
 今回は、542×430の24bit画像として取得されました。

(6) CF_HTML  ("HTML Format")
 HTML の内容を表す、BOM 無し UTF-8 データです。先頭に
Version:1.0
StartHTML:000000199
EndHTML:000001318
StartFragment:000001219
EndFragment:000001260
StartSelection:000001219
EndSelection:000001260
SourceURL:http://www.officedaytime.com/clipmm/
 なヘッダーが付与され、その後に MSHTML でクリッピング加工された
 HTML テキストが付随します。

(7) CF_UNICODETEXT  (&HD)
 ドロップされたアイテムの URL を示す UTF-16 文字列です。
 今回は、(4) と同じ文字列が入っていました。

(8) CF_TEXT  (&HD)
 ドロップされたアイテムの URL を示す 既定のコードページ文字列です。
 文字コードが異なるだけで、中身は (7) と一緒です。

(9) "DragImageBits"
 画像をドラッグしている最中に浮かび上がる半透明の画像です。
 (5) と同様に DIB ですが、アルファ値が入るので色数は 32bit です。

(10) "DragContext"
 内容の意味は分かりません。16 バイトのバイナリが入っていました。
 00,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00
引用返信 編集キー/
■80801 / inTopicNo.4)  Re[2]: WebBrowser上でドラッグできないようにしたい
□投稿者/ オニオコゼ (2回)-(2016/08/12(Fri) 14:06:06)
No80796 (魔界の仮面弁士 さん) に返信
> これでどうでしょう。
> 選択されたテキストや画像をドラッグすることはできなくなりますが、
> 範囲選択のためのドラッグ操作は可能にしています。

ありがとうございました!
まさに、こういうことをやりたかったのです。

※ところで、AttachEventHandlerの第二引数は、
 「AddressOf ondragstart」ではなくって「AddressOf ondragstartEventCancel」でいいですよね?

Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
  WebBrowser1.Document.Body.AttachEventHandler("ondragstart", AddressOf EventCancel)
End Sub


また、ドラッグされるデータの種類の件もありがとうございました。
昨日、試しに別のFormにDragOverイベントを用意し、
問題のあるPCで色々と試したところ、
e.Data.GetDataPresent(DataFormats.FileDrop)でTrueを返すのに
DirectCast(e.Data.GetData(DataFormats.FileDrop), String())がNothngとなるケースがあり(常ではない)、
何が問題なのか分かりませんでした。
また、他のPCではこのような問題は発生しませんでした。

ただし、ドラッグが出来なくなれば、今の所何の問題もないので、
当面はこれで様子を見ようと思います。

今後とも宜しくお願い申し上げます。
解決済み
引用返信 編集キー/
■80803 / inTopicNo.5)  Re[3]: WebBrowser上でドラッグできないようにしたい
□投稿者/ 魔界の仮面弁士 (814回)-(2016/08/12(Fri) 15:47:06)
No80801 (オニオコゼ さん) に返信
> ※ところで、AttachEventHandlerの第二引数は、
>  「AddressOf ondragstart」ではなくって「AddressOf ondragstartEventCancel」でいいですよね?
おぉ゛っと。
参考情報として onselectstart を追記した時に直し漏れました。orz


ちなみに今回提示した EventCancel の実装は、WebBrowser を
IE11 モードで駆動させた場合には使えません。
window.event の動作が変更されているためです。
https://msdn.microsoft.com/ja-jp/library/dn384058.aspx


もしも IE11 モードを利用する事があれば、下記のように変更して下さい。
(このコードは、IE10 以下のモードでは使えません)

Private Sub EventCancel(sender As Object, e As EventArgs)
  Dim win = WebBrowser1.Document.Window.DomWindow
  Dim ev = win.event
  CallByName(ev, "preventDefault", CallType.Method)
  CallByName(ev, "stopPropagation", CallType.Method)
  CallByName(ev, "stopImmediatePropagation", CallType.Method)
  System.Runtime.InteropServices.Marshal.ReleaseComObject(ev)
  System.Runtime.InteropServices.Marshal.ReleaseComObject(win)
End Sub



> e.Data.GetDataPresent(DataFormats.FileDrop)でTrueを返すのに
> DirectCast(e.Data.GetData(DataFormats.FileDrop), String())がNothngとなるケースがあり(常ではない)、
> 何が問題なのか分かりませんでした。

当方では未確認ですが、保護モードが関係しているかもしれません。
https://social.msdn.microsoft.com/Forums/ja-JP/fa558b11-a1e5-46c9-9854-643a00384cdb?forum=csharpgeneralja
引用返信 編集キー/
■80807 / inTopicNo.6)  Re[4]: WebBrowser上でドラッグできないようにしたい
□投稿者/ オニオコゼ (3回)-(2016/08/12(Fri) 16:55:02)
2016/08/12(Fri) 16:56:10 編集(投稿者)

No80803 (魔界の仮面弁士 さん) に返信
> ちなみに今回提示した EventCancel の実装は、WebBrowser を
> IE11 モードで駆動させた場合には使えません。
> window.event の動作が変更されているためです。
> https://msdn.microsoft.com/ja-jp/library/dn384058.aspx

情報ありがとうございます。
WebBrowserで使用するバージョンを特に指定しない場合であれば
(レジストリを書き換えるんでしたっけ)
特に問題ないでしょうか?
(あるいは、IEのモードを判別して対応した方がよいのでしょうか?)


>>e.Data.GetDataPresent(DataFormats.FileDrop)でTrueを返すのに
>>DirectCast(e.Data.GetData(DataFormats.FileDrop), String())がNothngとなるケースがあり(常ではない)、
>>何が問題なのか分かりませんでした。
>
> 当方では未確認ですが、保護モードが関係しているかもしれません。
> https://social.msdn.microsoft.com/Forums/ja-JP/fa558b11-a1e5-46c9-9854-643a00384cdb?forum=csharpgeneralja

なるほど、そういうことですか。
WebBrowserに表示するHTMLは、確かにローカル内にあります。
貴重なアドバイス、ありがとうございました。
引用返信 編集キー/
■80815 / inTopicNo.7)  Re[5]: WebBrowser上でドラッグできないようにしたい
□投稿者/ 魔界の仮面弁士 (815回)-(2016/08/12(Fri) 18:22:36)
No80807 (オニオコゼ さん) に返信
> (レジストリを書き換えるんでしたっけ)
はい、FEATURE_BROWSER_EMULATION ですね。
https://www.ipentec.com/document/document.aspx?page=csharp-change-webbrower-control-internet-explorer-version

上記以外のレジストリ設定に付いては下記をご覧ください。
https://msdn.microsoft.com/en-us/library/ee330720.aspx


> WebBrowserで使用するバージョンを特に指定しない場合であれば
> 特に問題ないでしょうか?
IE7〜IE11 環境の場合、レジストリ指定がない場合には、
常に IE7 モードで動作します。
(.NET 2.0 以降に搭載の Managed 版は、IE7 以降が対象になります)


IE3.01 および IE4.0〜IE6.0 の WebBrowser は、
IE バージョンと同じエンジンが使われます。
(VB.NET 2002 などで AxWebBrowser を使う場合など)


> (あるいは、IEのモードを判別して対応した方がよいのでしょうか?)
どうするかは、作成する「アプリケーションの仕様」として決めてしまえば良いかと。
引用返信 編集キー/
■80832 / inTopicNo.8)  Re[2]: WebBrowser上でドラッグできないようにしたい
□投稿者/ WebSurfer (1000回)-(2016/08/13(Sat) 14:46:41)
No80796 (魔界の仮面弁士 さん) に返信

> これでどうでしょう。
> 選択されたテキストや画像をドラッグすることはできなくなりますが、
> 範囲選択のためのドラッグ操作は可能にしています。
> 
> 
> Private Sub EventCancel(sender As Object, e As EventArgs)
>   Dim win = WebBrowser1.Document.Window.DomWindow
>   Dim ev = win.event
>   ev.cancelBubble = True
>   ev.returnValue = False
>   System.Runtime.InteropServices.Marshal.ReleaseComObject(ev)
>   System.Runtime.InteropServices.Marshal.ReleaseComObject(win)
> End Sub
> 
> Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
>   WebBrowser1.Document.Body.AttachEventHandler("ondragstart", AddressOf ondragstart)
>   'WebBrowser1.Document.Body.AttachEventHandler("onselectstart", AddressOf EventCancel)
> End Sub

アンマネージ側を意識しなくても、HtmlDocument クラスに提供されているメソッド、
プロパティ、イベントだけでドラッグできないようにするという方法はあると思うの
ですが、そうしないのは何か理由があるのでしょうか?

例えば img 要素の画像をドラッグできないようにするのであれば、以下のようにして
目的を果たせるはずです。IE11 でどうなるかは試してませんので分かりませんが。

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    HtmlElementCollection images = webBrowser1.Document.GetElementsByTagName("img");
    foreach (HtmlElement img in images)
    {
        img.Drag += new HtmlElementEventHandler(img_Drag);
    }
}

void img_Drag(object sender, HtmlElementEventArgs e)
{
    e.ReturnValue = false;
}

何か理由があって、上記のようなことではダメということでしたら、理由を教えていた
だけると幸いです。

引用返信 編集キー/
■80873 / inTopicNo.9)  Re[3]: WebBrowser上でドラッグできないようにしたい
□投稿者/ オニオコゼ (4回)-(2016/08/16(Tue) 11:25:33)
No80832 (WebSurfer さん) に返信
> 例えば img 要素の画像をドラッグできないようにするのであれば、以下のようにして
> 目的を果たせるはずです。IE11 でどうなるかは試してませんので分かりませんが。

ありがとうございます。
WebBrowserを使う際、HtmlElementクラスはよく利用していますので、
こちらの方がスッキリして使いやすいです。

さらに、テキストの外部ドラッグは不要なので、魔界の仮面弁士 さんのアドバイスを元に
bodyに対するドラッグ制御として、以下のようなコードでうまくいきました。

Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
    
    Dim body As HtmlElement = WebBrowser1.Document.Body

    '(実際にはここに他の処理を行う)

    AddHandler body.Drag, AddressOf body_Drag
End Sub

Private Sub body_Drag(ByVal sender As Object, ByVal e As HtmlElementEventArgs)
    e.ReturnValue = False
End Sub

皆さま、貴重なアドバイス、ありがとうございました。
今後とも宜しくお願い申し上げます。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -