winform程序窗体MID相关设置

在winform程序设计中经常会遇到一些设置性问题,在此记录总结一些经常遇到的小问题。

1.MDI多窗体程序中,子窗口点击最大化,会出现看到子窗口的icon显示在菜单中,而实际上正常状态下子窗口的showIcon属性是false的。但最大化之后就是出显示在父窗口的菜单栏上,默认icon看起来不太好看。 这情况怎么样出掉icon.就是子窗口最大化不是显示icon。

做法:

 在父窗体的MenuStrip控件中添加一个ItemAdd事件

menuStrip_ItemAdded事件中添加如下代码:

        /// <summary>
        /// 子窗口最大化时去掉主窗体菜单的icon图标
        /// 在mdi子窗体最大化的时候,会发生如下动作:
        /// 会在父窗体的MenuStrip上添加4个Item.
        /// 分别为Icon,最大化,恢复跟最小化。
        /// 其中除了Icon之外,其他三个的Text属性都赋予了文本值。
        /// 另外,Icon作为MenuStrip的第一项Item,它的索引为0.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuStrip1_ItemAdded(object sender, ToolStripItemEventArgs e)
        {
            if (e.Item.Text == "")
            {
                menuStrip1.Items.RemoveAt(0);
            }
        }


OK 问题解决。

2. 在winform程序中如果我们添加一个默认MDI窗体,那么会有一些默认菜单选项。实际当中很多菜单是不需要的,我们可以删除。

如果我们添加一个单文档窗体,同时修改了isMdiContainer设置为ture,也能实现MDI窗体效果,如果这时候得自己添加菜单menuStrip然后逐个设置,添加系统默认MDI窗体还一些有功能菜单,比如窗口菜单,这个是比较通用的,基本上所有程序都可以用的。 自己添加单个文档窗口再修改成MDI窗体的这些功能就没有了。那么可以添加个别代码就可以实现相关功能。如有实现默认窗口菜单功能,除了水平平铺/垂直平铺/重叠.几个选项外,最主要一个功能还能根据一当前子窗口打开情况,显示成列表形式。

其实只设置menuStrip一个属性MdiWindowListItem,指向窗口菜单项。 代码如下:

  this.menuStrip1.MdiWindowListItem = this.windowTSMI;

OK,运行程序打开多个子窗口的时候就是排列出来了,且当前活动窗口就会在前面打勾。

3. 多次打开子窗口只显示一次。

一般情况下,打开子窗口多次我们代码如下:

        /// <summary>
        /// 环境参数配置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EnvirnomentForm_Click(object sender, EventArgs e)
        {
            FrmEnvirnomentSet envie = new FrmEnvirnomentSet();
            envie.MdiParent = this;
            envie.Show();
        }


那么重复点击多次菜单就会生成多个相同的窗口,因为每一次都是new 出来的。并不是运行同一个实例。

        /// <summary>
        /// 通过窗口标题判断窗口是否存在,目的是为了只打开一次
        /// </summary>
        /// <param name="mdiFrm">包含多个子窗口的主窗口</param>
        /// <param name="caption">子窗口标题</param>
        /// <returns></returns>
        private static bool IsWinExist(Form mdiFrm, string caption)
        {
            bool isExist = false;
            foreach (Form frm in mdiFrm.MdiChildren)
            {
                if (frm.Text.Equals(caption))
                {
                    isExist = true;
                    frm.Activate();
                    frm.Show();
                    break;
                }
            }
            return isExist;
        }

        /// <summary>
        /// 环境参数配置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EnvirnomentForm_Click(object sender, EventArgs e)
        {
            string caption = otherQueryTSMI.Text;//用菜单名称
            if (!IsWinExist(this, caption))
            {
                FrmEnvirnomentSet envie = new FrmEnvirnomentSet();                          
                envie.MdiParent = this;
                envie.Text = caption;
                envie.Show();
            }
        }

这样通过判断标题Title的名称,很容易实现重复操作只打开一次窗口。当然也有其他很办法来实现这个功能,但我觉得这个最简单的办法。

 4.实现动态菜单功能

有时程序需要动态菜单去配置,把菜单项写在数据库或者XML文件中,然后根据不同配置显示不同的菜单项

我这里只是为了简单实现动态配置菜单功能,通过配置数据库相关字段来实现动态菜单

做法如下:

