C# 我可以获得设置WinForms窗体的行为吗';使用hwnd/NativeWindow的所有者?

C# 我可以获得设置WinForms窗体的行为吗';使用hwnd/NativeWindow的所有者?,c#,winforms,hwnd,C#,Winforms,Hwnd,我的应用程序是vb6可执行文件,但系统中一些较新的表单是用C#编写的。我希望能够使用主应用程序窗口的句柄设置C#表单的所有者属性,以便在我的应用程序和其他应用程序之间来回切换时,对话框保持在顶部 我可以获得主应用程序窗口的hwnd。我不确定我能从那里做些什么 2008年10月20日17:06更新: 斯科特 谢谢你的回复。我忽略了Show/ShowDialog方法参数不是Form类型——我只查看了Owner属性 我稍微修改了上面使用的代码——我们有一个组件,它一般加载表单并调用ShowDialo

我的应用程序是vb6可执行文件,但系统中一些较新的表单是用C#编写的。我希望能够使用主应用程序窗口的句柄设置C#表单的所有者属性,以便在我的应用程序和其他应用程序之间来回切换时,对话框保持在顶部

我可以获得主应用程序窗口的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);
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
代码所做的操作进行操作,则会执行以下步骤:

  • 从给定的hwnd创建新的IntPtr
  • 创建一个新的NativeWindow对象,并将其句柄指定为IntPtr
  • 将IntPtr(在finally块中)设置为IntPtr.Zero
  • 我想是这最后一个障碍给你带来了麻烦。在我的代码中,finally块将在调用
    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()的信息!:-)