Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/WinFormsUI/Docking/DockPanel.MdiClientController.cs @ 2508

Last change on this file since 2508 was 2134, checked in by gkronber, 15 years ago

Added up to date source of Weifen Luo dock panel suit in a separate project (and added strong name key). Removed binary versions of Weifen Luo dock panel suite and references to it. #687 (Update AdvancedOptimizationFrontend to use more recent version of Weifen Luo Docking library)

File size: 16.3 KB
Line 
1using System;
2using System.Drawing;
3using System.Windows.Forms;
4using System.ComponentModel;
5using System.ComponentModel.Design;
6using System.Runtime.InteropServices;
7
8namespace WeifenLuo.WinFormsUI.Docking
9{
10    partial class DockPanel
11    {
12        //  This class comes from Jacob Slusser's MdiClientController class:
13        //  http://www.codeproject.com/cs/miscctrl/mdiclientcontroller.asp
14        private class MdiClientController : NativeWindow, IComponent, IDisposable
15        {
16            private bool m_autoScroll = true;
17            private BorderStyle m_borderStyle = BorderStyle.Fixed3D;
18            private MdiClient m_mdiClient = null;
19            private Form m_parentForm = null;
20            private ISite m_site = null;
21
22            public MdiClientController()
23            {
24            }
25
26            public void Dispose()
27            {
28                Dispose(true);
29                GC.SuppressFinalize(this);
30            }
31
32            protected virtual void Dispose(bool disposing)
33            {
34                if (disposing)
35                {
36                    lock (this)
37                    {
38                        if (Site != null && Site.Container != null)
39                            Site.Container.Remove(this);
40
41                        if (Disposed != null)
42                            Disposed(this, EventArgs.Empty);
43                    }
44                }
45            }
46
47            public bool AutoScroll
48            {
49                get { return m_autoScroll; }
50                set
51                {
52                    // By default the MdiClient control scrolls. It can appear though that
53                    // there are no scrollbars by turning them off when the non-client
54                    // area is calculated. I decided to expose this method following
55                    // the .NET vernacular of an AutoScroll property.
56                    m_autoScroll = value;
57                    if (MdiClient != null)
58                        UpdateStyles();
59                }
60            }
61
62            public BorderStyle BorderStyle
63            {
64                set
65                {
66                    // Error-check the enum.
67                    if (!Enum.IsDefined(typeof(BorderStyle), value))
68                        throw new InvalidEnumArgumentException();
69
70                    m_borderStyle = value;
71
72                    if (MdiClient == null)
73                        return;
74
75                    // This property can actually be visible in design-mode,
76                    // but to keep it consistent with the others,
77                    // prevent this from being show at design-time.
78                    if (Site != null && Site.DesignMode)
79                        return;
80
81                    // There is no BorderStyle property exposed by the MdiClient class,
82                    // but this can be controlled by Win32 functions. A Win32 ExStyle
83                    // of WS_EX_CLIENTEDGE is equivalent to a Fixed3D border and a
84                    // Style of WS_BORDER is equivalent to a FixedSingle border.
85
86                    // This code is inspired Jason Dori's article:
87                    // "Adding designable borders to user controls".
88                    // http://www.codeproject.com/cs/miscctrl/CsAddingBorders.asp
89
90                    // Get styles using Win32 calls
91                    int style = NativeMethods.GetWindowLong(MdiClient.Handle, (int)Win32.GetWindowLongIndex.GWL_STYLE);
92                    int exStyle = NativeMethods.GetWindowLong(MdiClient.Handle, (int)Win32.GetWindowLongIndex.GWL_EXSTYLE);
93
94                    // Add or remove style flags as necessary.
95                    switch (m_borderStyle)
96                    {
97                        case BorderStyle.Fixed3D:
98                            exStyle |= (int)Win32.WindowExStyles.WS_EX_CLIENTEDGE;
99                            style &= ~((int)Win32.WindowStyles.WS_BORDER);
100                            break;
101
102                        case BorderStyle.FixedSingle:
103                            exStyle &= ~((int)Win32.WindowExStyles.WS_EX_CLIENTEDGE);
104                            style |= (int)Win32.WindowStyles.WS_BORDER;
105                            break;
106
107                        case BorderStyle.None:
108                            style &= ~((int)Win32.WindowStyles.WS_BORDER);
109                            exStyle &= ~((int)Win32.WindowExStyles.WS_EX_CLIENTEDGE);
110                            break;
111                    }
112
113                    // Set the styles using Win32 calls
114                    NativeMethods.SetWindowLong(MdiClient.Handle, (int)Win32.GetWindowLongIndex.GWL_STYLE, style);
115                    NativeMethods.SetWindowLong(MdiClient.Handle, (int)Win32.GetWindowLongIndex.GWL_EXSTYLE, exStyle);
116
117                    // Cause an update of the non-client area.
118                    UpdateStyles();
119                }
120            }
121
122            public MdiClient MdiClient
123            {
124                get { return m_mdiClient; }
125            }
126
127            [Browsable(false)]
128            public Form ParentForm
129            {
130                get { return m_parentForm; }
131                set
132                {
133                    // If the ParentForm has previously been set,
134                    // unwire events connected to the old parent.
135                    if (m_parentForm != null)
136                    {
137                        m_parentForm.HandleCreated -= new EventHandler(ParentFormHandleCreated);
138                        m_parentForm.MdiChildActivate -= new EventHandler(ParentFormMdiChildActivate);
139                    }
140
141                    m_parentForm = value;
142
143                    if (m_parentForm == null)
144                        return;
145
146                    // If the parent form has not been created yet,
147                    // wait to initialize the MDI client until it is.
148                    if (m_parentForm.IsHandleCreated)
149                    {
150                        InitializeMdiClient();
151                        RefreshProperties();
152                    }
153                    else
154                        m_parentForm.HandleCreated += new EventHandler(ParentFormHandleCreated);
155
156                    m_parentForm.MdiChildActivate += new EventHandler(ParentFormMdiChildActivate);
157                }
158            }
159
160            public ISite Site
161            {
162                get { return m_site; }
163                set
164                {
165                    m_site = value;
166
167                    if (m_site == null)
168                        return;
169
170                    // If the component is dropped onto a form during design-time,
171                    // set the ParentForm property.
172                    IDesignerHost host = (value.GetService(typeof(IDesignerHost)) as IDesignerHost);
173                    if (host != null)
174                    {
175                        Form parent = host.RootComponent as Form;
176                        if (parent != null)
177                            ParentForm = parent;
178                    }
179                }
180            }
181
182            public void RenewMdiClient()
183            {
184                // Reinitialize the MdiClient and its properties.
185                InitializeMdiClient();
186                RefreshProperties();
187            }
188
189            public event EventHandler Disposed;
190
191            public event EventHandler HandleAssigned;
192
193            public event EventHandler MdiChildActivate;
194
195            public event LayoutEventHandler Layout;
196
197            protected virtual void OnHandleAssigned(EventArgs e)
198            {
199                // Raise the HandleAssigned event.
200                if (HandleAssigned != null)
201                    HandleAssigned(this, e);
202            }
203
204            protected virtual void OnMdiChildActivate(EventArgs e)
205            {
206                // Raise the MdiChildActivate event
207                if (MdiChildActivate != null)
208                    MdiChildActivate(this, e);
209            }
210
211            protected virtual void OnLayout(LayoutEventArgs e)
212            {
213                // Raise the Layout event
214                if (Layout != null)
215                    Layout(this, e);
216            }
217
218            public event PaintEventHandler Paint;
219
220            protected virtual void OnPaint(PaintEventArgs e)
221            {
222                // Raise the Paint event.
223                if (Paint != null)
224                    Paint(this, e);
225            }
226
227            protected override void WndProc(ref Message m)
228            {
229                switch (m.Msg)
230                {
231                    case (int)Win32.Msgs.WM_NCCALCSIZE:
232                        // If AutoScroll is set to false, hide the scrollbars when the control
233                        // calculates its non-client area.
234                        if (!AutoScroll)
235                            NativeMethods.ShowScrollBar(m.HWnd, (int)Win32.ScrollBars.SB_BOTH, 0 /*false*/);
236                        break;
237                }
238
239                base.WndProc(ref m);
240            }
241
242            private void ParentFormHandleCreated(object sender, EventArgs e)
243            {
244                // The form has been created, unwire the event, and initialize the MdiClient.
245                this.m_parentForm.HandleCreated -= new EventHandler(ParentFormHandleCreated);
246                InitializeMdiClient();
247                RefreshProperties();
248            }
249
250            private void ParentFormMdiChildActivate(object sender, EventArgs e)
251            {
252                OnMdiChildActivate(e);
253            }
254
255            private void MdiClientLayout(object sender, LayoutEventArgs e)
256            {
257                OnLayout(e);
258            }
259
260            private void MdiClientHandleDestroyed(object sender, EventArgs e)
261            {
262                // If the MdiClient handle has been released, drop the reference and
263                // release the handle.
264                if (m_mdiClient != null)
265                {
266                    m_mdiClient.HandleDestroyed -= new EventHandler(MdiClientHandleDestroyed);
267                    m_mdiClient = null;
268                }
269
270                ReleaseHandle();
271            }
272
273            private void InitializeMdiClient()
274            {
275                // If the mdiClient has previously been set, unwire events connected
276                // to the old MDI.
277                if (MdiClient != null)
278                {
279                    MdiClient.HandleDestroyed -= new EventHandler(MdiClientHandleDestroyed);
280                    MdiClient.Layout -= new LayoutEventHandler(MdiClientLayout);
281                }
282
283                if (ParentForm == null)
284                    return;
285
286                // Get the MdiClient from the parent form.
287                foreach (Control control in ParentForm.Controls)
288                {
289                    // If the form is an MDI container, it will contain an MdiClient control
290                    // just as it would any other control.
291
292                    m_mdiClient = control as MdiClient;
293                    if (m_mdiClient == null)
294                        continue;
295
296                    // Assign the MdiClient Handle to the NativeWindow.
297                    ReleaseHandle();
298                    AssignHandle(MdiClient.Handle);
299
300                    // Raise the HandleAssigned event.
301                    OnHandleAssigned(EventArgs.Empty);
302
303                    // Monitor the MdiClient for when its handle is destroyed.
304                    MdiClient.HandleDestroyed += new EventHandler(MdiClientHandleDestroyed);
305                    MdiClient.Layout += new LayoutEventHandler(MdiClientLayout);
306
307                    break;
308                }
309            }
310
311            private void RefreshProperties()
312            {
313                // Refresh all the properties
314                BorderStyle = m_borderStyle;
315                AutoScroll = m_autoScroll;
316            }
317
318            private void UpdateStyles()
319            {
320                // To show style changes, the non-client area must be repainted. Using the
321                // control's Invalidate method does not affect the non-client area.
322                // Instead use a Win32 call to signal the style has changed.
323                NativeMethods.SetWindowPos(MdiClient.Handle, IntPtr.Zero, 0, 0, 0, 0,
324                    Win32.FlagsSetWindowPos.SWP_NOACTIVATE |
325                    Win32.FlagsSetWindowPos.SWP_NOMOVE |
326                    Win32.FlagsSetWindowPos.SWP_NOSIZE |
327                    Win32.FlagsSetWindowPos.SWP_NOZORDER |
328                    Win32.FlagsSetWindowPos.SWP_NOOWNERZORDER |
329                    Win32.FlagsSetWindowPos.SWP_FRAMECHANGED);
330            }
331        }
332
333        private MdiClientController m_mdiClientController = null;
334        private MdiClientController GetMdiClientController()
335        {
336            if (m_mdiClientController == null)
337            {
338                m_mdiClientController = new MdiClientController();
339                m_mdiClientController.HandleAssigned += new EventHandler(MdiClientHandleAssigned);
340                m_mdiClientController.MdiChildActivate += new EventHandler(ParentFormMdiChildActivate);
341                m_mdiClientController.Layout += new LayoutEventHandler(MdiClient_Layout);
342            }
343
344            return m_mdiClientController;
345        }
346
347        private void ParentFormMdiChildActivate(object sender, EventArgs e)
348        {
349            if (GetMdiClientController().ParentForm == null)
350                return;
351
352            IDockContent content = GetMdiClientController().ParentForm.ActiveMdiChild as IDockContent;
353            if (content == null)
354                return;
355
356            if (content.DockHandler.DockPanel == this && content.DockHandler.Pane != null)
357                content.DockHandler.Pane.ActiveContent = content;
358        }
359
360        private bool MdiClientExists
361        {
362            get { return GetMdiClientController().MdiClient != null; }
363        }
364
365        private void SetMdiClientBounds(Rectangle bounds)
366        {
367            GetMdiClientController().MdiClient.Bounds = bounds;
368        }
369
370        private void SuspendMdiClientLayout()
371        {
372            if (GetMdiClientController().MdiClient != null)
373                GetMdiClientController().MdiClient.SuspendLayout();
374        }
375
376        private void ResumeMdiClientLayout(bool perform)
377        {
378            if (GetMdiClientController().MdiClient != null)
379                GetMdiClientController().MdiClient.ResumeLayout(perform);
380        }
381
382        private void PerformMdiClientLayout()
383        {
384            if (GetMdiClientController().MdiClient != null)
385                GetMdiClientController().MdiClient.PerformLayout();
386        }
387
388        // Called when:
389        // 1. DockPanel.DocumentStyle changed
390        // 2. DockPanel.Visible changed
391        // 3. MdiClientController.Handle assigned
392        private void SetMdiClient()
393        {
394            MdiClientController controller = GetMdiClientController();
395
396            if (this.DocumentStyle == DocumentStyle.DockingMdi)
397            {
398                controller.AutoScroll = false;
399                controller.BorderStyle = BorderStyle.None;
400                if (MdiClientExists)
401                    controller.MdiClient.Dock = DockStyle.Fill;
402            }
403            else if (DocumentStyle == DocumentStyle.DockingSdi || DocumentStyle == DocumentStyle.DockingWindow)
404            {
405                controller.AutoScroll = true;
406                controller.BorderStyle = BorderStyle.Fixed3D;
407                if (MdiClientExists)
408                    controller.MdiClient.Dock = DockStyle.Fill;
409            }
410            else if (this.DocumentStyle == DocumentStyle.SystemMdi)
411            {
412                controller.AutoScroll = true;
413                controller.BorderStyle = BorderStyle.Fixed3D;
414                if (controller.MdiClient != null)
415                {
416                    controller.MdiClient.Dock = DockStyle.None;
417                    controller.MdiClient.Bounds = SystemMdiClientBounds;
418                }
419            }
420        }
421
422        internal Rectangle RectangleToMdiClient(Rectangle rect)
423        {
424            if (MdiClientExists)
425                return GetMdiClientController().MdiClient.RectangleToClient(rect);
426            else
427                return Rectangle.Empty;
428        }
429    }
430}
Note: See TracBrowser for help on using the repository browser.