zoukankan      html  css  js  c++  java
  • C#窗体嵌入SetParent的用法

    模块化的开发,将模块合并到一起的时候,遇到了Mdi不能添加到其它窗口下的问题。

    分两种情况:

    将mdi窗口A设成普通窗口B的子控件,需要将A的TopLevel设置成false,但是Mdi窗口的TopLevel必须为顶级;

    将mdi窗口A设成mdi窗口B的子窗口,A.MdiParent = B,编译时不通过,窗口不能既是mdi子级,又是mdi父级。

    最后通过windows Api强制将mdi窗口A的parent设置成窗口B。

    复制代码
    [DllImport("user32.dll", EntryPoint = "SetParent")]
    public static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
    MDIParent1 form = new MDIParent1();
    SetParent(form.Handle, this.Handle);
    form.Location = new Point(0, 0);
    form.Size = this.Size;
    form.Show();
    复制代码

    通过SetParent将mdi窗口强行放到了普通的Form下。

    调试的时候,界面上达到了预期的目标,但是发现了另一个新的问题。

    焦点在mdi的子窗口上时,mdi窗口上的控件无效,点击事件全部触发不了;焦点在mdi的父窗口上时,mdi窗口的控件又“激活”了。而在单独打开mdi窗口时,完全不存在这个问题。

    查询了一下msdn里面的SetParent的说明,发现了如下段:

    “For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, it is not possible to change a window from parent to child or from child to parent.”

    我的理解是,虽然用SetParent强制将普通窗口设置成mdi的父窗口,但是mdi的子级窗口的属性却没有赋予。

    解决的思路,调用另一个windows·Api SetWindowLong强制修改mdi的窗口属性。

    复制代码
    private const int GWL_STYLE = -16;
    private const int WS_CHILD = 0x40000000;//设置窗口属性为child
    
    [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    public static extern int GetWindowLong(IntPtr hwnd, int nIndex);
    
    [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
    public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);
    
    var s = GetWindowLong(form.Handle, GWL_STYLE);
    SetWindowLong(form.Handle, GWL_STYLE, s | WS_CHILD);
    复制代码

    至此,问题算解决了。发一个效果图:

    补充一个bug:虽然解决了mdiParent获取焦点的问题,后来发现mdiChild获取焦点又不正常了。如果mdiChild,如上图中的Form2界面上有TextBox控件时,修改TextBox的文字时,光标的位置,总是不正常。能力有限,尚待解决。

  • 相关阅读:
    vim 一些操作
    RedisTemplate 获取过期时间的问题
    SpringBoot 配置 Redis 多缓存名(不同缓存名缓存失效时间不同)
    Vue ElementUI Tree组件 回显问题(设置选择父级时会全选所有的子级,有此业务场景是不适合的)
    动态切换数据库源码解析
    @Primary 注解的作用
    @Value注解的使用
    Shiro&Jwt验证
    浏览器缓存和Service Worker
    Javascript的事件模型和Promise实现
  • 原文地址:https://www.cnblogs.com/xtfnpgy/p/9285428.html
Copyright © 2011-2022 走看看