WinForm常用控件
一 关闭最小化
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (e.CloseReason == CloseReason.UserClosing) { e.Cancel = true; this.WindowState = FormWindowState.Minimized; } }
二 退出程序接口
System.Environment.Exit(0);
三 最小化或关闭时隐藏到系统托盘
1 添加托盘图标控件NotifyIcon
直接从工具箱中拖动添加即可。
2 添加(重写)窗口尺寸变动函数Form1_Resize
private void Form1_Resize(object sender, EventArgs e) { if (this.WindowState == FormWindowState.Minimized) //最小化到系统托盘 { NotifyIcon1.Visible = true; //显示托盘图标 this.Hide(); //隐藏窗口 } }
3 添加(重写)关闭窗口事件
4 添加双击托盘图标事件(双击显示窗口)
private void NotifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) { NotifyIcon1.Visible = false; this.Show(); WindowState = FormWindowState.Normal; this.Focus(); }
5 添加托盘图标的右键菜单
本节。
(具体代码略) "退出"菜单:Application.Exit(); "显示窗口"菜单:参考STEP4
四 子窗口最大最小按钮
窗体的 FormBorderStyle 设置为 sizable 才会出现最大/小化按钮。
五 DataGridView
1 点击事件
DataGridView点击事件并不总是触发,使用 CellClick事件而不是 CellContentClick ,因为当单击任何 部分时触发该事件(不只是它里面的内容)。
2 自动宽度
1、AllCells 调整列宽,以适合该列中的所有单元格的内容,包括标题单元格。 2、AllCellsExceptHeader 调整列宽,以适合该列中的所有单元格的内容,不包括标题单元格。 3、ColumnHeader 调整列宽,以适合列标题单元格的内容。 4、DisplayedCells 调整列宽,以适合当前屏幕上显示的行的列中的所有单元格的内容,包括标题单元格。 5、DisplayedCellsExceptHeader 调整列宽,以适合当前屏幕上显示的行的列中的所有单元格的内容,不包括标题单元格。 6、Fill 调整列宽,使所有列的宽度正好填充控件的显示区域,只需要水平滚动保证列宽在DataGridViewColumn.MinimumWidth 属性值以上。相对列宽由相对 DataGridViewColumn.FillWeight 属性值决定。 7、None 列宽不会自动调整。 8、NotSet 列的大小调整行为从 DataGridView.AutoSizeColumnsMode 属性继承。
整体自动宽度:Autosizecolumnsmode = file;,特定列固定宽度:AutoSizeMode = None。
3 不显示第一列
RowHeadersVisible = false
六 C# TreeView 右键菜单
方法一: 在winform中,添加一个contextMenuStrip1,设置TreeView的属性ContextMenuStrip为contextMenuStrip1,并为这个contextMenuStrip1添加几个菜单项,点击每个菜单项,实现其click事件,然后添加treeivew的nodemouseclick事件,类似如下代码:
//右键菜单 private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Button != MouseButtons.Right) return; if (e.Node.Parent == null || e.Node == null) return; treeView1.SelectedNode = e.Node; contextMenuStrip1.Show(tv_Roots, e.X, e.Y); } void contextMenuStripItem_Click(object sender, EventArgs e)//编辑飞行段 { }
方法二:不同节点对应不同的右键菜单
private void tvOneRoot_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Button != MouseButtons.Right) return; if (e.Node == null) return; //无节点 if (e.Node.Level == 0) return; int nodeType = GetNodeTypeByGuid(e.Node.Name); tvOneRoot.SelectedNode = e.Node; InitcmsOneRout(nodeType); cmsOneRout.Show(tvOneRoot, e.X, e.Y); } /// <summary> /// 初始化cmsOneRoot 从nodetype /// </summary> /// <param name="nodetype"></param> private void InitcmsOneRout(int nodetype) { cmsOneRout = new ContextMenuStrip(); if (nodetype == -1) { ToolStripMenuItem tmiEditRoutStation = new ToolStripMenuItem("编辑飞行站点"); tmiEditRoutStation.Click += new EventHandler(tmiEditRoutStation_Click); cmsOneRout.Items.Add(tmiEditRoutStation); ToolStripMenuItem tmiMoveRouteStation = new ToolStripMenuItem("更改位置"); tmiMoveRouteStation.Click += new EventHandler(tmiMoveRouteStation_Click); cmsOneRout.Items.Add(tmiMoveRouteStation); ToolStripMenuItem tmiDeleRouteStation = new ToolStripMenuItem("删除飞行站点"); tmiDeleRouteStation.Click += new EventHandler(tmiDeleRouteStation_Click); cmsOneRout.Items.Add(tmiDeleRouteStation); } else if (nodetype == 0) { ToolStripMenuItem tmiEditRout = new ToolStripMenuItem("编辑飞行段属性"); tmiEditRout.Click += new EventHandler(tmiEditRout_Click); cmsOneRout.Items.Add(tmiEditRout); ToolStripMenuItem tmiDeleteRout = new ToolStripMenuItem("删除飞行段"); tmiDeleteRout.Click += new EventHandler(tmiDeleteRout_Click); cmsOneRout.Items.Add(tmiDeleteRout); } else if (nodetype == 1) { } else if (nodetype == 2) { } else { } } void tmiEditRout_Click(object sender, EventArgs e)//编辑飞行段 { string routId = tvOneRoot.SelectedNode.Name; RouteParameter rp = GetRouteParaByGuid(routId); FrmPointProperty frm = new FrmPointProperty(rp, 0, 1); frm.OnRoutInfoUpdated += new FrmPointProperty.DelegateRouteInfoUpdated(frm_OnRoutInfoUpdated); frm.ShowDialog(); }
七 c# winform窗体如何设置才可以不能随意拖动大小
八 滚动条查看PictureBox的大图片
PictureBox自身没有滚动条,看不到大图片,而Panel自带滚动条,可以用Panel给PictureBox加上滚动条,设置Panel属性AutoScroll为true,设置PictureBox属性SizeMode为AutoSize,这样就可以用滚动条来看PictureBox中的大图片。
九 DockPanel
1 不显示关闭按钮
示例:
imageShow = ImageShow.GetInstance(); imageShow.Show(this.dockPanel1); imageShow.CloseButton = false; imageShow.CloseButtonVisible = false;
2 不可浮动
拖动:如果你想使你的子窗体可以任意拖动,那么你在设置子窗体的DockAreas属性时,保持默认值,不要修改; 固定:只需设置你窗体的DockAreas为Document就行了。
3 判断Dockpanel中存在多少个子窗体或Contents
foreach (DockContent frm in this.dockPanel1.Contents) { //这样设置后,所有的继承与DockContent的窗体都会被计算在内的 }
4 子窗体布局
在用DockPanel做MDI程序时,子窗体的初始化布局的实现,比如停靠左边,“日”字型的,有两种方法:
Me.DockPanel1.DockLeftPortion = 0.15停靠区域占窗口比例
方法1:
frm1.show(DockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockTop) frm1.Show(DockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockLeft) frm1.DockAreas = WeifenLuo.WinFormsUI.Docking.DockAreas.DockLeft frm2.Show(DockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockBottom) frm2.Show(DockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockLeft) frm2.DockAreas = WeifenLuo.WinFormsUI.Docking.DockAreas.DockLeft
方法2:
frm1.Show(DockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockLeft) frm1.DockAreas = WeifenLuo.WinFormsUI.Docking.DockAreas.DockLeft frm2.Show(frm1.Pane, WeifenLuo.WinFormsUI.Docking.DockAlignment.Bottom, 0.618) frm2.DockAreas = WeifenLuo.WinFormsUI.Docking.DockAreas.DockLeft
相对于方法1,方法2可以设置两个子窗口的高度比例,更好用些。
5 示例
C# 开源控件DockPanel 使用心得: C#实现浮动和多标签窗体解决方案—使用Dockpanel:
十 父子窗口传值
Winform中如何实现父窗体传递数据到子窗体并刷新子窗体:
十一 子窗口间传值
十二 Log4net
AssemblyInfo.cs:
using System.Resources; # line 1 [assembly: NeutralResourcesLanguage("zh-Hans")] # line 38 [assembly: log4net.Config.XmlConfigurator(Watch = true)]
App.config:
<configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <!--log4net配置start--> <log4net> <logger name="Log"> <level value="INFO" /> <param name="Encoding" value="utf-8" /> <appender-ref ref="RollingLog" /> </logger> <logger name="Err"> <level value="ERROR" /> <appender-ref ref="RollingErr" /> </logger> <appender name="RollingLog" type="log4net.Appender.RollingFileAppender"> <file value="Log" /> <appendToFile value="true" /> <rollingStyle value="Date" /> <datePattern value="yyyyMMdd.txt" /> <!--不加utf-8编码格式,中文字符将显示成乱码--> <param name="Encoding" value="utf-8" /> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="记录时间:%d 线程ID:[%thread]- 操作信息:%m%n" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="INFO" /> <param name="LevelMax" value="INFO" /> </filter> </appender> <appender name="RollingErr" type="log4net.Appender.RollingFileAppender"> <file value="Err" /> <param name="Encoding" value="utf-8" /> <appendToFile value="true" /> <rollingStyle value="Date" /> <datePattern value="yyyyMMdd.txt" /> <!--不加utf-8编码格式,中文字符将显示成乱码--> <param name="Encoding" value="utf-8" /> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="记录时间:%d 线程ID:[%thread]- 错误描述:%m%n" /> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ERROR" /> <param name="LevelMax" value="ERROR" /> </filter> </appender> </log4net> <!--log4net配置end-->
LogHelp.cs:
using log4net; using System.Diagnostics; using System.Reflection; namespace Log_Helper { public class LogHelp { private static readonly ILog logInfo = LogManager.GetLogger("Log"); private static readonly ILog logErr = LogManager.GetLogger("Err"); /// <summary> /// 记录正常的消息 /// </summary> /// <param name="msg">消息内容</param> public static void info(string msg) { logInfo.Info(msg); } /// <summary> /// 记录异常信息 /// </summary> /// <param name="msg">异常信息内容</param> public static void error(string msg) { StackTrace stackTrace = new StackTrace(); StackFrame stackFrame = stackTrace.GetFrame(1); MethodBase methodBase = stackFrame.GetMethod(); logErr.Error("类名:" + methodBase.ReflectedType.Name + " 方法名:" + methodBase.Name + " 信息:" + msg); } } }
log4net.config
<?xml version="1.0" encoding="utf-8" ?> <log4net> <!--根配置--> <root> <!--日志级别:可选值: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF--> <!--OFF: 0--> <!--FATAL: FATAL--> <!--ERROR: ERROR、FATAL--> <!--WARN: WARN、ERROR、FATAL--> <!--INFO: INFO、WARN、ERROR、FATAL--> <!--DEBUG: DEBUG、INFO、WARN、ERROR、FATAL--> <!--ALL: DEBUG、INFO、WARN、ERROR、FATAL--> <level value="DEBUG"/> <appender-ref ref="ErrorLog" /> <appender-ref ref="WarnLog" /> <appender-ref ref="InfoLog" /> <appender-ref ref="DebugLog" /> </root> <!-- 错误 Error.log--> <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender"> <!--目录路径,可以是相对路径或绝对路径--> <param name="File" value="./logs/error/"/> <param name="Encoding" value="utf-8" /> <!--文件名,按日期生成文件夹--> <param name="DatePattern" value="yyyyMMdd.txt"/> <!--追加到文件--> <appendToFile value="true"/> <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--写到一个文件--> <staticLogFileName value="false"/> <!--单个文件大小。单位:KB|MB|GB--> <maximumFileSize value="900MB"/> <!--最多保留的文件数,设为"-1"则不限--> <maxSizeRollBackups value="15"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="[%d{HH:mm:ss}][%thread][%logger] - %m%n"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="ERROR" /> <param name="LevelMax" value="ERROR" /> </filter> </appender> <!-- 警告 Warn.log--> <appender name="WarnLog" type="log4net.Appender.RollingFileAppender"> <!--目录路径,可以是相对路径或绝对路径--> <param name="File" value="./logs/warn/"/> <!--文件名,按日期生成文件夹--> <param name="DatePattern" value="yyyyMMdd.txt"/> <param name="Encoding" value="utf-8" /> <!--追加到文件--> <appendToFile value="true"/> <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--写到一个文件--> <staticLogFileName value="false"/> <!--单个文件大小。单位:KB|MB|GB--> <maximumFileSize value="900MB"/> <!--最多保留的文件数,设为"-1"则不限--> <maxSizeRollBackups value="15"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="[%d{HH:mm:ss}][%thread][%logger] - %m%n"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="WARN" /> <param name="LevelMax" value="WARN" /> </filter> </appender> <!-- 信息 Info.log--> <appender name="InfoLog" type="log4net.Appender.RollingFileAppender"> <!--目录路径,可以是相对路径或绝对路径--> <param name="File" value="./logs/info/"/> <!--文件名,按日期生成文件夹--> <param name="DatePattern" value="yyyyMMdd.txt"/> <param name="Encoding" value="utf-8" /> <!--追加到文件--> <appendToFile value="true"/> <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--写到一个文件--> <staticLogFileName value="false"/> <!--单个文件大小。单位:KB|MB|GB--> <maximumFileSize value="900MB"/> <!--最多保留的文件数,设为"-1"则不限--> <maxSizeRollBackups value="15"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="[%d{HH:mm:ss}][%thread][%logger] - %m%n"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="INFO" /> <param name="LevelMax" value="INFO" /> </filter> </appender> <!-- 调试 Debug.log--> <appender name="DebugLog" type="log4net.Appender.RollingFileAppender"> <!--目录路径,可以是相对路径或绝对路径--> <param name="File" value="./logs/debug/"/> <!--文件名,按日期生成文件夹--> <param name="DatePattern" value="yyyyMMdd.txt"/> <param name="Encoding" value="utf-8" /> <!--追加到文件--> <appendToFile value="true"/> <!--创建日志文件的方式,可选值:Date[日期],文件大小[Size],混合[Composite]--> <rollingStyle value="Composite"/> <!--写到一个文件--> <staticLogFileName value="false"/> <!--单个文件大小。单位:KB|MB|GB--> <maximumFileSize value="900MB"/> <!--最多保留的文件数,设为"-1"则不限--> <maxSizeRollBackups value="15"/> <!--日志格式--> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="[%d{HH:mm:ss}][%thread][%logger] - %m%n"/> </layout> <filter type="log4net.Filter.LevelRangeFilter"> <param name="LevelMin" value="DEBUG" /> <param name="LevelMax" value="DEBUG" /> </filter> </appender> </log4net>
十三 页面继承
1 winform 窗体继承后无法编辑
并非所有控件都支持从基本窗体进行可视化继承。以下控件不支持本演练中描述的场景: WebBrowser、ToolStrip、ToolStripPanel、TableLayoutPanel、FlowLayoutPanel、DataGridView 。继承窗体中的这些控件是无论您使用何种修饰符(私有(private)、 protected 或公共(public)),始终为只读。
2 继承窗体 无法拖动修改控件大小
问题描述:一个窗体集成父窗体,发现无法直接拖动修改的控件,比如修改大小等。 特征: 不禁使父窗体控件,就算新加一个控件也会这样:鼠标放到控件移动手方块上会出现一个“继承的控件”的tooptip, 异常 正常情况 原因: 父窗体设置了WindowState属性为:System.Windows.Forms.FormWindowState.Maximized; 在父窗体的designer.cs中有这么一句话:this.WindowState = System.Windows.Forms.FormWindowState.Maximized;; 解决办法: 一、去掉这句话; 二、放在窗体构造函数中,在这句话前面加上判断,如果VS处于设计模式,就返回;
public frmBaseChild() { InitializeComponent(); if (CheckDesingModel.IsDesingMode) return;//如果处于设计模式,返回 this.WindowState = System.Windows.Forms.FormWindowState.Maximized; }
CheckDesingModel类:
internal class CheckDesingModel { public static bool IsDesingMode { get { bool ReturnFlag = false; if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) ReturnFlag = true; else if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv") ReturnFlag = true; //if (ReturnFlag) // Msg.Warning("设计模式"); //else Msg.Warning("非设计模式!"); return ReturnFlag; } } }
十四 类调用主窗体控件
在Form1类下定义静态变量,构造方法中引用这个Form1
class Form1: Form { public static Form1 form1; public Form1() { InitializeComponent(); form1 = this; } public void Method() { } }
调用该窗体的控件或方法
Form1.form1.Button; Form1.form1.Method();
十五 用户控件属性集合定义
上面已经说过使用属性集合,是因为自定义的控件中有多相同的对象需要在调用时进行设置。(当然你要说是为了把多个属性放在一起好找也不是不行) 下面用两个例子来说明 例1:控件中用到多个图形对象(前景、背景、标志…) 1、创建一个类用来封装调用控件后添加图片对象时需要设置的属性
public class BsItem : Component { private Image _imageItem; [Description("选中图片"), Category("外观")] public Image SelectImage { get { return _imageItem; } } private string _ImageName; [Description("图片路径"), Category("外观")] public string ImageName { get { return _ImageName; } set { _ImageName = value; this._imageItem = Image.FromFile(_ImageName); _ImageName = System.IO.Path.GetFileName(_ImageName); Name = _ImageName; } } }
2、定义一个图片集合
private List<BsItem> items = new List<BsItem>(); [TypeConverter(typeof(System.ComponentModel.CollectionConverter))]//指定编辑器特性 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]//设定序列化特性 [Category("外观"), Description("图像文件集")] public List<BsItem> ImageList { get { return items; } } [Browsable(false)]//不显示Name 属性 public string Name { get; set; }
private List<DataAttribute> mDataAttribute = new List<DataAttribute>(); [TypeConverter(typeof(System.ComponentModel.CollectionConverter))]//指定类型装换器 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Category("外观"), Description("图像文件集")] public List<DataAttribute> MDataAttribut { get { return mDataAttribute; } set { mDataAttribute = value; } } public class DataAttribute { [Description("变量名称"), Browsable(true)] public string VariableName { get; set; } [Description("允许读取变量值"), Browsable(true)] public bool ReadEnabled { get; set; } [Description("变量存储区"), Browsable(true)] public catalogOne CatalogOneName { get; set; } [Description("全局数据块号,DB1对应用户程序的最小全局DB块"), Browsable(true)] public catalogTwo CatalogTwoName { get; set; } [Description("变量为1时显示的图片"), Browsable(true)] public Image TrueImage { get; set; } [Description("变量为0时显示的图片"), Browsable(true)] public Image FalseImaRge { get; set; } [Description("变量未加载时显示的图片"), Browsable(true)] public Image NotImage { get; set; } }