WinForm入門與基本控件使用詳解
一.Winform入門
WinForm 是 Windows Form 的簡稱,是基于 .NET Framework 平臺的客戶端(PC軟件)開發(fā)技術,一般使用 C# 編程。在VS2019中,C# WinForm 編程需要創(chuàng)建「Windows窗體應用程序」項目。Windows 窗體應用程序是 C# 語言中的一個重要應用,也是 C# 語言最常見的應用。使用 C# 語言編寫的 Windows 應用程序與 Windows 操作系統(tǒng)的界面類似,每個界面都是由窗體構(gòu)成的,并且能通過鼠標單擊、鍵盤輸入等操作完成相應的功能。WinForm支持可視化設計,簡單易上手,并可以接入大量的第三方UI庫或自定義控件,給桌面應用開發(fā)帶來了無限可能。
1.WinForm項目結(jié)構(gòu)
1.WinForm項目結(jié)構(gòu)
(1)引用:包括所有的系統(tǒng)庫文件的引用依賴
(2)App.config:當前項目的配置文件
(3)Form1.cs:當前窗體的事件邏輯源碼
- Form1.Designer.cs:當前窗體的控件布局源碼
- Form1.resx:當前窗體的資源文件(圖片、圖標、資源等)
- 注意:
a.Form1.cs和Form1.Designer.cs都定義了Form1類,該類使用了Partial關鍵詞聲明,其定義的類可以在多個地方被定義,最后編譯的時候會被當作一個類來處理。因此兩個文件各司其職,最后合并為一個類編譯。
b.要手動實現(xiàn)自定義窗體,可以添加自己的類,然后繼承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.開啟窗口的消息循環(huán),初始化并啟動Form1窗口
Application.Run(new Form1());
}
}
}2.窗口設計與控件布局
2.窗體控件布局文件
(1)操作:在設計界面拖拽控件,可以完成界面布局(控件大小、名稱、類型、樣式等) (2)原理:設計界面自動關聯(lián)Form1.Designer.cs文件,在InitializeComponent()方法中會自動生成相關代碼
(3)設計原則:
- Form1.Designer.cs文件:窗體控件布局文件,一般【不需要我們修改】,只要通過設計界面代碼就會自動生成。
- Form1.cs文件:窗體事件邏輯代碼的實現(xiàn),一般【需要我們手動書寫】,包括觸發(fā)事件、回調(diào)、數(shù)據(jù)交互、跳轉(zhuǎn)等等
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(){
//先調(diào)用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中自動生成該控件相應方法名稱的事件觸發(fā)函數(shù)
(2) MessageBox.Show():顯示彈出消息提示框
(3)GUI界面下Console.WriteLine不顯示,需要使用調(diào)試模式
namespace WindowsFormsApp_learning
{
/**
* 4.WinForm事件處理
* (1)操作:在設計界面-控件屬性-閃電符號(事件)-添加事件,就會自動生成相應方法名稱的事件觸發(fā)函數(shù)
* (2) MessageBox:顯示消息提示框
* (3)GUI界面下Console.WriteLine不顯示,需要使用調(diào)試模式
*/
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)步驟:
添加按鈕控件到布局
書寫事件處理函數(shù),必須符合 void function_name(object param1,EventArgs e){}的形式
添加注冊事件,this.Btn_design.Click += new EventHandler(this.showTip);
(2)注意:事件處理機制用到了委托和事件的C#基礎,有時間可以看一下
下一步的學習請前往 WindowsFormApp_demo1(實現(xiàn)一個顯示本地時間的APP)
namespace WindowsFormsApp_learning
{
/**
* 5.手動添加事件處理(以Btn_design為例)
* (1)步驟:
* - 添加按鈕控件到布局
* - 書寫事件處理函數(shù),必須符合 void function_name(object param1,EventArgs e){}的形式
* - 添加注冊事件,this.Btn_design.Click += new EventHandler(this.showTip);
* (2)注意:事件處理機制用到了委托和事件的C#基礎,有時間可以看一下
* 下一步的學習請前往 WindowsFormApp_demo1(實現(xiàn)一個顯示時間的APP)
*/
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//2.1 注冊Click事件為手動添加的函數(shù)
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添加點擊事件,在事件中獲取系統(tǒng)時間,并賦值給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布局開發(fā)
1.常見的WinForm 自動界面布局(設計界面拖拽布局)
(1)操作:拖拽控件,放置在UI設計界面上布局
(2)技巧:通過ctrl+多個控件選定,可以在上方工具欄進行細節(jié)的對齊微調(diào),比如居中對齊、左對齊等。
(3)本質(zhì):每次拖拽添加一個布局控件,就會在窗口相應的Designer.cs設計布局代碼文件中的InitializeComponent()方法中自動生成布局代碼(比如Location、Size等),來實現(xiàn)布局。
(4)存在的問題:自動布局雖然方便靈活,但是當窗口大小拉伸改變時,布局控件不能實現(xiàn)自動適應,仍會保持原大小,因此自動布局只適用于窗口大小不變的情況

1. 手動布局解決自適應問題
2.WinForm界面手動布局(并解決自適應問題)
(1)步驟:
- 通過設計界面拖拽/手動注冊組件的方式,初始化初始界面布局(此時屬于自動布局)
- 在Form.cs邏輯代碼中重寫Form父類的OnLayout方法,在方法內(nèi)實現(xiàn)手動布局。OnLayout方法會在窗口大小變化時自動被回調(diào)調(diào)用,來重新設置組件的位置大小等屬性實現(xiàn)自適應。
a.調(diào)用父類的OnLayout(),不是必須的。
b.獲取當前窗口大小 CilentSize(僅客戶區(qū),不含標題欄)
c.計算和設置每一個控件新的的大小和位置,實現(xiàn)動態(tài)布局
(2)注意:
- Size屬性指窗口大小(包括工具欄),ClientSize指客戶區(qū)大?。ú话ぞ邫冢?br /> - 本質(zhì):OnLayout方法會在窗口大小變化時自動被調(diào)用,來設置組件的位置實現(xiàn)自適應
namespace WindowsFormsApp_learning
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//重寫父類的OnLayout方法,實現(xiàn)手動布局自適應
protected override void OnLayout(LayoutEventArgs levent)
{
//1.調(diào)用父類的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:固定、錨定(無論窗口怎么變化,控件的相對位置都不變)
- 含義:固定控件與父窗口的【上下左右邊距】不變,實現(xiàn)控件的錨定
- 左上角固定:選定 Top,Left(默認)
- 頂部固定,水平拉伸:選定 Top,Left,Right
- 居中固定:None(取消所有)
- *注意:Anchor效果的好壞取決于控件的初始位置,因為控件的初始位置決定了控件的邊距!所以要讓控件固定右上角,就要初始設計時就放在右上角!
(2)Dock:??繉傩?,將控件??吭诟复翱诘囊粋?cè)或者中央
- Top:上,控件??吭谌萜魃蟼?cè),寬度填滿容器,高度可以調(diào)節(jié)
- Bottom:下,控件??吭谌萜飨聜?cè),寬度填滿容器,高度可以調(diào)節(jié)
- Left:左,控件??吭谌萜髯髠?cè),高度填滿容器,寬度可以調(diào)節(jié)
- Right:右,控件??吭谌萜饔覀?cè),高度填滿容器,寬度可以調(diào)節(jié)
- Fill,中,控件填滿容器中間剩余部分(所以說與控件添加順序有關)
- None,無,不使用Dock屬性
- *注意:
a.容器之間可以嵌套,使用布局屬性(容器就是存放組件的,比如Panel)
b.Dock屬性與Anchor屬性不能同時使用
c.Dock屬性不是固定邊距了,就是相對位置填充