/// <summary>
        /// 根据数据库仪器表创建动态菜单
         /// </summary>
        /// <param name="parent">ToolStripMenuItem根,如第一个菜单根名称为:CollectTSMI</param>
        private void CreateMenu(ToolStripMenuItem parent)
        {
           //操作数据库获取一个DataTable
            clsMachineOpr bll= new clsMachineOpr();
            DataTable dtbl = bll.GetColumnDataTable(0, "IsShow=True ORDER BY OrderId ASC", "MachineName,MachineModel,IsSupport");
            if (dtbl != null && dtbl.Rows.Count > 0)
            {
                htbl = new Hashtable();
                string code = string.Empty;
                string text = string.Empty;
                ToolStripMenuItem tsmi = null;

                //菜单部分
                for (int i = 0; i < dtbl.Rows.Count; i++)
                {
                    code = dtbl.Rows[i]["MachineModel"].ToString().Trim();
                    text = dtbl.Rows[i]["MachineName"].ToString().Trim();
                   // 加到hashtale中以备程序其他使用,这里不是必须的
                    htbl.Add(code, text);
                    if (Convert.ToBoolean(dtbl.Rows[i]["IsSupport"]))
                    {
                        defaultMethodTag = code;
                    }
                    //可以添加前缀或者后缀,根据实际需要设置吧
                    //code = "Auto_" + code;
                    //text +="XXXXX";

                    tsmi = new ToolStripMenuItem();
                    tsmi.Name = code;
                    tsmi.Text = text;
                    tsmi.Click += new EventHandler(DynamicTSMI_Click);
                    parent.DropDownItems.Add(tsmi);
                }
                //加分隔符
                ToolStripSeparator tStripSeparator1 = new ToolStripSeparator();
                tStripSeparator1.Name = "tStripSeparator1";
                tStripSeparator1.Size = new System.Drawing.Size(217, 6);
                parent.DropDownItems.Add(tStripSeparator1);

             }
            //如果还有其他固定的子菜单项,继续添加
            parent.DropDownItems.Add(otherDataHandTSMI);
        }

        /// <summary>
        /// 动态菜单事件,
        /// 采用反射技术。
        /// 注意:菜单click事件函数只能用public访问权限
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DynamicTSMI_Click(object sender, EventArgs e)
        {  
            //如果是独立的外部类
            // MenuClickMethod menuClickMethod = new MenuClickMethod();
            //创建菜单调用方法类的实例,MenuClickMethod 的方法以子菜单名字命名,预先定义好每个
            //子菜单的操作,采用外部类的方法可以实现更加动态,接近插件形式进行封装.
            //但本次时间过紧,不考虑用外部类和插件形式实现。使用内部公有方法即可实现

            Type type = this.GetType(); //menuClickMethod.GetType();如果用外部类采用注释的代码
            try
            {
                //动态获取方法对象
                MethodInfo mi = type.GetMethod(((ToolStripMenuItem)sender).Name);
                mi.Invoke(this, null);  //menuClickMethod  //如果用外部类调用,则用注解代码替换this。指定方法
            }
            catch (Exception ex)
            {
                //  throw ex;
                MessageBox.Show(ex.Message + ex.Source);
            }
        }

     //调用方法
       /// <summary>
       ///  这里菜单点击操作函数
       /// 函数名称要跟前面数据字段相同
        /// 且要设置成public
       /// </summary>
        public void XXXX()
        {
            //相当于点击菜单事件,操作你要实现的功能。。。。
        }


5.限制程序只能打开一个,如果有应用正在运行,再次打开相同程序会给予用户提示

做法如下:

        /// <summary>
        /// 实现程序启动唯一实例的一种方法 
        /// </summary>
        private static void GetSingleThread()
        {
            string name = Process.GetCurrentProcess().ProcessName;
            int id = Process.GetCurrentProcess().Id;
            Process[] prc = Process.GetProcesses();
            foreach (Process pr in prc)
            {
                if ((name == pr.ProcessName) && (pr.Id != id))
                {
                    MessageBox.Show("对不起,本机已经有XXX统正在运行!\n.", caption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    System.Environment.Exit(0);
                }
            }
            
        }


6.关闭窗口给予提示信息

 

复制代码
   ///   <summary>
        
///  重写系统消息函数。
        
///  即在关闭系统时提示!
        
///   </summary>
        
///   <param name="msg"> 消息对象 </param>
         protected   override   void  WndProc( ref  Message msg)
        {
            
const   int  syscommand  =   0x0112 ;
            
const   int  close  =   0xF060 ;
            
if  (msg.Msg  ==  syscommand  &&  (( int )msg.WParam  ==  close))
            {
                
if  (MessageBox.Show( " 程序正在运行,是否确定退出? " " 系统提示 " , MessageBoxButtons.YesNo, MessageBoxIcon.Question)  ==  DialogResult.No)
                {
                    
return ;
                }
            }
            
base .WndProc( ref  msg);
        }
复制代码

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值