5

私のWPFアプリケーションでは、HwndHostを使用してWin32コンテンツをホストしています。ただし、HwndHostを作成しても、ネイティブウィンドウは作成されません。BuildWindowCore()むしろ、これは、後でWPFによって呼び出されるオーバーライドされたメソッドで実行されます。

ホストされているコンテンツは、独自の初期化のためにネイティブウィンドウのウィンドウハンドルを必要とします。残念ながら、ウィンドウの作成を強制する方法はありません(つまり、WPFでBuildWindowCoreを呼び出す)ので、初期化されるまでHwndHostをポーリングする2番目のスレッドがあります。

.NET 4.0 / WPF 4.0では、新しいメソッドWindowInteropHelper.EnsureHandle()が追加されました。これで状況が解決することを期待していましたが、HwndHost(Windowから派生していない)ではなく、Windowでのみ機能します。代わりに私に何ができるか提案がありますか?

編集:

考えられる解決策のために、さらにいくつかの制約を追加するのを忘れました。

  1. HwndHostは、ユーザー設定に応じて、アプリケーションのメインウィンドウの子になることも、(サードパーティのドッキングマネージャーを介して)新しいウィンドウに配置することもできるコントロールに配置されます。これは、ウィンドウの作成中に、親ウィンドウ(したがってそのhWnd)がどうなるかわからないことを意味します。
  2. ネイティブコードは初期化中にhWndを必要としますが、ウィンドウはユーザーが表示を要求した場合にのみ表示されます(つまり、最初は表示されません)。可能であれば、ウィンドウを表示する必要はありませんが、すぐに非表示にするだけです。
4

4 に答える 4

3

完璧な解決策はないようです。質問されたときと比べて、アプローチを少し変更しました。

HwndHostから派生したクラスのコンストラクターには、パラメーターの1つとして(可能な)親hWndがあります。CreateWindow()次に、指定された親hWndを使用して、ネイティブメソッドを使用してネイティブウィンドウを作成します。作成したhWndを別のプロパティに保存します。このプロパティは、HwndHostのHandleプロパティの代わりにどこでも使用します。そうすれば、ウィンドウを表示する必要はありません(これにより制約#2が解決されます)。

オーバーライドされたBuildWindowCore()メソッドでは、指定された親hWndをコンストラクターで指定されたものと比較します。それらが異なる場合は、ネイティブSetParent()メソッドを使用してホストウィンドウの親を変更します(これにより制約#1が解決されます)。これは、親hWndを格納する人がいないことに依存していることに注意してください。

コードでは、関連する部分(チェックは省略):

public class Win32Window : HwndHost
{
    public Win32Window(IntPtr parentHwnd)
    {
        this.ParentHwnd = parentHwnd;
        this.Win32Handle = NativeMethods.CreateWindowEx( /* parameters omitted*/ );
    }

    public IntPtr Win32Handle { get; private set; }
    private IntPtr ParentHwnd { get; set; }

    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        if (hwndParent.Handle != this.ParentHwnd)
        {
            NativeMethods.SetParent(this.Win32Handle, hwndParent.Handle);
        }

        return new HandleRef(this, this.Win32Handle);
    }
}
于 2011-06-24T10:42:18.270 に答える
2

私も同様の状況にあり、次のようにして解決しました。

1)Rectをコンストラクター引数として受け取るHwndHost派生クラスを作成します(後でBuildWindowCoreで使用されます)。

public class MyHwndHost : HwndHost
{
    public MyHwndHost(Rect boundingBox)
    {
        BoundingBox = boundingBox;
    } 
}

2)子Border要素を使用してWPFウィンドウを作成します。

<Window Loaded="Window_Loaded">
    <Border Name="HostElement" />
</Window>

3)HwndHostインスタンスを作成し、Window_Loadedハンドラーのウィンドウに追加します。

void Window_Loaded(object sender, RoutedEventArgs e)
{
    MyHwndHost host = new MyHwndHost(LayoutInformation.GetLayoutSlot(HostElement));
    HostElement.Child = host;
}

4)また、Window_Loadedハンドラーで、P/InvokeまたはC++/CLIのいずれかを介してHWNDをネイティブクラスの初期化に渡します。そのHWNDを親として使用するようにネイティブクラスを設定し、子として独自のHWNDを作成します。

于 2011-05-27T14:47:01.053 に答える
1

少し遅れましたがUpdateLayout()、ホスティングコントロールを呼び出してみましたか?それは私のために働いた

于 2011-06-21T08:28:08.037 に答える
1

ハンドルIntPtrを含む継承されたクラスにイベントを追加しましたOnHandleCreatedHwndHostこのイベントは、内で呼び出されBuildWindowCore()ます。

つまり、要約すると次のようになります。

public class Win32WindowHost : HwndHost { ... }

var host = new Win32WindowHost();
host.OnHandleCreated += ( sender, e ) =>
{
    var handle = e.Handle;
    // Do stuff.
};

御馳走を動作します。

于 2014-02-19T11:47:36.373 に答える