hwnd / NativeWindowを使用してWinFormsフォームの所有者を設定する動作を取得できますか?
質問
私のアプリケーションはvb6実行可能ファイルですが、システム内のいくつかの新しいフォームはC#で記述されています。メインアプリケーションウィンドウへのハンドルを使用してC#フォームのOwnerプロパティを設定できるようにしたいので、アプリと他のアプリの間で前後にタブ移動するときにダイアログが一番上に残ります。
メインアプリケーションウィンドウのhwndを取得できます。そこから何ができるかわかりませんか?
2008年10月20日17:06に更新:
スコット、
ご回答ありがとうございます。 Show / ShowDialogメソッドのパラメーターはForm型ではないことを見落としていました-Ownerプロパティのみを見ていました。
上記から使用しているコードを少し変更しました。Formsを一般的に読み込み、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がないかもしれないことを示しています。他に提案があれば、返信してください。どうもありがとう。
08年11月10日16:25に更新
フォローアップのコメント-Scottの2番目の投稿のように、try / finallyでメソッド呼び出しに含める場合、finallyブロックの呼び出しは次のようになります。
parentWindow.ReleaseHandle();
解決
では、VB6からC#Windows Formクラスを呼び出しています。つまり、おそらく Show()
または ShowDialog()
を使用していることになります。これらのメソッドは両方とも、IWin32Windowパラメーターも取ります。このパラメーターは、Handleという名前のIntPtrプロパティを返すオブジェクトを単純に定義します。
そのため、VB6 hwndをフォームに渡すことができるように、パラメーターとして long
を受け取るWindows Formsクラスのオーバーロードコンストラクター(または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;
}
}
他のヒント
コメントとして投稿するには長すぎます...
実行中の問題は、ShowDialogオーバーロードで提示したコードをラップする方法にあると思います。 GetWindowFromHost
コードの実行内容に従うと、次の手順が実行されます。
- 指定されたhwndから新しいIntPtrを作成します。
- 新しいNativeWindowオブジェクトを作成し、そのハンドルをIntPtrに割り当てます。
- IntPtr(finallyブロック内)をIntPtr.Zeroに設定します。
問題を引き起こしているのはこの最後のブロックだと思います。私のコードでは、 this.ShowDialog(nativeWindow)
の呼び出しが終了した後に、finallyブロックが実行されます。その時点で、ハンドル(IntPtr)は使用されなくなりました。コードでは、IntPtrへの参照を保持する必要がある IWin32Window
を返します。このIntPtrは、 launchTarget.ShowDialog(parentWindow)
を呼び出すときにIntPtr.Zeroです。
次のようにコードを変更してみてください:
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();
}
これらの変更は機能するはずですが、これもテストされていません。