呈現 Windows Form 控制項Rendering a Windows Forms Control

呈現是指在使用者畫面上建立視覺表示的程式。Rendering refers to the process of creating a visual representation on a user's screen. Windows Forms 使用 GDI (新的 Windows 圖形程式庫) 來呈現。Windows Forms uses GDI (the new Windows graphics library) for rendering. 提供 GDI 存取的 managed 類別位於System.Drawing命名空間及其子命名空間中。The managed classes that provide access to GDI are in the System.Drawing namespace and its subnamespaces.

控制項呈現包含下列元素:The following elements are involved in control rendering:

  • 基類所提供的繪製功能System.Windows.Forms.ControlThe drawing functionality provided by the base class System.Windows.Forms.Control.

  • GDI 圖形程式庫的基本元素。The essential elements of the GDI graphics library.

  • 繪製區域的幾何。The geometry of the drawing region.

  • 釋放圖形資源的程式。The procedure for freeing graphics resources.

控制項所提供的繪圖功能Drawing Functionality Provided by Control

基類Control透過其Paint事件提供繪圖功能。The base class Control provides drawing functionality through its Paint event. 每當控制項需要更新Paint其顯示時, 就會引發事件。A control raises the Paint event whenever it needs to update its display. 如需 .NET Framework 中事件的詳細資訊, 請參閱處理和引發事件For more information about events in the .NET Framework, see Handling and Raising Events.

Paint事件的事件資料類別會保存繪製控制項所需的資料, 也就是繪圖物件的控制碼, 以及代表要在其中繪製之區域的矩形物件。 PaintEventArgsThe event data class for the Paint event, PaintEventArgs, holds the data needed for drawing a control — a handle to a graphics object and a rectangle object that represents the region to draw in. 這些物件會在下列程式碼片段中以粗體顯示。These objects are shown in bold in the following code fragment.

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 討論中所述。Graphics is a managed class that encapsulates drawing functionality, as described in the discussion of GDI later in this topic. ClipRectangleRectangle結構的實例, 會定義可在其中繪製控制項的可用區域。The ClipRectangle is an instance of the Rectangle structure and defines the available area in which a control can draw. 控制項開發人員可以ClipRectangle使用控制項的ClipRectangle屬性來計算, 如本主題稍後的 geometry 討論中所述。A control developer can compute the ClipRectangle using the ClipRectangle property of a control, as described in the discussion of geometry later in this topic.

控制項必須藉由覆寫其繼承自OnPaint Control的方法來提供轉譯邏輯。A control must provide rendering logic by overriding the OnPaint method that it inherits from Control. OnPaint取得繪圖物件的Graphics ClipRectangle存取權, 以及透過傳遞給它之PaintEventArgs實例的屬性, 在中繪製的矩形。OnPaint gets access to a graphics object and a rectangle to draw in through the Graphics and the ClipRectangle properties of the PaintEventArgs instance passed to it.

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

基類OnPaint Paint的方法不會執行任何繪製功能, 而只會叫用向事件註冊的事件委派。 ControlThe OnPaint method of the base Control class does not implement any drawing functionality but merely invokes the event delegates that are registered with the Paint event. 當您覆OnPaint寫時, 通常OnPaint應該叫用基類的方法, 讓註冊Paint的委派接收事件。When you override OnPaint, you should typically invoke the OnPaint method of the base class so that registered delegates receive the Paint event. 不過, 繪製其整個介面的控制項不應叫用基類的OnPaint, 因為這會引進閃爍。However, controls that paint their entire surface should not invoke the base class's OnPaint, as this introduces flicker. 如需覆寫OnPaint事件的範例, 請參閱如何:建立顯示進度的 Windows Forms 控制項。For an example of overriding the OnPaint event, see the How to: Create a Windows Forms Control That Shows Progress.

注意

請勿直接從控制項叫用, 而是叫用方法Invalidate (繼承自Control) 或其他叫用的方法InvalidateOnPaintDo not invoke OnPaint directly from your control; instead, invoke the Invalidate method (inherited from Control) or some other method that invokes Invalidate. 方法接著會叫用。 OnPaint InvalidateThe Invalidate method in turn invokes OnPaint. 方法會多載, 而根據提供給Invalidate e的引數, 控制項會重新繪製其部分或全部的螢幕區域。 InvalidateThe Invalidate method is overloaded, and, depending on the arguments supplied to Invalidate e, a control redraws either some or all of its screen area.

基類Control會定義另一個適用于繪製的OnPaintBackground方法, 也就是方法。The base Control class defines another method that is useful for drawing — the OnPaintBackground method.

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

