• c#: 颜色选择控件之实现


    参考ColorComboBox做修改,并对颜色名做些修正,用于CR MVMixer产品中,聊作备忘~

    效果图:

    代码:

    //颜色拾取框
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace CRMVMixer
    {
        //event handler delegate
        public delegate void ColorChangedHandler(object sender, ColorChangeArgs e);
    
        [ToolboxBitmap(typeof(ComboBox))]
        public class ColorComboBox : ComboBox
        {
            private PopupWindow popupWnd;
            private ColorPopup colors = new ColorPopup();
            private Color selectedColor = Color.Black;
            private Timer timer = new Timer();
            public event ColorChangedHandler ColorChanged;
    
            //constructor...
            public ColorComboBox()
                : this(Color.Black)
            {
            }
    
            public ColorComboBox(Color selectedColor)
            {
                this.SuspendLayout();
                // 
                // ColorCombo
                // 
                this.AutoSize = false;
                this.Size = new Size(92, 22);
                this.Text = string.Empty;
                this.DrawMode = DrawMode.OwnerDrawFixed;
                this.DropDownStyle = ComboBoxStyle.DropDownList;
                this.ItemHeight = 16;
    
                timer.Tick += new EventHandler(OnCheckStatus);
                timer.Interval = 50;
                timer.Start();
                colors.SelectedColor = this.selectedColor = selectedColor;
                this.ResumeLayout(false);
            }
    
            [DefaultValue(typeof(Color), "Black")]
            public Color SelectedColor
            {
                get { return selectedColor; }
                set
                {
                    selectedColor = value;
                    colors.SelectedColor = value;
                    Invalidate();
                }
            }
    
            protected override void WndProc(ref Message m)
            {
                //256: WM_KEYDOWN, 513: WM_LBUTTONDOWN, 515: WM_LBUTTONDBLCLK
                if (m.Msg == 256 || m.Msg == 513 || m.Msg == 515)
                {
                    if (m.Msg == 513)
                        PopupColorPalette();
                    return;
                }
                base.WndProc(ref   m);
            }
    
            private void PopupColorPalette()
            {
                //create a popup window
                popupWnd = new PopupWindow(colors);
    
                //calculate its position in screen coordinates
                Rectangle rect = Bounds;
                rect = this.Parent.RectangleToScreen(rect);
                Point pt = new Point(rect.Left, rect.Bottom);
    
                //tell it that we want the ColorChanged event
                popupWnd.ColorChanged += new ColorChangedHandler(OnColorChanged);
    
                //show the popup
                popupWnd.Show(pt);
                //disable the button so that the user can't click it
                //while the popup is being displayed
                this.Enabled = false;
                this.timer.Start();
            }
    
            //event handler for the color change event from the popup window
            //simply relay the event to the parent control
            protected void OnColorChanged(object sender, ColorChangeArgs e)
            {
                //if a someone wants the event, and the color has actually changed
                //call the event handler
                if (ColorChanged != null && e.color != this.selectedColor)
                {
                    this.selectedColor = e.color;
                    ColorChanged(this, e);
                }
                else //otherwise simply make note of the new color
                    this.selectedColor = e.color;
            }
    
            protected override void OnDrawItem(DrawItemEventArgs e)
            {
                var g = e.Graphics;
                e.DrawBackground();
                var brush = new SolidBrush(this.selectedColor);
                var rect = e.Bounds;
                rect.Width -= 1;
                rect.Height -= 1;
                g.FillRectangle(brush, rect);
                g.DrawRectangle(Pens.Black, rect);
                e.DrawFocusRectangle();
            }
    
            //This is the timer call back function. It checks to see 
            //if the popup went from a visible state to an close state
            //if so then it will uncheck and enable the button
            private void OnCheckStatus(object sender, EventArgs e)
            {
                if (popupWnd != null && !popupWnd.Visible)
                {
                    this.timer.Stop();
                    this.Enabled = true;
                }
            }
    
            /// <summary>
            /// a button style radio button that shows a color
            /// </summary>
            private class ColorRadioButton : RadioButton
            {
                public ColorRadioButton(Color color, Color backColor)
                {
                    this.ClientSize = new Size(21, 21);
                    this.Appearance = Appearance.Button;
                    this.Name = "button";
                    this.Visible = true;
                    this.ForeColor = color;
                    this.FlatAppearance.BorderColor = backColor;
                    this.FlatAppearance.BorderSize = 0;
                    this.FlatStyle = FlatStyle.Flat;
                    this.Paint += new PaintEventHandler(OnPaintButton);
                }
    
                private void OnPaintButton(object sender, PaintEventArgs e)
                {
                    //paint a square on the face of the button using the controls foreground color
                    Rectangle colorRect = new Rectangle(ClientRectangle.Left + 5, ClientRectangle.Top + 5, ClientRectangle.Width - 9, ClientRectangle.Height - 9);
                    e.Graphics.FillRectangle(new SolidBrush(this.ForeColor), colorRect);
                    e.Graphics.DrawRectangle(Pens.DarkGray, colorRect);
                }
            }
    
            ///<summary>
            ///this is the popup window.  This window will be the parent of the 
            ///window with the color controls on it
            ///</summary>
            private class PopupWindow : ToolStripDropDown
            {
                public event ColorChangedHandler ColorChanged;
                private ToolStripControlHost host;
                private ColorPopup content;
    
                public Color SelectedColor
                {
                    get { return content.SelectedColor; }
                }
    
                public PopupWindow(ColorPopup content)
                {
                    if (content == null)
                        throw new ArgumentNullException("content");
    
                    this.content = content;
                    this.AutoSize = false;
                    this.DoubleBuffered = true;
                    this.ResizeRedraw = true;
                    //create a host that will host the content
                    host = new ToolStripControlHost(content);
    
                    this.Padding = Margin = host.Padding = host.Margin = Padding.Empty;
                    this.MinimumSize = content.MinimumSize;
                    content.MinimumSize = content.Size;
                    MaximumSize = new Size(content.Size.Width + 1, content.Size.Height + 1);
                    content.MaximumSize = new Size(content.Size.Width + 1, content.Size.Height + 1);
                    Size = new Size(content.Size.Width + 1, content.Size.Height + 1);
    
                    content.Location = Point.Empty;
                    //add the host to the list
                    Items.Add(host);
                }
    
                protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
                {
                    //when the window close tell the parent that the color changed
                    if (ColorChanged != null)
                        ColorChanged(this, new ColorChangeArgs(this.SelectedColor));
                }
            }
    
            ///<summary>
            ///this class represends the control that has all the color radio buttons.
            ///this control gets embedded into the PopupWindow class.
            ///</summary>
            private class ColorPopup : UserControl
            {
                //private Color[] colors = { Color.Black, Color.Gray, Color.Maroon, Color.Olive, Color.Green, Color.Teal, Color.Navy, Color.Purple, Color.White, Color.Silver, Color.Red, Color.Yellow, Color.Lime, Color.Aqua, Color.Blue, Color.Fuchsia };
                private Color[] colors = {
                    Color.Black, Color.Navy, Color.DarkGreen, Color.DarkCyan, Color.DarkRed, Color.DarkMagenta, Color.Olive,
                    Color.LightGray, Color.DarkGray, Color.Blue, Color.Lime, Color.Cyan, Color.Red, Color.Fuchsia, 
                    Color.Yellow, Color.White, Color.RoyalBlue, Color.MediumBlue,  Color.LightGreen, Color.MediumSpringGreen, Color.Chocolate,
                    Color.Pink, Color.Khaki, Color.WhiteSmoke, Color.BlueViolet, Color.DeepSkyBlue, Color.OliveDrab, Color.SteelBlue,
                    Color.DarkOrange, Color.Tomato, Color.HotPink, Color.DimGray,
                };
                private string[] colorNames = {
                    "黑色", "藏青", "深绿", "深青", "红褐", "洋红", "褐绿", 
                    "浅灰", "灰色", "蓝色", "绿色", "青色", "红色", "紫红", 
                    "黄色", "白色", "蓝灰", "藏蓝", "淡绿", "青绿", "黄褐", 
                    "粉红", "嫩黄", "银白", "紫色", "天蓝", "灰绿", "青蓝", 
                    "橙黄", "桃红", "英红", "深灰"
                };
                private ToolTip toolTip = new ToolTip();
                private ColorRadioButton[] buttons;
                private Button moreColorsBtn;
                private Color selectedColor = Color.Black;
    
                ///<summary>
                ///get or set the selected color
                ///</summary>
                public Color SelectedColor
                {
                    get { return selectedColor; }
                    set
                    {
                        selectedColor = value;
                        Color[] colors = this.colors;
                        for (int i = 0; i < colors.Length; i++)
                            buttons[i].Checked = selectedColor == colors[i];
                    }
                }
    
                private void InitializeComponent()
                {
                    this.SuspendLayout();
                    this.Name = "Color Popup";
                    this.Text = string.Empty;
                    this.ResumeLayout(false);
                }
    
                public ColorPopup()
                {
                    InitializeComponent();
    
                    SetupButtons();
                    this.Paint += new PaintEventHandler(OnPaintBorder);
                }
    
                //place the buttons on the window.
                private void SetupButtons()
                {
                    Controls.Clear();
    
                    int x = 1;
                    int y = 2;
                    int breakCount = 7;
                    Color[] colors = this.colors;
                    this.buttons = new ColorRadioButton[colors.Length];
                    this.ClientSize = new Size(139, 137);
                    //color buttons
                    for (int i = 0; i < colors.Length; i++)
                    {
                        if (i > 0 && i % breakCount == 0)
                        {
                            y += 19;
                            x = 1;
                        }
                        buttons[i] = new ColorRadioButton(colors[i], this.BackColor);
                        buttons[i].Location = new Point(x, y);
                        toolTip.SetToolTip(buttons[i], colorNames[i]);
                        Controls.Add(buttons[i]);
                        buttons[i].Click += new EventHandler(BtnClicked);
                        if (selectedColor == colors[i])
                            buttons[i].Checked = true;
                        x += 19;
                    }
    
                    //line...
                    y += 24;
                    var label = new Label();
                    label.AutoSize = false;
                    label.Text = string.Empty;
                    label.Width = this.Width - 5;
                    label.Height = 2;
                    label.BorderStyle = BorderStyle.Fixed3D;
                    label.Location = new Point(4, y);
                    Controls.Add(label);
    
                    //button
                    y += 7;
                    moreColorsBtn = new Button();
                    moreColorsBtn.FlatStyle = FlatStyle.Popup;
                    moreColorsBtn.Text = "其它颜色...";
                    moreColorsBtn.Location = new Point(6, y);
                    moreColorsBtn.ClientSize = new Size(127, 23);
                    moreColorsBtn.Click += new EventHandler(OnMoreClicked);
                    Controls.Add(moreColorsBtn);
                }
    
                private void OnPaintBorder(object sender, PaintEventArgs e)
                {
                    var rect = this.ClientRectangle;
                    rect.Width -= 1;
                    rect.Height -= 1;
                    e.Graphics.DrawRectangle(new Pen(SystemColors.WindowFrame), rect);
                }
    
                public void BtnClicked(object sender, EventArgs e)
                {
                    selectedColor = ((ColorRadioButton)sender).ForeColor;
                    ((ToolStripDropDown)Parent).Close();
                }
    
                public void OnMoreClicked(object sender, EventArgs e)
                {
                    ((ToolStripDropDown)Parent).Close();
                    var pt = this.PointToScreen(this.Location);
                    var dlg = new ColorDialogEx(pt.X - 2, pt.Y);
                    dlg.Color = SelectedColor;
                    if (dlg.ShowDialog(this) == DialogResult.OK)
                        selectedColor = dlg.Color;
                }
            }
        }
    
        //define the color changed event argument
        public class ColorChangeArgs : System.EventArgs
        {
            //the selected color
            public Color color;
            public ColorChangeArgs(Color color)
            {
                this.color = color;
            }
        }
    
        //修正颜色框弹出位置
        public class ColorDialogEx : ColorDialog
        {
            private const Int32 WM_INITDIALOG = 0x0110;
            private const uint SWP_NOSIZE = 0x0001;
            private const uint SWP_SHOWWINDOW = 0x0040;
            private const uint SWP_NOZORDER = 0x0004;
            private const uint UFLAGS = SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW;
            private static readonly IntPtr HWND_TOP = new IntPtr(0);
    
            private int x;
            private int y;
            private string title = null;
    
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            private static extern bool SetWindowText(IntPtr hWnd, string text);
            [DllImport("user32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
    
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }
    
            public ColorDialogEx(int x, int y, String title = null)
            {
                this.x = x;
                this.y = y;
                this.title = title;
            }
    
            protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
            {
                IntPtr hookProc = base.HookProc(hWnd, msg, wparam, lparam);
                if (msg == WM_INITDIALOG)
                {
                    if (!string.IsNullOrEmpty(this.title))
                        SetWindowText(hWnd, this.title);
                    var r = new RECT();
                    GetWindowRect(hWnd, ref r);
                    int width = r.Right - r.Left;
                    int height = r.Bottom - r.Top;
                    var wa = Screen.PrimaryScreen.WorkingArea;
                    int sw = wa.Width;
                    int sh = wa.Height;
                    if (this.x > sw - width)
                        this.x = sw - width;
                    if (y > sh - height)
                        y = sh - height;
                    SetWindowPos(hWnd, HWND_TOP, this.x, this.y, 0, 0, UFLAGS);
                }
                return hookProc;
            }
        }
    }
  • 相关阅读:
    P3723 【[AH2017/HNOI2017]礼物】
    P4555 【[国家集训队]最长双回文串】
    manacher学习笔记
    多项式学习笔记
    题解 CF1097F 【Alex and a TV Show】
    docker数据卷容器
    python基础学习
    docker监控之cadvisor
    docker监控系统
    ssh配置详解及公私钥批量分发
  • 原文地址:https://www.cnblogs.com/crwy/p/14673041.html
Copyright © 2020-2023  润新知