2

を使用する場合System.Windows.Forms.ShowDialog(IWin32Window)、任意のウィンドウ ハンドルを表すものを渡して、IWin32Windowそのウィンドウに対してモーダルにする必要がありますか?

Internet Explorer 7 拡張機能の一部として、Internet Explorer タブに関するウィンドウ モーダルを開こうとしています。現在選択されているタブではありませんが、タブの hwnd を取得できれば OK です。ただし、これを ShowDialog に渡すと、フォームが表示されますが、モーダルではありません。所有者であるはずのタブを含め、Internet Explorer で操作を行うことができます。私のフォームは Internet Explorer ウィンドウの上に浮いて表示され、一番上に表示されるので、通常のフォームとして開かれただけではなく、正しくモーダルではありません。

Spy++を使用すると、フォームを見つけることができ、その所有者ハンドルが正しく設定されています。

これは、何かが間違っているということですか、それとも私が何か間違ったことをしているということですか? フォームを正しくモーダルにするにはどうすればよいですか?

参考までに、このラッパー クラスを使用してIWin32Windowfromを作成していますhwnd(ありがとうRyan! ):

/// <summary>
/// Wrapper class so that we can return an IWin32Window given a hwnd
/// </summary>
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
    public WindowWrapper(IntPtr handle)
    {
        _hwnd = handle;
    }

    public IntPtr Handle
    {
        get { return _hwnd; }
    }

    private IntPtr _hwnd;
}

更新: Internet Explorer 7 & .NET 2.0 の使用

更新: Spy++ とそれが公開するハンドルをもう少しいじってみると、別のものを使用するとhwnd、ウィンドウをタブにモーダルにすることができることがわかりました。

Spy ++では class として表示されるIWebBrowser2.HWND dochwndで提案されているように、タブを使用していました。クラス の子があり、これには Internet_Explorer_Server の子があります。の を使用すると、正しく動作します。たとえば、マウスで他のタブをクリックすると、Internet Explorer は正常に反応します。興味のあるタブをマウスでクリックすると、windows d'oh サウンドが再生され、何もしません。TabWindowClassShell DocObject ViewhwndInternet Explorer_Server

Internet_Explorer_Server をプログラムで取得する方法はまだわかりませんが、hwnd可能なはずです。

また、価値のあることとして、他のウィンドウ ハンドルで遊んでいる間、通常、フォームを他のアプリケーションやダイアログに対してモーダルにすることができました。したがって、私の質問に対する答えは「すべてのハンドルではなく多くのハンドル」であると思います...おそらくアプリケーションに依存しますか?

更新: 別の補足事項: フォームをウィンドウ全体ではなくタブに対してモーダルにしたかった当初の理由は、MessageBoxフォームから a を開くときに、フォームを所有者として渡すと、MessageBox常にフォームの上に開くとは限らないためです。 . Internet Explorer の新しいタブを開いたばかりでアクティブになっていない場合、MessageBoxタブが非表示になり、そのタブが点滅し始めます。ただし、モーダルでフォームを開いた状態で Internet Explorer が無効になっているため、そのタブに切り替えることができず、Internet Explorer がフリーズしていました。フォームモーダルをタブに開くとこれが解決すると思いましたが、別の解決策は使用を避けることであることがわかりましMessageBoxた.2番目のフォームを使用ShowDialog(this)し、最初のフォームから2番目のフォームが正しく前面に開きます。Form.ShowDialog()そのため、よりもうまく機能するようですMessageBox.Show()ある場合には。モーダル ダイアログとメッセージ ボックスに関する問題 での詳細な議論。

4

4 に答える 4

5

ShowDialog() は 2 つの重要なことを行います。呼び出し元のコードに対してモーダルに動作するように、メッセージ ループのポンピングを開始します。また、EnableWindow(false) API 呼び出しを使用して、アプリケーション内の他のウィンドウを無効にします。後者は、あなたの場合に起こっていないことです。無効にする必要があるウィンドウが WF ウィンドウではないことを考えると、まったく驚くべきことではありません。

EnableWindow() を自分で呼び出す必要がある場合があります。ダイアログを閉じる前に再度有効にしてください。そうしないと、Windows が別のアプリのウィンドウを探してフォーカスを移します。

于 2009-02-24T15:43:00.867 に答える
2

あなたのコードは正しいです。ただし、おそらく遭遇する問題は、IE にはタブに関連するスレッド モデルがあることです。正確な詳細はわかりませんが、短いバージョンでは、各タブが他のタブとは異なるスレッドで実行されている可能性があります。

ダイアログのモーダル性は、ダイアログが実行されているスレッドに固有です。他のスレッドの UI は、別のスレッドのモデル ダイアログの影響を受けません。このため、別のスレッドで実行されているタブにアクセスできる可能性は十分にあります。

于 2009-02-24T14:59:16.617 に答える
2

以下は、Ryan/Rory の WindowWrapper コードのより簡潔なバージョンです。

internal class WindowWrapper : IWin32Window
{
    public IntPtr Handle { get; private set; }
    public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}
于 2010-02-26T13:34:18.323 に答える
0

私はIE拡張からこれを試したことはありませんが、IEがWin32スタイルのモーダルウィンドウを「尊重」しない可能性があるという予感があります。window.open().

このコードを IE 以外のものに対してテストして、他のアプリケーションで正常に動作することを確認しましたか?

于 2009-02-24T14:12:23.127 に答える