首頁 > 軟體

WinForm入門與基本控制元件使用詳解

2022-06-23 14:01:17

一.Winform入門

        WinForm 是 Windows Form 的簡稱,是基於 .NET Framework 平臺的使用者端(PC軟體)開發技術,一般使用 C# 程式設計。在VS2019中,C# WinForm 程式設計需要建立「Windows表單應用程式」專案。Windows 表單應用程式是 C# 語言中的一個重要應用,也是 C# 語言最常見的應用。使用 C# 語言編寫的 Windows 應用程式與 Windows 作業系統的介面類似,每個介面都是由表單構成的,並且能通過滑鼠單擊、鍵盤輸入等操作完成相應的功能。WinForm支援視覺化設計,簡單易上手,並可以接入大量的第三方UI庫或自定義控制元件,給桌面應用開發帶來了無限可能。

1.WinForm專案結構 

1.WinForm專案結構
       (1)參照:包括所有的系統庫檔案的參照依賴
       (2)App.config:當前專案的組態檔
       (3)Form1.cs:當前表單的事件邏輯原始碼
             - Form1.Designer.cs:當前表單的控制元件佈局原始碼
             - Form1.resx:當前表單的資原始檔(圖片、圖示、資源等)
             - 注意:
                 a.Form1.cs和Form1.Designer.cs都定義了Form1類,該類使用了Partial關鍵詞宣告,其定義的類可以在多個地方被定義,最後編譯的時候會被當作一個類來處理。因此兩個檔案各司其職,最後合併為一個類編譯。
                 b.要手動實現自定義表單,可以新增自己的類,然後繼承Form類即可
       (4)Program.cs:當前專案程式的主入口Main,啟動專案,執行初始視窗

namespace WindowsFormsApp_learning
{
	//Program.cs 入口程式解讀
    static class Program
    {
        /// <summary>
        /// 應用程式的主入口點。
        /// </summary>
        //1.[STAThread]  Attributes語法,修飾Main方法。示應用程式的預設執行緒模型是單執行緒單元 (STA)
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //2.開啟視窗的訊息迴圈,初始化並啟動Form1視窗
            Application.Run(new Form1());
        }
    }
}

 2.視窗設計與控制元件佈局

2.表單控制元件佈局檔案

 (1)操作:在設計介面拖拽控制元件,可以完成介面佈局(控制元件大小、名稱、型別、樣式等)  (2)原理:設計介面自動關聯Form1.Designer.cs檔案,在InitializeComponent()方法中會自動生成相關程式碼

 (3)設計原則:

         - Form1.Designer.cs檔案:表單控制元件佈局檔案,一般【不需要我們修改】,只要通過設計介面程式碼就會自動生成。

        - Form1.cs檔案:表單事件邏輯程式碼的實現,一般【需要我們手動書寫】,包括觸發事件、回撥、資料互動、跳轉等等

3.手動新增控制元件:不通過設計介面,有兩種方式

 (1)在Form1.Designer.cs中新增:

          private System.Windows.Forms.Button btn_design;//宣告控制元件
           //預設的控制元件初始化方法
           InitializeComponent():{
               this.btn_design = new System.Windows.Forms.Button();//定義控制元件
               this.btn_design.Text = "自定義控制元件";//設定Text屬性
               this.btn_design.Location = new Point(40,40);//設定佈局位置 Point(x,y)
               this.btn_design.Size = new Size(100,40);//設定尺寸大小 Size(width,height)
               this.Controls.Add(this.btn_design);//註冊控制元件到表單
           }

  (2)在Form1.cs中新增:

           private Button btn_design;//宣告控制元件
           public Form1(){
               //先呼叫Designer.cs中的控制元件初始化方法
               InitializeComponent();
               this.btn_design = new System.Windows.Forms.Button();//定義控制元件
               this.btn_design.Text = "自定義控制元件";//設定Text屬性
               this.btn_design.Location = new Point(40,40);//設定佈局位置 Point(x,y)
               this.btn_design.Size = new Size(100,40);//設定尺寸大小 Size(width,height)
               this.Controls.Add(this.btn_design);//註冊控制元件到表單
           }

(3)注意:

         1. 一般我們都使用拖拽新增控制元件,當然也有特殊情況需要我們手動新增(比如自定義控制元件)
         2. 表單GUI中,左上角為原點(0,0),豎直向下為y軸,水平向右為x軸(寬度表示x軸上長度,高度表示y軸上長度),單位為畫素。

 3.視窗事件

