// *********************************
// Message from Original Author:
//
// 2008 Jose Menendez Poo
// Please give me credit if you use this code. It's all I ask.
// Contact me for more info: menendezpoo@gmail.com
// *********************************
//
// Original project from http://ribbon.codeplex.com/
// Continue to support and maintain by http://officeribbon.codeplex.com/
using System.ComponentModel;
using System.Drawing;
namespace System.Windows.Forms
{
public class RibbonHost : RibbonItem
{
private Control ctl;
private Font ctlFont;
private Size ctlSize;
private RibbonElementSizeMode _lastSizeMode;
public event MouseEventHandler ClientMouseMove;
///
/// Occurs when the SizeMode of the controls container is changing. if you manually set the size of the control you need to set the Handled flag to true.
///
[Description("Occurs when the SizeMode of the Controls container is changing. if you manually set the size of the control you need to set the Handled flag to true.")]
public event RibbonHostSizeModeHandledEventHandler SizeModeChanging;
public delegate void RibbonHostSizeModeHandledEventHandler(object sender, RibbonHostSizeModeHandledEventArgs e);
///
/// Gets or sets the control that this item will host
///
public Control HostedControl
{
get => ctl;
set
{
ctl = value;
NotifyOwnerRegionsChanged();
//_mouseHook = new RibbonHelpers.GlobalHook(RibbonHelpers.GlobalHook.HookTypes.Mouse);
//_mouseHook.MouseDown += new MouseEventHandler(_mouseHook_MouseDown);
//_mouseHook.MouseUp += new MouseEventHandler(_mouseHook_MouseUp);
if (ctl != null && Site == null)
{
//changing the owner changes the font so let save it for future use
ctlFont = ctl.Font;
ctlSize = ctl.Size;
//hook into some needed events
ctl.MouseMove += ctl_MouseMove;
CanvasChanged += RibbonHost_CanvasChanged;
//we must know when our tab changes so we can hide the control
if (OwnerTab != null)
Owner.ActiveTabChanged += Owner_ActiveTabChanged;
//the control must always have the same parent as the host item so set it here.
if (Owner != null)
Owner.Controls.Add(ctl);
ctl.Font = ctlFont;
/*Initially set the control to be hidden. If it needs to be displayed immediately it will get set in the
* placecontrol function. This was located at the top of the function, however it caused the control
* if located on a dropdown to not appear the correct size. A second showing fixed the issue. Seems to
* because the control is added to the ribbon while invisible??? */
ctl.Visible = false;
}
}
}
///
/// Raises the paint event and draws the control
///
///
///
public override void OnPaint(object sender, RibbonElementPaintEventArgs e)
{
if (Owner != null)
{
StringFormat f = StringFormatFactory.CenterNoWrap(StringTrimming.None);
if (Site != null && Site.DesignMode)
{
Owner.Renderer.OnRenderRibbonItemText(new RibbonTextEventArgs(Owner, e.Graphics, Bounds, this, Bounds, Site.Name, f));
}
else
{
Owner.Renderer.OnRenderRibbonItemText(new RibbonTextEventArgs(Owner, e.Graphics, Bounds, this, Bounds, Text, f));
if (ctl != null)
{
if (ctl.Parent != Canvas)
Canvas.Controls.Add(ctl);
//time to show our control
ctl.Location = new Point(Bounds.Left, (SizeMode == RibbonElementSizeMode.DropDown) ? Bounds.Top : Bounds.Top);
ctl.Visible = true;
ctl.BringToFront();
}
}
}
}
///
/// Sets the bounds of the panel
///
///
public override void SetBounds(Rectangle bounds)
{
base.SetBounds(bounds);
}
///
/// Measures the size of the panel on the mode specified by the event object
///
///
///
///
///
public override Size MeasureSize(object sender, RibbonElementMeasureSizeEventArgs e)
{
if (Site != null && Site.DesignMode && Owner != null)
{
//when in design mode just paint the name of this control
int Width = Convert.ToInt32(e.Graphics.MeasureString(Site.Name, Owner.Font).Width);
int Height = 20;
SetLastMeasuredSize(new Size(Width, Height));
}
else if (ctl == null || !Visible)
SetLastMeasuredSize(new Size(0, 0));
else
{
ctl.Visible = false;
if (_lastSizeMode != e.SizeMode)
{
_lastSizeMode = e.SizeMode;
RibbonHostSizeModeHandledEventArgs hev = new RibbonHostSizeModeHandledEventArgs(e.Graphics, e.SizeMode);
OnSizeModeChanging(ref hev);
}
SetLastMeasuredSize(new Size(ctl.Size.Width, ctl.Size.Height));
}
return LastMeasuredSize;
}
///
/// Call this method when you need to close a popup that the control is contained in
///
public void HostCompleted()
{
//Kevin Carbis - Clear everything by simulating the click event on the parent item
//just in case we are in a popup window
OnClick(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0));
}
///
/// Raises the event
///
///
public virtual void OnSizeModeChanging(ref RibbonHostSizeModeHandledEventArgs e)
{
if (SizeModeChanging != null)
{
SizeModeChanging(this, e);
}
}
private void PlaceControls()
{
if (ctl != null && Site == null)
{
ctl.Location = new Point(Bounds.Left + 1, Bounds.Top + 1);
//if we are located directly in a panel then we need to make sure the panel is not in overflow
//mode or we will look bad showing on the panel when we shouldn't be
if ((Canvas is Ribbon) && (OwnerPanel != null && OwnerPanel.SizeMode == RibbonElementSizeMode.Overflow))
ctl.Visible = false;
}
}
private void ctl_MouseMove(object sender, MouseEventArgs e)
{
// Note: Unlike all other Ribbon components, e.X and e.Y coordinates are based on the controls Top and Left, not the Ribbons.
//Console.WriteLine(e.Location.ToString());
/* If control is on the Ribbon send the mouse move event to the Ribbon directly, converting from
* control coordinates to Ribbon coordinates. */
if (OwnerItem == null)
{
MouseEventArgs eRibbonArgs = new MouseEventArgs(e.Button, e.Clicks,
Owner.PointToClient(ctl.PointToScreen(e.Location)).X,
Owner.PointToClient(ctl.PointToScreen(e.Location)).Y, e.Delta);
/* This should probably raise an event, however there is no reference to hosted controls on the Ribbon.
* In the future, probably better to have a control collection for hosted controls on the Ribbon and monitor the
* mousemove there and filter down. */
Owner.OnRibbonHostMouseMove(eRibbonArgs);
}
else
{
// Raise MouseMove event to any container (i.e. containing DropDown).
MouseEventArgs eContArgs = new MouseEventArgs(e.Button, e.Clicks, Bounds.Left + e.X, Bounds.Top + e.Y, e.Delta);
if (ClientMouseMove != null)
ClientMouseMove(this, eContArgs);
}
OnMouseMove(e);
}
private void Owner_ActiveTabChanged(object sender, EventArgs e)
{
//hide this control if our tab is not the active tab
if (ctl != null && OwnerTab != null && Owner.ActiveTab != OwnerTab)
ctl.Visible = false;
}
private void RibbonHost_CanvasChanged(object sender, EventArgs e)
{
if (ctl != null)
{
Canvas.Controls.Add(ctl);
ctl.Font = ctlFont;
//ctl.Location = new System.Drawing.Point(Bounds.Left + 1, Bounds.Top + 1);
}
}
internal override void SetSizeMode(RibbonElementSizeMode sizeMode)
{
base.SetSizeMode(sizeMode);
if (ctl != null && OwnerPanel != null && OwnerPanel.SizeMode == RibbonElementSizeMode.Overflow)
{
ctl.Visible = false;
}
}
}
}