Hi, I post here the code for our gallery tooltips. The code is encapsulated in a wider class that is able to fill in a ribbon bar with various controls. We provide a "thin" object that implements callback interface and some meta-data for GUI. At the moment code is a bit messy and surely deserve a dedicated class ! Just pay attention to how 'tag' member is filled, that's the most messy part of the code.
This first method adds an item to a gallery described by 'site' parameter. If no such gallery exists a new one is created with tab and group.
The first part of the trick for tooltips is to listen to the three events : TrackingImage, MouseLeave and GalleryDropMenu.
- Code: Select all
private KryptonRibbonGroupGallery GetGalleryItem(IGalleryCallbacks callbacks, UIGalleryAttribute site, IUIItem item)
{
// Eventually localize the strings
site.Tab = StringLocalization.Get(site.Tab, callbacks.GetType().Assembly);
site.Group = StringLocalization.Get(site.Group, callbacks.GetType().Assembly);
KryptonRibbonGroup group = GetGroup(site);
KryptonRibbonGroupGallery gal = group.Items.FirstOrDefault(b => (((Object[])b.Tag)[1] as UIButtonAttribute).Name == site.Name) as KryptonRibbonGroupGallery;
if (gal == null)
{
gal = new KryptonRibbonGroupGallery();
gal.Tag = new Object[] { callbacks, site, new List<IUIItem>(), false };
gal.LargeItemCount = site.LargeItemCount;
gal.MediumItemCount = site.MediumItemCount;
gal.ImageList = new ImageList();
gal.ImageList.ColorDepth = ColorDepth.Depth32Bit;
gal.ImageList.ImageSize = new Size(site.ImageSize, site.ImageSize);
gal.Gallery.ButtonStyle = ButtonStyle.Form;
gal.SelectedIndexChanged += OnGalleryIndex;
group.Items.Add(gal);
gal.TrackingImage += GalleryTrackingImageCallback;
gal.Gallery.MouseLeave += GalleryMouseLeaveCallback;
gal.GalleryDropMenu += GalleryDropMenuCallback;
// This allow the callback to raise an event to manually change current selected index
callbacks.SelectedIndexChanged += new ItemIndexHandler((index) => { gal.SelectedIndex = index; });
}
if (item != null)
{
// Eventually localize the strings
item.Label = StringLocalization.Get(item.Label, callbacks.GetType().Assembly);
item.Tooltip = StringLocalization.Get(item.Tooltip, callbacks.GetType().Assembly);
gal.ImageList.Images.Add(item.Label, m_IconManager.GetImage(item.Image, callbacks.GetType().Assembly));
((List<IUIItem>)((Object[])gal.Tag)[2]).Add(item);
if (item.Index < 0)
item.Index = gal.ImageList.Images.Count - 1;
// This allows selected item to change when an action is executed outside GUI (from Undo/Redo) for exemple
item.IndexChanged += new ItemIndexHandler((index) => { gal.SelectedIndex = index; });
}
return gal;
}
And the code for those three callbacks is below :
- Code: Select all
private void GalleryTrackingImageCallback(object sender, ImageSelectEventArgs args)
{
KryptonRibbonGroupGallery gal = sender as KryptonRibbonGroupGallery;
bool dispose = true;
if (args.ImageIndex >= 0 && args.ImageIndex < args.ImageList.Images.Count)
{
string label = args.ImageList.Images.Keys[args.ImageIndex];
if (label != null && label != "")
{
VisualPopupToolTip toolTip = new VisualPopupToolTip(new PaletteRedirect(KryptonManager.CurrentGlobalPalette), new ContentValues(label), KryptonManager.CurrentGlobalPalette.GetRenderer());
if (gal.Gallery.Tag != null)
(gal.Gallery.Tag as VisualPopupToolTip).Dispose();
gal.Gallery.Tag = toolTip;
Point toolTipPos;
bool dropDownVisible = (bool)((Object[])gal.Tag)[3];
if (dropDownVisible)
{
toolTipPos = System.Windows.Forms.Cursor.Position;
toolTip.ShowCalculatingSize(toolTipPos);
}
else
{
// Beware of magic numbers !
KryptonRibbon rib = Menu as KryptonRibbon;
Rectangle galRect = gal.Gallery.RectangleToScreen(gal.Gallery.ClientRectangle);
Rectangle ribRect = rib.RectangleToScreen(rib.ClientRectangle);
int leftGalToCurPos = (System.Windows.Forms.Cursor.Position.X - galRect.Left - gal.Gallery.Padding.Left - 1);
// 4 stands for an item horizontal padding
int itemWidth = args.ImageList.ImageSize.Width + 4;
// 23 stands for the distance added by ShowCalculatingSize()
toolTipPos = new Point(galRect.Left + gal.Gallery.Padding.Left + 23 + ((leftGalToCurPos / itemWidth) * itemWidth), ribRect.Bottom - 23);
toolTip.ShowCalculatingSize(toolTipPos);
}
dispose = false;
}
}
if (dispose && gal.Gallery.Tag != null)
(gal.Gallery.Tag as VisualPopupToolTip).Dispose();
}
private void GalleryMouseLeaveCallback(object sender, EventArgs args)
{
KryptonGallery gal = sender as KryptonGallery;
if (gal.Tag != null)
(gal.Tag as VisualPopupToolTip).Dispose();
}
private void GalleryDropMenuClosedCallback(object sender, ToolStripDropDownClosedEventArgs e)
{
KryptonContextMenu menu = sender as KryptonContextMenu;
if (menu.Tag == null)
return;
KryptonRibbonGroupGallery gal = menu.Tag as KryptonRibbonGroupGallery;
if (gal.Tag == null)
return;
((Object[])gal.Tag)[3] = false;
}
private void GalleryDropMenuCallback(object sender, GalleryDropMenuEventArgs e)
{
KryptonRibbonGroupGallery gal = sender as KryptonRibbonGroupGallery;
e.KryptonContextMenu.Tag = gal;
e.KryptonContextMenu.Closed += GalleryDropMenuClosedCallback;
if (gal.Tag != null)
((Object[])gal.Tag)[3] = true;
}