中國最大的web開發資源網站及技術社區,
我們先來看看issuevision中一個用戶控件panecaption在可視化設計器中的屬性窗口.
 再看一下在另一個用戶控件staffpane中使用它時的屬性窗口:
 大家會發現它多出來很多個屬性,這些屬性是原來繼承控件中沒有的屬性,如:inactivetextcolor,inactivetextcolor等等.它們是如何實現的呢?我們就來看一下這個用戶控件的代碼panecaption.cs吧.
namespace issuevision
{
 // custom control that draws the caption for each pane. contains an active 
 // state and draws the caption different for each state. caption is drawn
 // with a gradient fill and antialias font.
 public class panecaption : usercontrol
 {
 private class consts
 {
 ......
 可以看到它是由 system.windows.forms.usercontrol 繼承而來,圖一顯示了它的默認屬性.下面我們接著panecaption.cs代碼,看看是如何將屬性或事件顯示在可視化設計器中.
 [defaultvalueattribute(typeof(color), "3, 55, 145")]
 [descriptionattribute("low color of the inactive gradient.")]
 [categoryattribute("appearance")]
 public color inactivegradientlowcolor
 {
 get
 {
 return m_colorinactivelow;
 }
 set
 {
 if (value == color.empty)
 {
 value = color.fromargb(3, 55, 145);
 }
 m_colorinactivelow = value;
 creategradientbrushes(); //自定義方法,用于創建線形漸變筆刷
 invalidate(); //control.invalidate 方法,使控件的特定區域無效并向控件發送繪制消息
 }
 }
 [categoryattribute("appearance")]
 [descriptionattribute("high color of the inactive gradient.")]
 [defaultvalueattribute(typeof(color), "90, 135, 215")]
 public color inactivegradienthighcolor
 {
 get
 {
 return m_colorinactivehigh;
 }
 set
 {
 if (value == color.empty)
 {
 value = color.fromargb(90, 135, 215);
 }
 m_colorinactivehigh = value;
 creategradientbrushes();
 invalidate();
 }
 }
 [descriptionattribute("text displayed in the caption.")]
 [defaultvalueattribute("")]
 [categoryattribute("appearance")]
 public string caption
 {
 get
 {
 return m_text;
 }
 set
 {
 m_text = value;
 invalidate();
 }
 }
 其結果如下圖所示:
 我們可以看到views,staff list背景都是使用這個自定義的panecaption產生漸變效果(由inactivegradienthighcolor和inactivegradientlowcolor屬性實現),文字views和staff list是由屬性caption實現.
--------------------------------------------------------------------------------
 代碼分析:
 最重要的是 categoryattribute 類,它指定屬性或事件將顯示在可視化設計器中的哪個類別,具體類別如下表:
 類別
 說明
 
 action 關于可用操作的屬性。 
 appearance 影響實體外觀的屬性。 
 behavior 影響實體行為的屬性。 
 data 關于數據的屬性。 
 format 影響格式的屬性。 
 layout 關于布局的屬性。 
 default 沒有類別的屬性屬于默認類別。 
有關更多信息,請參閱.net framework 1.1 sdk 
 我們看到舉例的這三個屬性categoryattribute屬性值都為categoryattribute("appearance"),從圖二可以看出,這些屬性都顯示在"外觀"下.
 defaultvalueattribute 屬性顧名思義,就是此自定義屬性的默認值.
 descriptionattribute 屬性則為此自定義屬性的描述.
 關鍵部分已經設置完成,剩下的就是如何實現屬性的效果了,我以代碼說明:
 protected override void onpaint(painteventargs e)
 {
 drawcaption(e.graphics);
 base.onpaint(e);
 }
 // draw the caption
 private void drawcaption(graphics g)
 {
 // background
 g.fillrectangle(this.backbrush, this.displayrectangle);
 
 if (m_antialias)
 g.textrenderinghint = system.drawing.text.textrenderinghint.antialias;
 
 // need a rectangle when want to use ellipsis
 rectanglef bounds = new rectanglef(consts.posoffset, 
 0,
 this.displayrectangle.width - consts.posoffset, 
 this.displayrectangle.height);
 g.drawstring(m_text, this.font, this.textbrush, bounds, m_format);
 }
 使用graphics.drawstring 繪制出caption(即文字views和staff list),graphics.fillrectangle 繪制漸變背景.注意此graphics.fillrectangle 方法的第一個參數為筆刷,此筆刷就為上面自定義屬性代碼中creategradientbrushes() 方法所創建的筆刷.代碼如下:
 private void creategradientbrushes()
 {
 // can only create brushes when have a width and height
 if (width > 0 && height > 0)
 {
 if (m_brushactive != null)
 {
 m_brushactive.dispose();
 }
 // 其中 m_coloractivehigh 值就為自定義屬性inactivegradienthighcolor的值,m_coloractivelow則為自定義屬性inactivegradientlowcolor的值.
 m_brushactive = new lineargradientbrush(displayrectangle, m_coloractivehigh, m_coloractivelow, lineargradientmode.vertical);
 
 if (m_brushinactive != null)
 {
 m_brushinactive.dispose();
 }
 
 m_brushinactive = new lineargradientbrush(displayrectangle, m_colorinactivehigh, m_colorinactivelow, lineargradientmode.vertical);
 }
 }
// gradient brush for the background
 private lineargradientbrush backbrush
 {
 get
 {
 if (m_active && m_allowactive)
 return m_brushactive;
 else
 return m_brushinactive;
 }
 }
 補充一點:根據gdi+要求,所有圖形的繪制都通過onpaint()方法繪制,只用重載此方法,就可以重新繪制所需的圖形了.(此方法就如java中的paintcomponet()方法一樣)
 這次就寫這么多了,希望大家多多交流,這也只是我一個人的認識,還要多和大家交流才會有提高.