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; }
}
经验分享 程序员 微信小程序 职场和发展