123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- // ***********************************************************************
- // Assembly : HZH_Controls
- // Created : 08-17-2019
- //
- // ***********************************************************************
- // <copyright file="TabControlExt.cs">
- // Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
- // </copyright>
- //
- // Blog: https://www.cnblogs.com/bfyx
- // GitHub:https://github.com/kwwwvagaa/NetWinformControl
- // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
- //
- // If you use this code, please keep this note.
- // ***********************************************************************
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Windows.Forms;
- namespace HZH_Controls.Controls
- {
- /// <summary>
- /// Class TabControlExt.
- /// Implements the <see cref="System.Windows.Forms.TabControl" />
- /// </summary>
- /// <seealso cref="System.Windows.Forms.TabControl" />
- public class TabControlExt : TabControl
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="TabControlExt" /> class.
- /// </summary>
- public TabControlExt()
- : base()
- {
- SetStyles();
- //this.Multiline = true;
- this.ItemSize = new Size(this.ItemSize.Width, 50);
- }
- /// <summary>
- /// Sets the styles.
- /// </summary>
- private void SetStyles()
- {
- base.SetStyle(
- ControlStyles.UserPaint |
- ControlStyles.DoubleBuffer |
- ControlStyles.OptimizedDoubleBuffer |
- ControlStyles.AllPaintingInWmPaint |
- ControlStyles.ResizeRedraw |
- ControlStyles.SupportsTransparentBackColor, true);
- base.UpdateStyles();
- }
- /// <summary>
- /// Gets or sets a value indicating whether this instance is show close BTN.
- /// </summary>
- /// <value><c>true</c> if this instance is show close BTN; otherwise, <c>false</c>.</value>
- [Description("是否显示关闭按钮"), Category("自定义")]
- public bool IsShowCloseBtn { get; set; }
- /// <summary>
- /// The back color
- /// </summary>
- private Color _backColor = Color.White;
- /// <summary>
- /// 此成员对于此控件无意义。
- /// </summary>
- /// <value>The color of the back.</value>
- [Browsable(true)]
- [EditorBrowsable(EditorBrowsableState.Always)]
- [DefaultValue(typeof(Color), "White")]
- public override Color BackColor
- {
- get { return _backColor; }
- set
- {
- _backColor = value;
- base.Invalidate(true);
- }
- }
- /// <summary>
- /// The border color
- /// </summary>
- private Color _borderColor = Color.FromArgb(232, 232, 232);
- /// <summary>
- /// Gets or sets the color of the border.
- /// </summary>
- /// <value>The color of the border.</value>
- [DefaultValue(typeof(Color), "232, 232, 232")]
- [Description("TabContorl边框色")]
- public Color BorderColor
- {
- get { return _borderColor; }
- set
- {
- _borderColor = value;
- base.Invalidate(true);
- }
- }
- /// <summary>
- /// The head selected back color
- /// </summary>
- private Color _headSelectedBackColor = Color.FromArgb(255, 85, 51);
- /// <summary>
- /// Gets or sets the color of the head selected back.
- /// </summary>
- /// <value>The color of the head selected back.</value>
- [DefaultValue(typeof(Color), "255, 85, 51")]
- [Description("TabPage头部选中后的背景颜色")]
- public Color HeadSelectedBackColor
- {
- get { return _headSelectedBackColor; }
- set { _headSelectedBackColor = value; }
- }
- /// <summary>
- /// The head selected border color
- /// </summary>
- private Color _headSelectedBorderColor = Color.FromArgb(232, 232, 232);
- /// <summary>
- /// Gets or sets the color of the head selected border.
- /// </summary>
- /// <value>The color of the head selected border.</value>
- [DefaultValue(typeof(Color), "232, 232, 232")]
- [Description("TabPage头部选中后的边框颜色")]
- public Color HeadSelectedBorderColor
- {
- get { return _headSelectedBorderColor; }
- set { _headSelectedBorderColor = value; }
- }
- /// <summary>
- /// The header back color
- /// </summary>
- private Color _headerBackColor = Color.White;
- /// <summary>
- /// Gets or sets the color of the header back.
- /// </summary>
- /// <value>The color of the header back.</value>
- [DefaultValue(typeof(Color), "White")]
- [Description("TabPage头部默认背景颜色")]
- public Color HeaderBackColor
- {
- get { return _headerBackColor; }
- set { _headerBackColor = value; }
- }
- /// <summary>
- /// 绘制控件的背景。
- /// </summary>
- /// <param name="pevent">包含有关要绘制的控件的信息的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
- protected override void OnPaintBackground(PaintEventArgs pevent)
- {
- if (this.DesignMode == true)
- {
- LinearGradientBrush backBrush = new LinearGradientBrush(
- this.Bounds,
- SystemColors.ControlLightLight,
- SystemColors.ControlLight,
- LinearGradientMode.Vertical);
- pevent.Graphics.FillRectangle(backBrush, this.Bounds);
- backBrush.Dispose();
- }
- else
- {
- this.PaintTransparentBackground(pevent.Graphics, this.ClientRectangle);
- }
- }
- /// <summary>
- /// TabContorl 背景色设置
- /// </summary>
- /// <param name="g">The g.</param>
- /// <param name="clipRect">The clip rect.</param>
- protected void PaintTransparentBackground(Graphics g, Rectangle clipRect)
- {
- if ((this.Parent != null))
- {
- clipRect.Offset(this.Location);
- PaintEventArgs e = new PaintEventArgs(g, clipRect);
- GraphicsState state = g.Save();
- g.SmoothingMode = SmoothingMode.HighSpeed;
- try
- {
- g.TranslateTransform((float)-this.Location.X, (float)-this.Location.Y);
- this.InvokePaintBackground(this.Parent, e);
- this.InvokePaint(this.Parent, e);
- }
- finally
- {
- g.Restore(state);
- clipRect.Offset(-this.Location.X, -this.Location.Y);
- //新加片段,待测试
- using (SolidBrush brush = new SolidBrush(_backColor))
- {
- clipRect.Inflate(1, 1);
- g.FillRectangle(brush, clipRect);
- }
- }
- }
- else
- {
- System.Drawing.Drawing2D.LinearGradientBrush backBrush = new System.Drawing.Drawing2D.LinearGradientBrush(this.Bounds, SystemColors.ControlLightLight, SystemColors.ControlLight, System.Drawing.Drawing2D.LinearGradientMode.Vertical);
- g.FillRectangle(backBrush, this.Bounds);
- backBrush.Dispose();
- }
- }
- /// <summary>
- /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
- /// </summary>
- /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
- protected override void OnPaint(PaintEventArgs e)
- {
- // Paint the Background
- base.OnPaint(e);
- this.PaintTransparentBackground(e.Graphics, this.ClientRectangle);
- this.PaintAllTheTabs(e);
- this.PaintTheTabPageBorder(e);
- this.PaintTheSelectedTab(e);
- }
- /// <summary>
- /// Paints all the tabs.
- /// </summary>
- /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
- private void PaintAllTheTabs(System.Windows.Forms.PaintEventArgs e)
- {
- if (this.TabCount > 0)
- {
- for (int index = 0; index < this.TabCount; index++)
- {
- this.PaintTab(e, index);
- }
- }
- }
- /// <summary>
- /// Paints the tab.
- /// </summary>
- /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
- /// <param name="index">The index.</param>
- private void PaintTab(System.Windows.Forms.PaintEventArgs e, int index)
- {
- GraphicsPath path = this.GetTabPath(index);
- this.PaintTabBackground(e.Graphics, index, path);
- this.PaintTabBorder(e.Graphics, index, path);
- this.PaintTabText(e.Graphics, index);
- this.PaintTabImage(e.Graphics, index);
- if (IsShowCloseBtn)
- {
- Rectangle rect = this.GetTabRect(index);
- e.Graphics.DrawLine(new Pen(_borderColor, 1F), new Point(rect.Right - 15, rect.Top + 5), new Point(rect.Right - 5, rect.Top + 15));
- e.Graphics.DrawLine(new Pen(_borderColor, 1F), new Point(rect.Right - 5, rect.Top + 5), new Point(rect.Right - 15, rect.Top + 15));
- }
- }
- /// <summary>
- /// 设置选项卡头部颜色
- /// </summary>
- /// <param name="graph">The graph.</param>
- /// <param name="index">The index.</param>
- /// <param name="path">The path.</param>
- private void PaintTabBackground(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path)
- {
- Rectangle rect = this.GetTabRect(index);
- if (rect.Width == 0 || rect.Height == 0) return;
- System.Drawing.Brush buttonBrush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, _headerBackColor, _headerBackColor, LinearGradientMode.Vertical); //非选中时候的 TabPage 页头部背景色
- graph.FillPath(buttonBrush, path);
- //if (index == this.SelectedIndex)
- //{
- // //buttonBrush = new System.Drawing.SolidBrush(_headSelectedBackColor);
- // graph.DrawLine(new Pen(_headerBackColor), rect.Right+2, rect.Bottom, rect.Left + 1, rect.Bottom);
- //}
- buttonBrush.Dispose();
- }
- /// <summary>
- /// 设置选项卡头部边框色
- /// </summary>
- /// <param name="graph">The graph.</param>
- /// <param name="index">The index.</param>
- /// <param name="path">The path.</param>
- private void PaintTabBorder(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path)
- {
- Pen borderPen = new Pen(_borderColor);// TabPage 非选中时候的 TabPage 头部边框色
- if (index == this.SelectedIndex)
- {
- borderPen = new Pen(_headSelectedBorderColor); // TabPage 选中后的 TabPage 头部边框色
- }
- graph.DrawPath(borderPen, path);
- borderPen.Dispose();
- }
- /// <summary>
- /// Paints the tab image.
- /// </summary>
- /// <param name="g">The g.</param>
- /// <param name="index">The index.</param>
- private void PaintTabImage(System.Drawing.Graphics g, int index)
- {
- Image tabImage = null;
- if (this.TabPages[index].ImageIndex > -1 && this.ImageList != null)
- {
- tabImage = this.ImageList.Images[this.TabPages[index].ImageIndex];
- }
- else if (this.TabPages[index].ImageKey.Trim().Length > 0 && this.ImageList != null)
- {
- tabImage = this.ImageList.Images[this.TabPages[index].ImageKey];
- }
- if (tabImage != null)
- {
- Rectangle rect = this.GetTabRect(index);
- g.DrawImage(tabImage, rect.Right - rect.Height - 4, 4, rect.Height - 2, rect.Height - 2);
- }
- }
- /// <summary>
- /// Paints the tab text.
- /// </summary>
- /// <param name="graph">The graph.</param>
- /// <param name="index">The index.</param>
- private void PaintTabText(System.Drawing.Graphics graph, int index)
- {
- string tabtext = this.TabPages[index].Text;
- System.Drawing.StringFormat format = new System.Drawing.StringFormat();
- format.Alignment = StringAlignment.Near;
- format.LineAlignment = StringAlignment.Center;
- format.Trimming = StringTrimming.EllipsisCharacter;
- Brush forebrush = null;
- if (this.TabPages[index].Enabled == false)
- {
- forebrush = SystemBrushes.ControlDark;
- }
- else
- {
- forebrush = SystemBrushes.ControlText;
- }
- Font tabFont = this.Font;
- if (index == this.SelectedIndex)
- {
- if (this.TabPages[index].Enabled != false)
- {
- forebrush = new SolidBrush(_headSelectedBackColor);
- }
- }
- Rectangle rect = this.GetTabRect(index);
- var txtSize = ControlHelper.GetStringWidth(tabtext, graph, tabFont);
- Rectangle rect2 = new Rectangle(rect.Left + (rect.Width - txtSize) / 2 - 1, rect.Top, rect.Width, rect.Height);
- graph.DrawString(tabtext, tabFont, forebrush, rect2, format);
- }
- /// <summary>
- /// 设置 TabPage 内容页边框色
- /// </summary>
- /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
- private void PaintTheTabPageBorder(System.Windows.Forms.PaintEventArgs e)
- {
- if (this.TabCount > 0)
- {
- Rectangle borderRect = this.TabPages[0].Bounds;
- //borderRect.Inflate(1, 1);
- Rectangle rect = new Rectangle(borderRect.X - 2, borderRect.Y - 1, borderRect.Width + 5, borderRect.Height + 2);
- ControlPaint.DrawBorder(e.Graphics, rect, this.BorderColor, ButtonBorderStyle.Solid);
- }
- }
- /// <summary>
- /// Paints the selected tab.
- /// </summary>
- /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
- private void PaintTheSelectedTab(System.Windows.Forms.PaintEventArgs e)
- {
- if (this.SelectedIndex == -1)
- return;
- Rectangle selrect;
- int selrectRight = 0;
- selrect = this.GetTabRect(this.SelectedIndex);
- selrectRight = selrect.Right;
- e.Graphics.DrawLine(new Pen(_headSelectedBackColor), selrect.Left, selrect.Bottom + 1, selrectRight, selrect.Bottom + 1);
- }
- /// <summary>
- /// Gets the tab path.
- /// </summary>
- /// <param name="index">The index.</param>
- /// <returns>GraphicsPath.</returns>
- private GraphicsPath GetTabPath(int index)
- {
- System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
- path.Reset();
- Rectangle rect = this.GetTabRect(index);
- switch (Alignment)
- {
- case TabAlignment.Top:
- break;
- case TabAlignment.Bottom:
- break;
- case TabAlignment.Left:
- break;
- case TabAlignment.Right:
- break;
- }
- path.AddLine(rect.Left, rect.Top, rect.Left, rect.Bottom + 1);
- path.AddLine(rect.Left, rect.Top, rect.Right, rect.Top);
- path.AddLine(rect.Right, rect.Top, rect.Right, rect.Bottom + 1);
- path.AddLine(rect.Right, rect.Bottom + 1, rect.Left, rect.Bottom + 1);
- return path;
- }
- /// <summary>
- /// Sends the message.
- /// </summary>
- /// <param name="hWnd">The h WND.</param>
- /// <param name="Msg">The MSG.</param>
- /// <param name="wParam">The w parameter.</param>
- /// <param name="lParam">The l parameter.</param>
- /// <returns>IntPtr.</returns>
- [DllImport("user32.dll")]
- private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
- /// <summary>
- /// The wm setfont
- /// </summary>
- private const int WM_SETFONT = 0x30;
- /// <summary>
- /// The wm fontchange
- /// </summary>
- private const int WM_FONTCHANGE = 0x1d;
- /// <summary>
- /// 引发 <see cref="M:System.Windows.Forms.Control.CreateControl" /> 方法。
- /// </summary>
- protected override void OnCreateControl()
- {
- base.OnCreateControl();
- this.OnFontChanged(EventArgs.Empty);
- }
- /// <summary>
- /// 引发 <see cref="E:System.Windows.Forms.Control.FontChanged" /> 事件。
- /// </summary>
- /// <param name="e">包含事件数据的 <see cref="T:System.EventArgs" />。</param>
- protected override void OnFontChanged(EventArgs e)
- {
- base.OnFontChanged(e);
- IntPtr hFont = this.Font.ToHfont();
- SendMessage(this.Handle, WM_SETFONT, hFont, (IntPtr)(-1));
- SendMessage(this.Handle, WM_FONTCHANGE, IntPtr.Zero, IntPtr.Zero);
- this.UpdateStyles();
- }
- /// <summary>
- /// 此成员重写 <see cref="M:System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message@)" />。
- /// </summary>
- /// <param name="m">一个 Windows 消息对象。</param>
- protected override void WndProc(ref Message m)
- {
- if (m.Msg == 0x0201) // WM_LBUTTONDOWN
- {
- if (!DesignMode)
- {
- if (IsShowCloseBtn)
- {
- var mouseLocation = this.PointToClient(Control.MousePosition);
- int index = GetMouseDownTabHead(mouseLocation);
- if (index >= 0)
- {
- Rectangle rect = this.GetTabRect(index);
- var closeRect = new Rectangle(rect.Right - 15, rect.Top + 5, 10, 10);
- if (closeRect.Contains(mouseLocation))
- {
- this.TabPages.RemoveAt(index);
- return;
- }
- }
- }
- }
- }
- base.WndProc(ref m);
- }
- /// <summary>
- /// 在调度键盘或输入消息之前,在消息循环内对它们进行预处理。
- /// </summary>
- /// <param name="msg">通过引用传递的 <see cref="T:System.Windows.Forms.Message" />,它表示要处理的消息。可能的值有 WM_KEYDOWN、WM_SYSKEYDOWN、WM_CHAR 和 WM_SYSCHAR。</param>
- /// <returns>如果消息已由控件处理,则为 true;否则为 false。</returns>
- /// <PermissionSet>
- /// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
- /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
- /// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
- /// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
- /// </PermissionSet>
- public override bool PreProcessMessage(ref Message msg)
- {
- return base.PreProcessMessage(ref msg);
- }
- /// <summary>
- /// Gets the mouse down tab head.
- /// </summary>
- /// <param name="point">The point.</param>
- /// <returns>System.Int32.</returns>
- private int GetMouseDownTabHead(Point point)
- {
- for (int i = 0; i < this.TabCount; i++)
- {
- Rectangle rect = this.GetTabRect(i);
- if (rect.Contains(point))
- {
- return i;
- }
- }
- return -1;
- }
- }
- }
|