星期二, 8月 25, 2015

[C#] PictureBox - 區段顏色

論壇問題,簡化成在動態產生 PicutrBox 並根據資料在 Paint Event 內畫出各區段顏色

專案內容
[C#] PictureBox - 區段顏色-2

WinForm Layout:只放一個 FlowLayoutPanel 容器

[C#] PictureBox - 區段顏色-1


SectionColor Class
using System.Drawing;

namespace MachStauts
{
    /// <summary>
    /// 設備區段資訊
    /// </summary>
    public class SectionColor
    {
        /// <summary>
        /// 區段號碼
        /// </summary>
        public int SectNO { get; set; }
        /// <summary>
        /// 區段繪圖 X 軸起始位置
        /// </summary>
        public int SectStart { get; set; }
        /// <summary>
        /// 區段寬度
        /// </summary>
        public int SectWidth { get; set; }
        /// <summary>
        /// 區段顏色
        /// </summary>
        public Color SectColor { get; set; }
    }
}
C# WinForm Code
namespace MachStauts
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DrawStatus(GetDataSource());
        }

        private DataTable GetDataSource()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("MachNO", typeof(string));
            dt.Columns.Add("Col1", typeof(string));
            dt.Columns.Add("Col2", typeof(string));
            dt.Columns.Add("Col3", typeof(string));
            dt.Columns.Add("Col4", typeof(string));
            dt.Columns.Add("Col5", typeof(string));
            dt.Rows.Add("Mach01", "Run", "Run", "Down", "Down", "Down");
            dt.Rows.Add("Mach02", "Idle", "Idle", "Idle", "Run", "Run");
            dt.Rows.Add("Mach03", "Run", "Idle", "Run", "Idle", "Run");
            return dt;
        }

        private Color GetSectionColor(string Status)
        {
            Color c = new Color();
            switch (Status)
            {
                case "Run":
                    c = Color.Green;
                    break;
                case "Idle":
                    c = Color.Yellow;
                    break;
                case "Down":
                    c = Color.Red;
                    break;
                default:
                    c = Color.Black;
                    break;
            }
            return c;
        }

        private void DrawStatus(DataTable dt)
        {
            int
                RowCount = dt.Rows.Count,
                ColumnCount = dt.Columns.Count,
                X = 0,
                ColWidth = 0;
    
            string
                Status = string.Empty;

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                PictureBox pb = new PictureBox();
                pb.Name = string.Format("PB{0}", i.ToString("00"));
                // 預設 PictureBox 寬度 = FlowLayoutPanel 寬度
                pb.Width = flowLayoutPanel1.Width;
                // PictureBox 預設高度為 20 
                pb.Height = 20;

                // Section 起始位置
                X = 0;
                // Section 繪圖寬度
                ColWidth = pb.Width / ColumnCount;
                // 紀錄設備全部 Section 資訊
                List<SectionColor> result = new List<SectionColor>();
                for (int j = 1; j < ColumnCount; j++)
                {
                    Status = dt.Rows[i][j].ToString();

                    SectionColor SC = new SectionColor();
                    SC.SectNO = j;
                    SC.SectStart = X;
                    SC.SectColor = GetSectionColor(Status);
                    SC.SectWidth = ColWidth;
                    result.Add(SC);

                    X += ColWidth;
                }

                // 把 Section 資訊轉成陣列存放在 Tag Property 內
                pb.Tag = result.ToArray();
                pb.Paint += pb_Paint;

                flowLayoutPanel1.Controls.Add(pb);
            }
        }

        void pb_Paint(object sender, PaintEventArgs e)
        {

            PictureBox PB = sender as PictureBox;
            if (PB == null) return;

            // 把 PictureBox.Tag Property 的 Section 資訊抓出來繪圖用
            SectionColor[] scs = PB.Tag as SectionColor[];
            if (scs == null) return ;

            SolidBrush b;
            Rectangle rec;
            foreach (SectionColor sc in scs)
            {
                b = new SolidBrush(sc.SectColor);
                rec = new Rectangle(sc.SectStart, 0, sc.SectWidth, PB.Height);
                e.Graphics.FillRectangle(b, rec);
            }
        }
    }
}
繪圖效果

[C#] PictureBox - 區段顏色-0

Coding 筆記
  • 利用 FlowLayoutPanel 控件,可以免去動態產生 PictureBox 時,還要指定 PictureBox 的位置
  • 動態產生的 PictureBox 只能在 Paint 內針對 Graphics 進行繪圖,在非 Paint 的地方繪圖,都沒有成功
    參考資料
  • 論壇討論 12

沒有留言:

張貼留言