明輝手游網(wǎng)中心:是一個免費提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

使用 Microsoft.NET Frameworks 創(chuàng)建基于 Windows 的應(yīng)用程序(轉(zhuǎn))

[摘要]摘要: :本文介紹了 Win 表單這一新的窗體程序包,借助這一程序包,開發(fā)人員能夠充分利用 Microsoft Windows 操作系統(tǒng)所提供的 UI 功能。 目錄 簡介 介紹 Win Forms ...
摘要: :本文介紹了 Win 表單這一新的窗體程序包,借助這一程序包,開發(fā)人員能夠充分利用 Microsoft Windows 操作系統(tǒng)所提供的 UI 功能。

目錄

簡介
介紹 Win Forms
更好的易學(xué)易用性
布局
GDI+
訪問底層系統(tǒng)
結(jié)論

--------------------------------------------------------------------------------


簡介

目前 Web 已成了街談巷議的話題,看起來好像 Microsoft® Visual Studio® 開發(fā)系統(tǒng)對創(chuàng)建基于 Microsoft Windows® 的傳統(tǒng)應(yīng)用程序的支持有所減弱。實際上,Microsoft 對基于 Windows 的應(yīng)用程序開發(fā)方面的投資在不斷加大。

Win 表單是一個新的窗體程序包,借助這一程序包,開發(fā)人員能夠充分利用 Microsoft Windows® 操作系統(tǒng)所提供的豐富的用戶界面功能,創(chuàng)建基于 Windows 的應(yīng)用程序。Win Forms 是新的 Microsoft®.NET 平臺的一個組成部分,它提供了許多新技術(shù),包括通用的應(yīng)用程序框架、可管理的執(zhí)行環(huán)境、一體化的安全性以及面向?qū)ο蟮脑O(shè)計原則。而且,Win Forms 全面支持快速簡便地接入 Web Services 以及建立豐富的基于 ADO+ 數(shù)據(jù)模型的數(shù)據(jù)感知應(yīng)用程序。得益于 Visual Studio 中新的共享開發(fā)環(huán)境,開發(fā)人員能夠使用包括 Microsoft Visual Basic® 和 C# 在內(nèi)的任何支持 .NET 平臺的語言創(chuàng)建 Win Forms 應(yīng)用程序。


介紹 Win Forms

就像剛才所說的,Win Forms 是專用于 Windows 客戶機 UI 編程的 .NET Framework 的命名空間。它與 ASP+ UI 程序包(即 Web Forms)共享同樣的設(shè)計原則,但其類和實現(xiàn)卻全然不同。在 Microsoft Win32® API 和 Web 組件之間沒有魔術(shù)般變形的類。就像所有的 .NET Frameworks 一樣,一致性已成為優(yōu)先考慮的問題。其目的是為了 Win Forms 開發(fā)人員能夠迅速適應(yīng)在 Web Forms 中編寫代碼,反之亦然。例如,所有命名空間都有 Button 類,每一個都有文本、默認的 OnClick 事件以及 ForeColor、BackColor 和 Font 屬性。

Win Forms 的所有控件都基于 System.WinForms.Control 類。Control 已內(nèi)置了所有基本的 HWND 功能,并且它能處理我們已經(jīng)熟悉并喜愛的絕大多數(shù)通用 WM_xxxx 消息。RichControl 由 Control 派生而來,其中添加了布局邏輯和繪圖代碼。System.WinForms 命名空間中的絕大多數(shù)控件實際上都由 RichControl 派生而來。ScrollableControl 能夠支持窗口客戶區(qū)域的滾動。一般情況下,對滾動功能的支持是通過 ContainerControl 實現(xiàn)的,后者由 ScrollableControl 派生而來,并增加了對管理子控件、焦點問題和跨欄的支持。Form 由 ContainerControl 派生而來,是 Win Form 的頂級控件,它帶有控制標題欄、系統(tǒng)菜單、非矩形窗口和默認控件的屬性。UserControl 也由 ContainterControl 派生而來,是開發(fā)人員能夠創(chuàng)建的控件的基本類。UserControl 一般用于托管其它子控件,但對于外部客戶機來說,它又是作為單個單元出現(xiàn)的。UserControl 和 Form 在 Microsoft® Visual Studio.NET 中都有可視設(shè)計器,您會找到用于添加和設(shè)計由其所派生的類的項。