3.WinForm布局器
4.布局器 LayoutEngine
(1)含義:布局器就是容器內(nèi)部組件的默認排列方式,所有的容器都帶有一個默認的布局器
(2)自定義控件如何加入設計界面:
- 工具 -> 選項 -> Windows窗體設計器 -> 常規(guī) -> 自動填充工具箱 -> True
- 添加自定義的控件類源碼到項目下
- 生成/重新生成結(jié)局方案 F7
- 重新打開設計界面,在工具箱就可以看到自己的控件
(3)系統(tǒng)提供的布局器-FlowLayoutPanel(流式布局):
- 含義:普通的Panel面板容器控件,使用了FlowLayout流式布局,即所有內(nèi)部組件按照順序從左到右從上到下依次排列
- FlowLayoutPanel也可以使用Anchor、Dock等屬性,因為他也是窗體容器內(nèi)的一個組件
- 控件的選擇技巧:多個控件疊加到一起時,可以右鍵最上層控件,來進行重疊控件的選擇
(4)系統(tǒng)提供的布局器-TableLayoutPanel(表格布局):
- 含義:普通的Panel面板容器,使用了TableLayout表格布局,即所有內(nèi)部組件可以放置到不同的表格中(每個表格只能放置一個控件)
- TableLayoutPanel也可以使用Anchor、Dock等屬性,因為他也是窗體容器內(nèi)的一個組件。搭配布局與布局屬性,可以實現(xiàn)很多不同的布局效果。
- 刪除/添加行、列:右鍵表格Panel,可以添加、刪除行/列
- 調(diào)整表格大?。罕砀駥傩訡olumns可以通過絕對值、百分比、自動調(diào)整等方式來調(diào)整單元格的大小
a.絕對:固定像素值大小
b.百分比:除去絕對大小后,單元格占剩余大小的百分比
c.自動調(diào)整:根據(jù)內(nèi)部控件的大小生成
- 跨行/列控件:在控件的ColumnSpan/RowSpan調(diào)整控件可以跨行/跨列布局
- *注意: TableLayoutPanel 控件每個單元格只能包含一個子控件。
(5)系統(tǒng)提供的布局工具-默認布局:默認布局可以通過控件拖拽放置,并可以使用Anchor、Dock來調(diào)整
(6)自定義布局器:用戶可以自己設計實現(xiàn)布局器,這屬于WinForm高級的內(nèi)容,后面學習。

