c# Form实用小技巧

    技术2026-08-19  9

    1 重写Form关闭按钮在

    protected override void WndProc(ref Message m){ const int WM_SYSCOMMAND = 0x0112; const int SC_CLOSE = 0xF060; if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE) { //捕捉关闭窗体消息 Application.ExitThread(); return; } base.WndProc(ref m); }

    2 退出系统

    Application.Exit();//好像只在主线程可以起作用,而且当有线程,或是阻塞方法的情况下,很容易失灵 this.Close();//只是关闭当前窗体。 Application.ExitThread();//退出当前线程上的消息循环,并关闭该线程上的所有窗口。 也会失灵 Environment.Exit(0); //前面三种方法都不能很好的退出程序,此方法可以完全退出程序,这个要强制得多。 Process.GetCurrentProcess().Kill();//此方法完全奏效,绝对是完全退出。

    3 路径

    Winform获取应用程序的当前路径的方法集合,具体如下,值得收藏 //获取当前进程的完整路径,包含文件名(进程名)。 string str = this.GetType().Assembly.Location; result: X:\xxx\xxx\xxx.exe (.exe文件所在的目录+.exe文件名) //获取新的Process 组件并将其与当前活动的进程关联的主模块的完整路径,包含文件名(进程名)。 string str = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; result: X:\xxx\xxx\xxx.exe (.exe文件所在的目录+.exe文件名) //获取和设置当前目录(即该进程从中启动的目录)的完全限定路径。 string str = System.Environment.CurrentDirectory; result: X:\xxx\xxx (.exe文件所在的目录) //获取当前 Thread 的当前应用程序域的基目录,它由程序集冲突解决程序用来探测程序集。 string str = System.AppDomain.CurrentDomain.BaseDirectory; result: X:\xxx\xxx\ (.exe文件所在的目录+"\") //获取和设置包含该应用程序的目录的名称。 string str = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase; result: X:\xxx\xxx\ (.exe文件所在的目录+"\") //获取启动了应用程序的可执行文件的路径,不包括可执行文件的名称。 string str = System.Windows.Forms.Application.StartupPath; result: X:\xxx\xxx (.exe文件所在的目录) //获取启动了应用程序的可执行文件的路径,包括可执行文件的名称。 string str = System.Windows.Forms.Application.ExecutablePath; result: X:\xxx\xxx\xxx.exe (.exe文件所在的目录+.exe文件名) //获取应用程序的当前工作目录(不可靠)。 string str = System.IO.Directory.GetCurrentDirectory(); result: X:\xxx\xxx (.exe文件所在的目录)

    4 打开文件对话框

    OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Excel文件.xls;*.xlsx)|*.xls;*.xlsx|所有文件|*.*";//提示1|类型1|提示2|类型2… ofd.ValidateNames = true;//验证用户输入是否是一个有效的Windows文件名。 ofd.CheckPathExists = true;//验证路径有效性。 ofd.CheckFileExists = true;//验证文件有效性。 if (ofd.ShowDialog() == DialogResult.OK) { string strFileName = ofd.FileName; //其他代码 }

    5 保存文件对话框

    SaveFileDialog sfd = new SaveFileDialog(); //设置文件类型 sfd.Filter = "数据库备份文件(*.bak)|*.bak|数据文件(*.mdf)|*.mdf|日志文件(*.ldf)|*.ldf"; //设置默认文件类型显示顺序 sfd.FilterIndex = 1; //保存对话框是否记忆上次打开的目录 sfd.RestoreDirectory = true; //设置默认的文件名 sfd.DefaultFileName = "YourFileName"; //点了保存按钮进入 if (sfd.ShowDialog() == DialogResult.OK) { string localFilePath = sfd.FileName.ToString(); //获得文件路径 string fileNameExt = localFilePath.Substring(localFilePath.LastIndexOf("\\") + 1); //获取文件名,不带路径 }

    6 无边框移动

    1.定义一个位置信息Point用于存储鼠标位置

    private Point mPoint;

    2.给窗体等控件增加MouseDown和MouseMove事件

    /// <summary> /// 鼠标按下 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void panel1_MouseDown(object sender, MouseEventArgs e) { mPoint = new Point(e.X, e.Y); } /// <summary> /// 鼠标移动 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void panel1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y); } }

    7 拖动窗体改变大小/双击最大化(无边框窗体)

    [DllImport("user32.dll")]//命名空间System.Runtime.InteropServices; public static extern bool ReleaseCapture(); [DllImport("user32.dll")] public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); public const int WM_SYSCOMMAND = 0x0112; public const int SC_MOVE = 0xF010; public const int HTCAPTION = 0x0002; public const int SC_MINIMIZE = 0xF020; public const int SC_MAXIMIZE = 0xF030; public const int SC_RESTORE = 0xF120; public const int SC_SIZE = 0xF000; //改变窗体大小,SC_SIZE+下面的值 public const int LEFT = 0x0001;//光标在窗体左边缘 public const int RIGHT = 0x0002;//右边缘 public const int UP = 0x0003;//上边缘 public const int LEFTUP = 0x0004;//左上角 public const int RIGHTUP = 0x0005;//右上角 public const int BOTTOM = 0x0006;//下边缘 public const int LEFTBOTTOM = 0x0007;//左下角 public const int RIGHTBOTTOM = 0x0008;//右下角 //双击事件 private void panel2_MouseDown(object sender, MouseEventArgs e) { if (e.Clicks <= 1) { //拖动窗体 ReleaseCapture();//释放label1对鼠标的捕捉 SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); } else if (e.Clicks == 2) { if (this.WindowState == FormWindowState.Maximized) { //还原窗体 ReleaseCapture(); SendMessage(this.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); } else if (this.WindowState == FormWindowState.Normal) { //最大化窗体 ReleaseCapture(); SendMessage(this.Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); } } } //以下为拖动右下角改变窗体大小的处理。 private void pictureBox4_MouseDown(object sender, MouseEventArgs e) { if (e.Clicks <= 1) { this.Cursor = Cursors.SizeNWSE; ReleaseCapture(); SendMessage(this.Handle, WM_SYSCOMMAND, SC_SIZE + RIGHTBOTTOM, 0);//拖动右下角改变窗体大小 } }

    8 窗体自适应

    自适应类 using System.Collections.Generic; using System.Windows.Forms; namespace WindowsFormsApplication1 { class AutoSizeFormClass { //(1).声明结构,只记录窗体和其控件的初始位置和大小。 public struct controlRect { public int Left; public int Top; public int Width; public int Height; } //(2).声明 1个对象 //注意这里不能使用控件列表记录 List nCtrl;,因为控件的关联性,记录的始终是当前的大小。 // public List oldCtrl= new List();//这里将西文的大于小于号都过滤掉了,只能改为中文的,使用中要改回西文 public List<controlRect> oldCtrl = new List<controlRect>(); int ctrlNo = 0;//1; //(3). 创建两个函数 //(3.1)记录窗体和其控件的初始位置和大小, public void controllInitializeSize(Control mForm) { controlRect cR; cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height; oldCtrl.Add(cR);//第一个为"窗体本身",只加入一次即可 AddControl(mForm);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用 //this.WindowState = (System.Windows.Forms.FormWindowState)(2);//记录完控件的初始位置和大小后,再最大化 //0 - Normalize , 1 - Minimize,2- Maximize } private void AddControl(Control ctl) { foreach (Control c in ctl.Controls) { //**放在这里,是先记录控件的子控件,后记录控件本身 //if (c.Controls.Count > 0) // AddControl(c);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用 controlRect objCtrl; objCtrl.Left = c.Left; objCtrl.Top = c.Top; objCtrl.Width = c.Width; objCtrl.Height = c.Height; oldCtrl.Add(objCtrl); //**放在这里,是先记录控件本身,后记录控件的子控件 if (c.Controls.Count > 0) AddControl(c);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用 } } //(3.2)控件自适应大小, public void controlAutoSize(Control mForm) { if (ctrlNo == 0) { //*如果在窗体的Form1_Load中,记录控件原始的大小和位置,正常没有问题,但要加入皮肤就会出现问题,因为有些控件如dataGridView的的子控件还没有完成,个数少 //*要在窗体的Form1_SizeChanged中,第一次改变大小时,记录控件原始的大小和位置,这里所有控件的子控件都已经形成 controlRect cR; // cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height; cR.Left = 0; cR.Top = 0; cR.Width = mForm.PreferredSize.Width; cR.Height = mForm.PreferredSize.Height; oldCtrl.Add(cR);//第一个为"窗体本身",只加入一次即可 AddControl(mForm);//窗体内其余控件可能嵌套其它控件(比如panel),故单独抽出以便递归调用 } float wScale = (float)mForm.Width / (float)oldCtrl[0].Width;//新旧窗体之间的比例,与最早的旧窗体 float hScale = (float)mForm.Height / (float)oldCtrl[0].Height;//.Height; ctrlNo = 1;//进入=1,第0个为窗体本身,窗体内的控件,从序号1开始 AutoScaleControl(mForm, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用 } private void AutoScaleControl(Control ctl, float wScale, float hScale) { int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0; //int ctrlNo = 1;//第1个是窗体自身的 Left,Top,Width,Height,所以窗体控件从ctrlNo=1开始 foreach (Control c in ctl.Controls) { //**放在这里,是先缩放控件的子控件,后缩放控件本身 //if (c.Controls.Count > 0) // AutoScaleControl(c, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用 ctrLeft0 = oldCtrl[ctrlNo].Left; ctrTop0 = oldCtrl[ctrlNo].Top; ctrWidth0 = oldCtrl[ctrlNo].Width; ctrHeight0 = oldCtrl[ctrlNo].Height; //c.Left = (int)((ctrLeft0 - wLeft0) * wScale) + wLeft1;//新旧控件之间的线性比例 //c.Top = (int)((ctrTop0 - wTop0) * h) + wTop1; c.Left = (int)((ctrLeft0) * wScale);//新旧控件之间的线性比例。控件位置只相对于窗体,所以不能加 + wLeft1 c.Top = (int)((ctrTop0) * hScale);// c.Width = (int)(ctrWidth0 * wScale);//只与最初的大小相关,所以不能与现在的宽度相乘 (int)(c.Width * w); c.Height = (int)(ctrHeight0 * hScale);// ctrlNo++;//累加序号 //**放在这里,是先缩放控件本身,后缩放控件的子控件 if (c.Controls.Count > 0) AutoScaleControl(c, wScale, hScale);//窗体内其余控件还可能嵌套控件(比如panel),要单独抽出,因为要递归调用 } } } } 自适应 1.声明自适应类实例 AutoSizeFormClass asc = new AutoSizeFormClass(); 2,在初始化的时候 asc.controllInitializeSize(this); 3,在SizeChanged事件中 asc.controlAutoSize(this);

    9 窗体快捷键的使用

    1.响应 Form窗体的 KeyDown 事件

    需要设置Form窗体的 KeyPreview 属性为 true (默认false)

    private void MainForm_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.F1: //... break; case Keys.Escape: //... break; case Keys.O: if (e.Control) { // Ctrl + O } break; case Keys.Oemcomma: //逗号键 // ... break; case Keys.OemPeriod: //句号键 // ... break; case Keys.Oem1: // 分号 // ... break; case Keys.Oem7: // 引号 // ... break; case Keys.Up: // 无效 // ... return true; case Keys.Down: //无效 // ... return true; }

    2.重载 ProcessCmdKey 方法

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { switch (keyData) { case Keys.Up: // ... return true; case Keys.Down: // ... return true; } return false; }

    10.文件相关操作

    创建文件夹 if (!Directory.Exists("文件夹名称")) { Directory.CreateDirectory("文件夹名称"); }
    Processed: 0.013, SQL: 9