呈現 Windows Form 控制項

轉譯是指在使用者畫面上建立視覺標記法的程式。 Windows Forms 使用 GDI (新的 Windows 圖形庫) 進行轉譯。 提供 GDI 存取權的 System.Drawing Managed 類別位於 命名空間及其子名稱空間中。

下列元素涉及控制項轉譯:

  • 基類 System.Windows.Forms.Control 所提供的繪圖功能。

  • GDI 圖形庫的基本元素。

  • 繪圖區域的幾何。

  • 釋放圖形資源的程式。

控制項提供的繪圖功能

基類 Control 會透過其 Paint 事件提供繪圖功能。 每當控制項需要更新其顯示時, Paint 就會引發 事件。 如需 .NET Framework 中事件的詳細資訊,請參閱 處理和引發事件

事件的事件 PaintEventArgs 資料類別 Paint 會保存繪製控制項所需的資料— 繪圖物件的控制碼,以及代表要繪製之區域的矩形物件。 這些物件會在下列程式碼片段中以粗體顯示。

Public Class PaintEventArgs  
   Inherits EventArgs  
   Implements IDisposable  
  
   Public ReadOnly Property ClipRectangle() As System.Drawing.Rectangle  
      ...  
   End Property  
  
   Public ReadOnly Property Graphics() As System.Drawing.Graphics  
      ...  
   End Property  
   ' Other properties and methods.  
   ...  
End Class  
public class PaintEventArgs : EventArgs, IDisposable {  
public System.Drawing.Rectangle ClipRectangle {get;}  
public System.Drawing.Graphics Graphics {get;}  
// Other properties and methods.  
...  
}  

Graphics 是封裝繪圖功能的 Managed 類別,如本主題稍後的 GDI 討論中所述。 ClipRectangle是 結構的實例, Rectangle 並定義控制項可以繪製的可用區域。 控制項開發人員可以使用 控制項的 屬性來計算 ClipRectangleClipRectangle ,如本主題稍後的 geometry 討論中所述。

控制項必須覆寫繼承自 Control 的方法, OnPaint 以提供轉譯邏輯。 OnPaint 會取得繪圖物件的存取權,以及要透過 Graphics 傳遞至繪圖物件的 實例屬性來 ClipRectangle 繪製的 PaintEventArgs 矩形。

Protected Overridable Sub OnPaint(pe As PaintEventArgs)  
protected virtual void OnPaint(PaintEventArgs pe);  

OnPaintControl 類的 方法不會實作任何繪圖功能,而只會叫用向 Paint 事件註冊的事件委派。 當您覆寫 OnPaint 時,通常應該叫 OnPaint 用基類的 方法,讓已註冊的委派接收 Paint 事件。 不過,繪製其整個介面的控制項不應該叫用基類 的 OnPaint ,因為這樣會引入閃爍。 如需覆寫 OnPaint 事件的範例,請參閱 如何:建立顯示進度 的 Windows Forms 控制項。

注意

請勿直接從控制項叫 OnPaint 用 ;相反地,請叫 Invalidate 用 方法(繼承自 Control )或其他叫用 的方法 Invalidate 。 方法 Invalidate 接著會叫用 OnPaint 。 方法 Invalidate 會多載,而且,根據提供給 Invalidatee 的引數,控制項會重繪其部分或所有螢幕區域。

Control 類會定義另一個對繪圖很有用的方法, 方法 OnPaintBackground

Protected Overridable Sub OnPaintBackground(pevent As PaintEventArgs)  
protected virtual void OnPaintBackground(PaintEventArgs pevent);  

OnPaintBackground 繪製視窗的背景(並因此圖形),並保證快速,同時 OnPaint 繪製詳細資料,而且可能較慢,因為個別繪製要求會合並成一個 Paint 事件,其中涵蓋必須重新繪製的所有區域。 例如,您可能想要叫 OnPaintBackground 用 控制項的漸層色彩背景。

雖然 OnPaintBackground 具有類似事件的命名法,而且採用與 OnPaint 方法相同的引數, OnPaintBackground 但不是真正的事件方法。 沒有 PaintBackground 事件, OnPaintBackground 而且不會叫用事件委派。 覆 OnPaintBackground 寫 方法時,不需要衍生類別叫 OnPaintBackground 用其基類的 方法。

