C# WinForm窗體及其控件自適應各種屏幕分辨率
一。說明
我們自己編寫程序的界面,會遇到各種屏幕分辨率,只有自適應才能顯的美觀。實際上,做到這點也很簡單,就是首先記錄窗體和它上面控件的初始位置和大小,當窗體改變比例時,其控件的位置和大小也按此比例變化即可。因為窗體上控件的位置和大小是相對於自己所在的窗體的,也就是所謂的窗口坐標。
在這里我們只考慮相對於自己窗體的窗口坐標更簡單,也就是成比例變化。為了多個窗體共用,我在這里創建一個類AutoSizeFormClass ,1.使用它去記錄窗體和其控件的初始位置和大小,2.根據窗體變化了的大小,成比例地實現其控件的水平和垂直方向的變化,也就是自適應。
二。使用方法
使用方法很簡單,
1.把自適應的類整體復制到你的工程命名空間里,
然后在需要自適應的窗體中做3步即可:
2.聲明自適應類實例。
3.為窗體添加Load事件,並在其方法Form1_Load中,調用類的初始化方法,記錄窗體和其控件初始位置和大小
4.為窗體添加SizeChanged事件,並在其方法Form1_SizeChanged中,調用類的自適應方法,完成自適應
三。完整代碼如下:
(一)。自適應窗體的代碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsApplication1 { public partial class Form1 : Form { //1.聲明自適應類實例 AutoSizeFormClass asc = new AutoSizeFormClass(); public Form1() { InitializeComponent(); } //2. 為窗體添加Load事件,並在其方法Form1_Load中,調用類的初始化方法,記錄窗體和其控件的初始位置和大小 private void Form1_Load(object sender, EventArgs e) { asc.controllInitializeSize(this); } //3.為窗體添加SizeChanged事件,並在其方法Form1_SizeChanged中,調用類的自適應方法,完成自適應 private void Form1_SizeChanged(object sender, EventArgs e) { asc.controlAutoSize(this); } } }
(二)自適應類的代碼
using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; namespace WindowsApplication1 { class AutoSizeFormClass { //(1).聲明結構,只記錄窗體和其控件的初始位置和大小。 public struct controlRect { public int Left; public int Top; public int Width; public int Height; } //(2).聲明 1個對象 //注意這里不能使用控件列表記錄 List<Control> nCtrl;,因為控件的關聯性,記錄的始終是當前的大小。 public List<controlRect> oldCtrl; //int ctrl_first = 0; //(3). 創建兩個函數 //(3.1)記錄窗體和其控件的初始位置和大小, public void controllInitializeSize(Form mForm) { // if (ctrl_first == 0) { // ctrl_first = 1; oldCtrl = new List<controlRect>(); controlRect cR; cR.Left = mForm.Left; cR.Top = mForm.Top; cR.Width = mForm.Width; cR.Height = mForm.Height; oldCtrl.Add(cR); foreach (Control c in mForm.Controls) { controlRect objCtrl; objCtrl.Left = c.Left; objCtrl.Top = c.Top; objCtrl.Width = c.Width; objCtrl.Height = c.Height; oldCtrl.Add(objCtrl); } } // this.WindowState = (System.Windows.Forms.FormWindowState)(2);//記錄完控件的初始位置和大小后,再最大化 //0 - Normalize , 1 - Minimize,2- Maximize } //(3.2)控件自適應大小, public void controlAutoSize(Form mForm) { //int wLeft0 = oldCtrl[0].Left; ;//窗體最初的位置 //int wTop0 = oldCtrl[0].Top; ////int wLeft1 = this.Left;//窗體當前的位置 //int wTop1 = this.Top; float wScale = (float)mForm.Width / (float)oldCtrl[0].Width;//新舊窗體之間的比例,與最早的舊窗體 float hScale = (float)mForm.Height / (float)oldCtrl[0].Height;//.Height; int ctrLeft0, ctrTop0, ctrWidth0, ctrHeight0; int ctrlNo = 1;//第1個是窗體自身的 Left,Top,Width,Height,所以窗體控件從ctrlNo=1開始 foreach (Control c in mForm.Controls) { 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 += 1; } } } }
當然,窗口坐標和屏幕坐標也是可以相互轉換的,
private void Form1_MouseDown(object sender, MouseEventArgs e) { int x = e.X; //相對form窗口的坐標,客戶區坐標 int y = e.Y; int x1 = Control.MousePosition.X;//相對顯示器,屏幕的坐標 int y1 = Control.MousePosition.Y; }
它們之間轉換如下:
this.Location; // 窗體所在坐標 this.PointToScreen(new Point(0, 0)); // 客戶區坐標轉換為屏幕坐標 this.PointToClient(new Point(0, 0)); // 屏幕坐標轉換為客戶區坐標