4.WinForm 自動新增事件處理
   (1)操作:在設計介面-控制元件屬性-閃電符號(事件)-新增事件,就會在Form1.cs中自動生成該控制元件相應方法名稱的事件觸發函數
   (2) MessageBox.Show():顯示彈出訊息提示框
   (3)GUI介面下Console.WriteLine不顯示,需要使用偵錯模式

namespace WindowsFormsApp_learning
{
 
    /**
     * 4.WinForm事件處理
     *  (1)操作:在設計介面-控制元件屬性-閃電符號(事件)-新增事件,就會自動生成相應方法名稱的事件觸發函數
     *  (2) MessageBox:顯示訊息提示框
     *  (3)GUI介面下Console.WriteLine不顯示,需要使用偵錯模式
     */
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        //Button的Click點選事件(自動新增)
        private void showMessage(object sender, EventArgs e)
        {
            MessageBox.Show("Hello World!");
        }
    }
}

 5.手動新增事件處理(以Btn_design為例)

(1)步驟:

新增按鈕控制元件到佈局

書寫事件處理常式,必須符合 void function_name(object param1,EventArgs e){}的形式

新增註冊事件,this.Btn_design.Click += new EventHandler(this.showTip);

(2)注意:事件處理機制用到了委託和事件的C#基礎,有時間可以看一下

下一步的學習請前往 WindowsFormApp_demo1(實現一個顯示本地時間的APP)

namespace WindowsFormsApp_learning
{
    /**
     * 5.手動新增事件處理(以Btn_design為例)
     *  (1)步驟:
     *      - 新增按鈕控制元件到佈局
     *      - 書寫事件處理常式,必須符合 void function_name(object param1,EventArgs e){}的形式
     *      - 新增註冊事件,this.Btn_design.Click += new EventHandler(this.showTip);
     *  (2)注意:事件處理機制用到了委託和事件的C#基礎,有時間可以看一下
     *  下一步的學習請前往 WindowsFormApp_demo1(實現一個顯示時間的APP)
     */
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //2.1 註冊Click事件為手動新增的函數
            this.Btn_design.Click += new EventHandler(this.showTip);
        }
 
        //2.Button的Click點選事件(手動新增)
        public void showTip(Object sender,EventArgs e)
        {
            MessageBox.Show("手動新增!");
        }
    }
}

 4.時間顯示器小練習

設計一個能獲取本地時間並顯示在文字方塊的時間檢視器,設計思路就是:

        1.在UI設計介面新增一個按鈕Button和一個用來顯示時間的文字方塊TextBox

        2.給按鈕Button新增點選事件,在事件中獲取系統時間,並賦值給TextBox顯示

(1)介面設計 

 (2)邏輯程式碼

namespace WindowsFormsApp_Demo1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        //點選事件:獲取當前時間賦值給TextBox
        private void ShowTime(object sender, EventArgs e)
        {
            string time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            this.Time_filed.Text = time;
        }
    }
}

二.WinForm佈局開發

1.常見的WinForm 自動介面佈局(設計介面拖拽佈局)
        (1)操作:拖拽控制元件,放置在UI設計介面上佈局
        (2)技巧:通過ctrl+多個控制元件選定,可以在上方工具列進行細節的對齊微調,比如居中對齊、左對齊等。
        (3)本質:每次拖拽新增一個佈局控制元件,就會在視窗相應的Designer.cs設計佈局程式碼檔案中的InitializeComponent()方法中自動生成佈局程式碼(比如Location、Size等),來實現佈局。
        (4)存在的問題:自動佈局雖然方便靈活,但是當視窗大小拉伸改變時,佈局控制元件不能實現自動適應,仍會保持原大小,因此自動佈局只適用於視窗大小不變的情況

1. 手動佈局解決自適應問題

2.WinForm介面手動佈局(並解決自適應問題)
(1)步驟:
        - 通過設計介面拖拽/手動註冊元件的方式,初始化初始介面佈局(此時屬於自動佈局)
        - 在Form.cs邏輯程式碼中重寫Form父類別的OnLayout方法,在方法內實現手動佈局。OnLayout方法會在視窗大小變化時自動被回撥呼叫,來重新設定元件的位置大小等屬性實現自適應。
                a.呼叫父類別的OnLayout(),不是必須的。
                b.獲取當前視窗大小 CilentSize(僅客戶區,不含標題列)
                c.計算和設定每一個控制元件新的的大小和位置,實現動態佈局
