一.Winform入門
WinForm 是 Windows Form 的簡稱,是基于 .NETFramework 平臺的客戶端(PC軟件)開發(fā)技術(shù),,一般使用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關(guān)鍵詞聲明,其定義的類可以在多個地方被定義,,最后編譯的時候會被當作一個類來處理,。因此兩個文件各司其職,最后合并為一個類編譯,。 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)原理:設計界面自動關(guān)聯(lián)Form1.Designer.cs文件,,在InitializeComponent()方法中會自動生成相關(guān)代碼
(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ū)大小(不包含工具欄) - 本質(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布局屬性(控件與布局相關(guān)的屬性,,設計界面可見) **(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,,中,控件填滿容器中間剩余部分(所以說與控件添加順序有關(guān)) - 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)整表格大小:表格屬性Columns可以通過絕對值,、百分比,、自動調(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ù),,如果沒有g(shù)et則字段為只寫的 - set訪問器:set訪問器接受它的輸入?yún)?shù)–value,,并把它賦給字段,value是隱式參數(shù),。用于設置數(shù)據(jù),,如果沒有set則字段為只讀的 **(3)使用方式:**直接使用Class.StudentName來獲取和設置數(shù)據(jù),就像是直接使用公開的屬性一樣 (4)自動屬性:簡化字段和屬性的關(guān)系 - 用法:public 數(shù)據(jù)類型 屬性名{ get; set; } - *原理:c# 允許只聲明屬性而不聲明后備字段,,編譯器會創(chuàng)建隱藏的后備字段,。并且自動掛接到get,set訪問器上。 (5)注意: - 屬性也可以不與字段關(guān)聯(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;
}
}
}
|