圖 1. Win Forms 控件層次結(jié)構(gòu)

既然我們已了解 Win Forms 的(最)基本方面,讓我們揭開它的面紗,看看其表面下的一些相當不錯的功能。


更好的易學(xué)易用性

Win Forms 的主要目的是盡可能地提高定位到 Win32 平臺的開發(fā)人員的工作效率。無論是圖形設(shè)備界面 (GDI) 還是窗口狀態(tài)管理,為 Win32 編程通常都是很困難的。例如,類似 WS_BORDER 或 WS_CAPTION 的一些窗口樣式只能在創(chuàng)建窗口時指定或修改。而 WS_VISIBLE 或 WS_CHILD 等其它窗口樣式則可以對已創(chuàng)建的窗口進行修改。Win Forms 盡力消除了這些細微的差別,并確保操作過程始終保持一致性?梢噪S時地、不限次序地對 Win Forms 控件的屬性進行設(shè)置,總能產(chǎn)生預(yù)期效果。如果改動過程需要創(chuàng)建新的 HWND,Win Forms 框架能夠自動地、透明地重新生成窗口,并為其應(yīng)用相適宜的所有設(shè)置。

由控件獲得通知或事件在 Win Forms 中也要容易得多。Win Forms 事件都基于稱為 Delegates 的一個通用語言運行時功能。Delegates 從本質(zhì)上講是對類型安全的、可靠的函數(shù)指針。對于任一控件的任一事件,都可以添加代理處理程序;絕不會強迫您創(chuàng)建派生類以通過替代處理事件,創(chuàng)建事件映射,或僅為處理一個事件而為類的所有事件實施一個接口。也可以通過替代派生類處理事件,但這種方式一般用于控件創(chuàng)建者或更為高級的應(yīng)用。匯集某一按鈕的 Click 事件相當簡單:

public class ButtonClickForm: System.WinForms.Form {
private System.WinForms.Button button1;
public ButtonClickForm() {
// 創(chuàng)建按鈕
button1 = new System.WinForms.Button();
// 添加處理程序
button1.AddOnClick(new System.EventHandler(button1_Click));
// 將按鈕添加到窗體中
this.Controls.Add(button1);
}

private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("button1 clicked!");
}
}

這里,我們創(chuàng)建了一個按鈕,并添加了一個名為 button1_Click 的處理程序方法,通過短短幾行代碼,在單擊該按鈕后,將調(diào)用這一方法。請注意,即使處理程序方法被標記為專用,創(chuàng)建這一掛鉤的代碼仍可以使用該方法,單擊按鈕后,按鈕將能夠激活這一方法的事件。

啟動 Win Forms 項目的過程也得到了簡化。使用 Visual Studio.NET 創(chuàng)建 Win Forms 項目的過程只會創(chuàng)建一個要編譯的項目文件:Form1.cs。沒有頭文件,沒有接口定義文件,沒有引導(dǎo)程序文件,沒有資源文件,沒有庫文件。項目所需的所有信息都包含在窗體的代碼中。這樣做有一個好處:項目由一個簡單的單窗體應(yīng)用程序擴展到復(fù)雜的、帶有多個代碼文件的多窗體應(yīng)用程序要方便得多。鏈接過程不需要中間對象文件,只有代碼和已構(gòu)建的、受管理的所有 DLL。只要您習(xí)慣了這一方法,就能明顯地感覺到創(chuàng)建 .NET Framework 應(yīng)用程序和創(chuàng)建 C/C++ 應(yīng)用程序之間復(fù)雜性的不同。因為信息僅僅包含在代碼文件中,在 Visual Studio.NET 環(huán)境外創(chuàng)建版本的過程也非常容易,無論是 Visual Basic 代碼、C# 代碼,還是任何其它語言編寫的針對 .NET Framework 的代碼。

