余小章 @ 大內聖殿
祕訣無它, 唯勤而已, by 余小章

导航

 

上篇 [C#.NET][Winform] 製作不同顏色相間隔的 ListBox 在Winform裡已經實作了DrawItem事件,我們可以再進一步將這個功能打包成屬於自己的控制項

首先開啟Control Library專案

image

 

繼承ListBox

image

加入要重繪的屬性,並加入適當的 Attribute,在這裡主要是處理屬性的預設值

private Color _RowColor1 = Color.CornflowerBlue;
/// <summary>
/// 第一列的顏色
/// </summary>
[DefaultValue(typeof(Color), "CornflowerBlue")]
[Browsable(true), Category("重繪設定"), Description("第一列的顏色")]
public Color RowColor1
{
    get { return _RowColor1; }
    set { _RowColor1 = value; }
}

private Color _RowColor2 = Color.PaleGreen;
/// <summary>
/// 第二列的顏色
/// </summary>
[DefaultValue(typeof(Color), "PaleGreen")]
[Browsable(true), Category("重繪設定"), Description("第二列的顏色")]
public Color RowColor2
{
    get { return _RowColor2; }
    set { _RowColor2 = value; }
}

private Color _RowGradualColor1 = Color.Thistle;
/// <summary>
/// 第一列的漸層色
/// </summary>
[DefaultValue(typeof(Color), "Thistle")]
[Browsable(true), Category("重繪設定"), Description("第一列的漸層色")]
public Color RowGradualColor1
{
    get { return _RowGradualColor1; }
    set { _RowGradualColor1 = value; }
}

private Color _RowGradualColor2 = Color.DarkKhaki;
/// <summary>
/// 第二列的漸層色
/// </summary>
[DefaultValue(typeof(Color), "DarkKhaki")]
[Browsable(true), Category("重繪設定"), Description("第二列的漸層色")]
public Color RowGradualColor2
{
    get { return _RowGradualColor2; }
    set { _RowGradualColor2 = value; }
}

private Color _SelectRowColor = Color.White;
[DefaultValue(typeof(Color), "White")]
[Browsable(true), Category("重繪設定"), Description("選擇列的顏色")]
public Color SelectRowColor
{
    get { return _SelectRowColor; }
    set { _SelectRowColor = value; }
}

private bool _IsGradualColor = true;
/// <summary>
/// 是否使用漸層色
/// </summary>
[Browsable(true), Category("重繪設定"), Description("是否使用漸層色")]
[DefaultValue(true)]
public bool IsGradualColor
{
    get { return _IsGradualColor; }
    set { _IsGradualColor = value; this.Invalidate(); }
}

static string[] testData = new string[] { "1", "2", "gy", "余小章" };
private bool _IsUseDefauleData = false;
[DefaultValue(false)]
[Browsable(true), Category("重繪設定"), Description("是否使用預設資料")]
public bool IsUseDefauleData
{
    get
    {
        if (_IsUseDefauleData)
            this.DataSource = testData;
        else
            this.DataSource = null;
        return _IsUseDefauleData;
    }
    set
    {
        _IsUseDefauleData = value;
        if (value)
            this.DataSource = testData;
        else
            this.DataSource = null;
    }
}

因為我在Library裡有使用DataSource、Items兩個屬性,所以會讓VS自動產生出程式碼,會導致一些錯誤發生

image

所以我用[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]重新定義這兩個屬性,不讓VS自動產生程式碼

[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new object DataSource
{
    get { return base.DataSource; }
    set { base.DataSource = value; }
}

[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new ListBox.ObjectCollection Items
{
    get { return base.Items; }
}

我想要變更預設值所以再重新定義

[Browsable(true)]
[DefaultValue(typeof(DrawMode), "OwnerDrawFixed")]
public new DrawMode DrawMode
{
    get { return base.DrawMode; }
    set { base.DrawMode = value; }
}

在建構子裡設定DrawMode 屬性以及註冊DrawItem事件

public ListBoxControl()
{
    InitializeComponent();
    this.DrawMode = DrawMode.OwnerDrawFixed;
    this.DrawItem += new DrawItemEventHandler(ListBoxControl_DrawItem);
}
void ListBoxControl_DrawItem(object sender, DrawItemEventArgs e)
{
    ListBox list = (ListBox)sender;
    if (list.Items.Count <= 0)
        return;

    //定義框的大小
    Rectangle rec = new Rectangle(0, 0, list.Width, list.Height);

    //定義一般筆刷
    SolidBrush brushRow1 = new SolidBrush(this.RowColor1);
    SolidBrush brushRow2 = new SolidBrush(this.RowColor2);

    //定義漸層筆刷
    LinearGradientBrush linBrushRow1 = new LinearGradientBrush(rec, this.RowColor1, this.RowGradualColor1, LinearGradientMode.BackwardDiagonal);
    LinearGradientBrush linBrushRow2 = new LinearGradientBrush(rec, this.RowColor2, this.RowGradualColor2, LinearGradientMode.BackwardDiagonal);

    //選筆刷
    Brush brush;
    if (this.IsGradualColor)
    {
        if (e.Index % 2 == 0)
            brush = linBrushRow1;
        else
            brush = linBrushRow2;
    }
    else
    {
        if (e.Index % 2 == 0)
            brush = brushRow1;
        else
            brush = brushRow2;
    }
    //畫框
    e.Graphics.FillRectangle(brush, e.Bounds);
    bool selected = ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ? true : false;
    if (selected)
    {
        e.Graphics.FillRectangle(new SolidBrush(this.SelectRowColor), e.Bounds);
    }
    //畫字
    e.Graphics.DrawString(list.Items[e.Index].ToString(), this.Font, Brushes.Black, e.Bounds);
    //畫焦點框
    e.DrawFocusRectangle();
}
這樣一來我們所開發的控制項已經完成了,接下來就測試這控制項的效果,在原本方案裡再新增一個Winform的Demo專案,按下Shift+Ctrl+B建置方案
image

 

在Demo專案裡,便可以看到我們所開發的控制項,把它拖拉到Winform裡,便可以使用了

image


後記:DrawListBoxControl.zip

開發控制項要注意的觸發事件非常的多,跟我們寫一般的程式有差益,要注意控制項第一次匯製時VS所產生的程式碼,有沒有錯誤,這牽扯到控制項的生命週期,這必須要多做一些測試,可以先把會產生錯誤的部份隱藏起來。

 

posted on 2011-12-27 15:25  余小章  阅读(836)  评论(0编辑  收藏  举报