星期日, 9月 04, 2022

[C#] ComboBoxRenderer

根據官方文章 - ComboBoxRenderer 類別 的筆記,練習時發現原本的 Code 在 Font 變化時,ComboBox Size 不會跟著變化,改寫成透過 MeasureString() 來取得字型高度並設定 ComboBox Size

CustomComboBox Code,CustomComboBox 是繼承 Control 來做的喔
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

namespace ComboBoxRendererSample
{
    public class CustomComboBox : Control
    {
        private Size arrowSize;
        private Rectangle arrowRectangle;
        private Rectangle topTextBoxRectangle;    // ComboBox 本身文字顯示
        private Rectangle bottomTextBoxRectangle; // ComboBox 下拉選項文字顯示
        private ComboBoxState textBoxState = ComboBoxState.Normal;
        private ComboBoxState arrowState = ComboBoxState.Normal;

        public Font Font
        {
            get => base.Font;
            set
            {
                base.Font = value;
                Invalidate();
            }
        }

        public CustomComboBox() : base()
        {
            Location = new Point(10, 10);
            Size = new Size(300, 200);
            Font = new Font("微軟正黑體", 20);
            Text = "Click the button";
        }

        // Draw the combo box in the current state.
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (ComboBoxRenderer.IsSupported == false)
            {
                Parent.Text = "Visual Styles Disabled";
                return;
            }

            // ComboBox 高度部分改用 MeasureString() 根據字型來調整
            SizeF stringSizeFormat = e.Graphics.MeasureString(Text, Font);
            int Height = (int)stringSizeFormat.Height;

            arrowSize = new Size(18, Height);

            arrowRectangle = new Rectangle(
                ClientRectangle.X + ClientRectangle.Width - arrowSize.Width - 1,
                ClientRectangle.Y + 1,
                arrowSize.Width,
                Height);

            topTextBoxRectangle = new Rectangle(
                ClientRectangle.X,
                ClientRectangle.Y,
                ClientRectangle.Width,
                Height + 2);

            bottomTextBoxRectangle = new Rectangle(
                ClientRectangle.X,
                ClientRectangle.Y + topTextBoxRectangle.Height,
                ClientRectangle.Width,
                topTextBoxRectangle.Height);

            // Always draw the main text box and drop down arrow in their current states
            ComboBoxRenderer.DrawTextBox(e.Graphics, topTextBoxRectangle, Text, Font, textBoxState);

            ComboBoxRenderer.DrawDropDownButton(e.Graphics, arrowRectangle, arrowState);

            // Only draw the bottom text box if the arrow has been clicked
            if (textBoxState == ComboBoxState.Pressed)
            {
                string bottomText = "Using ComboBoxRenderer";
                ComboBoxRenderer.DrawTextBox(e.Graphics, bottomTextBoxRectangle, bottomText, Font, textBoxState);
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (ComboBoxRenderer.IsSupported == false ||
                arrowRectangle.Contains(e.Location) == false)
                return;

            // Draw the arrow in the pressed state.
            arrowState = ComboBoxState.Pressed;

            // The user has activated the combo box.
            if (textBoxState == ComboBoxState.Normal)
            {
                Text = "Clicked!";
                textBoxState = ComboBoxState.Pressed;
            }
            // The user has deactivated the combo box.
            else
            {
                Text = "Click here";
                textBoxState = ComboBoxState.Normal;
            }

            Invalidate();
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (ComboBoxRenderer.IsSupported == false ||
                arrowRectangle.Contains(e.Location) == false)
                return;

            arrowState = ComboBoxState.Normal;
            Invalidate();
        }
    }
}
CustomComboBox 會隨字型變化 Size 且下拉箭頭會在高度中央,該篇個人重點

[C#] ComboBoxRenderer-1

範例執行初始畫面

[C#] ComboBoxRenderer-2

點擊 TextBox 部分不會有反應,必須點擊下拉箭頭

[C#] ComboBoxRenderer-3

再次點擊下拉箭頭,BottomTextBox (這名稱取的有點奇怪) 會收回

[C#] ComboBoxRenderer-4

沒有留言:

張貼留言