C# 我可以获得设置WinForms窗体的行为吗';使用hwnd/NativeWindow的所有者?
我的应用程序是vb6可执行文件,但系统中一些较新的表单是用C#编写的。我希望能够使用主应用程序窗口的句柄设置C#表单的所有者属性,以便在我的应用程序和其他应用程序之间来回切换时,对话框保持在顶部 我可以获得主应用程序窗口的hwnd。我不确定我能从那里做些什么C# 我可以获得设置WinForms窗体的行为吗';使用hwnd/NativeWindow的所有者?,c#,winforms,hwnd,C#,Winforms,Hwnd,我的应用程序是vb6可执行文件,但系统中一些较新的表单是用C#编写的。我希望能够使用主应用程序窗口的句柄设置C#表单的所有者属性,以便在我的应用程序和其他应用程序之间来回切换时,对话框保持在顶部 我可以获得主应用程序窗口的hwnd。我不确定我能从那里做些什么 2008年10月20日17:06更新: 斯科特 谢谢你的回复。我忽略了Show/ShowDialog方法参数不是Form类型——我只查看了Owner属性 我稍微修改了上面使用的代码——我们有一个组件,它一般加载表单并调用ShowDialo
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);
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();
}
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;
}
不幸的是,这不是我所希望的。表单确实以模式显示,但当我用tab键离开并返回到父窗口时,它没有显示在正确的位置,也没有显示在顶部。我们的modals在任务栏中不显示任务,因此窗口似乎“消失”(尽管它仍然存在于alt tab窗口列表中)。这对我来说意味着我可能没有正确的hwnd。如果您还有其他建议,请回复。再次感谢
于2008年11月10日16:25更新 一个后续评论-如果您将其分解为try/finally中的方法调用,如Scott的第2篇文章中所述,finally块中的调用应该是:
parentWindow.ReleaseHandle();
因此,您正在从VB6调用一个C#Windows窗体类,这意味着您可能正在使用Show()
或ShowDialog()
,对吗?这两种方法还采用IWin32Window参数,该参数仅定义一个返回名为Handle的IntPtr属性的对象
因此,您需要为Windows窗体类添加重载构造函数(或ShowDialog方法),这些类将long
作为参数,以便将VB6 hwnd传递给窗体。进入C#code之后,需要从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
代码所做的操作进行操作,则会执行以下步骤:
this.ShowDialog(nativeWindow)
完成后运行。此时,不再使用句柄(IntPtr)。在代码中,您返回的是一个iwin32窗口
,该窗口仍应包含对该IntPtr的引用,在调用launchTarget.ShowDialog(parentWindow)
时该IntPtr.Zero
请尝试将代码更改为如下所示:
Form launchTarget = FormFactory.GetForm(xxx); // psuedo-code for generic form loader
launchTarget.StartPosition = FormStartPosition.CenterParent;
IWin32Window parentWindow = GetWindowFromHwnd(hwnd);
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();
}
然后将您的呼叫代码更改为如下所示:
Form launchTarget = FormFactory.GetForm(xxx); // psuedo-code for generic form loader
launchTarget.StartPosition = FormStartPosition.CenterParent;
IWin32Window parentWindow = GetWindowFromHwnd(hwnd);
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();
}
这些更改应该可以工作,但这仍然没有经过测试。Scott-很抱歉,耽搁了这么长时间,我被扯到了其他事情上。您提交的原始答案非常有效。我只需要通过ShowDialog传递NativeWindow,而不是设置Form.Owner。我的另一个问题是调用代码首先没有传递正确的hWnd。感谢您,以上两个问题都是可以解决的--对于中心性,请确保设置:“form.StartPosition=FormStartPosition.CenterParent”--对于顶部性,请确保设置:form.TopMost=true;--顺便说一句,感谢您提供有关ReleaseHandle()的信息!:-)