因為 Win Forms 建立在通用語言運行時的基礎(chǔ)之上,開發(fā)人員可以任選目前針對通用語言運行時的眾多語言中的一種,構(gòu)建 Win32 應(yīng)用程序。開發(fā)人員現(xiàn)在可以使用多種語言編寫 Win Forms 應(yīng)用程序(或 Web Forms 應(yīng)用程序或 Data 應(yīng)用程序):從 C# 到 COBOL 到 Eiffel 再到 Perl 等等,中間還有很多種(上一次計數(shù)是 17 種)。方便易用再加上廣泛的應(yīng)用場合相得益彰,為開發(fā)人員提供了深厚的基礎(chǔ),使他們能夠迅速有效地使用 Win Forms 構(gòu)建實用的應(yīng)用程序。


布局

如果您曾嘗試創(chuàng)建能夠正常調(diào)整大小的窗體,您就會知道這一過程有多么困難。Microsoft Foundation Classes (MFC) 或早期的 Visual Basic 版本沒有對這一功能提供內(nèi)置的支持。然而現(xiàn)在只需幾行代碼(通常情況下您甚至不需要編寫這些代碼,因為在設(shè)計時就能通過 Property Browser 實現(xiàn)這些功能。,即可創(chuàng)建能夠正常調(diào)整大小的對話框。

基本布局由兩條組成:Anchoring 和 Docking。RichControl 有一個 Anchor 屬性,它是一種枚舉類型,可以用“或”操作將這些值組合在一起,以說明控件將與其父控件的某一邊保持恒定距離。例如,如果您將一個按鈕置于窗體上,并將 Anchor 屬性設(shè)置為 AnchorStyles.BottomRight,則在調(diào)整按鈕的大小時,按鈕將與窗體的底邊和右邊保持同一距離。此外,如果將 Anchor 設(shè)置為 AnchorStyles.All,則按鈕的各個邊都與窗體的對應(yīng)邊保持同一距離,在調(diào)整按鈕大小時仍要滿足這些約束條件。

Docking 實際上是 Anchoring 的一個特殊情況。RichControl 的 Dock 屬性說明控件要將自身固定到其父控件的哪一邊。Docking 可以是 Top、Left、Right、Bottom 或 Fill。在每種情況下,控件都將移動到盡量靠近指定邊,并調(diào)整其大小,以填滿那一邊。如果父控件的大小有所調(diào)整,這一狀況仍將保持。將一個控件移動到父控件的底端,并將 Anchor 設(shè)置為 AnchorStyle.BottomLeftRight,可以模擬 Docking Bottom。在此處的示例中,列表框是 Docked Left,按鈕與窗體的頂端、左邊和右邊保持恒定距離,由此它們保持了相對位置和大小。下面的示例對話框(圖 2)完全使用 Visual Studio.NET 中的 Win Forms 設(shè)計器創(chuàng)建,只花了兩分鐘的時間,沒有編寫一行代碼。



圖 2. 使用 Win Forms 設(shè)計器所創(chuàng)建的可調(diào)整大小的對話框

// ResizableSample.cs
namespace ResizableSampleNamespace {

using System;
using System.Drawing;
using System.ComponentModel;
using System.WinForms;

/// <summary>
///ResizableSample 的摘要說明。
/// </summary>
public class ResizableSample : System.WinForms.Form {
/// <summary>
///為 Win Forms 設(shè)計器所要求
/// </summary>
private System.ComponentModel.Container components;
private System.WinForms.Button button3;
private System.WinForms.Button button2;
private System.WinForms.Button button1;
private System.WinForms.ListBox listBox1;
public ResizableSample() {
// 為 Win Form 設(shè)計器支持所要求
InitializeComponent();

}

/// <summary>
///釋放正在使用的所有資源
/// </summary>
public override void Dispose() {
base.Dispose();
components.Dispose();
}


/// <summary>
///應(yīng)用程序的主入口點。
/// </summary>
public static void Main(string[] args) {
Application.Run(new ResizableSample());
}


/// <summary>
///設(shè)計器支持所要求的方法 — 不要用編輯器
///修改這一方法的內(nèi)容
/// </summary>
private void InitializeComponent()
 {
this.components = new System.ComponentModel.Container();
this.button2 = new System.WinForms.Button();
this.button3 = new System.WinForms.Button();
this.button1 = new System.WinForms.Button();
this.listBox1 = new System.WinForms.ListBox();
//@design this.TrayLargeIcon = false;
//@design this.TrayHeight = 0;
this.Text = "Resizable Dialog";
this.IMEMode = System.WinForms.IMEMode.Off;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(256, 173);
button2.Location = new System.Drawing.Point(152, 60);
button2.Size = new System.Drawing.Size(92, 32);
button2.TabIndex = 2;
button2.Anchor = System.WinForms.AnchorStyles.TopLeftRight;
button2.Text = "Cancel";
button3.Location = new System.Drawing.Point(152, 120);
button3.Size = new System.Drawing.Size(92, 44);
button3.TabIndex = 3;
button3.Anchor = System.WinForms.AnchorStyles.All;
button3.Text = "Filler";
button1.Location = new System.Drawing.Point(152, 8);
button1.Size = new System.Drawing.Size(92, 32);
button1.TabIndex = 1;
button1.Anchor = System.WinForms.AnchorStyles.TopLeftRight;
button1.Text = "OK";
listBox1.Size = new System.Drawing.Size(120, 173);
listBox1.Dock = System.WinForms.DockStyle.Left;
listBox1.TabIndex = 0;
listBox1.Items.All = new object[] {"Item One",
"Item Two",
"Item Three",
"Item Four"};
this.Controls.Add(button3);
this.Controls.Add(button2);
this.Controls.Add(button1);
this.Controls.Add(listBox1);
 }

}
}


GDI+

Win Forms 全面利用了 GDI+ 這一 Microsoft 下一代的二維圖形系統(tǒng)。Win Forms 中的圖形編程模式完全是面向?qū)ο蟮模魇礁鳂拥漠嫻P、筆刷、圖像和其它圖形對象與 .NET Framework 的其它部分一樣,遵循了簡單易用的指導(dǎo)方針。開發(fā)人員目前可以使用相當不錯的一些繪圖新功能,如 alpha 混色、漸變色、紋理、消除鋸齒以及采用除位圖外的其它圖像格式。與 Windows 2000 操作系統(tǒng)分層和透明的窗口功能配合使用,開發(fā)人員能夠毫不費力地創(chuàng)建豐富的、更為圖形化的 Win32 應(yīng)用程序。

