1. 程式人生 > 實用技巧 >使用c#自定義點陣圖按鈕

使用c#自定義點陣圖按鈕

介紹 自定義點陣圖控制元件背後的動機是允許為每個按鈕狀態顯示不同的點陣圖影象。這包括禁用、正常、滑鼠移動和按下按鈕。除了按鈕圖形之外,包含按鈕文字並控制文字對按鈕影象的對齊也是很重要的。它遵循XP風格的外觀和感覺,並有一些獨特的裝飾。 使用的程式碼 程式碼可以分為3個主要部分:資料、呈現和事件。 資料:私有變數儲存狀態和屬性設定。在大多數情況下,這段程式碼遵循屬性引用或更改成員變數值的實踐。每個屬性在下面的屬性表中進行了描述。渲染:按鈕的渲染通過幾種方法進行;然而,OnPaint方法是為按鈕渲染呼叫其他繪製方法的驅動程式。事件:覆蓋了許多方法來處理事件處理和管理按鈕的狀態。方法是OnMouseDown, OnMouseUp, OnMouseLeave, OnMouseMove, OnEnabledChanged, OnLostFocus。 當檢視原始碼時,可以很容易地找到這些節,因為#region關鍵字用於程式碼分離。 資料 首先,讓我們探討一下屬性。 Bitmap按鈕屬性 按鈕的背景色背景顏色bordercolor薄一個畫素寬度的顏色邊界周圍的按鈕字型字型用來渲染按鈕文字的文字字型顏色顏色imagealign指定影象的對齊imagebordercolor如果ImageBorderEnabled是真的,那麼這個屬性包含的顏色渲染後的影象邊界。此外,StretchImage屬性必須為假。imageborderenabled true如果渲染一個影象邊界,否則false imagedropshadow true,如果渲染一個陰影周圍的影象邊界,imagefocused影象用於渲染時,按鈕有焦點和在正常狀態,imageinactive影象時,按鈕禁用。注意,如果影象未定義,則使用正常影象的灰度版本來替代當滑鼠在按鈕上時使用的imagemouseover影象,但當按鈕處於其正常狀態時未按下imagenormal影象。注意,這個形象必須設定為影象按鈕imagepressed影象按鈕被按下時使用innerbordercolor內部邊界的顏色按鈕是在其正常狀態innerbordercolor_focus內部邊界的顏色當按鈕焦點innerbordercolor_mouseover內部邊界的顏色當滑鼠在按鈕offsetpressedcontent如果這是設定為true,按鈕被按下,按鈕的內容發生了變化。它儲存每個按鈕內容之間的畫素填充量。這是影象、文字和邊框之間的空間。如果為真,則指示將當前影象拉伸到按鈕上。文字將在按鈕textalignment定義了文字的對齊方式如果為真,文字會投射陰影 所有屬性都已新增到屬性頁中的appearance類別中。下面的圖片是他們的快照。 呈現 按鈕的呈現由OnPaint方法執行。這依次呼叫幾個例程來處理按鈕的呈現細節。 CreateRegion:建立一個透明的圓形按鈕控制paint_background邊緣:顯示按鈕的背景paint_text:呈現的文字和文字陰影paint_border:呈現1畫素與邊框按鈕paint_innerborder:呈現2畫素寬度內邊界paint_focusborder:呈現1畫素寬度衝焦點邊界內的按鈕 詳情請參閱下面的程式碼片段: 隱藏,複製Code

/// <summary>
/// This method paints the button in its entirety.
/// </summary>
/// <paramname="e">paint arguments use to paint the button</param>
protected override void OnPaint(PaintEventArgs e)
{				
	CreateRegion(0);			
	paint_Background(e);
	paint_Text(e);
	paint_Image(e);			
	paint_Border(e);
	paint_InnerBorder(e);
	paint_FocusBorder(e);
}

畫背景可能會很有趣。所採取的方法允許在多個顏色(意味著超過兩種顏色)之間進行梯度背景插值。首先,混合物件需要初始化一個顏色陣列,以及插值的位置。接下來,可以像往常一樣建立漸變筆刷。最後一步是將混合物件連線到畫筆。這是通過設定畫筆的內插顏色屬性來完成的。 下面是一個例子,插值多種顏色: 隱藏,收縮,複製Code

Color[] ColorArray = new Color[]{
   System.Drawing.Color.White,
   System.Drawing.Color.Yellow,
   System.Drawing.Color.Blue,
   System.Drawing.Color.Green,               
   System.Drawing.Color.Red,
   System.Drawing.Color.Black};				
float
[] PositionArray = new float[]{0.0f,.15f,.40f,.65f,.80f,1.0f}; // // create blend variable for the interpolate the colors // System.Drawing.Drawing2D.ColorBlend blend = new System.Drawing.Drawing2D.ColorBlend(); blend.Colors = ColorArray; blend.Positions = PositionArray; // // create vertical gradient brush // System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, this.BackColor,Blend(this.BackColor,this.BackColor,10), System.Drawing.Drawing2D.LinearGradientMode.Vertical); brush.InterpolationColors = blend; // // fill the rectangle // g.FillRectangle(brush, rect); // // release resources // brush.Dispose();

對於渲染文字,我使用System.Drawing。拉帶的方法。棘手的部分是決定在哪裡繪製文字。由於程式碼太多,所以將該功能放在helper函式中,以防止它干擾paint_Text方法。這個方法的一個有趣之處在於它實現了投影功能。這僅僅涉及到創造ing筆刷與阿爾法元件,並繪製文字照常。 隱藏,複製Code

