6

私のアプリケーションは vb6 実行可能ファイルですが、システム内の一部の新しいフォームは C# で記述されています。メイン アプリケーション ウィンドウへのハンドルを使用して C# フォームの Owner プロパティを設定できるようにしたいと考えています。これにより、アプリと他のアプリの間でタブを行ったり来たりしてもダイアログが上部に表示されたままになります。

メイン アプリケーション ウィンドウの hwnd を取得できます。そこから何ができるかわかりませんか?


更新 2008 年 10 月 20 日 17:06:

スコット、

返信ありがとうございます。Show/ShowDialog メソッド パラメータが Form 型ではないことを見逃していました。Owner プロパティだけを見ていました。

上記から使用しているコードを少し変更しました。フォームを一般的にロードして ShowDialog を呼び出すコンポーネントがあります。私のコードは次のようになります。

Form launchTarget = FormFactory.GetForm(xxx);  // psuedo-code for generic form loader
launchTarget.StartPosition = FormStartPosition.CenterParent;
IWin32Window parentWindow = GetWindowFromHwnd(hwnd);

launchTarget.ShowDialog(parentWindow);

GetWindowFromHwndあなたのコードのメソッドラップバージョンです:

private IWin32Window GetWindowFromHost(int hwnd)
{
    IWin32Window window = null;
    IntPtr handle = new IntPtr(hwnd);

    try
    {
        NativeWindow nativeWindow = new NativeWindow();
        nativeWindow.AssignHandle(handle);
        window = nativeWindow;
    }
    finally
    {
        handle = IntPtr.Zero;
    }

    return window;
}

残念ながら、これは私が望んでいたことをしていません。フォームはモーダルに表示されますが、正しい位置に表示されず、タブを離して親ウィンドウに戻ってもまだ上に表示されません。私たちのモーダルはタスクバーにタスクを表示しないため、ウィンドウは「消える」ように見えます (ただし、alt-tab ウィンドウ リストにはまだ存在します)。それは、私が正しい hwnd を持っていない可能性があることを示しています。他に提案がある場合は、返信してください。再度、感謝します。


UPDATE 10 11月. 082008-11-10 16:25:00

フォローアップの 1 つのコメント - Scott の 2 番目の投稿のように、try/finally のメソッド呼び出しに分解すると、finally ブロックの呼び出しは次のようになります。

parentWindow.ReleaseHandle();
4

2 に答える 2

9

つまり、VB6 から C# Windows Form クラスを呼び出しています。つまり、おそらくShow()またはを使用しているということですよShowDialog()ね?これらのメソッドはどちらも IWin32Window パラメーターも受け取ります。これは、Handle という名前の IntPtr プロパティを返すオブジェクトを定義するだけです。

longそのため、フォームに VB6 hwnd を渡すことができるように、パラメーターとしてを受け取る Windows フォーム クラスにオーバーロードされたコンストラクター (または ShowDialog メソッド) を追加する必要があります。C# コード内に入ったら、hwnd から IntPtr を作成してNativeWindowオブジェクトに割り当て、それを所有者として渡す必要があります。

テストされていませんが、次のようなものが機能するはずです。

public DialogResult ShowDialog(long hwnd)
{
   IntPtr handle = new IntPtr(hwnd);
   try
   {
      NativeWindow nativeWindow = new NativeWindow();

      nativeWindow.AssignHandle(handle);
      return this.ShowDialog(nativeWindow);
   }
   finally
   {
      handle = IntPtr.Zero;
   }
}
于 2008-10-17T20:36:13.303 に答える
2

これはコメントとして投稿するには長すぎます...

あなたが実行している問題は、ShowDialog オーバーロードで提示したコードをラップする方法だと思います。GetWindowFromHostコードが行っていることに従うと、次の手順が実行されます。

  1. 指定された hwnd から新しい IntPtr を作成します。
  2. 新しい NativeWindow オブジェクトを作成し、そのハンドルを IntPtr に割り当てます。
  3. IntPtr (finally ブロック内) を IntPtr.Zero に設定します。

問題を引き起こしているのは、この finally ブロックだと思います。私のコードでは、finally ブロックはthis.ShowDialog(nativeWindow)finished への呼び出しの後に実行されます。その時点で、ハンドル (IntPtr) は使用されなくなりました。あなたのコードでは、IWin32Window呼び出し時に IntPtr.Zero である IntPtr への参照を保持している必要がある を返していますlaunchTarget.ShowDialog(parentWindow)

コードを次のように変更してみてください。

private NativeWindow GetWindowFromHost(int hwnd)
{
   IntPtr handle = new IntPtr(hwnd);
   NativeWindow nativeWindow = new NativeWindow();
   nativeWindow.AssignHandle(handle);
   return window;
}

次に、呼び出しコードを次のように変更します。

Form launchTarget = FormFactory.GetForm(xxx);  // psuedo-code for generic form 
loaderlaunchTarget.StartPosition = FormStartPosition.CenterParent;
NativeWindow parentWindow = GetWindowFromHwnd(hwnd);

try
{
   launchTarget.ShowDialog(parentWindow);
}
finally
{
   parentWindow.DestroyHandle();
}

これらの変更は機能するはずですが、これもテストされていません。

于 2008-10-20T17:27:56.617 に答える