GDI+ 基本概念

類別 Graphics 提供繪製各種圖案的方法,例如圓形、三角形、弧線和省略號,以及顯示文字的方法。 System.Drawing命名空間及其子空間包含類別,這些類別會封裝圖形元素,例如圖形(圓形、矩形、弧線和其他)、色彩、字型、筆刷等等。 如需 GDI 的詳細資訊,請參閱 使用 Managed Graphics 類別 。 GDI 的基本概念也會在如何:建立顯示進度 的 Windows Forms 控制項中 說明。

繪圖區域的幾何

控制項 ClientRectangle 的 屬性會指定使用者畫面上控制項可用的矩形區域,而 ClipRectanglePaintEventArgs 屬性則指定實際繪製的區域。 (請記住,繪製是在採用 PaintEventArgs 實例作為引數的事件方法中 Paint 完成的。 控制項可能需要只繪製其可用區域的一部分,就像控制項的顯示社區段變更時的情況一樣。 在這些情況下,控制項開發人員必須計算實際矩形來繪製,並將該矩形傳遞至 Invalidate 。 採用 或 Region 做為引數的多 Rectangle 載版本 Invalidate 會使用該引數來產生 ClipRectanglePaintEventArgs 屬性。

下列程式碼片段顯示自訂控制項如何 FlashTrackBar 計算要繪製的矩形區域。 變數 client 表示 ClipRectangle 屬性。 如需完整的範例,請參閱 如何:建立顯示進度 的 Windows Forms 控制項。

Rectangle invalid = new Rectangle(
    client.X + min,
    client.Y,
    max - min,
    client.Height);

Invalidate(invalid);
Dim invalid As Rectangle = New Rectangle( _
    client.X + lmin, _
    client.Y, _
    lmax - lmin, _
    client.Height)

Invalidate(invalid)

釋放圖形資源

繪圖物件很昂貴,因為它們使用系統資源。 這類物件包括 類別的 System.Drawing.Graphics 實例,以及 、 System.Drawing.Pen 和其他圖形類別的實例 System.Drawing.Brush 。 請務必只在需要圖形資源時建立圖形資源,並在使用完畢後立即釋放它。 如果您建立實作 IDisposable 介面的類型,請在完成時呼叫其 Dispose 方法,以釋放資源。

下列程式碼片段顯示自訂控制項如何 FlashTrackBar 建立及釋放 Brush 資源。 如需完整的原始程式碼,請參閱 如何:建立顯示進度 的 Windows Forms 控制項。

private Brush baseBackground = null;
Private baseBackground As Brush
base.OnPaint(e);
if (baseBackground == null) {
    if (showGradient) {
        baseBackground = new LinearGradientBrush(new Point(0, 0),
                                                 new Point(ClientSize.Width, 0),
                                                 StartColor,
                                                 EndColor);
    }
    else if (BackgroundImage != null) {
        baseBackground = new TextureBrush(BackgroundImage);
    }
    else {
        baseBackground = new SolidBrush(BackColor);
    }
}
MyBase.OnPaint(e)

If (baseBackground Is Nothing) Then

    If (myShowGradient) Then
        baseBackground = New LinearGradientBrush(New Point(0, 0), _
                                                 New Point(ClientSize.Width, 0), _
                                                 StartColor, _
                                                 EndColor)
    ElseIf (BackgroundImage IsNot Nothing) Then
        baseBackground = New TextureBrush(BackgroundImage)
    Else
        baseBackground = New SolidBrush(BackColor)
    End If

End If
protected override void OnResize(EventArgs e) {
    base.OnResize(e);
    if (baseBackground != null) {
        baseBackground.Dispose();
        baseBackground = null;
    }
}
Protected Overrides Sub OnResize(ByVal e As EventArgs)
    MyBase.OnResize(e)
    If (baseBackground IsNot Nothing) Then
        baseBackground.Dispose()
        baseBackground = Nothing
    End If
End Sub

另請參閱