三.WinForm常用控件
1.Winform 組件的使用
(1)TextBox:輸入文本框
- 常用屬性:尺寸Size、單行/多行Multiline、密碼輸入PasswordChar、只讀ReadOnly、顯示/獲取文本Text等
- 常用事件:KeyPress按下按鍵(常用于輸出完成點擊回車,box.Text取輸入值,事件e.keyChar取按下哪個鍵)
(2)CheckBox:復選框
- 常用屬性:尺寸Size、顯示文本Text、Checked是否勾選
- 常用事件:Click點擊事件、CheckedChanged勾選狀態(tài)改變事件
(3)ComboBox:下拉列表(只能單選)
- 常用屬性:
a.添加數(shù)據(jù)項:設計器編輯添加(屬性->數(shù)據(jù)->Items,一行表示一個數(shù)據(jù)項)、程序手工添加(comboBox.Items.Add("some");)
b.其他設置:Size尺寸、Text提示文本等
- 常用事件:
a.獲取選中的項:SelectedItem(選中項的值)、SelectedIndex(選中項的索引,-1表示未選中)
b.選項改變事件:SelectedIndexChanged
- 注意:Item可以添加字符串,也可以添加任意object類型(比如自定義對象),對象會以object.toString顯示
(4)ListBox:列表框(展示數(shù)據(jù)、可單選/多選)
- 常用屬性:SelectionMode(單選/多選模式)
a.單選模式獲取選項:SelectedItem/SelectedIndex(選中項的值/索引)
b.多選模式獲取選項:SelectedIndices/SelectedItems(選中項的索引集合/值集合)
c.添加數(shù)據(jù)項:設計器編輯添加(屬性->數(shù)據(jù)->Items)、程序手工添加(listBox.Items.Add("some");)
- 常用事件:SelectedIndexChanged(選項改變)
- 注意:Item可以添加字符串,也可以添加任意object類型(比如自定義對象),對象會以object.toString顯示
(5)練習:學生信息編輯器實例(本代碼)
1.界面展示

