diff --git a/.semver.txt b/.semver.txt index b112f91..c787b21 100644 --- a/.semver.txt +++ b/.semver.txt @@ -1 +1 @@ -1.0.21 +1.0.22 diff --git a/src/MonsterMonitor/MonsterMonitor.csproj b/src/MonsterMonitor/MonsterMonitor.csproj index 14abc3d..1eb9296 100644 --- a/src/MonsterMonitor/MonsterMonitor.csproj +++ b/src/MonsterMonitor/MonsterMonitor.csproj @@ -6,10 +6,10 @@ 7.3 MonsterMonitor devenv - 1.0.21 - 1.0.21 - 1.0.21 - 1.0.21 + 1.0.22 + 1.0.22 + 1.0.22 + 1.0.22 diff --git a/src/MonsterMonitor/UI/MainForm.cs b/src/MonsterMonitor/UI/MainForm.cs index 081f158..7370817 100644 --- a/src/MonsterMonitor/UI/MainForm.cs +++ b/src/MonsterMonitor/UI/MainForm.cs @@ -1,5 +1,6 @@ using System; using System.Drawing; +using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; using MonsterMonitor.Models; @@ -9,6 +10,9 @@ namespace MonsterMonitor.UI { public sealed class MainForm : Form { + private const int EmGetFirstVisibleLine = 0x00CE; + private const int EmLineScroll = 0x00B6; + private readonly RichTextBox _console = new RichTextBox(); private readonly Button _btnSettings = new Button(); private readonly Button _btnExit = new Button(); @@ -192,14 +196,49 @@ namespace MonsterMonitor.UI return; } + var wasNearBottom = IsConsoleNearBottom(); + var firstVisibleLineBeforeAppend = GetFirstVisibleLine(_console); + _console.SelectionStart = _console.TextLength; _console.SelectionLength = 0; _console.SelectionColor = GetColor(entry.Level); _console.AppendText($"[{entry.Timestamp:HH:mm:ss}] [{entry.Level}] {entry.Message}{Environment.NewLine}"); _console.SelectionColor = _console.ForeColor; - _console.ScrollToCaret(); + + if (wasNearBottom) + { + _console.ScrollToCaret(); + return; + } + + var firstVisibleLineAfterAppend = GetFirstVisibleLine(_console); + var linesToRestore = firstVisibleLineBeforeAppend - firstVisibleLineAfterAppend; + if (linesToRestore != 0) + { + SendMessage(_console.Handle, EmLineScroll, IntPtr.Zero, (IntPtr)linesToRestore); + } } + private bool IsConsoleNearBottom() + { + if (_console.TextLength == 0) + { + return true; + } + + var bottomLeftPoint = new Point(1, Math.Max(0, _console.ClientSize.Height - 1)); + var lastVisibleCharIndex = _console.GetCharIndexFromPosition(bottomLeftPoint); + return lastVisibleCharIndex >= _console.TextLength - 2; + } + + private static int GetFirstVisibleLine(RichTextBox richTextBox) + { + return SendMessage(richTextBox.Handle, EmGetFirstVisibleLine, IntPtr.Zero, IntPtr.Zero).ToInt32(); + } + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); + private void ConfigureUpdateTimer() { _updateTimer.Interval = (int)TimeSpan.FromHours(1).TotalMilliseconds;