如果觸發(fā)了控件的 OnPaint 事件,能夠由 PaintEventArgs 訪問的 System.Drawing.Graphics 對象就成為一個 GDI+ 圖形對象。圖形對象能夠執(zhí)行的所有操作都通過 GDI+ 實施。作為一個示例,使用 GDI+ 創(chuàng)建一個繪制漸變背景的按鈕。



圖 3. 使用 GDI+ 創(chuàng)建的按鈕

以下是實現(xiàn)這一按鈕的代碼:

public class GradientButton : Button {
// 保留顏色設(shè)置的成員
private Color startColor;
private Color endColor;

// 書寫文字時我們將需要它
private static StringFormat format = new StringFormat();
public GradientButton() : base() {
// 初始化顏色
startColor = SystemColors.InactiveCaption;
endColor = SystemColors.ActiveCaption;
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
}

/// <summary>
/// 漸變色的終止顏色
// </summary>
public Color EndColor {
get {
return this.endColor;
 }
set {
this.endColor = value;
// 如有必要,則導(dǎo)致重新繪制
if (this.IsHandleCreated && this.Visible) {
Invalidate();
}
 }
 }


/// <summary>
/// 漸變色的起始顏色
// </summary>
public Color StartColor {
get {
return this.startColor;
 }
set {
this.startColor = value;
// 如有必要,則導(dǎo)致重新繪制
if (this.IsHandleCreated && this.Visible) {
Invalidate();
 }
}
 }

protected override void OnPaint(PaintEventArgs pe) {
// 繪制按鈕的常規(guī)背景以形成
// 邊框,等等。
base.OnPaint(pe);
Graphics g = pe.Graphics;
Rectangle clientRect = this.ClientRectangle;
// 縮小矩形,以免繪制時出界
clientRect.Inflate(-1,-1);
// 創(chuàng)建漸變筆刷,從
// 左上角運行到右下角。
Brush backgroundBrush = new LinearGradientBrush(
new Point(clientRect.X,clientRect.Y),
new Point(clientRect.Width, clientRect.Height),
startColor,
endColor);
// 以漸變色填充背景....
g.FillRectangle(backgroundBrush, clientRect);
// 在客戶機區(qū)域的中間書寫文字。
g.DrawString(this.Text,
this.Font,
new SolidBrush(this.ForeColor),
clientRect,
format);
 }
}