OnPaintBackground繪製視窗的背景 (也就是圖形), 並保證快速, 同時OnPaint繪製詳細資料, 而且可能會變慢, 因為個別的繪製要求會合並成一個Paint事件, 其中涵蓋了必須是的所有區域支取.OnPaintBackground paints the background (and thereby the shape) of the window and is guaranteed to be fast, while OnPaint paints the details and might be slower because individual paint requests are combined into one Paint event that covers all areas that have to be redrawn. 比方說, OnPaintBackground如果您想要繪製控制項的漸層色彩背景, 您可能會想要叫用。You might want to invoke the OnPaintBackground if, for instance, you want to draw a gradient-colored background for your control.

雖然OnPaintBackground具有類似事件的命名法, 並採用與OnPaint方法相同的引數OnPaintBackground , 但並不是真正的事件方法。While OnPaintBackground has an event-like nomenclature and takes the same argument as the OnPaint method, OnPaintBackground is not a true event method. 沒有事件, 也OnPaintBackground不會叫用事件委派。 PaintBackgroundThere is no PaintBackground event and OnPaintBackground does not invoke event delegates. 覆寫OnPaintBackground方法時, 不需要衍生類別來叫用其基類OnPaintBackground的方法。When overriding the OnPaintBackground method, a derived class is not required to invoke the OnPaintBackground method of its base class.

GDI + 基本概念GDI+ Basics

Graphics類別提供繪製各種形狀 (例如圓形、三角形、弧形和橢圓形) 的方法, 以及用來顯示文字的方法。The Graphics class provides methods for drawing various shapes such as circles, triangles, arcs, and ellipses, as well as methods for displaying text. System.Drawing命名空間及其子命名空間包含封裝圖形專案 (例如圓形、矩形、弧形等等)、色彩、字型、筆刷等的類別。The System.Drawing namespace and its subnamespaces contain classes that encapsulate graphics elements such as shapes (circles, rectangles, arcs, and others), colors, fonts, brushes, and so on. 如需 GDI 的詳細資訊, 請參閱使用 Managed 圖形類別For more information about GDI, see Using Managed Graphics Classes. GDI 的基本知識也會在如何:建立顯示進度的 Windows Forms 控制項。The essentials of GDI are also described in the How to: Create a Windows Forms Control That Shows Progress.

繪圖區域的幾何Geometry of the Drawing Region

控制項ClientRectangle的屬性會指定使用者畫面上控制項可用的矩形區域, ClipRectangle而的屬性PaintEventArgs則會指定實際繪製的區域。The ClientRectangle property of a control specifies the rectangular region available to the control on the user's screen, while the ClipRectangle property of PaintEventArgs specifies the area that is actually painted. (請記住, 繪製作業會在Paint PaintEventArgs接受實例做為其引數的事件方法中完成)。(Remember that painting is done in the Paint event method that takes a PaintEventArgs instance as its argument). 控制項可能只需要繪製其可用區域的一部分, 如同控制項的小部分顯示變更的情況。A control might need to paint only a portion of its available area, as is the case when a small section of the control's display changes. 在這些情況下, 控制項開發人員必須計算要在其中繪製的實際矩形, 並Invalidate將其傳遞給。In those situations, a control developer must compute the actual rectangle to draw in and pass that to Invalidate. Invalidate ClipRectangle PaintEventArgs採用或做Region為引數的多載版本, 會使用該引數來產生的屬性。 RectangleThe overloaded versions of Invalidate that take a Rectangle or Region as an argument use that argument to generate the ClipRectangle property of PaintEventArgs.

下列程式碼片段顯示FlashTrackBar自訂控制項如何計算要在中繪製的矩形區域。The following code fragment shows how the FlashTrackBar custom control computes the rectangular area to draw in. client 變數ClipRectangle代表屬性。The client variable denotes the ClipRectangle property. 如需完整範例, 請參閱如何:建立顯示進度的 Windows Forms 控制項。For a complete sample, see How to: Create a Windows Forms Control That Shows Progress.

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)

釋放圖形資源Freeing Graphics Resources

繪圖物件的成本很高, 因為它們使用系統資源。Graphics objects are expensive because they use system resources. 這類物件包含System.Drawing.Graphics類別的實例System.Drawing.Brush, 以及、 System.Drawing.Pen和其他圖形類別的實例。Such objects include instances of the System.Drawing.Graphics class as well as instances of System.Drawing.Brush, System.Drawing.Pen, and other graphics classes. 只有在需要時才建立圖形資源, 並在您完成使用它之後立即發行, 這點很重要。It is important that you create a graphics resource only when you need it and release it soon as you are finished using it. 如果您建立的型IDisposable別會執行介面, 請在完成時Dispose呼叫它的方法, 以便釋放資源。If you create a type that implements the IDisposable interface, call its Dispose method when you are finished with it in order to free resources.

下列程式碼片段顯示FlashTrackBar自訂控制項如何建立和Brush釋放資源。The following code fragment shows how the FlashTrackBar custom control creates and releases a Brush resource. 如需完整的原始程式碼, 請參閱如何:建立顯示進度的 Windows Forms 控制項。For the complete source code, see How to: Create a Windows Forms Control That Shows Progress.

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

另請參閱See also