• winform之在主窗体中不显示子窗体的菜单栏


    在MDi窗体嵌入子窗体后不显示菜单栏

    背景:

    由于之前做的一个程序的功能全部都是放在一个界面上的,有一个功能能够在数据库查询数据,并返回到界面上,数据量比较小的时候还好,但是数据量多了,导致它阻塞的其他线程,经过一系列讨论之后,决定将一个界面换成一个主界面加多个子界面。

    实施:

    多个子界面迁移完成之后,使用下面的方法将其放置的主界面中(先将主窗体的IsMdiContainer设置为true,不然会报错)

    Form frm = new SssForm();
    foreach (Form childForm in MdiChildren)
    {
        if (childForm != CccForm)
        {
            childForm.Close();
        }
    }
    this.CccForm.Visible = false;
    frm.MdiParent = this;
    frm.Show();
    frm.WindowState = FormWindowState.Maximized;
    

    然后在主窗体和子窗体的属性那里把ControlBox属性设置为false,然后测试发现主窗体一开始是没有菜单栏的,但是打开子窗体之后就会在主窗体的右上角显示出菜单栏

    查阅了一些网上的办法去改变其他属性值,但是测试之后发现没有用,有说用pannel的,但是我的这个程序需要在Mdi中实现,就没有去实践了,后面就去问gpt4了,最后用gpt4给的方法实现了

    这个方法是重写WndProc,在获取到子窗体需要重新计算大小时,直接告诉系统我们只需要计算工作区,而不需要把菜单栏加入进来,这里微软的官方文档里面也有写到[(https://learn.microsoft.com/zh-cn/windows/win32/winmsg/wm-nccalcsize)]

    以下是代码实现:

    protected override void WndProc(ref Message m)
    {
        const int WM_NCCALCSIZE = 0x0083;
        const int WM_NCHITTEST = 0x0084;
    
        switch (m.Msg)
        {
            case WM_NCCALCSIZE:
                // 当窗体的大小需要重新计算时,系统会发送WM_NCCALCSIZE消息
                // 这里可以修改消息的处理,以改变窗体非客户区的大小
                // 如果wParam是TRUE(非零),则指示客户区大小需要重新计算
                // 通过简单地返回0,我们可以告诉Windows我们已处理消息,不需要默认的非客户区
                // 这实际上会移除所有的非客户区,包括边框和标题栏
                if (m.WParam.ToInt32() != 0)
                {
                    // 返回0表示我们处理了这个消息,不再需要默认的处理
                    // 这将去除非客户区,包括标题栏和边框
                    m.Result = IntPtr.Zero;
                    return;
                }
                break;
            case WM_NCHITTEST:
                // 可以在这里处理鼠标事件,例如检测鼠标是否在我们自定义的标题栏区域内
                // 这对于添加拖动行为等自定义交互是有用的
                base.WndProc(ref m);
                if ((int)m.Result == 0x01) // HTCLIENT
                {
                    // 可以修改m.Result来改变鼠标的行为,例如使其支
                    // m.Result = (IntPtr)2; // HTCAPTION 表示标题栏,允许拖动窗体
                }
                return;
        }
        base.WndProc(ref m);
    }
    

    然后根据我想要的功能给它简单的优化了一些

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x0083 && m.WParam.ToInt32() != 0)
        {
            m.Result = IntPtr.Zero;
            return;
        }
        base.WndProc(ref m);
    }
    

    效果图:

  • 相关阅读:
    git -- 清除本地分支以及删除远程分支
    事故报告模板
    TorchScript 解读(三):jit 中的 subgraph rewriter
    Java学习 - MySQL数据库中提到的 视图 是什么? 如何使用?
    嵌入式 定时器/定时器中断实验
    获取和设置小程序和h5的页面栈
    阿里P8架构师进阶心得:分布式数据库架构MyCat学习笔记送给你
    使去中心化媒体网络相关联的NFT元数据标准
    将python脚本打包为exe可执行文件
    3.7Docker consul的容器服务更新与发现
  • 原文地址:https://www.cnblogs.com/wuchen9527/p/18147718