(2)注意:
      - Size屬性指視窗大小(包括工具列),ClientSize指客戶區大小(不包含工具列)
      - 本質:OnLayout方法會在視窗大小變化時自動被呼叫,來設定元件的位置實現自適應

namespace WindowsFormsApp_learning
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        //重寫父類別的OnLayout方法,實現手動佈局自適應
        protected override void OnLayout(LayoutEventArgs levent)
        {
            //1.呼叫父類別的OnLayout(),不是必須的
            base.OnLayout(levent);
            //2.獲取當前客戶視窗大小 ClientSize
            int w = this.ClientSize.Width;
            int h = this.ClientSize.Height;
            //3.計算並設定每一個控制元件的大小和位置
            int yoff = 0;
 
            yoff = 4;
            this.text_box.Location = new Point(0, yoff);//座標(0,4)
            this.text_box.Size = new Size(w - 80, 30);//尺寸(w-80,30)
            this.btn_click.Location = new Point(w - 80, yoff);//座標(w-80,4)
            this.btn_click.Size = new Size(80, 30);//尺寸(80,30)
 
            yoff += 30;//第一行的高度
            yoff += 4;//間隔
            this.panel1.Location = new Point(0, yoff);
            this.panel1.Size = new Size(w, h - yoff - 4);
        }
    }
}

2.WinForm佈局屬性

3.WinForm佈局屬性(控制元件與佈局相關的屬性,設計介面可見)
(1)Anchor:固定、錨定(無論視窗怎麼變化,控制元件的相對位置都不變)
        - 含義:固定控制元件與父視窗的【上下左右邊距】不變,實現控制元件的錨定
        - 左上角固定:選定 Top,Left(預設)
        - 頂部固定,水平拉伸:選定 Top,Left,Right
        - 居中固定:None(取消所有)
        - *注意:Anchor效果的好壞取決於控制元件的初始位置,因為控制元件的初始位置決定了控制元件的邊距!所以要讓控制元件固定右上角,就要初始設計時就放在右上角!
(2)Dock:停靠屬性,將控制元件停靠在父視窗的一側或者中央
        - Top:上,控制元件停靠在容器上側,寬度填滿容器,高度可以調節
        - Bottom:下,控制元件停靠在容器下側,寬度填滿容器,高度可以調節
        - Left:左,控制元件停靠在容器左側,高度填滿容器,寬度可以調節
        - Right:右,控制元件停靠在容器右側,高度填滿容器,寬度可以調節
        - Fill,中,控制元件填滿容器中間剩餘部分(所以說與控制元件新增順序有關)
        - None,無,不使用Dock屬性
        - *注意:
                a.容器之間可以巢狀,使用佈局屬性(容器就是存放元件的,比如Panel)
                b.Dock屬性與Anchor屬性不能同時使用
                c.Dock屬性不是固定邊距了,就是相對位置填充

 3.WinForm佈局器

4.佈局器 LayoutEngine
(1)含義:佈局器就是容器內部元件的預設排列方式,所有的容器都帶有一個預設的佈局器
(2)自定義控制元件如何加入設計介面:
        - 工具 -> 選項 -> Windows表單設計器 -> 常規 -> 自動填充工具箱 -> True
        - 新增自定義的控制元件類原始碼到專案下
        - 生成/重新生成結局方案 F7
        - 重新開啟設計介面,在工具箱就可以看到自己的控制元件
(3)系統提供的佈局器-FlowLayoutPanel(流式佈局):
        - 含義:普通的Panel面板容器控制元件,使用了FlowLayout流式佈局,即所有內部元件按照順序從左到右從上到下依次排列
        - FlowLayoutPanel也可以使用Anchor、Dock等屬性,因為他也是表單容器內的一個元件
        - 控制元件的選擇技巧:多個控制元件疊加到一起時,可以右鍵最上層控制元件,來進行重疊控制元件的選擇
(4)系統提供的佈局器-TableLayoutPanel(表格佈局):
        - 含義:普通的Panel面板容器,使用了TableLayout表格佈局,即所有內部元件可以放置到不同的表格中(每個表格只能放置一個控制元件)
        - TableLayoutPanel也可以使用Anchor、Dock等屬性,因為他也是表單容器內的一個元件。搭配佈局與佈局屬性,可以實現很多不同的佈局效果。
        - 刪除/新增行、列:右鍵表格Panel,可以新增、刪除行/列
        - 調整表格大小:表格屬性Columns可以通過絕對值、百分比、自動調整等方式來調整單元格的大小
                a.絕對:固定畫素值大小
                b.百分比:除去絕對大小後,單元格佔剩餘大小的百分比
                c.自動調整:根據內部控制元件的大小生成
        - 跨行/列控制元件:在控制元件的ColumnSpan/RowSpan調整控制元件可以跨行/跨列布局
        - *注意: TableLayoutPanel 控制元件每個單元格只能包含一個子控制元件。
