同步操作将从 电脑程序爱好者/基于导航菜单的 WinForm 项目的基础框架 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Drawing.Drawing2D;using System.Runtime.InteropServices;using System.Windows.Forms;using HDC = System.IntPtr;using HWND = System.IntPtr;namespace NavTabControl{public sealed class UITabControl : TabControl, IStyleInterface{public const int VK_RBUTTON = 0x2;public const int VK_LBUTTON = 0x1;public const int WM_PAINT = 0xF;[StructLayout(LayoutKind.Sequential)]public struct PAINTSTRUCT{public IntPtr hdc;public bool fErase;public RECT rcPaint;public bool fRestore;public bool fIncUpdate;[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]public byte[] rgbReserved;}private readonly UITabControlHelper Helper;private int DrawedIndex = -1;private readonly Timer timer = new Timer();[DllImport("user32")]public static extern int GetCursorPos(out POINT lpPoint);[DllImport("user32")] public static extern int FindWindowEx(HWND hwnd1, HWND hwnd2, string lpsz1, string lpsz2);[DllImport("user32")] public static extern short GetKeyState(int nVirtKey);[DllImport("user32")] public static extern int GetWindowRect(HWND hwnd, ref RECT lpRect);[DllImport("user32")] public static extern int BeginPaint(HWND hwnd, ref PAINTSTRUCT lpPaint);[DllImport("user32")] public static extern int EndPaint(HWND hwnd, ref PAINTSTRUCT lpPaint);[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]public static extern bool PtInRect([In] ref RECT lprc, Point pt);[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool bRepaint = true);public UITabControl(){SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);ItemSize = new Size(150, 40);DrawMode = TabDrawMode.OwnerDrawFixed;Font = UIFontColor.Font;AfterSetFillColor(FillColor);Size = new Size(450, 270);Helper = new UITabControlHelper(this);timer.Interval = 500;timer.Tick += Timer_Tick;}~UITabControl(){timer.Stop();timer.Dispose();}private string mainPage = "";[DefaultValue(true)][Description("主页名称,此页面不显示关闭按钮")]public string MainPage{get => mainPage;set{mainPage = value;Invalidate();}}private void Timer_Tick(object sender, EventArgs e){timer.Stop();DrawedIndex = SelectedIndex;}protected override void OnSelected(TabControlEventArgs e){base.OnSelected(e);if (ShowActiveCloseButton && !ShowCloseButton){timer.Start();}}protected override bool ProcessCmdKey(ref Message msg, Keys keyData){if (ForbidCtrlTab){switch (keyData){case (Keys.Tab | Keys.Control)://组合键在调试时,不容易捕获;可以先按住Ctrl键(此时在断点处已经捕获),然后按下Tab键,都释放后,再进入断点处单步向下执行;//此时会分两次进入断点,第一次(好像)是处理Ctrl键,第二次处理组合键return true;}}return base.ProcessCmdKey(ref msg, keyData);}[DefaultValue(true)][Description("是否禁用Ctrl+Tab")]public bool ForbidCtrlTab { get; set; } = true;public void SelectPage(int pageIndex) => Helper.SelectPage(pageIndex);public void SelectPage(Guid pageGuid) => Helper.SelectPage(pageGuid);public void AddPage(UIPage page) => Helper.AddPage(page);public void AddPage(Guid guid, UIPage page) => Helper.AddPage(guid, page);public void AddPage(int index, UIPage page) => Helper.AddPage(index, page);public void AddPages(params UIPage[] pages){foreach (var page in pages) AddPage(page);}public void AddPage(int pageIndex, UITabControl page) => Helper.AddPage(pageIndex, page);public void AddPage(Guid guid, UITabControl page) => Helper.AddPage(guid, page);private Color _fillColor = UIColor.LightBlue;private Color tabBackColor = Color.FromArgb(56, 56, 56);/// <summary>/// Tag字符串/// </summary>[DefaultValue(null)][Description("获取或设置包含有关控件的数据的对象字符串")]public string TagString { get; set; }/// <summary>/// 自定义主题风格/// </summary>[DefaultValue(false)][Description("获取或设置可以自定义主题风格")]public bool StyleCustomMode { get; set; }private HorizontalAlignment textAlignment = HorizontalAlignment.Center;[DefaultValue(HorizontalAlignment.Center)][Description("文字显示方向")]public HorizontalAlignment TextAlignment{get => textAlignment;set{textAlignment = value;Invalidate();}}private bool tabVisible = true;[DefaultValue(true)][Description("标签页是否显示")]public bool TabVisible{get => tabVisible;set{tabVisible = value;if (!tabVisible){ItemSize = new Size(0, 1);}else{if (ItemSize == new Size(0, 1)){ItemSize = new Size(150, 40);}}Invalidate();}}/// <summary>/// 当使用边框时填充颜色,当值为背景色或透明色或空值则不填充/// </summary>[Description("当使用边框时填充颜色,当值为背景色或透明色或空值则不填充")][DefaultValue(typeof(Color), "235, 243, 255")]public Color FillColor{get => _fillColor;set{_fillColor = value;AfterSetFillColor(value);_style = UIStyle.Custom;Invalidate();}}/// <summary>/// 边框颜色/// </summary>[Description("边框颜色")][DefaultValue(typeof(Color), "56, 56, 56")]public Color TabBackColor{get => tabBackColor;set{tabBackColor = value;_menuStyle = UIMenuStyle.Custom;Invalidate();}}private Color tabSelectedColor = Color.FromArgb(36, 36, 36);/// <summary>/// 边框颜色/// </summary>[Description("选中Tab页背景色")][DefaultValue(typeof(Color), "36, 36, 36")]public Color TabSelectedColor{get => tabSelectedColor;set{tabSelectedColor = value;_menuStyle = UIMenuStyle.Custom;Invalidate();}}private Color tabSelectedForeColor = UIColor.Blue;/// <summary>/// 边框颜色/// </summary>[Description("选中Tab页字体色")][DefaultValue(typeof(Color), "80, 160, 255")]public Color TabSelectedForeColor{get => tabSelectedForeColor;set{tabSelectedForeColor = value;_style = UIStyle.Custom;Invalidate();}}private Color tabUnSelectedForeColor = Color.FromArgb(240, 240, 240);/// <summary>/// 边框颜色/// </summary>[Description("未选中Tab页字体色")][DefaultValue(typeof(Color), "240, 240, 240")]public Color TabUnSelectedForeColor{get => tabUnSelectedForeColor;set{tabUnSelectedForeColor = value;_menuStyle = UIMenuStyle.Custom;Invalidate();}}private Color tabSelectedHighColor = UIColor.Blue;/// <summary>/// 边框颜色/// </summary>[Description("选中Tab页高亮")][DefaultValue(typeof(Color), "80, 160, 255")]public Color TabSelectedHighColor{get => tabSelectedHighColor;set{tabSelectedHighColor = value;_style = UIStyle.Custom;Invalidate();}}private UIStyle _style = UIStyle.Blue;/// <summary>/// 主题样式/// </summary>[DefaultValue(UIStyle.Blue), Description("主题样式")]public UIStyle Style{get => _style;set => SetStyle(value);}[Browsable(false)]public override Rectangle DisplayRectangle{get{Rectangle rect = base.DisplayRectangle;if (tabVisible){return new Rectangle(rect.Left - 4, rect.Top - 4, rect.Width + 8, rect.Height + 8);}else{return new Rectangle(rect.Left - 4, rect.Top - 5, rect.Width + 8, rect.Height + 9);}}}private void AfterSetFillColor(Color color){foreach (TabPage page in TabPages){page.BackColor = color;}}public void SetStyle(UIStyle style){SetStyleColor(UIStyles.GetStyleColor(style));_style = style;}public void SetStyleColor(UIBaseStyle uiColor){if (uiColor.IsCustom()) return;tabSelectedForeColor = tabSelectedHighColor = uiColor.MenuSelectedColor;_fillColor = uiColor.PlainColor;Invalidate();}private UIMenuStyle _menuStyle = UIMenuStyle.Black;[DefaultValue(UIMenuStyle.Black)][Description("主题风格")]public UIMenuStyle MenuStyle{get => _menuStyle;set{if (value != UIMenuStyle.Custom){SetMenuStyle(UIStyles.MenuColors[value]);}_menuStyle = value;}}private void SetMenuStyle(UIMenuColor uiColor){tabBackColor = uiColor.BackColor;tabSelectedColor = uiColor.SelectedColor;tabUnSelectedForeColor = uiColor.UnSelectedForeColor;Invalidate();}protected override void CreateHandle(){base.CreateHandle();DoubleBuffered = true;SizeMode = TabSizeMode.Fixed;Appearance = TabAppearance.Normal;Alignment = TabAlignment.Top;}private bool showCloseButton;[DefaultValue(false), Description("所有Tab页面标题显示关闭按钮")]public bool ShowCloseButton{get => showCloseButton;set{showCloseButton = value;if (showActiveCloseButton) showActiveCloseButton = false;Invalidate();}}private bool showActiveCloseButton;[DefaultValue(false), Description("当前激活的Tab页面标题显示关闭按钮")]public bool ShowActiveCloseButton{get => showActiveCloseButton;set{showActiveCloseButton = value;if (showCloseButton) showCloseButton = false;Invalidate();}}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);// 绘制背景色e.Graphics.Clear(TabBackColor);if (!TabVisible){return;}for (int index = 0; index <= TabCount - 1; index++){Rectangle TabRect = new Rectangle(GetTabRect(index).Location.X - 2, GetTabRect(index).Location.Y - 2, ItemSize.Width, ItemSize.Height);Bitmap bmp = new Bitmap(TabRect.Width, TabRect.Height);Graphics g = Graphics.FromImage(bmp);SizeF sf = e.Graphics.MeasureString(TabPages[index].Text, Font);int textLeft = ImageList?.ImageSize.Width ?? 0;if (ImageList != null) textLeft += 4 + 4 + 6;if (TextAlignment == HorizontalAlignment.Right)textLeft = (int)(TabRect.Width - 4 - sf.Width);if (TextAlignment == HorizontalAlignment.Center)textLeft = textLeft + (int)((TabRect.Width - textLeft - sf.Width) / 2.0f);// 绘制标题g.Clear(TabBackColor);if (index == SelectedIndex){g.Clear(TabSelectedColor);g.FillRectangle(TabSelectedHighColor, 0, bmp.Height - 4, bmp.Width, 4);}g.DrawString(TabPages[index].Text, Font, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, textLeft, TabRect.Top + 2 + (TabRect.Height - sf.Height - 4) / 2.0f);var menuItem = Helper[index];bool show1 = TabPages[index].Text != MainPage;bool show2 = menuItem == null || !menuItem.AlwaysOpen;bool showButton = show1 && show2;if (showButton){if (ShowCloseButton || (ShowActiveCloseButton && index == SelectedIndex)){g.DrawFontImage(77, 28, index == SelectedIndex ? tabSelectedForeColor : TabUnSelectedForeColor, new Rectangle(TabRect.Width - 28, TabRect.Top, 24, TabRect.Height));}}// 绘制图标if (ImageList != null){int imageIndex = TabPages[index].ImageIndex;if (imageIndex >= 0 && imageIndex < ImageList.Images.Count){g.DrawImage(ImageList.Images[imageIndex], 4 + 6, TabRect.Y + (TabRect.Height - ImageList.ImageSize.Height) / 2.0f, ImageList.ImageSize.Width, ImageList.ImageSize.Height);}}if (RightToLeftLayout && RightToLeft == RightToLeft.Yes){bmp = bmp.HorizontalFlip();}e.Graphics.DrawImage(bmp, TabRect.Left, TabRect.Top);bmp.Dispose();}}protected override void OnMouseDown(MouseEventArgs e){base.OnMouseDown(e);int removeIndex = -1;for (int index = 0; index <= TabCount - 1; index++){Rectangle TabRect = new Rectangle(GetTabRect(index).Location.X - 2, GetTabRect(index).Location.Y - 2, ItemSize.Width, ItemSize.Height);Rectangle rect = new Rectangle(TabRect.Right - 28, TabRect.Top, 24, TabRect.Height);if (e.Location.InRect(rect)){removeIndex = index;break;}}if (removeIndex < 0 || removeIndex >= TabCount){return;}var menuItem = Helper[removeIndex];bool show1 = TabPages[removeIndex].Text != MainPage;bool show2 = menuItem == null || !menuItem.AlwaysOpen;bool showButton = show1 && show2;if (showButton){if (ShowCloseButton){if (BeforeRemoveTabPage == null || BeforeRemoveTabPage.Invoke(this, removeIndex)){RemoveTabPage(removeIndex);}}else if (ShowActiveCloseButton && removeIndex == SelectedIndex){if (DrawedIndex == removeIndex){if (BeforeRemoveTabPage == null || BeforeRemoveTabPage.Invoke(this, removeIndex)){RemoveTabPage(removeIndex);}}}}}public delegate bool OnBeforeRemoveTabPage(object sender, int index);public delegate void OnAfterRemoveTabPage(object sender, int index);public event OnBeforeRemoveTabPage BeforeRemoveTabPage;public event OnAfterRemoveTabPage AfterRemoveTabPage;[DefaultValue(false)][Description("多页面框架时,包含UIPage,在点击Tab页关闭时关闭UIPage")]public bool AutoClosePage { get; set; }internal void RemoveTabPage(int index){if (index < 0 || index >= TabCount){return;}TabPage tabPage = TabPages[index];if (AutoClosePage){var pages = tabPage.GetControls<UIPage>();for (int i = 0; i < pages.Count; i++){pages[i].Final();pages[i].Dispose();pages[i] = null;}}TabPages.Remove(TabPages[index]);AfterRemoveTabPage?.Invoke(this, index);if (TabCount == 0) return;if (index == 0) SelectedIndex = 0;if (index > 0) SelectedIndex = index - 1;}public enum UITabPosition{Left,Right}[DefaultValue(UITabPosition.Left)][Description("标签页显示位置")]public UITabPosition TabPosition{get => (RightToLeftLayout && RightToLeft == RightToLeft.Yes)? UITabPosition.Right: UITabPosition.Left;set{RightToLeftLayout = value == UITabPosition.Right;RightToLeft = (value == UITabPosition.Right) ? RightToLeft.Yes : RightToLeft.No;}}protected override void OnSelectedIndexChanged(EventArgs e){base.OnSelectedIndexChanged(e);Init(SelectedIndex);}public void Init(int index = 0){if (index < 0 || index >= TabPages.Count){return;}if (SelectedIndex != index)SelectedIndex = index;List<UIPage> pages = TabPages[SelectedIndex].GetControls<UIPage>();foreach (var page in pages){page.Init();}//List<UITabControlMenu> leftTabControls = TabPages[SelectedIndex].GetControls<UITabControlMenu>();//foreach (var tabControl in leftTabControls)//{// tabControl.Init();//}List<UITabControl> topTabControls = TabPages[SelectedIndex].GetControls<UITabControl>();foreach (var tabControl in topTabControls){tabControl.Init();}}internal IntPtr UpDownButtonHandle => FindUpDownButton();private IntPtr FindUpDownButton(){return (HDC)FindWindowEx(Handle, IntPtr.Zero, UpDownButtonClassName, null);}public void OnPaintUpDownButton(UpDownButtonPaintEventArgs e){Graphics g = e.Graphics;Rectangle rect = e.ClipRectangle;Color upButtonArrowColor = tabUnSelectedForeColor;Color downButtonArrowColor = tabUnSelectedForeColor;Rectangle upButtonRect = rect;upButtonRect.X = 0;upButtonRect.Y = 0;upButtonRect.Width = rect.Width / 2 - 1;upButtonRect.Height -= 1;Rectangle downButtonRect = rect;downButtonRect.X = upButtonRect.Right + 1;downButtonRect.Y = 0;downButtonRect.Width = rect.Width / 2 - 1;downButtonRect.Height -= 1;g.Clear(tabBackColor);if (Enabled){if (e.MouseOver){if (e.MousePress){//鼠标按下if (e.MouseInUpButton)upButtonArrowColor = Color.FromArgb(200, TabSelectedHighColor);elsedownButtonArrowColor = Color.FromArgb(200, TabSelectedHighColor);}else{//鼠标移动if (e.MouseInUpButton)upButtonArrowColor = TabSelectedHighColor;elsedownButtonArrowColor = TabSelectedHighColor;}}}else{upButtonArrowColor = SystemColors.ControlDark;downButtonArrowColor = SystemColors.ControlDark;}g.SmoothingMode = SmoothingMode.AntiAlias;RenderButton(g, upButtonRect, upButtonArrowColor, ArrowDirection.Left);RenderButton(g, downButtonRect, downButtonArrowColor, ArrowDirection.Right);UpDownButtonPaintEventHandler handler = Events[EventPaintUpDownButton] as UpDownButtonPaintEventHandler;handler?.Invoke(this, e);}internal void RenderButton(Graphics g, Rectangle rect, Color arrowColor, ArrowDirection direction){switch (direction){case ArrowDirection.Left:g.DrawFontImage(61700, 24, arrowColor, rect);break;case ArrowDirection.Right:g.DrawFontImage(61701, 24, arrowColor, rect, 1);break;}}private static readonly object EventPaintUpDownButton = new object();private const string UpDownButtonClassName = "msctls_updown32";private UpDownButtonNativeWindow _upDownButtonNativeWindow;protected override void OnHandleCreated(EventArgs e){base.OnHandleCreated(e);if (UpDownButtonHandle != IntPtr.Zero){if (_upDownButtonNativeWindow == null){_upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);}}}protected override void OnCreateControl(){base.OnCreateControl();if (UpDownButtonHandle != IntPtr.Zero){if (_upDownButtonNativeWindow == null){_upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);}}}protected override void OnHandleDestroyed(EventArgs e){base.OnHandleDestroyed(e);if (_upDownButtonNativeWindow != null){_upDownButtonNativeWindow.Dispose();_upDownButtonNativeWindow = null;}}protected override void OnControlAdded(ControlEventArgs e){base.OnControlAdded(e);if (UpDownButtonHandle != IntPtr.Zero){if (_upDownButtonNativeWindow == null){_upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);}}if (e.Control is TabPage){e.Control.Padding = new Padding(0);}}protected override void OnSizeChanged(EventArgs e){base.OnSizeChanged(e);if (UpDownButtonHandle != IntPtr.Zero){if (_upDownButtonNativeWindow == null){_upDownButtonNativeWindow = new UpDownButtonNativeWindow(this);}}}private class UpDownButtonNativeWindow : NativeWindow, IDisposable{private UITabControl _owner;private bool _bPainting;private Rectangle clipRect;public UpDownButtonNativeWindow(UITabControl owner){_owner = owner;AssignHandle(owner.UpDownButtonHandle);}private bool LeftKeyPressed(){if (SystemInformation.MouseButtonsSwapped){return (GetKeyState(VK_RBUTTON) < 0);}return (GetKeyState(VK_LBUTTON) < 0);}/// <summary>/// 获取鼠标位置/// </summary>/// <returns></returns>private Point GetCursorPos(){UITabControl.GetCursorPos(out POINT pos);return new Point(pos.X, pos.Y);}private void DrawUpDownButton(){RECT rect = new RECT();bool mousePress = LeftKeyPressed();Point cursorPoint = SystemEx.GetCursorPos();GetWindowRect(Handle, ref rect);var mouseOver = PtInRect(ref rect, cursorPoint);cursorPoint.X -= rect.Left;cursorPoint.Y -= rect.Top;var mouseInUpButton = cursorPoint.X < clipRect.Width / 2;using (Graphics g = Graphics.FromHwnd(Handle)){UpDownButtonPaintEventArgs e = new UpDownButtonPaintEventArgs(g, clipRect, mouseOver, mousePress, mouseInUpButton);_owner.OnPaintUpDownButton(e);}}protected override void WndProc(ref Message m){switch (m.Msg){case WM_PAINT:if (!_bPainting){Point UpDownButtonLocation = new Point(_owner.Size.Width - 52, 0);Size UpDownButtonSize = new Size(52, _owner.ItemSize.Height);clipRect = new Rectangle(UpDownButtonLocation, UpDownButtonSize);MoveWindow(Handle, UpDownButtonLocation.X, UpDownButtonLocation.Y, clipRect.Width, clipRect.Height);PAINTSTRUCT ps = new PAINTSTRUCT();_bPainting = true;BeginPaint(m.HWnd, ref ps);DrawUpDownButton();EndPaint(m.HWnd, ref ps);_bPainting = false;m.Result = new IntPtr(1);}else{base.WndProc(ref m);}break;default:base.WndProc(ref m);break;}}#region IDisposable 成员public void Dispose(){_owner = null;base.ReleaseHandle();}#endregion IDisposable 成员}public delegate void UpDownButtonPaintEventHandler(object sender, UpDownButtonPaintEventArgs e);public class UpDownButtonPaintEventArgs : PaintEventArgs{public UpDownButtonPaintEventArgs(Graphics graphics,Rectangle clipRect,bool mouseOver,bool mousePress,bool mouseInUpButton): base(graphics, clipRect){MouseOver = mouseOver;MousePress = mousePress;MouseInUpButton = mouseInUpButton;}public bool MouseOver { get; }public bool MousePress { get; }public bool MouseInUpButton { get; }}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。