winform程序窗体相关设置

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

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

做法:

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

menuStrip_ItemAdded事件中添加如下代码:

 

View Code
/// <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. 多次打开子窗口只显示一次。

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

 

View Code
 /// <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 出来的。并不是运行同一个实例。

 

View Code
    /// <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文件中,然后根据不同配置显示不同的菜单项

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

做法如下:

 

View Code
        /// <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(2176);
                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(
thisnull);  //menuClickMethod  //如果用外部类调用,则用注解代码替换this。指定方法
            }
            
catch (Exception ex)
            {
                
//  throw ex;
                MessageBox.Show(ex.Message + ex.Source);
            }
        }

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

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

做法如下:

 

View Code
        /// <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.关闭窗口给予提示信息

 

View Code
  /// <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);
        }

 

posted on 2011-06-23 11:50  陈国利  阅读(2184)  评论(5编辑  收藏  举报