就像您所看到的,這并不是非常困難。得益于 Win Forms 和 GDI+ 面向?qū)ο蟮脑O(shè)計,無需編寫任何復(fù)雜的代碼,即可實現(xiàn)我們的 GradientButton,并且在設(shè)計器中,可以通過 Property Browser 操作 Text、Font、StartColor 和 EndColor。


訪問底層系統(tǒng)

許多框架的一個缺點就是:如果人們編寫的應(yīng)用程序類型與示例和演示中的嚴格一致,則這些框架的效果相當不錯,但有時開發(fā)人員發(fā)現(xiàn),一旦他們希望用框架進行一些有創(chuàng)造性的工作,某些情況下就會碰到障礙或遭到失敗。如果遇到這一情況,Win Forms 框架自始至終都能夠允許開發(fā)人員訪問系統(tǒng)基礎(chǔ)結(jié)構(gòu)。當然,希望 Win Forms 這樣一個設(shè)計優(yōu)良的框架不會使用戶遭遇這種情況,但可能發(fā)生的情況幾乎是無限的。所有的控件都有 Handle 屬性,允許訪問控件的窗口句柄 (HWND),GDI 對象也提供了類似的句柄訪問過程。而且,Control 實際上擁有一個名為 WndProc 的受保護的虛擬方法,對于少數(shù) Win Forms 尚不能支持的消息,可以替代該方法,添加處理方式。

例如,假設(shè)您的應(yīng)用程序是資源密集型的,需要響應(yīng) WM_COMPACTING。如果系統(tǒng)檢測到內(nèi)存不足,會向所有高層窗口廣播 WM_COMPACTING,您就會知道 Win Forms 框架對這一消息沒有提供內(nèi)置支持,由此,可以添加如下處理過程:

/// <summary>
///Win32Form1 的摘要說明。
/// </summary>
public class CompactableForm : System.WinForms.Form {
private EventHandler handler;
public void AddOnCompacting(EventHandler h) {
handler = (EventHandler) Delegate.Combine(handler, h);
}


protected override void OnCompacting(EventArgs e) {
// 查看運行時系統(tǒng)能否釋放任何東西
System.GC.Collect();
// 調(diào)用任一處理程序。
if (handler != null) handler(this, e);
 }

public void RemoveOnCompacting(EventHandler h) {
handler = (EventHandler) Delegate.Remove(handler, h);
}


protected override void WndProc(ref Message m) {
case (m.msg) {
case win.WM_COMPACTING:
OnCompacting(EventArgs.Empty);
break;
}
base.WndProc(m);
 }

}

只需數(shù)行代碼,當系統(tǒng)試著收集未用資源時,利用新的 CompactableForm 類或由此派生的類即可得到通知,并作出響應(yīng)。


結(jié)論

盡管在許多開發(fā)人員的計劃中,針對 Web 的開發(fā)是當前工作的重點,而定位于熟悉的 Win32 平臺仍然是一個不得不面對的情況。有了 Win Forms,Windows 開發(fā)人員無論是新手還是老手,都會發(fā)現(xiàn)使用豐富的接口創(chuàng)建復(fù)雜的應(yīng)用程序是一個很方便的過程,而這些接口與 .NET Framework 中具有 Web 和數(shù)據(jù)功能的許多技術(shù)配合良好。

通過利用跨語言繼承、碎片收集和安全性等通用語言運行時提高工作效率的優(yōu)秀功能,開發(fā)人員將從 .NET Framework 和 Win Forms 中獲益。