2.實體類 Student(封裝信息)
1.C# 類的屬性與字段
(1)字段:字段是類的成員變量,用于類內(nèi)特征的數(shù)據(jù)存儲(靜態(tài)) 比如private int Id;
(2)屬性:屬性是對字段特征的動態(tài)描述,用于向外界提供數(shù)據(jù),本質(zhì)上就是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'。用于獲取數(shù)據(jù),如果沒有get則字段為只寫的
- set訪問器:set訪問器接受它的輸入?yún)?shù)--value,并把它賦給字段,value是隱式參數(shù)。用于設置數(shù)據(jù),如果沒有set則字段為只讀的
(3)使用方式:直接使用Class.StudentName來獲取和設置數(shù)據(jù),就像是直接使用公開的屬性一樣
(4)自動屬性:簡化字段和屬性的關系
- 用法:public 數(shù)據(jù)類型 屬性名{ get; set; }
- *原理:c# 允許只聲明屬性而不聲明后備字段,編譯器會創(chuàng)建隱藏的后備字段。并且自動掛接到get,set訪問器上。
(5)注意:
- 屬性也可以不與字段關聯(lián),可以當作函數(shù)進行復雜計算,比較自由靈活
- 屬性也可不用顯示聲明相應的字段,直接用于存貯數(shù)據(jù)。(自動屬性)
- 也可以通定義其他set、get函數(shù)來實現(xiàn)訪問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();
//初始化數(shù)據(jù)
LoadData();
}
/**
* 保存按鈕觸發(fā)事件-保存學生信息到本地文件
*/
private void save_student(object sender, EventArgs e)
{
Student student = new Student();
student.SduId =Convert.ToInt32(sdu_Id.Text.Trim()); //Convert格式轉(zhuǎn)換
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("操作成功");
}
//讀取文件,加載數(shù)據(jù)
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->添加資源->添加現(xiàn)有文件->選擇本地圖片->重命名(規(guī)范化,以后使用時直接調(diào)用名字使用資源)
b.能添加什么類型的資源:字符串、文本文檔、圖片、視頻、音頻等
c.原理:Resources.resx將添加的資源整合到了項目exe當中,因此就算刪除源文件也不影響項目運行。在調(diào)用資源時,是通過自動生成的方法來獲取資源。
d.優(yōu)點:將資源統(tǒng)一到項目中來,并且可以通過規(guī)范化的命名直接調(diào)用資源。
e.使用:通過 Properties.Resources.資源名稱; 來直接調(diào)用你的資源,方便快捷
- 網(wǎng)絡資源:比如"http://baidu/image/meinv.jpg"
(2)圖片資源加載類:
- C# 提供了Image抽象類,作為所有圖片資源的總稱
- C# 提供了Image抽象類的具體實現(xiàn)類 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控件,沒有過多的設計。圖片來源的設置使用代碼方式,原因是在以后開發(fā)中圖片往往不是固定的,需要動態(tài)變化,因此使用代碼方式動態(tài)設置圖片來源是比較推薦的。
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 入門內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
c#斐波那契數(shù)列(Fibonacci)(遞歸,非遞歸)實現(xiàn)代碼
c#斐波那契數(shù)列(Fibonacci)(遞歸,非遞歸)實現(xiàn)代碼,需要的朋友可以參考一下2013-05-05