(5)系統提供的佈局工具-預設佈局:預設佈局可以通過控制元件拖拽放置,並可以使用Anchor、Dock來調整
(6)自定義佈局器:使用者可以自己設計實現佈局器,這屬於WinForm高階的內容,後面學習。

三.WinForm常用控制元件

1.Winform 元件的使用
(1)TextBox:輸入文字方塊
        - 常用屬性:尺寸Size、單行/多行Multiline、密碼輸入PasswordChar、唯讀ReadOnly、顯示/獲取文字Text等
        - 常用事件:KeyPress按下按鍵(常用於輸出完成點選回車,box.Text取輸入值,事件e.keyChar取按下哪個鍵)
(2)CheckBox:核取方塊
        - 常用屬性:尺寸Size、顯示文字Text、Checked是否勾選
        - 常用事件:Click點選事件、CheckedChanged勾選狀態改變事件
(3)ComboBox:下拉選單(只能單選)
        - 常用屬性:
                a.新增資料項:設計器編輯新增(屬性->資料->Items,一行表示一個資料項)、程式手工新增(comboBox.Items.Add("some");)
                b.其他設定:Size尺寸、Text提示文字等
        - 常用事件:
                a.獲取選中的項:SelectedItem(選中項的值)、SelectedIndex(選中項的索引,-1表示未選中)
                b.選項改變事件:SelectedIndexChanged
        - 注意:Item可以新增字串,也可以新增任意object型別(比如自定義物件),物件會以object.toString顯示
(4)ListBox:列表框(展示資料、可單選/多選)
        - 常用屬性:SelectionMode(單選/多選模式)
                a.單選模式獲取選項:SelectedItem/SelectedIndex(選中項的值/索引)
                b.多選模式獲取選項:SelectedIndices/SelectedItems(選中項的索引集合/值集合)
                c.新增資料項:設計器編輯新增(屬性->資料->Items)、程式手工新增(listBox.Items.Add("some");)
        - 常用事件:SelectedIndexChanged(選項改變)
        - 注意:Item可以新增字串,也可以新增任意object型別(比如自定義物件),物件會以object.toString顯示
(5)練習:學生資訊編輯器範例(本程式碼)

1.介面展示 

2.實體類 Student(封裝資訊)

1.C# 類的屬性與欄位
(1)欄位:欄位是類的成員變數,用於類內特徵的資料儲存(靜態) 比如private int Id;
(2)屬性:屬性是對欄位特徵的動態描述,用於向外界提供資料,本質上就是get、set方法。
        - 完整屬性用法:

private string sdu_name;//宣告欄位
 
public string StudentName{//宣告屬性
      get{ return sdu_name; }
      set{
         if(value==null)sdu_name = "admin";
         sdu_name = value;
      }
}


        - get存取器:get存取器必須包含return語句,返回欄位‘realValue'。用於獲取資料,如果沒有get則欄位為只寫的
        - set存取器:set存取器接受它的輸入引數--value,並把它賦給欄位,value是隱式引數。用於設定資料,如果沒有set則欄位為唯讀的
(3)使用方式:直接使用Class.StudentName來獲取和設定資料,就像是直接使用公開的屬性一樣 
(4)自動屬性:簡化欄位和屬性的關係
        - 用法:public 資料型別 屬性名{ get; set; }
        - *原理:c# 允許只宣告屬性而不宣告後備欄位,編譯器會建立隱藏的後備欄位。並且自動掛接到get,set存取器上。
(5)注意:
        - 屬性也可以不與欄位關聯,可以當作函數進行復雜計算,比較自由靈活
        - 屬性也可不用顯示宣告相應的欄位,直接用於存貯資料。(自動屬性)
        - 也可以通定義其他set、get函數來實現存取private欄位的功能

namespace WindowsFormsApp_learning
{
    class Student
    {
        //屬性存取器
        public int SduId { get; set; }
        public string SduName { get; set; }
        public bool SduSex { get; set; }
        public string SduPhone
        {
            get; set;
        }
 
        public Student(int sduId, string sduName, bool sduSex, string sduPhone)
        {
            SduId = sduId;
            SduName = sduName;
            SduSex = sduSex;
            SduPhone = sduPhone;
        }
 
