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

ASP.NET可交互式位圖窗體設(shè)計(jì)(3)

[摘要]構(gòu)造函數(shù)   構(gòu)造函數(shù)傳遞三個(gè)參數(shù):包含圓的中心坐標(biāo)的點(diǎn)、圓的半徑以及一個(gè) System.Drawing.Color 結(jié)構(gòu)(包含用于繪制圓輪廓的顏色)。   然后我們根據(jù)中心和半徑計(jì)算邊框,并將筆顏色項(xiàng)設(shè)置為我們傳遞的顏色對(duì)象。   繪圖代碼   Draw 方法重載實(shí)際上非常簡(jiǎn)單:它根...
 構(gòu)造函數(shù)
  構(gòu)造函數(shù)傳遞三個(gè)參數(shù):包含圓的中心坐標(biāo)的點(diǎn)、圓的半徑以及一個(gè) System.Drawing.Color 結(jié)構(gòu)(包含用于繪制圓輪廓的顏色)。 
  
  然后我們根據(jù)中心和半徑計(jì)算邊框,并將筆顏色項(xiàng)設(shè)置為我們傳遞的顏色對(duì)象。 
  
  繪圖代碼
  Draw 方法重載實(shí)際上非常簡(jiǎn)單:它根據(jù)我們保存在構(gòu)造函數(shù)中的顏色對(duì)象創(chuàng)建一個(gè)筆對(duì)象,然后使用該筆,調(diào)用 Graphics.DrawEllipse 方法繪制圓,同時(shí)傳遞了我們?cè)缦葎?chuàng)建的邊框。 
  
  圖形、筆和畫(huà)筆
  這里我們需要解釋一下 Graphics、Pen 和 Brush 對(duì)象。(在開(kāi)始填充我們的可填充對(duì)象時(shí),就會(huì)看到 Brush 對(duì)象。) 
  
  Graphics 對(duì)象代表一個(gè)與某個(gè)真實(shí)繪圖空間相關(guān)聯(lián)的虛擬化的繪圖空間。虛擬化是指,通過(guò)在 Graphics 對(duì)象上繪圖,我們可以使用相同的 Graphics 方法在與該對(duì)象相關(guān)聯(lián)的任何類型的實(shí)際表面上繪圖。對(duì)于那些習(xí)慣于使用 MFC 或 Microsoft Windows? SDK 編程的用戶,Graphics 對(duì)象相當(dāng)于 Windows 中稱為“設(shè)備上下文”(或 DC)的 .NET 版本。 
  
  在此 Windows 窗體應(yīng)用程序中,傳遞到 Draw 方法的 Graphics 對(duì)象將與屏幕上的一個(gè)窗口相關(guān)聯(lián) -- 這里是 PictureBox。在我們的 Microsoft ASP.NET 應(yīng)用程序中使用這一代碼時(shí),傳遞給 Draw 方法的 Graphics 對(duì)象將與一個(gè)位圖圖像相關(guān)聯(lián)。它也可以和打印機(jī)或其他設(shè)備相關(guān)聯(lián)。 
  
  這個(gè)方案的優(yōu)點(diǎn)是我們可以使用相同的繪圖代碼在不同的表面上繪圖。在我們的繪圖代碼中,我們不需要知道任何有關(guān)屏幕、位圖、打印機(jī)等等之間的不同 -- .NET Framework(以及底層的操作系統(tǒng))可以為我們處理所有細(xì)節(jié)。 
  
  利用相同的標(biāo)記,筆和畫(huà)筆成為虛擬化的繪圖工具。筆代表線條屬性 -- 顏色、寬度、樣式,甚至可以是用來(lái)繪制線的位圖。畫(huà)筆代表一個(gè)填充區(qū)域的屬性 -- 顏色、樣式,甚至可以是用來(lái)填充區(qū)域的位圖。 
  
  在使用 Using 后清除(或至少 Dispose)
  Graphics、Pen 和 Brush 對(duì)象都與相似類型的 Windows 對(duì)象相關(guān)聯(lián)。這些 Windows 對(duì)象分配在操作系統(tǒng)的內(nèi)存中 -- 這些內(nèi)存尚未被 .NET 運(yùn)行時(shí)管理。長(zhǎng)時(shí)間將這些對(duì)象駐留在內(nèi)存中會(huì)導(dǎo)致性能問(wèn)題,并且在 Microsoft Windows 98 下,當(dāng)圖形堆填滿時(shí)會(huì)導(dǎo)致繪圖問(wèn)題。因此,我們應(yīng)盡快釋放這些 Windows 對(duì)象。 
  
  當(dāng)相應(yīng)的 .NET Framework 對(duì)象完成操作并回收內(nèi)存后,.NET 運(yùn)行時(shí)會(huì)自動(dòng)釋放 Windows 對(duì)象。但回收內(nèi)存的時(shí)間會(huì)很長(zhǎng) -- 如果我們不迅速釋放這些對(duì)象,所有不幸的事情(包括填滿 Windows 堆)都可能發(fā)生。在該應(yīng)用程序的 ASP.NET 版本中,由于很多用戶在同一臺(tái)服務(wù)器上訪問(wèn)該應(yīng)用程序,所以這種現(xiàn)象會(huì)更加嚴(yán)重。 
  
  因?yàn)檫@些對(duì)象與未管理的資源相關(guān)聯(lián),所以它們實(shí)現(xiàn) IDisposable 接口。該接口有一個(gè)方法,即 Dispose,它將 .NET Framework 對(duì)象從 Windows 對(duì)象中分離出來(lái),并釋放 Windows 對(duì)象,從而使計(jì)算機(jī)處于良好的狀態(tài)。 
  
  這時(shí)您只需完成一項(xiàng)任務(wù):確保在使用完該對(duì)象后,調(diào)用 Dispose 方法。 
  
  Visual Basic .NET 代碼中顯示了這一內(nèi)容的經(jīng)典形式:首先創(chuàng)建對(duì)象,然后在一個(gè) Try 塊中使用該對(duì)象,最后在 Finally 塊中清理該對(duì)象。Try/Finally 能夠確保即使出現(xiàn)異常也會(huì)清理對(duì)象。(在本例中,我們調(diào)用的繪圖方法可能不會(huì)引發(fā)異常,所以可能并不需要 Try/Finally 塊。但掌握這些技巧很有用,因此 Dr. GUI 也希望向您演示這一正確方法。) 
  
  這種形式很常見(jiàn),因此 C# 為其提供了一個(gè)私有語(yǔ)句:using。C# 代碼中的 using 語(yǔ)句等同于 Visual Basic .NET 代碼中的聲明和 Try/Finally -- 但更為簡(jiǎn)潔、方便,并減少了發(fā)生錯(cuò)誤的可能性。(Dr. GUI 不清楚為什么 Visual Basic .NET 不包含一些諸如 using 的語(yǔ)句。) 
  
  接口
  有些(但不是全部)可繪制對(duì)象可以被填充。某些對(duì)象(如點(diǎn)和線)不能被填充,因?yàn)樗鼈儾皇欠忾]的區(qū)域,而矩形和圓等對(duì)象可以是中空的,或者被填充。 
  
  另一方面,就象將所有可繪制對(duì)象作為多態(tài)處理一樣,我們也可以將所有可填充對(duì)象作為多態(tài)處理,這會(huì)很方便。例如,如同我們將所有可繪制對(duì)象放到一個(gè)集合中,通過(guò)遍歷集合并在每個(gè)對(duì)象上調(diào)用 Draw 來(lái)繪制對(duì)象一樣,我們可以將所有可填充對(duì)象放到一個(gè)集合中,而不考慮這些可填充對(duì)象的實(shí)際類型。因此,我們使用某種機(jī)制(如繼承)來(lái)獲得真正的多態(tài)。
  因?yàn)椴皇撬械目衫L制對(duì)象都可以被填充,因此不能將 Fill 方法的聲明放在抽象基類中。.NET Framework 不允許類的多重繼承,所以也不能將其放在另一個(gè)抽象基類中。并且如果我們從不是非可填充類的其他基類中派生出可填充對(duì)象,則不能將所有可繪制對(duì)象作為多態(tài)處理。 
  
  但 .NET Framework 支持接口 -- 并提供了一個(gè)可實(shí)現(xiàn)任意數(shù)量的接口的類。接口不具有任何實(shí)現(xiàn) -- 沒(méi)有代碼,也沒(méi)有任何數(shù)據(jù)。因此,實(shí)現(xiàn)接口的類必須提供所有內(nèi)容。 
  
  接口所能包含的只有聲明。以下是我們?cè)?C# 中的接口 IFillable。單擊此處在新窗口中查看全部源文件。
  
  
  
    C#
  public interface IFillable {
  void Fill(Graphics g);
  Color FillBrushColor { get; set; }
  } 
   
  
  以下是等同的 Visual Basic .NET 代碼。單擊此處在新窗口中查看全部源文件。
  
    Visual Basic .NET
  
  Public Interface IFillable
  Sub Fill(ByVal g As Graphics)
  Property FillBrushColor() As Color
  End Interface 
  
  我們不需要聲明方法或者 virtual/Overridable 或 abstract/MustOverride 屬性以及任何其他項(xiàng),因?yàn)榻涌谥械乃蟹椒ê蛯傩远甲詣?dòng)設(shè)置為公開(kāi)的和 abstract/MustOverride。 
  
  使用一個(gè)屬性:不能在接口中包含數(shù)據(jù)
  請(qǐng)注意,雖然我們不能在接口中聲明字段,但可以聲明一個(gè)屬性,因?yàn)閷傩詫?shí)際上是作為方法實(shí)現(xiàn)的。 
  
  但這樣做會(huì)給接口的實(shí)現(xiàn)者帶來(lái)負(fù)擔(dān),下面就會(huì)看到。實(shí)現(xiàn)者必須實(shí)現(xiàn) get 和 set 方法,以及實(shí)現(xiàn)該屬性所必需的任何數(shù)據(jù)。如果實(shí)現(xiàn)非常復(fù)雜,則可以編寫(xiě)一個(gè) helper 類以封裝某些部分。在本文稍后我們將就一個(gè)略微不同的上下文環(huán)境顯示如何使用 helper 類。 
  
  實(shí)現(xiàn)接口
  我們已經(jīng)定義了接口,現(xiàn)在可以在類中實(shí)現(xiàn)它了。請(qǐng)注意,我們必須提供所實(shí)現(xiàn)接口的完整實(shí)現(xiàn):不能只從中選取一部分。 
  
  下面我們看看 C# 中 DFilledRectangle 類的代碼。
  
  
    C#
  public class DFilledCircle : DHollowCircle, IFillable
  {
  public DFilledCircle(Point center, int radius, Color penColor,
  Color brushColor) : base(center, radius, penColor) {
  this.brushColor = brushColor;
  }
  
  public void Fill(Graphics g) {
  using (Brush b = new SolidBrush(brushColor)) {
  g.FillEllipse(b, bounding);
  }
  }
  protected Color brushColor;
  public Color FillBrushColor {
  get {
  return brushColor;
  }
  set {
  brushColor = value;
  }
  }
  public override void Draw(Graphics g) {
  Fill(g);
  base.Draw(g);
  }
  } 
  
  以下是 Visual Basic .NET 中 DFilledRectangle 類的代碼。
  
  
    Visual Basic .NET
  Public Class DFilledRectangle
  Inherits DHollowRectangle
  Implements IFillable
  Public Sub New(ByVal rect As Rectangle, _
  ByVal penColor As Color, ByVal brushColor As Color)
  MyBase.New(rect, penColor)
  Me.brushColor = brushColor
  End Sub
  Public Sub Fill(ByVal g As Graphics) Implements IFillable.Fill
  Dim b = New SolidBrush(FillBrushColor)
  Try
  g.FillRectangle(b, bounding)
  Finally
  b.dispose()
  End Try
  End Sub
  Protected brushColor As Color
  Public Property FillBrushColor() As Color _
  Implements IFillable.FillBrushColor
  Get
  Return brushColor
  End Get
  Set(ByVal Value As Color)
  brushColor = Value
  End Set
  End Property
  Public Overrides Sub Draw(ByVal g As Graphics)
  Dim p = New Pen(penColor)
  Try
  Fill(g)
  MyBase.Draw(g)
  Finally
  p.Dispose()
  End Try
  End Sub
  End Class 
   
  
  以下是有關(guān)這些類的注意事項(xiàng)。 
  
  從 HollowRectangle 中派生
  我們從這個(gè)類的空心版本中派生出填充類。這個(gè)類中的多數(shù)內(nèi)容都發(fā)生了改變:Draw 方法和構(gòu)造函數(shù)都是新的(但兩者都調(diào)用基類的版本),并且為 IFillable 接口的 Fill 方法以及 FillBrushColor 屬性添加了實(shí)現(xiàn)。 
  
  需要新構(gòu)造函數(shù)的原因是我們?cè)谶@個(gè)類中包含了需要初始化的其他數(shù)據(jù),即填充畫(huà)筆。(您可以回顧我們前面討論的畫(huà)筆。)請(qǐng)注意此構(gòu)造函數(shù)是如何調(diào)用基類構(gòu)造函數(shù)的:在 C# 中,該調(diào)用被內(nèi)置到聲明 (: base(center, radius, penColor)) 中;在 Visual Basic .NET 中,我們將它明確放在 New 方法(即構(gòu)造函數(shù))的第一行 (MyBase.New(rect, penColor))。 
  
  因?yàn)槲覀円呀?jīng)向基類構(gòu)造函數(shù)中傳遞了三個(gè)參數(shù)中的兩個(gè),現(xiàn)在只需初始化最后的字段即可。