zoukankan      html  css  js  c++  java
  • 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;
            }
        }
    }
  • 相关阅读:
    准备 FRM 考试——方法、工具与教训
    930. 和相同的二元子数组 前缀和
    1906. 查询差绝对值的最小值 前缀和
    剑指 Offer 37. 序列化二叉树 二叉树 字符串
    815. 公交路线 BFS
    518. 零钱兑换 II dp 完全背包
    1049. 最后一块石头的重量 II dp
    5779. 装包裹的最小浪费空间 二分
    5778. 使二进制字符串字符交替的最少反转次数 字符串 滑动窗口
    474. 一和零 dp
  • 原文地址:https://www.cnblogs.com/crwy/p/14673041.html
Copyright © 2011-2022 走看看