//
// paint text shadow
//
if(TextDropShadow)
{
	System.Drawing.Brush TransparentBrush0
          = new System.Drawing.SolidBrush( System.Drawing.Color.FromArgb(50, 
                System.Drawing.Color.Black  ) ) ;
	System.Drawing.Brush TransparentBrush1
           = new System.Drawing.SolidBrush( System.Drawing.Color.FromArgb(20, 
                System.Drawing.Color.Black  ) ) ;

	e.Graphics.DrawString(this.Text,this.Font,
                                               TransparentBrush0,pt.X,pt.Y+1);
	e.Graphics.DrawString(this.Text,this.Font, 
                                               TransparentBrush0,pt.X+1,pt.Y);
			
	e.Graphics.DrawString(this.Text,this.Font, 
                                            TransparentBrush1,pt.X+1,pt.Y+1);	
	e.Graphics.DrawString(this.Text,this.Font, 
                                            TransparentBrush1,pt.X,pt.Y+2);	
	e.Graphics.DrawString(this.Text,this.Font, 
                                            TransparentBrush1,pt.X+2,pt.Y);	
	TransparentBrush0.Dispose();
	TransparentBrush1.Dispose();	
}

繪製圖像是一個相當直接的過程。但是,在使用下面的方法時,我確實遇到了一些困難。它在使用資源編輯器建立的點陣圖時工作正常,但不幸的是,在使用第三方繪製程式建立的24點陣圖像時失敗了。解決方法涉及呼叫一個不同的DrawImage方法。它可能會慢一些,但在我理解問題是什麼之前,它必須暫時起作用。 隱藏,複製Code

// FAILED
g.DrawImage(image,rect.Left,rect.Top)
// WORKAROUND
g.DrawImage(image,rect, 0, 0 ,image.Width,image.Height, GraphicsUnit.Pixel);

用插值的顏色畫邊界也不困難。你可以像以前一樣建立一個漸變筆刷。當建立pen物件時,漸變筆刷作為引數傳遞。下面的程式碼片段就是這個過程的一個示例。 隱藏,複製Code

....
//
// create brush and pens
//
System.Drawing.Drawing2D.LinearGradientBrush brush
            = new System.Drawing.Drawing2D.LinearGradientBrush(rect,  
                  this.BackColor,Blend(this.BackColor,this.BackColor,10), 
                  System.Drawing.Drawing2D.LinearGradientMode.Vertical);
brush.InterpolationColors = blend;
System.Drawing.Pen pen0 = new System.Drawing.Pen(brush,1);
//
// draw line 0
//
g.DrawLine(pen0 , point_0,point_1);
....

事件 對該影象的資料和繪製作了簡要描述。按鈕的下一個重要方面是輸入捕獲和處理。所採用的方法涉及覆蓋基按鈕類中的方法。這些方法然後通過屬性直接更改按鈕的狀態。一旦狀態被改變,它們就會使控制元件失效,從而讓OnPaint()機制重新整理影象。下面是事件方法的列表,以及它們的目的: 事件方法按鈕狀態onmousedown設定BtnState推和CapturingMouse真正onmouseup BtnState正常和CapturingMouse為false onmouseleave集合BtnState正常如果我們CapturingMouse = true onmousemove CapturingMouse = true和滑鼠座標內按鈕區域,設定BtnState推,否則設定BtnState正常。 如果CapturingMouse = false,則將BtnState設定為滑鼠懸停 onenabledchanged按鈕變為啟用或禁用。如果按鈕啟用,則設定BtnState為Normal,否則設定BtnState為inactive 下面的程式碼塊顯示了事件程式碼的示例。事件通常由小程式碼組成。我應該介紹的一個小資訊是控制元件的捕獲屬性。通過將此設定為true,當指標在按鈕區域之外時,按鈕不會丟失輸入焦點。這一點很重要,因為如果按住滑鼠按鈕並且使用者將滑鼠指標移進或移出按鈕區域,則按鈕的狀態需要相應地更改。如果沒有設定Capture屬性,則當指標離開按鈕區域時,控制元件將停止捕獲輸入事件。 隱藏,複製Code

/// <summary>
/// Mouse Down Event:
/// set BtnState to Pushed and Capturing mouse to true
/// </summary>
/// <paramname="e"></param>
protected override void OnMouseDown(MouseEventArgs e)
{
  base.OnMouseDown (e);
  this.Capture = true;
  this.CapturingMouse = true;
  btnState = BtnState.Pushed;			
  this.Invalidate();
}

包裝的事情了… 這是該控制元件的第一次具體化,整個原始碼都在一個名為BitmapButton.cs的檔案中。稍後,如果時間允許並且控制元件令人感興趣,原始碼可以使用介面來將功能的不同方面元件化,並增強可擴充套件性和可維護性。如果能包含主題並從XML源訪問它們就好了。影象的快取(雙緩衝)也是一個選項。我期待建議,並希望點陣圖控制元件滿足您的需要或提供一些想法,您的控制元件。 歷史 版本日期更改為1.0 02-27-2005控制元件的初始釋出 許可證 本文沒有附帶明確的許可,但可能包含文章文字或下載檔案本身的使用條款。如果有疑問,請通過下面的討論區聯絡作者。可以在這裡找到作者可能使用的許可證列表。 本文轉載於:http://www.diyabc.com/frontweb/news499.html