使用 Microsoft.NET Frameworks 創(chuàng)建Windows應(yīng)用程序
2024-07-10 12:59:42
供稿:網(wǎng)友
 
網(wǎng)站運(yùn)營seo文章大全提供全面的站長(zhǎng)運(yùn)營經(jīng)驗(yàn)及seo技術(shù)!使用 microsoft.net frameworks 創(chuàng)建基于 windows 的應(yīng)用程序
shawn burke 
microsoft corporation 
2000年9月 
摘要: :本文介紹了 win 表單這一新的窗體程序包,借助這一程序包,開發(fā)人員能夠充分利用 microsoft windows 操作系統(tǒng)所提供的 ui 功能。 
目錄 
簡(jiǎn)介 
介紹 win forms 
更好的易學(xué)易用性 
布局 
gdi+ 
訪問底層系統(tǒng) 
結(jié)論 
--------------------------------------------------------------------------------
簡(jiǎn)介 
目前 web 已成了街談巷議的話題,看起來好像 microsoft® visual studio® 開發(fā)系統(tǒng)對(duì)創(chuàng)建基于 microsoft windows® 的傳統(tǒng)應(yīng)用程序的支持有所減弱。實(shí)際上,microsoft 對(duì)基于 windows 的應(yīng)用程序開發(fā)方面的投資在不斷加大。
win 表單是一個(gè)新的窗體程序包,借助這一程序包,開發(fā)人員能夠充分利用 microsoft windows® 操作系統(tǒng)所提供的豐富的用戶界面功能,創(chuàng)建基于 windows 的應(yīng)用程序。win forms 是新的 microsoft®.net 平臺(tái)的一個(gè)組成部分,它提供了許多新技術(shù),包括通用的應(yīng)用程序框架、可管理的執(zhí)行環(huán)境、一體化的安全性以及面向?qū)ο蟮脑O(shè)計(jì)原則。而且,win forms 全面支持快速簡(jiǎn)便地接入 web services 以及建立豐富的基于 ado+ 數(shù)據(jù)模型的數(shù)據(jù)感知應(yīng)用程序。得益于 visual studio 中新的共享開發(fā)環(huán)境,開發(fā)人員能夠使用包括 microsoft visual basic® 和 c# 在內(nèi)的任何支持 .net 平臺(tái)的語言創(chuàng)建 win forms 應(yīng)用程序。
介紹 win forms 
就像剛才所說的,win forms 是專用于 windows 客戶機(jī) ui 編程的 .net framework 的命名空間。它與 asp+ ui 程序包(即 web forms)共享同樣的設(shè)計(jì)原則,但其類和實(shí)現(xiàn)卻全然不同。在 microsoft win32® api 和 web 組件之間沒有魔術(shù)般變形的類。就像所有的 .net frameworks 一樣,一致性已成為優(yōu)先考慮的問題。其目的是為了 win forms 開發(fā)人員能夠迅速適應(yīng)在 web forms 中編寫代碼,反之亦然。例如,所有命名空間都有 button 類,每一個(gè)都有文本、默認(rèn)的 onclick 事件以及 forecolor、backcolor 和 font 屬性。
win forms 的所有控件都基于 system.winforms.control 類。control 已內(nèi)置了所有基本的 hwnd 功能,并且它能處理我們已經(jīng)熟悉并喜愛的絕大多數(shù)通用 wm_xxxx 消息。richcontrol 由 control 派生而來,其中添加了布局邏輯和繪圖代碼。system.winforms 命名空間中的絕大多數(shù)控件實(shí)際上都由 richcontrol 派生而來。scrollablecontrol 能夠支持窗口客戶區(qū)域的滾動(dòng)。一般情況下,對(duì)滾動(dòng)功能的支持是通過 containercontrol 實(shí)現(xiàn)的,后者由 scrollablecontrol 派生而來,并增加了對(duì)管理子控件、焦點(diǎn)問題和跨欄的支持。form 由 containercontrol 派生而來,是 win form 的頂級(jí)控件,它帶有控制標(biāo)題欄、系統(tǒng)菜單、非矩形窗口和默認(rèn)控件的屬性。usercontrol 也由 containtercontrol 派生而來,是開發(fā)人員能夠創(chuàng)建的控件的基本類。usercontrol 一般用于托管其它子控件,但對(duì)于外部客戶機(jī)來說,它又是作為單個(gè)單元出現(xiàn)的。usercontrol 和 form 在 microsoft® visual studio.net 中都有可視設(shè)計(jì)器,您會(huì)找到用于添加和設(shè)計(jì)由其所派生的類的項(xiàng)。
圖 1. win forms 控件層次結(jié)構(gòu)
既然我們已了解 win forms 的(最)基本方面,讓我們揭開它的面紗,看看其表面下的一些相當(dāng)不錯(cuò)的功能。
更好的易學(xué)易用性 
win forms 的主要目的是盡可能地提高定位到 win32 平臺(tái)的開發(fā)人員的工作效率。無論是圖形設(shè)備界面 (gdi) 還是窗口狀態(tài)管理,為 win32 編程通常都是很困難的。例如,類似 ws_border 或 ws_caption 的一些窗口樣式只能在創(chuàng)建窗口時(shí)指定或修改。而 ws_visible 或 ws_child 等其它窗口樣式則可以對(duì)已創(chuàng)建的窗口進(jìn)行修改。win forms 盡力消除了這些細(xì)微的差別,并確保操作過程始終保持一致性。可以隨時(shí)地、不限次序地對(duì) win forms 控件的屬性進(jìn)行設(shè)置,總能產(chǎn)生預(yù)期效果。如果改動(dòng)過程需要?jiǎng)?chuàng)建新的 hwnd,win forms 框架能夠自動(dòng)地、透明地重新生成窗口,并為其應(yīng)用相適宜的所有設(shè)置。
由控件獲得通知或事件在 win forms 中也要容易得多。win forms 事件都基于稱為 delegates 的一個(gè)通用語言運(yùn)行時(shí)功能。delegates 從本質(zhì)上講是對(duì)類型安全的、可靠的函數(shù)指針。對(duì)于任一控件的任一事件,都可以添加代理處理程序;絕不會(huì)強(qiáng)迫您創(chuàng)建派生類以通過替代處理事件,創(chuàng)建事件映射,或僅為處理一個(gè)事件而為類的所有事件實(shí)施一個(gè)接口。也可以通過替代派生類處理事件,但這種方式一般用于控件創(chuàng)建者或更為高級(jí)的應(yīng)用。匯集某一按鈕的 click 事件相當(dāng)簡(jiǎn)單:
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)建了一個(gè)按鈕,并添加了一個(gè)名為 button1_click 的處理程序方法,通過短短幾行代碼,在單擊該按鈕后,將調(diào)用這一方法。請(qǐng)注意,即使處理程序方法被標(biāo)記為專用,創(chuàng)建這一掛鉤的代碼仍可以使用該方法,單擊按鈕后,按鈕將能夠激活這一方法的事件。
啟動(dòng) win forms 項(xiàng)目的過程也得到了簡(jiǎn)化。使用 visual studio.net 創(chuàng)建 win forms 項(xiàng)目的過程只會(huì)創(chuàng)建一個(gè)要編譯的項(xiàng)目文件:form1.cs。沒有頭文件,沒有接口定義文件,沒有引導(dǎo)程序文件,沒有資源文件,沒有庫文件。項(xiàng)目所需的所有信息都包含在窗體的代碼中。這樣做有一個(gè)好處:項(xiàng)目由一個(gè)簡(jiǎn)單的單窗體應(yīng)用程序擴(kuò)展到復(fù)雜的、帶有多個(gè)代碼文件的多窗體應(yīng)用程序要方便得多。鏈接過程不需要中間對(duì)象文件,只有代碼和已構(gòu)建的、受管理的所有 dll。只要您習(xí)慣了這一方法,就能明顯地感覺到創(chuàng)建 .net framework 應(yīng)用程序和創(chuàng)建 c/c++ 應(yīng)用程序之間復(fù)雜性的不同。因?yàn)樾畔H僅包含在代碼文件中,在 visual studio.net 環(huán)境外創(chuàng)建版本的過程也非常容易,無論是 visual basic 代碼、c# 代碼,還是任何其它語言編寫的針對(duì) .net framework 的代碼。
因?yàn)?win forms 建立在通用語言運(yùn)行時(shí)的基礎(chǔ)之上,開發(fā)人員可以任選目前針對(duì)通用語言運(yùn)行時(shí)的眾多語言中的一種,構(gòu)建 win32 應(yīng)用程序。開發(fā)人員現(xiàn)在可以使用多種語言編寫 win forms 應(yīng)用程序(或 web forms 應(yīng)用程序或 data 應(yīng)用程序):從 c# 到 cobol 到 eiffel 再到 perl 等等,中間還有很多種(上一次計(jì)數(shù)是 17 種)。方便易用再加上廣泛的應(yīng)用場(chǎng)合相得益彰,為開發(fā)人員提供了深厚的基礎(chǔ),使他們能夠迅速有效地使用 win forms 構(gòu)建實(shí)用的應(yīng)用程序。
布局 
如果您曾嘗試創(chuàng)建能夠正常調(diào)整大小的窗體,您就會(huì)知道這一過程有多么困難。microsoft foundation classes (mfc) 或早期的 visual basic 版本沒有對(duì)這一功能提供內(nèi)置的支持。然而現(xiàn)在只需幾行代碼(通常情況下您甚至不需要編寫這些代碼,因?yàn)樵谠O(shè)計(jì)時(shí)就能通過 property browser 實(shí)現(xiàn)這些功能!),即可創(chuàng)建能夠正常調(diào)整大小的對(duì)話框。
基本布局由兩條組成:anchoring 和 docking。richcontrol 有一個(gè) anchor 屬性,它是一種枚舉類型,可以用“或”操作將這些值組合在一起,以說明控件將與其父控件的某一邊保持恒定距離。例如,如果您將一個(gè)按鈕置于窗體上,并將 anchor 屬性設(shè)置為 anchorstyles.bottomright,則在調(diào)整按鈕的大小時(shí),按鈕將與窗體的底邊和右邊保持同一距離。此外,如果將 anchor 設(shè)置為 anchorstyles.all,則按鈕的各個(gè)邊都與窗體的對(duì)應(yīng)邊保持同一距離,在調(diào)整按鈕大小時(shí)仍要滿足這些約束條件。
docking 實(shí)際上是 anchoring 的一個(gè)特殊情況。richcontrol 的 dock 屬性說明控件要將自身固定到其父控件的哪一邊。docking 可以是 top、left、right、bottom 或 fill。在每種情況下,控件都將移動(dòng)到盡量靠近指定邊,并調(diào)整其大小,以填滿那一邊。如果父控件的大小有所調(diào)整,這一狀況仍將保持。將一個(gè)控件移動(dòng)到父控件的底端,并將 anchor 設(shè)置為 anchorstyle.bottomleftright,可以模擬 docking bottom。在此處的示例中,列表框是 docked left,按鈕與窗體的頂端、左邊和右邊保持恒定距離,由此它們保持了相對(duì)位置和大小。下面的示例對(duì)話框(圖 2)完全使用 visual studio.net 中的 win forms 設(shè)計(jì)器創(chuàng)建,只花了兩分鐘的時(shí)間,沒有編寫一行代碼。
圖 2. 使用 win forms 設(shè)計(jì)器所創(chuàng)建的可調(diào)整大小的對(duì)話框
// 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è)計(jì)器所要求 
/// </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è)計(jì)器支持所要求
initializecomponent();
 }