        public Student()
        {
        }
    }
}

 3.邏輯事件程式碼Form.cs

namespace WindowsFormsApp_learning
{
    public partial class Form4 : Form
    {
        public Form4()
        {
            InitializeComponent();
            //初始化資料
            LoadData();
        }
 
        /**
         * 儲存按鈕觸發事件-儲存學生資訊到本地檔案
         */
        private void save_student(object sender, EventArgs e)
        {
            Student student = new Student();
            student.SduId =Convert.ToInt32(sdu_Id.Text.Trim()); //Convert格式轉換
            student.SduName = sdu_Name.Text.Trim();
            student.SduSex = (sdu_sex.SelectedIndex == 1);
            student.SduPhone = sdu_phone.Text.Trim();
            //以Json格式儲存到本地檔案
            string JsonStr = JsonConvert.SerializeObject(student, Formatting.Indented);
            AfTextFile.Write("student.txt", JsonStr,AfTextFile.UTF8);
            MessageBox.Show("操作成功");
        }
 
        //讀取檔案,載入資料
        private void LoadData()
        {
            string JsonStr = AfTextFile.Read("student.txt", AfTextFile.UTF8);
            if (JsonStr == null) return;
            Student student = JsonConvert.DeserializeObject<Student>(JsonStr);
            sdu_Id.Text = Convert.ToString(student.SduId);
            sdu_Name.Text = student.SduName;
            sdu_sex.SelectedIndex = student.SduSex?1:0;
            sdu_phone.Text = student.SduPhone;
        }
    }
}

四.圖片框與專案資源

1.圖片框與資源
(1)新增資源來源:
        - 本地檔案 : 本地資源路徑,比如"D\Resources\123.jpg"(注意使用Windows路徑格式)
        - 專案資原始檔:Properties/Resources.resx(專案資原始檔夾下)
                a.如何新增專案資原始檔:雙擊Properties/Resources.resx->新增資源->新增現有檔案->選擇本地圖片->重新命名(規範化,以後使用時直接呼叫名字使用資源)
                b.能新增什麼型別的資源:字串、文字檔案、圖片、視訊、音訊等
                c.原理:Resources.resx將新增的資源整合到了專案exe當中,因此就算刪除原始檔也不影響專案執行。在呼叫資源時,是通過自動生成的方法來獲取資源。
                d.優點:將資源統一到專案中來,並且可以通過規範化的命名直接呼叫資源。
                e.使用:通過 Properties.Resources.資源名稱; 來直接呼叫你的資源,方便快捷
        - 網路資源:比如"http://baidu/image/meinv.jpg"


(2)圖片資源載入類:
        - C# 提供了Image抽象類,作為所有圖片資源的總稱
        - C# 提供了Image抽象類的具體實現類 Bitmap(點陣圖、畫素圖),來具體載入讀取影象。
                a.比如Bitmap img = new Bitmap("D\Resources\123.jpg");
                b.比如Bitmap img = Properties.Resources.img_Conv;
 
(3)圖片框控制元件:PictureBox
        - Size、Location屬性:尺寸、位置
        - Image屬性:圖片資源(可以通過本地/專案資原始檔匯入)
        - SizeMode屬性:圖片的適應模式(StretchImage拉伸圖片和圖片框相同尺寸、Zoom縮放等)
        - ErrorImage、InitialImage屬性:載入失敗、載入圖片顯示之前所顯示的圖片
   
(4)圖片框控制元件視覺化設定:在設計裡拖動PictureBox並設定屬性即可。
(5)圖片框程式碼手動設定:

Bitmap img = Properties.Resources.img_Conv; //讀取圖片資源
pictureBox.Image = img;//手動設定圖片框控制元件 Image來源
pictureBox.SizeMode = PictureBoxSizeMode.Zoom;//手動設定圖片格式

1.新增資源

2.圖片框控制元件展示

        介面設計就是簡單的放置了一個PictureBox控制元件,沒有過多的設計。圖片來源的設定使用程式碼方式,原因是在以後開發中圖片往往不是固定的,需要動態變化,因此使用程式碼方式動態設定圖片來源是比較推薦的。

namespace WindowsFormsApp_learning
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            //初始化所有元件
            InitializeComponent();
            //初始化PictureBox控制元件-圖片資源
            Bitmap img = Properties.Resources.img_Conv;
            pictureBox.Image = img;
            pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
        }
    }
}

 到此這篇關於WinForm入門與基本控制元件使用詳解的文章就介紹到這了,更多相關WinForm 入門內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com