From b69488f9a626b527449c1297cb84b124030e6a6a Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Wed, 13 Feb 2019 22:07:48 +0000 Subject: [PATCH] Page switching now with 100% less flickering; page switching to a null view model is allowed now git-svn-id: file:///srv/devel/repo-conversion/nuwi@54 d2e56fa2-650e-0410-a79f-9358c0239efd --- Source/Views/MultiPageViewForm.cs | 63 ++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/Source/Views/MultiPageViewForm.cs b/Source/Views/MultiPageViewForm.cs index f0a1a6c..76174dc 100644 --- a/Source/Views/MultiPageViewForm.cs +++ b/Source/Views/MultiPageViewForm.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Reflection; +using System.Runtime.InteropServices; using System.Windows.Forms; using Nuclex.Support; @@ -13,6 +14,51 @@ namespace Nuclex.Windows.Forms.Views { /// Special view form that can display different child views public class MultiPageViewForm : ViewForm { + #region struct RedrawLockScope + + /// Prevents controls from redrawing themselves for a while + private struct RedrawLockScope : IDisposable { + + /// Window message that enables or disables control redraw + private const int WM_SETREDRAW = 11; + + /// Sends a window message to the specified window + /// Window a message will be sent to + /// ID of the message that will be sent + /// First argument to the window procedure + /// Second argument to the window procedure + /// The return value of the window procedure + [DllImport("user32")] + public static extern int SendMessage( + IntPtr windowHandle, int messageId, bool firstArgument, int secondArgument + ); + + /// Stops redrawing the specified control + /// Control to stop redrawing + public RedrawLockScope(Control control) { + if(Environment.OSVersion.Platform == PlatformID.Win32NT) { + SendMessage(control.Handle, WM_SETREDRAW, false, 0); + this.control = control; + } else { + this.control = null; + } + } + + /// Enables redrawing again when the lock scope is disposed + public void Dispose() { + if(this.control != null) { + SendMessage(this.control.Handle, WM_SETREDRAW, true, 0); + this.control.Invalidate(true); + } + } + + /// Control that has been stopped from redrawing itself + private Control control; + + } + + #endregion // struct RedrawLockScope + /// Initializes a new multi page view window /// /// Window manager that is used to set up the child views @@ -191,13 +237,18 @@ namespace Nuclex.Windows.Forms.Views { // Worst, but usual, case: the new page view model might require // a different view. Create or look up the new view and put it in the container { - disableActivePageView(); + if(pageViewModel == null) { + disableActivePageView(); + } else { + Control pageViewContainer = getPageViewContainer(); + using(new RedrawLockScope(pageViewContainer)) { + disableActivePageView(); - this.activePageView = getOrCreatePageView(pageViewModel); - - Control pageViewContainer = getPageViewContainer(); - pageViewContainer.Controls.Add(this.activePageView); - this.activePageView.Dock = DockStyle.Fill; + this.activePageView = getOrCreatePageView(pageViewModel); + pageViewContainer.Controls.Add(this.activePageView); + this.activePageView.Dock = DockStyle.Fill; + } + } } }