From 23768dbe0e262263a7b9ab542f5ac8eb3097d735 Mon Sep 17 00:00:00 2001 From: kislovdm Date: Thu, 30 Apr 2026 12:33:00 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BA=D1=80=D0=BE=D0=BB=D0=B0?= =?UTF-8?q?=20=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .semver.txt | 2 +- src/MonsterMonitor/MonsterMonitor.csproj | 8 ++--- src/MonsterMonitor/UI/MainForm.cs | 41 +++++++++++++++++++++++- 3 files changed, 45 insertions(+), 6 deletions(-) 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;