/// <summary>
/// 釋放正在使用的所有資源
/// </summary>
public override void dispose() {
base.dispose();
components.dispose();
 }
/// <summary>
/// 應(yīng)用程序的主入口點(diǎn)。
/// </summary>
public static void main(string[] args) {
application.run(new resizablesample());
 }
/// <summary>
 /// 設(shè)計(jì)器支持所要求的方法 — 不要用編輯器
 /// 修改這一方法的內(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、筆刷、圖像和其它圖形對(duì)象與 .net framework 的其它部分一樣,遵循了簡(jiǎn)單易用的指導(dǎo)方針。開發(fā)人員目前可以使用相當(dāng)不錯(cuò)的一些繪圖新功能,如 alpha 混色、漸變色、紋理、消除鋸齒以及采用除位圖外的其它圖像格式。與 windows 2000 操作系統(tǒng)分層和透明的窗口功能配合使用,開發(fā)人員能夠毫不費(fèi)力地創(chuàng)建豐富的、更為圖形化的 win32 應(yīng)用程序。
如果觸發(fā)了控件的 onpaint 事件,能夠由 painteventargs 訪問的 system.drawing.graphics 對(duì)象就成為一個(gè) gdi+ 圖形對(duì)象。圖形對(duì)象能夠執(zhí)行的所有操作都通過 gdi+ 實(shí)施。作為一個(gè)示例,使用 gdi+ 創(chuàng)建一個(gè)繪制漸變背景的按鈕。
圖 3. 使用 gdi+ 創(chuàng)建的按鈕
以下是實(shí)現(xiàn)這一按鈕的代碼:
public class gradientbutton : button {
// 保留顏色設(shè)置的成員
private color startcolor;
private color endcolor;
 
// 書寫文字時(shí)我們將需要它
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;
// 縮小矩形,以免繪制時(shí)出界
clientrect.inflate(-1,-1);
// 創(chuàng)建漸變筆刷,從
// 左上角運(yùn)行到右下角。
brush backgroundbrush = new lineargradientbrush(
new point(clientrect.x,clientrect.y), 
new point(clientrect.width, clientrect.height), 
startcolor, 
endcolor);
// 以漸變色填充背景....
g.fillrectangle(backgroundbrush, clientrect);
// 在客戶機(jī)區(qū)域的中間書寫文字。
g.drawstring(this.text, 
this.font, 
new solidbrush(this.forecolor), 
clientrect, 
format);
 }
}
就像您所看到的,這并不是非常困難。得益于 win forms 和 gdi+ 面向?qū)ο蟮脑O(shè)計(jì),無需編寫任何復(fù)雜的代碼,即可實(shí)現(xiàn)我們的 gradientbutton,并且在設(shè)計(jì)器中,可以通過 property browser 操作 text、font、startcolor 和 endcolor。
訪問底層系統(tǒng) 
許多框架的一個(gè)缺點(diǎn)就是:如果人們編寫的應(yīng)用程序類型與示例和演示中的嚴(yán)格一致,則這些框架的效果相當(dāng)不錯(cuò),但有時(shí)開發(fā)人員發(fā)現(xiàn),一旦他們希望用框架進(jìn)行一些有創(chuàng)造性的工作,某些情況下就會(huì)碰到障礙或遭到失敗。如果遇到這一情況,win forms 框架自始至終都能夠允許開發(fā)人員訪問系統(tǒng)基礎(chǔ)結(jié)構(gòu)。當(dāng)然,希望 win forms 這樣一個(gè)設(shè)計(jì)優(yōu)良的框架不會(huì)使用戶遭遇這種情況,但可能發(fā)生的情況幾乎是無限的。所有的控件都有 handle 屬性,允許訪問控件的窗口句柄 (hwnd),gdi 對(duì)象也提供了類似的句柄訪問過程。而且,control 實(shí)際上擁有一個(gè)名為 wndproc 的受保護(hù)的虛擬方法,對(duì)于少數(shù) win forms 尚不能支持的消息,可以替代該方法,添加處理方式。
例如,假設(shè)您的應(yīng)用程序是資源密集型的,需要響應(yīng) wm_compacting。如果系統(tǒng)檢測(cè)到內(nèi)存不足,會(huì)向所有高層窗口廣播 wm_compacting,您就會(huì)知道 win forms 框架對(duì)這一消息沒有提供內(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) {
// 查看運(yùn)行時(shí)系統(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ù)行代碼,當(dāng)系統(tǒng)試著收集未用資源時(shí),利用新的 compactableform 類或由此派生的類即可得到通知,并作出響應(yīng)。
結(jié)論 
盡管在許多開發(fā)人員的計(jì)劃中,針對(duì) web 的開發(fā)是當(dāng)前工作的重點(diǎn),而定位于熟悉的 win32 平臺(tái)仍然是一個(gè)不得不面對(duì)的情況。有了 win forms,windows 開發(fā)人員無論是新手還是老手,都會(huì)發(fā)現(xiàn)使用豐富的接口創(chuàng)建復(fù)雜的應(yīng)用程序是一個(gè)很方便的過程,而這些接口與 .net framework 中具有 web 和數(shù)據(jù)功能的許多技術(shù)配合良好。
通過利用跨語言繼承、碎片收集和安全性等通用語言運(yùn)行時(shí)提高工作效率的優(yōu)秀功能,開發(fā)人員將從 .net framework 和 win forms 中獲益。