|
|
How could I implement this?
Regards, ... Miguel
|
|
|
|
|
After six years I answer myself.
To support tooltip in Tabs, add the following code;
In class 'FATabStrip' add fields:
FATabStripItem tabTooltipFocus = null;
ToolTip tooltip = new ToolTip();
Inside method 'OnMouseMove(), to the end':
#region ToolTip management
FATabStripItem item = GetTabItemByPoint(e.Location);
if (item != null && item != tabTooltipFocus)
{
tabTooltipFocus = item;
OnMouseTabEnter(item, e.Location);
}
else if(item != tabTooltipFocus)
{
OnMouseTabLeave(item, e.Location);
tabTooltipFocus = null;
}
#endregion ToolTip management
Inside method 'OnMouseLeave()' and after 'base.OnMouseLeave()':
#region ToolTip management
tooltip.Hide(this);
tabTooltipFocus = null;
#endregion ToolTip management
and two new methos:
void OnMouseTabEnter(FATabStripItem item, Point pos)
{
Point p = new Point(pos.X, Cursor.Size.Height);
if(!String.IsNullOrEmpty(item.ToolTipText))
{
tooltip.Show(item.ToolTipText, this, p);
}
}
void OnMouseTabLeave(FATabStripItem item, Point pos)
{
tooltip.Hide(this);
}
and finally in the FATabStripItem class the property:
string ToolTipText_;
[Browsable(false)]
public string ToolTipText
{
get { return ToolTipText_; }
set
{
ToolTipText_ = value;
}
}
and as would the rabbit Bugs Bunny... That's all folks ...!
Unfortunately I just checked in Linux (mono-winforms) the call to "System.Windows.Forms.Cursor.Current.Size.Height" and also "Cursor.Size.Height" always returns zero.
To work well in Linux need to modify the code as follows:
void OnMouseTabEnter(FATabStripItem item, Point pos)
{
Point p;
int curHeight = System.Windows.Forms.Cursor.Current.Size.Height;
if(curHeight <= 0)
curHeight = (int)item.StripRect.Height + 10;
p = new Point(pos.X, curHeight);
if (!String.IsNullOrEmpty(item.TabPageToolTipText))
{
tooltip.Show(item.TabPageToolTipText, this, p);
}
}
No, it is not quite finished! After numerous tests, new code that is consistent across Windows and Linux:
In the constructor of class "FATabStrip", replace old code by;
tooltip = new ToolTip();
tooltip.ReshowDelay = 500;
tooltip.InitialDelay = 500;
tooltip.Popup += (object sender, PopupEventArgs e) => {
Point mp = PointToClient(MousePosition);
FATabStripItem item = GetTabItemByPoint(mp);
if(item == null)
e.Cancel = true;
};
Inside method 'OnMouseMove(), to the end', replace old code by:
#region ToolTip management
FATabStripItem item = GetTabItemByPoint(e.Location);
if (item != null && item != lastTabFocus)
{
if (ToolTipVisible == false)
{
lastTabFocus = item;
OnMouseTabEnter(item, e.Location);
}
else
{
if(Environment.OSVersion.Platform != PlatformID.Unix)
tooltip.RemoveAll();
OnMouseTabLeave(lastTabFocus);
lastTabFocus = null;
}
}
if(item == null && lastTabFocus != null)
{
if(Environment.OSVersion.Platform != PlatformID.Unix)
tooltip.RemoveAll();
OnMouseTabLeave(lastTabFocus);
lastTabFocus = null;
}
#endregion ToolTip management
Replace old fields;
FATabStripItem tabTooltipFocus = null;
ToolTip tooltip = new ToolTip();
by new fields;
FATabStripItem lastTabFocus = null;
ToolTip tooltip;
bool ToolTipVisible = false;
and new methods;
void OnMouseTabEnter(FATabStripItem item, Point pos)
{
if (!String.IsNullOrEmpty(item.TabPageToolTipText))
{
tooltip.SetToolTip(this, item.TabPageToolTipText);
ToolTipVisible = true;
}
}
void OnMouseTabLeave(FATabStripItem item)
{
tooltip.Hide(this);
ToolTipVisible = false;
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
#region ToolTip management
if(Environment.OSVersion.Platform != PlatformID.Unix)
tooltip.RemoveAll();
tooltip.Hide(this);
lastTabFocus = null;
ToolTipVisible = false;
#endregion ToolTip management
menuGlyph.IsMouseOver = false;
Invalidate(menuGlyph.Bounds);
closeButton.IsMouseOver = false;
Invalidate(closeButton.Bounds);
}
Yes now!That's it, buddy! I hope that the translator has done his job ...
modified 2-Feb-16 14:37pm.
|
|
|
|
|
VS 2010 projects produce
Warning 3 The referenced assembly "E:\Projects\TabStrip\bin\Debug\TabStrip.dll" could not be resolved because it has a dependency on "System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which is not in the currently targeted framework ".NETFramework,Version=v4.0,Profile=Client". Please remove references to assemblies not in the targeted framework or consider retargeting your project. Rolodex
when compiled.
VS 2005 projects work fine as do VS 2005 projects converted to VS 2010.
This is beyond my skills. Any advice?
Thanks
Enkur
|
|
|
|
|
Using full version of .NET and not the client profile versions will solve this problem.
|
|
|
|
|
I downloaded and installed the full .net, dotNetFx40_Full_setup.exe. It didn't help. I worked around the problem by restarting the project with VS 2005 then converting to VS 2010.
Thanks none-the-less,
Enkur
|
|
|
|
|
You have to set the Target Framework in VS to use '.Net Framework 4' and not '.Net Framework 4 Client Profile'
If you using VB.Net, to change the setting go to the properties, click 'compile' on the left tab, then click 'Advanced Compile options' button. From the 'Target Framework' drop down select '.Net Framework 4'
|
|
|
|
|
مهندس.. وقتی دات نت 4 انتخاب میشه.. تقویم اشتباه محاسبه میکنه
مثلا 10 تیر 1391 که روز شنبه میشه... توی این تقویم 5شنبه نشون داده میشه که اشتباه است.
لطفا یه راحلی برا این موضوع ارائه بدین..
متشکرم
|
|
|
|
|
After using this as a base for a gui I was working on I decided to post some of the extensions I added that answer some of your questions, see below:
Autoscroll
To answer the previous concerns about autoscrolling. I just docked a panel inside my tabpage:
Panel panel1 = new Panel();
panel1.AutoScroll = true;
UserControl1 uc1 = new UserControl1();
uc1.Dock = DockStyle.Fill;
panel1.Dock = DockStyle.Fill;
panel1.Controls.Add(uc1);
FATabStripItem tp = new FATabStripItem(treeView1.SelectedNode.Name, panel1);
Draggable
I updated FarsiLibrary.Win.FATabStrip class:
First add the following method to perform the move of the tabpage:
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (moved)
{
Point p = new Point(e.X, e.Y);
FATabStripItem dest = this.GetTabItemByPoint(p);
FATabStripItem src = selectedItem;
if (dest != null && src != null && dest != src)
{
System.Collections.ArrayList ar = new System.Collections.ArrayList(items.Count);
int srcint = items.IndexOf(src);
int destint = items.IndexOf(dest);
for (int i = 0; i < items.Count; i++)
{
if (i != srcint)
ar.Add(items[i]);
}
ar.Insert(destint, src);
items.Clear();
items.AddRange((FATabStripItem[])ar.ToArray(typeof(FATabStripItem)));
selectedItem = src;
}
}
moved = false;
dragging = false;
Cursor = Cursors.Default;
}
Then modify the following methods:
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button != MouseButtons.Left)
return;
HitTestResult result = HitTest(e.Location);
if(result == HitTestResult.MenuGlyph)
{
HandledEventArgs args = new HandledEventArgs(false);
OnMenuItemsLoading(args);
if (!args.Handled)
OnMenuItemsLoad(EventArgs.Empty);
ShowMenu();
}
else if (result == HitTestResult.CloseButton)
{
if (SelectedItem != null)
{
TabStripItemClosingEventArgs args = new TabStripItemClosingEventArgs(SelectedItem);
OnTabStripItemClosing(args);
if (!args.Cancel && SelectedItem.CanClose)
{
RemoveTab(SelectedItem);
OnTabStripItemClosed(EventArgs.Empty);
}
}
}
else if(result == HitTestResult.TabItem)
{
FATabStripItem item = GetTabItemByPoint(e.Location);
if (item != null)
{
SelectedItem = item;
dragging = true;
}
}
Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
moved = dragging;
if (moved)
Cursor = Cursors.UpArrow;
if (menuGlyph.Bounds.Contains(e.Location))
{
menuGlyph.IsMouseOver = true;
Invalidate(menuGlyph.Bounds);
}
else
{
if (menuGlyph.IsMouseOver && !menuOpen)
{
menuGlyph.IsMouseOver = false;
Invalidate(menuGlyph.Bounds);
}
}
if (closeButton.Bounds.Contains(e.Location))
{
closeButton.IsMouseOver = true;
Invalidate(closeButton.Bounds);
}
else
{
if (closeButton.IsMouseOver)
{
closeButton.IsMouseOver = false;
Invalidate(closeButton.Bounds);
}
}
}
protected override void OnMouseLeave(EventArgs e)
{
dragging = false;
moved = false;
base.OnMouseLeave(e);
menuGlyph.IsMouseOver = false;
Invalidate(menuGlyph.Bounds);
closeButton.IsMouseOver = false;
Invalidate(closeButton.Bounds);
}
You will also need to add these two fields:
private bool dragging = false;
private bool moved = false;
Feel free to change the cursor image, I used uparrow, but whatever meets your need. A good improvement would be to change cursor in the hover event when hovering over a tab rectangle.
Tab-Effects
For Colored Tabs and tabs with images on them I modified the item class FarsiLibrary.Win.FATabStripItem
add these fields:
private Color tabColor = SystemColors.Window;
private Color selectColor = SystemColors.Control;
and these properties:
public Color TabColor
{
get { return tabColor; }
set { tabColor = value; }
}
public Color SelectColor
{
get { return selectColor; }
set { selectColor = value; }
}
In the class FarsiLibrary.Win.FATabStrip I modified the method OnDrawTabPage. As you can see I only modified the left-to-right section but feel free to write mirror code for the right to left if you need it.
private void OnDrawTabPage(Graphics g, FATabStripItem currentItem)
{
bool isFirstTab = Items.IndexOf(currentItem) == 0;
Font currentFont = Font;
int imageWidth = (currentItem.Image != null)? currentItem.Image.Size.Width : 0;
if (currentItem == SelectedItem)
currentFont = new Font(Font, FontStyle.Bold);
SizeF textSize = g.MeasureString(currentItem.Title, currentFont, new SizeF(200, 10), sf);
textSize.Width += 25 + imageWidth;
RectangleF buttonRect = currentItem.StripRect;
GraphicsPath path = new GraphicsPath();
LinearGradientBrush brush;
int mtop = 3;
#region Draw Not Right-To-Left Tab
if (RightToLeft == RightToLeft.No)
{
if (currentItem == SelectedItem || isFirstTab)
{
path.AddLine(buttonRect.Left - 10, buttonRect.Bottom - 1,
buttonRect.Left + (buttonRect.Height/2) - 4, mtop + 4);
}
else
{
path.AddLine(buttonRect.Left, buttonRect.Bottom - 1, buttonRect.Left,
buttonRect.Bottom - (buttonRect.Height/2) - 2);
path.AddLine(buttonRect.Left, buttonRect.Bottom - (buttonRect.Height/2) - 3,
buttonRect.Left + (buttonRect.Height/2) - 4, mtop + 3);
}
path.AddLine(buttonRect.Left + (buttonRect.Height/2) + 2, mtop, buttonRect.Right - 3, mtop);
path.AddLine(buttonRect.Right, mtop + 2, buttonRect.Right, buttonRect.Bottom - 1);
path.AddLine(buttonRect.Right - 4, buttonRect.Bottom - 1, buttonRect.Left, buttonRect.Bottom - 1);
path.CloseFigure();
if (currentItem == SelectedItem)
{
brush =
new LinearGradientBrush(buttonRect, SystemColors.ControlLightLight, currentItem.SelectColor,
LinearGradientMode.Vertical);
}
else
{
brush =
new LinearGradientBrush(buttonRect, SystemColors.ControlLightLight, currentItem.TabColor,
LinearGradientMode.Vertical);
}
g.FillPath(brush, path);
g.DrawPath(SystemPens.ControlDark, path);
if (currentItem == SelectedItem)
{
g.DrawLine(new Pen(brush), buttonRect.Left - 9, buttonRect.Height + 2,
buttonRect.Left + buttonRect.Width - 1, buttonRect.Height + 2);
}
if (currentItem.Image != null)
g.DrawImage(currentItem.Image, new PointF(buttonRect.Left + buttonRect.Height-5, buttonRect.Top + (buttonRect.Height-currentItem.Image.Size.Height)/2));
PointF textLoc = new PointF(buttonRect.Left + buttonRect.Height + imageWidth, buttonRect.Top + (buttonRect.Height/2) - (textSize.Height/2) - 3);
RectangleF textRect = buttonRect;
textRect.Location = textLoc;
textRect.Width = buttonRect.Width - (textRect.Left - buttonRect.Left) - 4;
textRect.Height = textSize.Height + currentFont.Size/2;
if (currentItem == SelectedItem)
{
g.DrawString(currentItem.Title, currentFont, new SolidBrush(currentItem.ForeColor), textRect, sf);
}
else
{
g.DrawString(currentItem.Title, currentFont, new SolidBrush(currentItem.ForeColor), textRect, sf);
}
}
#endregion
#region Draw Right-To-Left Tab
currentItem.IsDrawn = true;
}
Finally I updated OnCalcTabPage method to make the tab a couple pixels longer:
private void OnCalcTabPage(Graphics g, FATabStripItem currentItem)
{
Font currentFont = Font;
if (currentItem == SelectedItem)
currentFont = new Font(Font, FontStyle.Bold);
SizeF textSize = g.MeasureString(currentItem.Title, currentFont, new SizeF(200, 10), sf);
textSize.Width += 23;
if (RightToLeft == RightToLeft.No)
{
RectangleF buttonRect = new RectangleF(DEF_START_POS, 3, textSize.Width, 17);
currentItem.StripRect = buttonRect;
DEF_START_POS += (int) textSize.Width;
}
else
{
RectangleF buttonRect = new RectangleF(DEF_START_POS - textSize.Width + 1, 3, textSize.Width - 1, 17);
currentItem.StripRect = buttonRect;
DEF_START_POS -= (int) textSize.Width;
}
}
|
|
|
|
|
how to do this in VB.NET? code converted does not work.
|
|
|
|
|
Hi guys.
Thank Hadi Eskandari for your works is greate.
I have a question is
How can i increase with and height of content area where Tabstripitem hosted controls?.
|
|
|
|
|
Great control specially for someone looking for RTL support. Missing support for mnemonic to activate tab page by keyboard shortcut key
|
|
|
|
|
Maybe this change can be useful to anyone
In only changes OnMouseDown as follows:
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Middle)
{
TabPageVisualStudio item = GetTabItemByPoint(e.Location);
if (item != null)
{
CloseTab(item);
}
return;
}
if (e.Button != MouseButtons.Left)
return;
HitTestResult result = HitTest(e.Location);
if (result == HitTestResult.MenuGlyph)
{
HandledEventArgs args = new HandledEventArgs(false);
OnMenuItemsLoading(args);
if (!args.Handled)
OnMenuItemsLoad(EventArgs.Empty);
ShowMenu();
}
else if (result == HitTestResult.CloseButton)
{
if (SelectedItem != null)
{
CloseTab(SelectedItem);
}
}
else if (result == HitTestResult.TabItem)
{
TabPageVisualStudio item = GetTabItemByPoint(e.Location);
if (item != null)
{
SelectedItem = item;
}
}
Invalidate();
}
... again, good work!
|
|
|
|
|
Hello,
Is there any way to detect when the mouse enters a strip. This could be useful to, for example, activate a tab when dragging items from any other tab.
By now, I added a new event:
public event Action<TabPageVisualStudio, MouseEventArgs> OnMouseOverTabStrip;
... and modified OnMouseMove as follows:
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (menuGlyph.Bounds.Contains(e.Location))
{
menuGlyph.IsMouseOver = true;
Invalidate(menuGlyph.Bounds);
}
else
{
if (menuGlyph.IsMouseOver && !menuOpen)
{
menuGlyph.IsMouseOver = false;
Invalidate(menuGlyph.Bounds);
}
}
if (closeButton.Bounds.Contains(e.Location))
{
closeButton.IsMouseOver = true;
Invalidate(closeButton.Bounds);
}
else
{
if (closeButton.IsMouseOver)
{
closeButton.IsMouseOver = false;
Invalidate(closeButton.Bounds);
}
}
var tab = GetTabItemByPoint(e.Location);
if (tab != null)
{
if (OnMouseOverTabStrip != null) OnMouseOverTabStrip(tab, e);
}
}
It works for me, but I'm not an expert creating user controls, so I don't know if it is elegant.
Thank you and very very good work !
modified on Friday, March 11, 2011 7:15 AM
|
|
|
|
|
aghrr... Control is great, but AutoScroll in tabstripitem doesn't work...
|
|
|
|
|
|
I encountered an error for TabStrip.
When I add a controlDataGridView on form1, after running form and return to form but the tabPages been deleted
|
|
|
|
|
I recently started from scratch on a tab control just because I wanted that close button and drop down list. But this tab control is almost perfect. even though it mimics VS's tabs almost perfectly. I think I will modify it to support Tab Icons. I really like tab icons, and I am disappointed that VS lacks them.
Thanks for this
|
|
|
|
|
I just wanted to say thanks for this great control set! This is exactly what I was looking for and it is easy to use. It is amazing that Microsoft hasn't added support for this into SDK.
FYI, works great with VS2010.
|
|
|
|
|
Hi,
How can I get a close button with event per FATabStripItem, right side of TitleText like IE8 tabs ?
|
|
|
|
|
If you notice, you need to change path.AddLine(buttonRect.Right, mtop + 2, buttonRect.Right, buttonRect.Bottom - 1); to path.AddLine(buttonRect.Right - 1, mtop + 2, buttonRect.Right, buttonRect.Bottom - 1);
You'll notice at the RIGHT-line of the SELECTED TAB while it is "over" another tab.
Any VB.Net Implimentations? ;_;
modified 20-Apr-22 21:01pm.
|
|
|
|
|
Excellent job.
Could you please tell me how I can move the tab bar to the bottom of the control?
Or, is it possible to dock it to any side of the screen?
Thanks,
coby
|
|
|
|
|
It's possible to have it in vb.net... it would be very useful for me... i tried to do it in vb.net but i didn't manage to make it work... can you help me? thx
|
|
|
|
|
I was attempting to use this control nested inside of other controls [I end up with a few split containers, and a couple of these things nested a few layers deep]. Once I threw a FlowLayoutPanel into the mix AND tried to have the FlowLayoutPanel resize its contained controls, I noticed that it would not resize the contained controls.
One way that I found to solve this was to add the following to FATabStrip.cs:
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
foreach (Control item in this.Controls)
{
FATabStripItem tabItem = item as FATabStripItem;
tabItem.SuspendLayout();
}
base.SetBoundsCore(x, y, width, height, specified);
foreach (Control item in this.Controls)
{
FATabStripItem tabItem = item as FATabStripItem;
tabItem.ResumeLayout();
}
}
|
|
|
|
|
Actually, even with the code above I still had the same problem when things got further nested [my most deeply nested item was quite a few layers deep in the control hierarchy] because I started making heavy use of OO for my base controls, etc.
The following piece of code in FATabStrip solved my problem and doesn't seem to slow it down:
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
Suspend(this);
base.SetBoundsCore(x, y, width, height, specified);
Resume(this);
}
private void Suspend(Control item)
{
item.SuspendLayout();
foreach (Control innerItem in item.Controls)
{
Suspend(innerItem);
}
}
private void Resume(Control item)
{
item.ResumeLayout();
foreach (Control innerItem in item.Controls)
{
Resume(innerItem);
}
}
Maybe this will help anybody else that ends up with controls which do not resize/repaint themselves correctly when using this control [and others that are similar to this control].
|
|
|
|
|