diff --git a/XenAdmin/Controls/SmartScrollTextBox.cs b/XenAdmin/Controls/SmartScrollTextBox.cs index 07e663901..8f63e11b0 100644 --- a/XenAdmin/Controls/SmartScrollTextBox.cs +++ b/XenAdmin/Controls/SmartScrollTextBox.cs @@ -46,8 +46,19 @@ namespace XenAdmin.Controls /// internal class SmartScrollTextBox : TextBox { - protected internal bool IsVerticalScrollBarAtBottom => - string.IsNullOrEmpty(Text) || GetPositionFromCharIndex(Text.Length).Y < Height; + private bool _scrolledProgrammatically; + + protected internal bool IsVerticalScrollBarAtBottom => GetPositionFromCharIndex(Text.Length - 1).Y < Height; + + public void SetTextWithoutScrolling(string text) + { + var oldVerticalPosition = Win32.GetScrollBarPosition(Handle, Win32.ScrollBarConstants.SB_VERT); + Text = text; + Win32.SetScrollPos(Handle, (int)Win32.ScrollBarConstants.SB_VERT, oldVerticalPosition, true); + + _scrolledProgrammatically = true; + Win32.PostMessageA(Handle, Win32.WM_VSCROLL, (int)Win32.ScrollBarCommands.SB_THUMBPOSITION + 0x10000 * oldVerticalPosition, 0); + } #region Custom Events @@ -72,11 +83,11 @@ namespace XenAdmin.Controls /// public event ScrollChange OnScrollChange; #endregion - + #region Control Overrides protected override void WndProc(ref Message m) { - if (OnScrollChange != null) + if (OnScrollChange != null && !_scrolledProgrammatically) { int newPosition; switch (m.Msg) @@ -97,6 +108,12 @@ namespace XenAdmin.Controls } } + + if (_scrolledProgrammatically) + { + _scrolledProgrammatically = false; + } + base.WndProc(ref m); } diff --git a/XenAdmin/Wizards/PatchingWizard/AutomatedUpdatesBasePage.cs b/XenAdmin/Wizards/PatchingWizard/AutomatedUpdatesBasePage.cs index 6e25356a5..c7988b413 100644 --- a/XenAdmin/Wizards/PatchingWizard/AutomatedUpdatesBasePage.cs +++ b/XenAdmin/Wizards/PatchingWizard/AutomatedUpdatesBasePage.cs @@ -43,6 +43,7 @@ using System.Windows.Forms; using XenAdmin.Diagnostics.Problems; using XenAdmin.Dialogs; using XenAdmin.Wizards.RollingUpgradeWizard.PlanActions; +using Console = System.Console; namespace XenAdmin.Wizards.PatchingWizard @@ -316,10 +317,18 @@ namespace XenAdmin.Wizards.PatchingWizard stringBuilder.Append(sb); } - textBoxLog.Text = stringBuilder.ToString(); - textBoxLog.SelectionStart = textBoxLog.Text.Length; + var newText = stringBuilder.ToString(); + if (!_userMovedVerticalScrollbar) + { + textBoxLog.Text = newText; + textBoxLog.SelectionStart = textBoxLog.Text.Length; textBoxLog.ScrollToCaret(); + } + else + { + textBoxLog.SetTextWithoutScrolling(newText); + } } private void WorkerDoWork(object sender, DoWorkEventArgs doWorkEventArgs) diff --git a/XenCenterLib/Win32.cs b/XenCenterLib/Win32.cs index 6c25de19e..8bfef0e44 100644 --- a/XenCenterLib/Win32.cs +++ b/XenCenterLib/Win32.cs @@ -387,6 +387,9 @@ namespace XenCenterLib public static extern bool EnumUILanguages(EnumUILanguagesProc pUILanguageEnumProc, uint dwFlags, IntPtr lParam); + [DllImport("user32.dll")] + public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw); + #region Window scrolling functions /// @@ -498,6 +501,10 @@ namespace XenCenterLib [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("user32.dll")] + public static extern bool PostMessageA(IntPtr hWnd, int nBar, int wParam, int lParam); #region Disk space functions