C# 有新的希望吗?使窗口成为MDI子对象

C# 有新的希望吗?使窗口成为MDI子对象,c#,winforms,mdi,C#,Winforms,Mdi,获取了一些C#窗体/控件,这些控件可以从Winforms MDI应用程序中Winform上的C#控件调用,也可以通过COM从PowerBuilder MDI应用程序使用的相同C#控件调用 我一直在使用WinAPI调用SetParent将表单附加到MDI 它在两种环境中都能工作(或似乎都能) 它让子窗口有自己的窗口状态(正常,最大化),而不是接受已经打开的子窗口的窗口状态(这是一个真正的痛苦) 假设控件名为T。控件T上的代码调用表单D 控件T位于表格X上。 控件T也位于表格Y上 在.Net中一切正

获取了一些C#窗体/控件,这些控件可以从Winforms MDI应用程序中Winform上的C#控件调用,也可以通过COM从PowerBuilder MDI应用程序使用的相同C#控件调用

我一直在使用WinAPI调用SetParent将表单附加到MDI

  • 它在两种环境中都能工作(或似乎都能)
  • 它让子窗口有自己的窗口状态(正常,最大化),而不是接受已经打开的子窗口的窗口状态(这是一个真正的痛苦)
  • 假设控件名为T。控件T上的代码调用表单D

    控件T位于表格X上。
    控件T也位于表格Y上

    在.Net中一切正常,表单D保留在MDI中

    以PB为单位:
    控制T在PB控制PX上。 控制T也在PB控制PY上

    对于PX来说,一切都很好。
    然而,对于PY来说,有一个问题-表单D似乎没有成为MDI子级-它可以进入应用程序之外,并且有一个任务栏图标。我要强调的是,这是使用与工作对象相同的对象。SetParent实际上是同一行代码

    进一步的研究表明,SetParent实际上不适用于正确的MDI子代-但这没关系,因为我们不需要合并菜单等

    有趣的是,我们发现,尽管SetParent似乎“起作用”,但如果您尝试GetParent,就无法获得句柄

    Form form = new MyForm();
    WindowsMessageHelper.SetParent(form.Handle, MDIParentHandle); //passed down 
    int parentHandle = WindowsMessageHelper.GetParent(form.Handle);
    
    parentHandle将始终为0

    有没有办法让表格D在任何情况下都能正常工作?我自己的研究结果并不乐观。我真的不想回去重写我的表单作为控件,并让PowerBuilder管理它们——主要是因为每个表单可能有多个实例,PowerBuilder必须处理它们(而不是我在.net应用程序中使用的控制器类/基类)


    我要强调的是,在.Net中没有问题,问题只出现在PowerBuilder应用程序中

    您的孩子需要是System.Windows.Forms.Form,并将其MDI Parent属性设置为MDI专利窗口(而不是其父窗口)

    容器还需要遵循一些规则

    通读一下可能会有进一步的帮助



    选项二:您可能无法使用单个控件执行此操作。在两个包装器中考虑内核实现的组成。第一个包装器用作WinForms MDI子级,第二个包装器用作COM包装器,在PowerBuilder工作的任何GUI框架下使用。

    您的子级需要是System.Windows.Forms.Form,并将其MDI Parent属性设置为MDI专利窗口(而不是其父级)

    容器还需要遵循一些规则

    通读一下可能会有进一步的帮助



    选项二:您可能无法使用单个控件执行此操作。在两个包装器中考虑内核实现的组成。第一个包装器充当WinForms MDI子级,第二个作为COM包装器,在PowerBuilder工作的任何GUI框架下使用。

    如果您还没有解决的唯一问题是GetParent不工作,您可能可以接受它

    编辑:但是asker有更多的问题

    有许多API poke必须依次完成才能使其工作。当通过COM接口使用它时,您可以更轻松地将其设置为用户控件并将其放置在本机MDI父级上;当将其放置在.NET MDI父级时,您可以更轻松地将其放置在.NET MDI子级上

    这里必须使用不同的基本窗口过程(DefWindowProc与DefMdiChildProc),为了实现这一点,您最终实现了DefMdiChildProc


    如果您使用.NET reflector,您可能能够找到一种方法,使System.Windows.Forms.Form为您调用DefMdiChildProc。

    如果您唯一尚未解决的问题是GetParent不起作用,您可能可以接受它

    编辑:但是asker有更多的问题

    有许多API poke必须依次完成才能使其工作。当通过COM接口使用它时,您可以更轻松地将其设置为用户控件并将其放置在本机MDI父级上;当将其放置在.NET MDI父级时,您可以更轻松地将其放置在.NET MDI子级上

    这里必须使用不同的基本窗口过程(DefWindowProc与DefMdiChildProc),为了实现这一点,您最终实现了DefMdiChildProc


    如果您使用.NET reflector,您可能能够找到一种方法使System.Windows.Forms.Form为您调用DefMdiChildProc。

    最后,我们发现不同之处在于PB为控件PX(调用表单D的地方)设置了.mdipalent,而不是PY


    排序完成后,我们得到了正确的MDIParent句柄,现在一切都正常了。

    最后,我们发现不同之处在于PB为控件PX(调用表单D的那一个)执行了与设置.MDIParent等效的操作,而不是为PY


    排序完成后,我们得到了正确的MDI父句柄,现在一切正常。

    我编辑了这个问题,希望能更清楚地说明为什么这个答案不够。在第二种情况下,SetParent没有诱导表单D的预期行为。我编辑了这个问题,希望能更清楚地说明为什么这个答案不够。在第二种情况下,SetParent不会导致表单D的预期行为。我编辑了这个问题,希望能更清楚地说明为什么这个答案不够-您的解决方案是纯.Net解决方案,这里没有问题。我编辑了这个问题,希望能更清楚地说明为什么这个答案不够-您的解决方案是纯.Net解决方案,没有问题。选项二是我们对其他表单所做的,但这意味着PB必须控制它们——无论如何,请看下面我的答案……我编辑了这个问题,希望能更清楚地说明为什么这个答案不够——您的解决方案是一个纯.Net解决方案,没有任何问题。我编辑了这个问题,希望能更清楚地说明问题