tangxu
2024-10-14 6cd995b71dfc74d4d96347d0bc535fddf36fa9df
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// *********************************
// 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;
 
        /// <summary>
        /// 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.
        /// </summary>
        [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);
 
        /// <summary>
        /// Gets or sets the control that this item will host
        /// </summary>
        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;
 
                }
            }
        }
 
        /// <summary>
        /// Raises the paint event and draws the control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        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();
                    }
                }
            }
        }
 
        /// <summary>
        /// Sets the bounds of the panel
        /// </summary>
        /// <param name="bounds"></param>
        public override void SetBounds(Rectangle bounds)
        {
            base.SetBounds(bounds);
        }
        /// <summary>
        /// Measures the size of the panel on the mode specified by the event object
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        /// 
        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;
        }
 
        /// <summary>
        /// Call this method when you need to close a popup that the control is contained in
        /// </summary>
        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));
        }
 
        /// <summary>
        /// Raises the <see cref="SizeModeChanging"/> event
        /// </summary>
        /// <param name="e"></param>
        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;
            }
        }
    }
}