1368 lines
44 KiB
C#
1368 lines
44 KiB
C#
/*
|
||
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
|
||
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
|
||
* 使用本代码请保留此处信息。作者联系方式:ping3108@163.com, 欢迎进行技术交流
|
||
*/
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Drawing.Drawing2D;
|
||
using System.Windows.Forms;
|
||
|
||
using MGdu.WinFormUI.MyGraphics;
|
||
//忽略没有注释警告
|
||
#pragma warning disable 1591
|
||
namespace MGdu.WinFormUI
|
||
{
|
||
/// <summary>
|
||
/// 该类处理mdi-bar的绘制及鼠标事件管理
|
||
/// </summary>
|
||
internal class MdiBarController
|
||
{
|
||
#region private var
|
||
|
||
GMForm _owner;
|
||
public List<MdiGMTabItem> _listTabItems { get; private set; }
|
||
|
||
// 有时候可能有很多tab,不能全部显示,那么就用两个变量来标识
|
||
// 是第几个到第几个tab被显示出来了。
|
||
int _beginShowIndex;
|
||
int _endShowIndex;
|
||
|
||
int _activeTabIndex;
|
||
|
||
// 有多少tab被隐藏了
|
||
int _hiddenTabsCount;
|
||
|
||
Point _lastMouseUpLocation;
|
||
|
||
WLButton _newTabBtn;
|
||
WLButton _listAllBtn;
|
||
|
||
EventHandler _newTabBtnClick;
|
||
EventHandler _tabCloseBtnClick;
|
||
|
||
ContextMenuStrip _menuPopup;
|
||
private Rectangle _hitTestBounds;
|
||
|
||
#endregion
|
||
|
||
#region event & event handler
|
||
|
||
public event EventHandler NewTabButtonClick
|
||
{
|
||
add { _newTabBtnClick = value; }
|
||
remove { _newTabBtnClick = null; }
|
||
}
|
||
|
||
public event EventHandler TabCloseButtonClick
|
||
{
|
||
add { _tabCloseBtnClick = value; }
|
||
remove { _tabCloseBtnClick = null; }
|
||
}
|
||
|
||
private void OnNewTabBtnClick(object sender, EventArgs e)
|
||
{
|
||
_newTabBtnClick?.Invoke(this, EventArgs.Empty);
|
||
}
|
||
|
||
private void OnTabCloseBtnClick(object sender, EventArgs e)
|
||
{
|
||
if (sender is Form f)
|
||
{
|
||
_tabCloseBtnClick?.Invoke(f, EventArgs.Empty);
|
||
}
|
||
}
|
||
|
||
private void OnListAllBtnClick(object sender, EventArgs e)
|
||
{
|
||
if (_listTabItems.Count < 1)
|
||
return;
|
||
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (tab.IsFormActive)
|
||
{
|
||
tab.MenuItemPop.Checked = true;
|
||
tab.MenuItemPop.Image = null;
|
||
}
|
||
else
|
||
{
|
||
tab.MenuItemPop.Checked = false;
|
||
tab.MenuItemPop.Image = tab.Form.Icon.ToBitmap();
|
||
}
|
||
tab.MenuItemPop.Text = tab.Form.Text;
|
||
|
||
if (!tab.IsHidden)
|
||
tab.MenuItemPop.Font = new Font(tab.MenuItemPop.Font, FontStyle.Bold);
|
||
else
|
||
tab.MenuItemPop.Font = new Font(tab.MenuItemPop.Font, FontStyle.Regular);
|
||
}
|
||
_menuPopup.Show(_owner, ListAllBtnBounds.Left, ListAllBtnBounds.Bottom);
|
||
}
|
||
|
||
private void OnActivateChild(Form child)
|
||
{
|
||
if (child != _owner.ActiveMdiChild)
|
||
{
|
||
if (_owner.XTheme.Mdi_UseMsgToActivateChild)
|
||
_owner.ActivateMdiChildForm(child);
|
||
else
|
||
child.Activate();
|
||
}
|
||
}
|
||
|
||
private void OnPopMenuItemClick(object sender, EventArgs e)
|
||
{
|
||
if (sender is ToolStripMenuItem ctl)
|
||
{
|
||
if (ctl.Tag is Form f)
|
||
{
|
||
OnActivateChild(f);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Constructor & initial
|
||
|
||
public MdiBarController(GMForm owner)
|
||
{
|
||
_owner = owner;
|
||
_listTabItems = new List<MdiGMTabItem>();
|
||
_newTabBtn = new WLButton(owner);
|
||
_listAllBtn = new WLButton(owner);
|
||
|
||
// ini _newtabbtn
|
||
_newTabBtn.ColorTable = NewTabBtnColor;
|
||
_newTabBtn.Click += new EventHandler(OnNewTabBtnClick);
|
||
_newTabBtn.ForePathGetter = new ButtonForePathGetter(
|
||
MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.CreatePlusFlag);
|
||
|
||
_listAllBtn.ColorTable = ListAllBtnColor;
|
||
_listAllBtn.Click +=new EventHandler(OnListAllBtnClick);
|
||
_listAllBtn.ForePathGetter = new ButtonForePathGetter(
|
||
MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.CreateDownTriangleFlag);
|
||
_listAllBtn.ForePathSize = new Size(10, 9);
|
||
_listAllBtn.ForeFont = new Font("微软雅黑", 8);
|
||
|
||
_menuPopup = new ContextMenuStrip();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region editable properties from thmem info
|
||
|
||
/// <summary>
|
||
/// use left,top,right to location the bar in owner form,
|
||
/// the margin is from Form.ClientRectangle
|
||
/// </summary>
|
||
public Padding Margin
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarMargin; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 整个标签栏高度,包含标签栏底部区域、标签、标签顶部空隙
|
||
/// </summary>
|
||
public int BarHeight
|
||
{
|
||
get { return BarBottomRegionHeight + Math.Max(TabHeight, TabHeightActive) + TabTopSpace; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 标签栏底部区域的高度
|
||
/// </summary>
|
||
public int BarBottomRegionHeight
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarBottomRegionHeight; }
|
||
}
|
||
/// <summary>
|
||
/// 是否显示标签栏边框
|
||
/// </summary>
|
||
public bool DrawBarBorder
|
||
{
|
||
get { return _owner.XTheme.Mdi_DrawBarBorder; }
|
||
}
|
||
/// <summary>
|
||
/// 是否显示标签栏背景
|
||
/// </summary>
|
||
public bool DrawBarBackgound
|
||
{
|
||
get { return _owner.XTheme.Mdi_DrawBarBackground; }
|
||
}
|
||
|
||
/// <summary>
|
||
///标签栏左内边距
|
||
/// </summary>
|
||
public int BarLeftPadding
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarLeftPadding; }
|
||
}
|
||
/// <summary>
|
||
/// 标签栏右内边距
|
||
/// </summary>
|
||
public int BarRightPadding
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarRightPadding; }
|
||
}
|
||
/// <summary>
|
||
/// 标签高度
|
||
/// </summary>
|
||
public int TabHeight
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabHeight; }
|
||
}
|
||
/// <summary>
|
||
/// 激活的标签高度
|
||
/// </summary>
|
||
public int TabHeightActive
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabHeightActive; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// tab顶部与bar顶部的空间,这个值用来计算 BarHeight
|
||
/// </summary>
|
||
public int TabTopSpace
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabTopSpace; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 每个标签的左右边界可以不是垂直的,而是都有一个斜度
|
||
/// </summary>
|
||
public int TabSlopeWidth
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabSlopeWidth; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// tab与tab之间的距离,用负值可以使tab有重叠的效果
|
||
/// </summary>
|
||
public int TabAndTabSpace
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabAndTabSpace; }
|
||
}
|
||
/// <summary>
|
||
/// 标签是否显示图标
|
||
/// </summary>
|
||
public bool ShowTabIcon
|
||
{
|
||
get { return _owner.XTheme.Mdi_ShowTabIcon; }
|
||
}
|
||
/// <summary>
|
||
/// 是否显示标签关闭按钮
|
||
/// </summary>
|
||
public bool ShowTabCloseIcon
|
||
{
|
||
get { return _owner.XTheme.Mdi_ShowTabCloseIcon; }
|
||
}
|
||
/// <summary>
|
||
/// 标签图标大小
|
||
/// </summary>
|
||
public Size IconSize
|
||
{
|
||
get { return ShowTabIcon ? new Size(16, 16) : Size.Empty; }
|
||
}
|
||
/// <summary>
|
||
/// 标签图标距离左边的距离
|
||
/// </summary>
|
||
public int IconLeftSpace
|
||
{
|
||
get { return TabSlopeWidth + (ShowTabIcon ? 2 : 0); }
|
||
}
|
||
/// <summary>
|
||
/// 标签文字距离左边的距离
|
||
/// </summary>
|
||
public int TextLeftSpace
|
||
{
|
||
get { return 2; }
|
||
}
|
||
/// <summary>
|
||
/// 标签关闭按钮的大小
|
||
/// </summary>
|
||
public Size TabCloseBtnSize
|
||
{
|
||
get { return new Size(16, 16); }
|
||
}
|
||
/// <summary>
|
||
/// 标签关闭按钮距离右边的距离
|
||
/// </summary>
|
||
public int TabCloseBtnRightSpace
|
||
{
|
||
get { return TabSlopeWidth + 2; }
|
||
}
|
||
/// <summary>
|
||
/// 是否显示新建标签按钮
|
||
/// </summary>
|
||
public bool ShowNewTabBtn
|
||
{
|
||
get { return _owner.XTheme.Mdi_ShowNewTabBtn; }
|
||
}
|
||
/// <summary>
|
||
/// 新建标签按钮的大小
|
||
/// </summary>
|
||
public Size NewTabBtnSize
|
||
{
|
||
get { return _owner.XTheme.Mdi_NewTabBtnSize; }
|
||
}
|
||
|
||
public Rectangle NewTabBtnBounds
|
||
{
|
||
get;
|
||
set;
|
||
}
|
||
/// <summary>
|
||
/// 新建标签距离左边的距离
|
||
/// </summary>
|
||
public int NewTabBtnLeftSpace
|
||
{
|
||
get { return _owner.XTheme.Mdi_NewTabBtnLeftSpace; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按钮与Bar底部的距离
|
||
/// </summary>
|
||
public int NewTabBtnBottomSpace
|
||
{
|
||
get { return _owner.XTheme.Mdi_NewTabBtnBottomSpace; }
|
||
}
|
||
|
||
public Rectangle ListAllBtnBounds { get; set; }
|
||
|
||
public Size ListAllBtnSize
|
||
{
|
||
get { return _owner.XTheme.Mdi_ListAllBtnSize; }
|
||
}
|
||
|
||
public int ListAllBtnLeftSpace
|
||
{
|
||
get { return _owner.XTheme.Mdi_ListAllBtnLeftSpace; }
|
||
}
|
||
|
||
public int ListAllBtnBottomSpace
|
||
{
|
||
get { return _owner.XTheme.Mdi_ListAllBtnBottomSpace; }
|
||
}
|
||
|
||
public BarButtonAlignmentType ListAllBtnAlign
|
||
{
|
||
get { return _owner.XTheme.Mdi_ListAllBtnAlign; }
|
||
}
|
||
|
||
public bool AlwaysShowListAllBtn
|
||
{ get { return _owner.XTheme.Mdi_AlwaysShowListAllBtn; } }
|
||
|
||
/// <summary>
|
||
/// 一个tab允许的最小宽度
|
||
/// </summary>
|
||
public int TabMinWidth
|
||
{
|
||
get
|
||
{
|
||
return Math.Max(TabSlopeWidth * 2 + IconLeftSpace + IconSize.Width
|
||
+ TabCloseBtnRightSpace + TabCloseBtnSize.Width + 36,
|
||
_owner.XTheme.Mdi_TabMinWidth);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 一个tab允许的最大显示宽度
|
||
/// </summary>
|
||
public int TabMaxWidth
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabMaxWidth; }
|
||
}
|
||
/// <summary>
|
||
/// 标签正常宽度
|
||
/// </summary>
|
||
public int TabNormalWidth
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabNormalWidth; }
|
||
}
|
||
|
||
#region bar & tab color
|
||
|
||
public Color BarBorderColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarBorderColor; }
|
||
}
|
||
|
||
public Color BarBackColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarBackColor; }
|
||
}
|
||
|
||
public Color TabOutterBorderColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabOutterBorderColor; }
|
||
}
|
||
|
||
public Color TabInnerBorderColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabInnerBorderColor; }
|
||
}
|
||
public bool TabShowBorder
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabShowBorder; }
|
||
}
|
||
public Color TabActiveBackColorTop
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabActiveBackColorTop; }
|
||
}
|
||
|
||
public Color TabActiveBackColorBottom
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabActiveBackColorBottom; }
|
||
}
|
||
|
||
public Color TabDeactiveBackColorTop
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabDeactiveBackColorTop; }
|
||
}
|
||
|
||
public Color TabDeactiveBackColorBottom
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabDeactiveBackColorBottom; }
|
||
}
|
||
|
||
public Color BarBottomRegionBackColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_BarBottomRegionBackColor; }
|
||
}
|
||
public Color TabActiveForeColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabActiveForeColor; }
|
||
}
|
||
public Color TabDeactiveForeColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_TabDeactiveForeColor; }
|
||
}
|
||
#endregion
|
||
|
||
#region tab btn color
|
||
|
||
public ButtonColorTable NewTabBtnColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_NewTabBtnColor; }
|
||
}
|
||
|
||
public ButtonColorTable ListAllBtnColor
|
||
{
|
||
get { return _owner.XTheme.Mdi_ListAllBtnColor; }
|
||
}
|
||
|
||
public ButtonColorTable TabCloseBtnColor
|
||
{
|
||
get { return ButtonColorTable.GetDefaultCloseBtnColor(); }
|
||
}
|
||
|
||
#endregion
|
||
|
||
#endregion
|
||
|
||
#region Calculated Properties
|
||
|
||
public int BarWidth
|
||
{
|
||
get { return _owner.ClientSize.Width - Margin.Left - Margin.Right; }
|
||
}
|
||
|
||
public Rectangle Bounds
|
||
{
|
||
get
|
||
{
|
||
return new Rectangle(
|
||
_owner.ClientRectangle.Left + Margin.Left,
|
||
_owner.ClientRectangle.Top + Margin.Top,
|
||
BarWidth,
|
||
BarHeight);
|
||
}
|
||
}
|
||
|
||
public Rectangle BarBottomRegionBounds
|
||
{
|
||
get
|
||
{
|
||
return new Rectangle(
|
||
Bounds.Left,
|
||
Bounds.Top + (Bounds.Height - BarBottomRegionHeight),
|
||
BarWidth,
|
||
BarBottomRegionHeight);
|
||
}
|
||
}
|
||
|
||
public Rectangle HitTestBounds
|
||
{
|
||
get { return _hitTestBounds; }
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region private method
|
||
|
||
private MdiGMTabItem CreateNewTab(Form f)
|
||
{
|
||
MdiGMTabItem tab = new MdiGMTabItem(this);
|
||
tab.Form = f;
|
||
tab.CloseBtn = new WLButton(_owner)
|
||
{
|
||
ColorTable = TabCloseBtnColor,
|
||
BorderType = ButtonBorderType.Ellipse,
|
||
DrawForePathTwice = true,
|
||
//tab.CloseBtn.DrawLightGlass = true;
|
||
ClickSendBackOject = f,
|
||
ForePathGetter = new
|
||
ButtonForePathGetter(MGdu.WinFormUI.MyGraphics.GraphicsPathHelper.CreateSingleLineCloseFlag)
|
||
};
|
||
tab.CloseBtn.Click += new EventHandler(OnTabCloseBtnClick);
|
||
|
||
// menu item
|
||
tab.MenuItemPop = new ToolStripMenuItem();
|
||
tab.MenuItemPop.Tag = f;
|
||
tab.MenuItemPop.Click += new EventHandler(OnPopMenuItemClick);
|
||
_menuPopup.Items.Add(tab.MenuItemPop);
|
||
return tab;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步_listTabItems与mdi主窗体实际存在的子form
|
||
/// </summary>
|
||
private void CheckTabItemsWithOwnerMdiForm()
|
||
{
|
||
List<Form> listCurrent = _owner.GetCurrentMdiChildren();
|
||
List<Form> newForm = new List<Form>();
|
||
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
tab.IsStillValid = false;
|
||
|
||
foreach (Form f in listCurrent)
|
||
{
|
||
MdiGMTabItem tab;
|
||
if (IsTabItemsContaining(f, out tab))
|
||
tab.IsStillValid = true;
|
||
else
|
||
newForm.Add(f);
|
||
}
|
||
|
||
// remove the closed form tab
|
||
for (int i = _listTabItems.Count - 1; i >= 0; i--)
|
||
if (!_listTabItems[i].IsStillValid)
|
||
{
|
||
_menuPopup.Items.Remove(_listTabItems[i].MenuItemPop);
|
||
_listTabItems[i].MenuItemPop.Dispose();
|
||
_listTabItems.RemoveAt(i);
|
||
}
|
||
|
||
// create tabs for newly added forms
|
||
foreach (Form f in newForm)
|
||
{
|
||
_listTabItems.Add(CreateNewTab(f));
|
||
}
|
||
|
||
// find the active tab
|
||
int j = 0;
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (tab.Form == _owner.ActiveMdiChild)
|
||
{
|
||
_activeTabIndex = j;
|
||
tab.IsFormActive = true;
|
||
}
|
||
else
|
||
tab.IsFormActive = false;
|
||
j++;
|
||
}
|
||
}
|
||
|
||
private bool IsTabItemsContaining(Form f, out MdiGMTabItem theTab)
|
||
{
|
||
theTab = null;
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (f == tab.Form)
|
||
{
|
||
theTab = tab;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为每个tab分配空间,如果tab数目太多,则有些会被隐藏
|
||
/// </summary>
|
||
private void CalculateSpaceForEachTab()
|
||
{
|
||
int beginOld = _beginShowIndex;
|
||
int endOld = _endShowIndex;
|
||
_beginShowIndex = 0;
|
||
_endShowIndex = _listTabItems.Count - 1;
|
||
_hiddenTabsCount = 0;
|
||
|
||
int availableWidth = BarWidth - BarLeftPadding - BarRightPadding;
|
||
if (ShowNewTabBtn)
|
||
availableWidth -= (NewTabBtnSize.Width + NewTabBtnLeftSpace);
|
||
if (AlwaysShowListAllBtn)
|
||
availableWidth -= (ListAllBtnSize.Width + ListAllBtnLeftSpace * 2);
|
||
//int tabCount = _listTabItems.Count;
|
||
|
||
int widthAll = 0;
|
||
int tabShorterThanNormalCount = 0;
|
||
int tabLongerThanMinWidthCount = 0;
|
||
int index = 0;
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
tab.FinalWidth = tab.GetFullShowTabWidth();
|
||
widthAll += (tab.FinalWidth + (index > 0 ? TabAndTabSpace : 0));
|
||
if (tab.FinalWidth < TabNormalWidth)
|
||
tabShorterThanNormalCount++;
|
||
if (tab.FinalWidth > TabMinWidth && index != _activeTabIndex)
|
||
tabLongerThanMinWidthCount++;
|
||
index++;
|
||
}
|
||
|
||
if (widthAll <= availableWidth)
|
||
{
|
||
#region 1. 能以全文本方法显示所有
|
||
int extraWidth = availableWidth - widthAll;
|
||
|
||
//把剩余的空间分配给那些还没有达到normal宽度的tab
|
||
index=0;
|
||
while (extraWidth > 0 && tabShorterThanNormalCount > 0)
|
||
{
|
||
if (_listTabItems[index].FinalWidth < TabNormalWidth)
|
||
{
|
||
if (extraWidth > 2)
|
||
{
|
||
_listTabItems[index].FinalWidth += 2;
|
||
extraWidth -= 2;
|
||
}
|
||
else
|
||
{
|
||
_listTabItems[index].FinalWidth += extraWidth;
|
||
extraWidth = 0;
|
||
}
|
||
if (_listTabItems[index].FinalWidth >= TabNormalWidth)
|
||
tabShorterThanNormalCount--;
|
||
}
|
||
index++;
|
||
if (index >= _listTabItems.Count)
|
||
index = 0;
|
||
}
|
||
return;
|
||
#endregion
|
||
}
|
||
|
||
|
||
// 空间有限不能以全文本方式显示所有tab,则统一缩小非active的tab
|
||
int neededWidth = widthAll - availableWidth;
|
||
|
||
#region 缩小非active tab,直到其达到tabminwidth
|
||
// 统一缩小非active-tab,看是否能在所有tab达到min宽度前腾出空间
|
||
index = 0;
|
||
while (neededWidth > 0 && tabLongerThanMinWidthCount > 0)
|
||
{
|
||
if (_listTabItems[index].FinalWidth > TabMinWidth && index != _activeTabIndex)
|
||
{
|
||
int diff = _listTabItems[index].FinalWidth - TabMinWidth;
|
||
if (diff > 2)
|
||
{
|
||
_listTabItems[index].FinalWidth -= 2;
|
||
neededWidth -= 2;
|
||
}
|
||
else
|
||
{
|
||
_listTabItems[index].FinalWidth = TabMinWidth;
|
||
neededWidth -= diff;
|
||
}
|
||
if (_listTabItems[index].FinalWidth <= TabMinWidth)
|
||
tabLongerThanMinWidthCount--;
|
||
}
|
||
index++;
|
||
if (index >= _listTabItems.Count)
|
||
index = 0;
|
||
}
|
||
#endregion
|
||
|
||
if (neededWidth <= 0)
|
||
{
|
||
// 2. 缩小非actvie-tab后,可以全部显示
|
||
return;
|
||
}
|
||
|
||
if ((_listTabItems[_activeTabIndex].FinalWidth > TabNormalWidth))
|
||
{
|
||
// 若active-tab的宽度大于normal,则逐渐减小到normal
|
||
int width = _listTabItems[_activeTabIndex].FinalWidth;
|
||
while (width > TabNormalWidth && neededWidth > 0)
|
||
{
|
||
width--;
|
||
neededWidth--;
|
||
}
|
||
_listTabItems[_activeTabIndex].FinalWidth = width;
|
||
if (neededWidth <= 0)
|
||
{
|
||
// 3. 缩小active-tab达到normal宽度后,可以显示全部标签
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
#region 4. 隐藏相应的tab
|
||
if (!AlwaysShowListAllBtn)
|
||
{
|
||
availableWidth -= (ListAllBtnSize.Width + ListAllBtnLeftSpace * 2);
|
||
neededWidth += (ListAllBtnSize.Width + ListAllBtnLeftSpace * 2);
|
||
}
|
||
if (availableWidth < _listTabItems[_activeTabIndex].FinalWidth)
|
||
{
|
||
_listTabItems[_activeTabIndex].FinalWidth = availableWidth;
|
||
if (availableWidth < (TabCloseBtnSize.Width + TabSlopeWidth * 2))
|
||
_listTabItems[_activeTabIndex].FinalWidth = TabCloseBtnSize.Width + TabSlopeWidth * 2;
|
||
}
|
||
_hiddenTabsCount = neededWidth / (TabMinWidth + TabAndTabSpace);
|
||
if ((neededWidth % (TabMinWidth + TabAndTabSpace)) != 0)
|
||
_hiddenTabsCount++;
|
||
if (_hiddenTabsCount >= _listTabItems.Count)
|
||
_hiddenTabsCount = _listTabItems.Count - 1;
|
||
|
||
//先看一下之前所隐藏的tab数是否与将要隐藏的tab数一致,如果一致,
|
||
//且不影响active的显示,则不需要改变之前所隐藏的tab
|
||
//若不行,则简单点,先隐藏右边,不够的再隐藏左边
|
||
#region 设置哪些tabs被隐藏
|
||
int showTabCount = endOld - beginOld + 1;
|
||
if ((_listTabItems.Count - _hiddenTabsCount) == showTabCount)
|
||
{
|
||
if (endOld > _listTabItems.Count - 1)
|
||
{
|
||
endOld = _listTabItems.Count - 1;
|
||
beginOld = endOld - showTabCount + 1;
|
||
}
|
||
|
||
if (beginOld <= _activeTabIndex && endOld >= _activeTabIndex)
|
||
{
|
||
_beginShowIndex = beginOld;
|
||
_endShowIndex = endOld;
|
||
}
|
||
else
|
||
{
|
||
//平移一下,使_actvieTabIndex包含其中
|
||
if (_activeTabIndex < beginOld)
|
||
{
|
||
_beginShowIndex = _activeTabIndex;
|
||
_endShowIndex = _activeTabIndex + showTabCount - 1;
|
||
}
|
||
else
|
||
{
|
||
_endShowIndex = _activeTabIndex;
|
||
_beginShowIndex = _activeTabIndex - showTabCount + 1;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//先隐藏右边,不够的再隐藏左边
|
||
int tabCntAfterActive = _listTabItems.Count - (_activeTabIndex + 1);
|
||
if (tabCntAfterActive >= _hiddenTabsCount)
|
||
{
|
||
_beginShowIndex = 0;
|
||
_endShowIndex = _listTabItems.Count - 1 - _hiddenTabsCount;
|
||
}
|
||
else
|
||
{
|
||
_beginShowIndex = _hiddenTabsCount - tabCntAfterActive;
|
||
_endShowIndex = _activeTabIndex;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
// 再次把多出的空间重新分配给能显示的tab
|
||
int remainWidth = _hiddenTabsCount * (TabMinWidth + TabAndTabSpace) - neededWidth;
|
||
if (remainWidth > (_endShowIndex - _beginShowIndex + 1) * 3)
|
||
{
|
||
int average = remainWidth / (_endShowIndex - _beginShowIndex + 1);
|
||
for (int i = _beginShowIndex; i <= _endShowIndex; i++)
|
||
_listTabItems[i].FinalWidth += average;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
private void SetTabsVisibility()
|
||
{
|
||
for (int i = 0; i < _listTabItems.Count; i++)
|
||
{
|
||
if (i >= _beginShowIndex && i <= _endShowIndex)
|
||
_listTabItems[i].IsHidden = false;
|
||
else
|
||
_listTabItems[i].IsHidden = true;
|
||
}
|
||
}
|
||
|
||
private void SetTabsAndBarButtonBounds()
|
||
{
|
||
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
|
||
{
|
||
SetListAllBtnBounds();
|
||
SetEachTabBounds();
|
||
SetNewTabBtnBounds();
|
||
}
|
||
else
|
||
{
|
||
SetEachTabBounds();
|
||
SetNewTabBtnBounds();
|
||
SetListAllBtnBounds();
|
||
}
|
||
|
||
SetHitTestBounds();
|
||
}
|
||
|
||
private void SetHitTestBounds()
|
||
{
|
||
int right = Bounds.Right - BarRightPadding;
|
||
|
||
if(ListAllBtnAlign != BarButtonAlignmentType.Left &&
|
||
(AlwaysShowListAllBtn || _hiddenTabsCount>0))
|
||
{
|
||
right = ListAllBtnBounds.Right;
|
||
}
|
||
else if (ShowNewTabBtn)
|
||
{
|
||
right = NewTabBtnBounds.Right;
|
||
}
|
||
else if (_listTabItems.Count > 0 && _endShowIndex < _listTabItems.Count)
|
||
{
|
||
right = _listTabItems[_endShowIndex].Bounds.Right;
|
||
}
|
||
|
||
int left = Bounds.Left + BarLeftPadding;
|
||
int width = right - left;
|
||
|
||
_hitTestBounds = new Rectangle(left, Bounds.Top, width, Bounds.Height);
|
||
}
|
||
|
||
private void SetEachTabBounds()
|
||
{
|
||
int x = Bounds.X + BarLeftPadding;
|
||
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
|
||
{
|
||
if (AlwaysShowListAllBtn || _hiddenTabsCount > 0)
|
||
{
|
||
x = ListAllBtnBounds.Right + ListAllBtnLeftSpace;
|
||
}
|
||
}
|
||
if (_listTabItems.Count > 0)
|
||
{
|
||
for (int i = _beginShowIndex; i <= _endShowIndex; i++)
|
||
{
|
||
int height = _listTabItems[i].IsFormActive ? TabHeightActive : TabHeight;
|
||
int y = Bounds.Bottom - BarBottomRegionHeight - height;
|
||
int w = _listTabItems[i].FinalWidth;
|
||
_listTabItems[i].Bounds = new Rectangle(x, y, w, height);
|
||
x += (w + TabAndTabSpace);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void SetNewTabBtnBounds()
|
||
{
|
||
int tabsCount = _listTabItems.Count;
|
||
int x;
|
||
if (tabsCount > 0 && _endShowIndex < tabsCount)
|
||
{
|
||
x = _listTabItems[_endShowIndex].Bounds.Right + NewTabBtnLeftSpace;
|
||
if (x > (Bounds.Right - BarRightPadding - NewTabBtnSize.Width))
|
||
x = Bounds.Right - BarRightPadding - NewTabBtnSize.Width;
|
||
if (x < Bounds.Left + BarLeftPadding)
|
||
x = Bounds.Left + BarLeftPadding;
|
||
}
|
||
else
|
||
{
|
||
x = Bounds.Left + BarLeftPadding;
|
||
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
|
||
x = ListAllBtnBounds.Right + ListAllBtnLeftSpace;
|
||
}
|
||
int y = Bounds.Bottom - NewTabBtnBottomSpace - NewTabBtnSize.Height;
|
||
var size = ShowNewTabBtn ? NewTabBtnSize : Size.Empty;
|
||
if (size.Width > Bounds.Width)
|
||
size.Width = Bounds.Width;
|
||
NewTabBtnBounds = new Rectangle(new Point(x, y), size);
|
||
}
|
||
|
||
private void SetListAllBtnBounds()
|
||
{
|
||
int x;
|
||
if (ListAllBtnAlign == BarButtonAlignmentType.Left)
|
||
{
|
||
x = Bounds.X + BarLeftPadding;
|
||
}
|
||
else
|
||
{
|
||
x = NewTabBtnBounds.Right;
|
||
if (ShowNewTabBtn || _listTabItems.Count > 0)
|
||
x += ListAllBtnLeftSpace;
|
||
if (x > (Bounds.Right - BarRightPadding - ListAllBtnSize.Width))
|
||
x = Bounds.Right - BarRightPadding - ListAllBtnSize.Width;
|
||
}
|
||
int y = Bounds.Bottom - ListAllBtnBottomSpace - ListAllBtnSize.Height;
|
||
var size = ((_hiddenTabsCount>0 || AlwaysShowListAllBtn) ? ListAllBtnSize : Size.Empty);
|
||
if (size.Width > Bounds.Width)
|
||
size.Width = Bounds.Width;
|
||
ListAllBtnBounds = new Rectangle(new Point(x, y), size);
|
||
}
|
||
|
||
private void RenderEachBarItem(Graphics g)
|
||
{
|
||
Region oldClip = g.Clip;
|
||
Region newClip = new Region(Bounds);
|
||
g.Clip = newClip;
|
||
SmoothingMode oldMode = g.SmoothingMode;
|
||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||
|
||
DrawBarBorderAndBackground(g);
|
||
DrawEachTabItem(g);
|
||
DrawOtherBarButtons(g);
|
||
DrawBarBottomRegion(g);
|
||
|
||
g.SmoothingMode = oldMode;
|
||
g.Clip = oldClip;
|
||
newClip.Dispose();
|
||
}
|
||
|
||
private void DrawBarBorderAndBackground(Graphics g)
|
||
{
|
||
Rectangle rect = Bounds;
|
||
if (DrawBarBackgound)
|
||
{
|
||
using (SolidBrush sb = new SolidBrush(BarBackColor))
|
||
{
|
||
g.FillRectangle(sb, rect);
|
||
}
|
||
}
|
||
if (DrawBarBorder)
|
||
{
|
||
rect.Width--;
|
||
rect.Height--;
|
||
using (Pen p = new Pen(BarBorderColor))
|
||
{
|
||
g.DrawRectangle(p, rect);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void DrawBarBottomRegion(Graphics g)
|
||
{
|
||
// bottom region
|
||
using (SolidBrush sb = new SolidBrush(BarBottomRegionBackColor))
|
||
{
|
||
using (NewSmoothModeGraphics newGP = new NewSmoothModeGraphics(g, SmoothingMode.HighSpeed))
|
||
{
|
||
g.FillRectangle(sb, BarBottomRegionBounds);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void DrawOtherBarButtons(Graphics g)
|
||
{
|
||
// new-tab-btn
|
||
if (ShowNewTabBtn)
|
||
{
|
||
_newTabBtn.Bounds = NewTabBtnBounds;
|
||
_newTabBtn.DrawButton(g);
|
||
}
|
||
|
||
// list-all-btn
|
||
if (_hiddenTabsCount > 0 || AlwaysShowListAllBtn)
|
||
{
|
||
_listAllBtn.Bounds = ListAllBtnBounds;
|
||
if (_hiddenTabsCount == 0)
|
||
_listAllBtn.Text = string.Empty;
|
||
else
|
||
_listAllBtn.Text = _hiddenTabsCount.ToString();
|
||
_listAllBtn.DrawButton(g);
|
||
}
|
||
}
|
||
|
||
private void DrawEachTabItem(Graphics g)
|
||
{
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (!tab.IsHidden && !tab.IsFormActive)
|
||
RenderTabItem(g, tab);
|
||
}
|
||
// active-tab last
|
||
if (_listTabItems.Count > 0)
|
||
RenderTabItem(g, _listTabItems[_activeTabIndex]);
|
||
}
|
||
|
||
private void RenderTabItem(Graphics g, MdiGMTabItem tab)
|
||
{
|
||
Rectangle rect = tab.Bounds;
|
||
Region oldRegion = g.Clip;
|
||
Region newRegion = new Region(rect);
|
||
g.Clip = newRegion;
|
||
|
||
// fill backgroung
|
||
Color backTop,backBottom;
|
||
if (tab.IsFormActive)
|
||
{
|
||
backTop = TabActiveBackColorTop;
|
||
backBottom = TabActiveBackColorBottom;
|
||
}
|
||
else
|
||
{
|
||
backTop = TabDeactiveBackColorTop;
|
||
backBottom = TabDeactiveBackColorBottom;
|
||
}
|
||
|
||
// background
|
||
using (LinearGradientBrush lb = new LinearGradientBrush(
|
||
rect, backTop, backBottom, LinearGradientMode.Vertical))
|
||
{
|
||
using (GraphicsPath path = PathGetter.GetTabBorderPath(rect, TabSlopeWidth))
|
||
{
|
||
g.FillPath(lb, path);
|
||
}
|
||
}
|
||
|
||
// icon
|
||
if (ShowTabIcon && tab.Form.Icon != null)
|
||
{
|
||
if (tab.IconRect.Right < tab.Bounds.Right)
|
||
g.DrawIcon(tab.Form.Icon, tab.IconRect);
|
||
}
|
||
if (tab.IsFormActive)
|
||
{
|
||
// text
|
||
TextRenderer.DrawText(g, tab.Form.Text, tab.Form.Font, tab.TextRect,TabActiveForeColor,
|
||
TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
|
||
}
|
||
else
|
||
{
|
||
TextRenderer.DrawText(g, tab.Form.Text, tab.Form.Font, tab.TextRect, TabDeactiveForeColor,
|
||
TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
|
||
}
|
||
// outter border
|
||
rect.Width--;
|
||
rect.Height--;
|
||
if (TabShowBorder)
|
||
{
|
||
using (Pen p = new Pen(TabOutterBorderColor))
|
||
{
|
||
if (tab.IsFormActive)
|
||
{
|
||
Rectangle rectTab = tab.Bounds;
|
||
Rectangle rectBottom = BarBottomRegionBounds;
|
||
Point p1 = new Point(rectBottom.X, rectBottom.Y - 1);
|
||
Point p2 = new Point(rectTab.X, rectTab.Bottom - 1);
|
||
Point p3 = new Point(rectTab.X + TabSlopeWidth, rectTab.Y);
|
||
Point p4 = new Point(rectTab.Right - 1 - TabSlopeWidth, rectTab.Y);
|
||
Point p5 = new Point(rectTab.Right - 1, rectTab.Bottom - 1);
|
||
Point p6 = new Point(rectBottom.Right - 1, rectBottom.Y - 1);
|
||
g.Clip = oldRegion;
|
||
//g.DrawLines(p, new Point[] { p1, p2, p3, p4, p5, p6 });
|
||
g.Clip = newRegion;
|
||
}
|
||
else
|
||
{
|
||
using (GraphicsPath path = PathGetter.GetTabBorderPath(rect, TabSlopeWidth))
|
||
{
|
||
//g.DrawPath(p, path);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// inner border
|
||
rect.Inflate(-1, -1);
|
||
rect.Height++; // 为了使bar-bottom-region 与 active-tab 的连线能覆盖非 active-tab 的底部的线
|
||
if (TabShowBorder)
|
||
{
|
||
using (Pen p = new Pen(TabInnerBorderColor))
|
||
{
|
||
using (GraphicsPath path = PathGetter.GetTabBorderPath(rect, TabSlopeWidth))
|
||
{
|
||
g.DrawPath(p, path);
|
||
}
|
||
}
|
||
}
|
||
// do not let the active-tab to have bottom-line
|
||
if (tab.IsFormActive)
|
||
{
|
||
Rectangle rtmp = tab.Bounds;
|
||
Point p1 = new Point(rtmp.Left + 1, rtmp.Bottom - 1);
|
||
Point p2 = new Point(rtmp.Right - 2, rtmp.Bottom - 1);
|
||
using (Pen pen = new Pen(backBottom))
|
||
{
|
||
g.DrawLine(pen, p1, p2);
|
||
}
|
||
}
|
||
if (ShowTabCloseIcon)
|
||
{
|
||
//close btn
|
||
tab.CloseBtn.Bounds = tab.CloseBtnRect;
|
||
tab.CloseBtn.DrawButton(g);
|
||
}
|
||
g.Clip = oldRegion;
|
||
newRegion.Dispose();
|
||
}
|
||
|
||
#region mouse operation
|
||
|
||
private void MouseOperationDown(Point location)
|
||
{
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (!tab.IsHidden)
|
||
{
|
||
if (tab.Bounds.Contains(location) && !tab.CloseBtnRect.Contains(location))
|
||
{
|
||
tab.Capture = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private void MouseOperationUp(Point location)
|
||
{
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (!tab.IsHidden)
|
||
{
|
||
if (tab.Capture && tab.Bounds.Contains(location))
|
||
{
|
||
tab.Capture = false;
|
||
OnActivateChild(tab.Form);
|
||
//break;
|
||
}
|
||
}
|
||
tab.Capture = false;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#endregion
|
||
|
||
#region public method
|
||
|
||
/// <summary>
|
||
/// 重绘整个标签栏
|
||
/// </summary>
|
||
/// <param name="g"></param>
|
||
public void RenderTheBar(Graphics g)
|
||
{
|
||
// 先把已关闭的form对应的tab删除,对新加的form则为其创建相应tab
|
||
CheckTabItemsWithOwnerMdiForm();
|
||
|
||
if (_listTabItems.Count > 0)
|
||
{
|
||
// 按照指定方式为每个tab分配空间
|
||
CalculateSpaceForEachTab();
|
||
SetTabsVisibility();
|
||
}
|
||
|
||
SetTabsAndBarButtonBounds();
|
||
|
||
RenderEachBarItem(g);
|
||
|
||
if (ShowNewTabBtn)
|
||
{
|
||
if (_lastMouseUpLocation != Point.Empty)
|
||
{
|
||
//gdu debug: currently we need this to set the btn back to normal
|
||
if (!NewTabBtnBounds.Contains(_lastMouseUpLocation)
|
||
&& _newTabBtn.State == GMButtonState.Hover)
|
||
_newTabBtn.MouseOperation(_lastMouseUpLocation, MouseOperationType.Move);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理鼠标事件。该方法会触发一些click事件,重刷一些按钮等
|
||
/// </summary>
|
||
/// <param name="location"></param>
|
||
/// <param name="type"></param>
|
||
public void MouseOperation(Point location, MouseOperationType type)
|
||
{
|
||
//if (type == MouseOperationType.Up)
|
||
_lastMouseUpLocation = location;
|
||
//else
|
||
// _lastMouseUpLocation = Point.Empty;
|
||
|
||
if (ShowNewTabBtn)
|
||
_newTabBtn.MouseOperation(location, type);
|
||
if (_hiddenTabsCount > 0 || AlwaysShowListAllBtn)
|
||
_listAllBtn.MouseOperation(location, type);
|
||
foreach (MdiGMTabItem tab in _listTabItems)
|
||
{
|
||
if (!tab.IsHidden)
|
||
{
|
||
if (ShowTabCloseIcon)
|
||
{ tab.CloseBtn.MouseOperation(location, type); }
|
||
}
|
||
}
|
||
|
||
switch (type)
|
||
{
|
||
case MouseOperationType.Down:
|
||
MouseOperationDown(location);
|
||
break;
|
||
|
||
case MouseOperationType.Up:
|
||
MouseOperationUp(location);
|
||
break;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 该类表示一个单独的标签项
|
||
/// </summary>
|
||
internal class MdiGMTabItem
|
||
{
|
||
|
||
#region 内部变量
|
||
|
||
#endregion
|
||
|
||
// mdi bar which this tab item is belong to
|
||
MdiBarController _barContainer;
|
||
|
||
public MdiGMTabItem(MdiBarController barContainer)
|
||
{
|
||
_barContainer = barContainer;
|
||
IsStillValid = true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 该标签所对应的窗体
|
||
/// </summary>
|
||
public Form Form { get; set; }
|
||
|
||
public bool IsFormActive { get; set; }
|
||
|
||
/// <summary>
|
||
/// 最终分配到的整个tab的宽度
|
||
/// </summary>
|
||
public int FinalWidth { get; set; }
|
||
|
||
/// <summary>
|
||
/// 表示所对应的form是否仍未被关闭
|
||
/// </summary>
|
||
public bool IsStillValid { get; set; }
|
||
|
||
public Rectangle Bounds { get; set; }
|
||
|
||
public WLButton CloseBtn { get; set; }
|
||
|
||
public bool Capture { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否因空间不足而被隐藏
|
||
/// </summary>
|
||
public bool IsHidden { get; set; }
|
||
|
||
public ToolStripMenuItem MenuItemPop { get; set; }
|
||
|
||
public Rectangle IconRect
|
||
{
|
||
get
|
||
{
|
||
return new Rectangle(
|
||
Bounds.Left + _barContainer.IconLeftSpace,
|
||
Bounds.Top + (Bounds.Height - _barContainer.IconSize.Height) / 2,
|
||
_barContainer.IconSize.Width,
|
||
_barContainer.IconSize.Height);
|
||
}
|
||
}
|
||
|
||
public Rectangle TextRect
|
||
{
|
||
get
|
||
{
|
||
int x = IconRect.Right + _barContainer.TextLeftSpace;
|
||
int w = CloseBtnRect.Left - x;
|
||
if (w < 0)
|
||
w = 0;
|
||
return new Rectangle(x, Bounds.Top, w, Bounds.Height);
|
||
}
|
||
}
|
||
|
||
public Rectangle CloseBtnRect
|
||
{
|
||
get
|
||
{
|
||
return new Rectangle(
|
||
Bounds.Right - _barContainer.TabCloseBtnRightSpace - _barContainer.TabCloseBtnSize.Width,
|
||
Bounds.Top + (Bounds.Height - _barContainer.TabCloseBtnSize.Height) / 2,
|
||
_barContainer.TabCloseBtnSize.Width,
|
||
_barContainer.TabCloseBtnSize.Height);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回全部显示该标签文本所需的长度
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private int GetFullTextLength()
|
||
{
|
||
if (string.IsNullOrEmpty(Form.Text))
|
||
return 0;
|
||
return TextRenderer.MeasureText(Form.Text, Form.Font).Width;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回显示全部文本时该tab所需的宽度,该宽度不超过bar-container
|
||
/// 规定的tabmaxwidth
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public int GetFullShowTabWidth()
|
||
{
|
||
int w = _barContainer.TabSlopeWidth * 2 + _barContainer.IconSize.Width
|
||
+ _barContainer.IconLeftSpace + _barContainer.TabCloseBtnSize.Width
|
||
+ _barContainer.TabCloseBtnRightSpace + GetFullTextLength();
|
||
if (w > _barContainer.TabMaxWidth)
|
||
w = _barContainer.TabMaxWidth;
|
||
return w;
|
||
}
|
||
}
|
||
|
||
public enum BarButtonAlignmentType
|
||
{
|
||
/// <summary>
|
||
/// 居左
|
||
/// </summary>
|
||
Left,
|
||
/// <summary>
|
||
/// 显示在最后一个标签后面
|
||
/// </summary>
|
||
AfterLastTab,
|
||
}
|
||
|
||
internal static class PathGetter
|
||
{
|
||
public static GraphicsPath GetTabBorderPath(Rectangle rect, int slopeWidth)
|
||
{
|
||
GraphicsPath path = new GraphicsPath();
|
||
|
||
Point p1 = new Point(rect.X + slopeWidth, rect.Y);
|
||
Point p2 = new Point(rect.Right - slopeWidth, rect.Y);
|
||
Point p3 = new Point(rect.Right, rect.Bottom);
|
||
Point p4 = new Point(rect.X, rect.Bottom);
|
||
|
||
path.AddLine(p1, p2);
|
||
path.AddLine(p3, p4);
|
||
path.CloseFigure();
|
||
|
||
return path;
|
||
}
|
||
}
|
||
}
|