123 lines
4.6 KiB
C#
123 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace UserControls
|
|
{
|
|
public partial class AutoScrollTextBox : TextBox
|
|
{
|
|
[DllImport("user32.dll")]
|
|
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
private static extern int GetScrollPos(IntPtr hWnd, int nBar);
|
|
[DllImport("user32.dll")]
|
|
private static extern bool PostMessageA(IntPtr hWnd, int nBar, int wParam, int lParam);
|
|
[DllImport("user32.dll")]
|
|
static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);
|
|
|
|
|
|
// Variables
|
|
private const int SB_HORZ = 0x0;
|
|
private const int SB_VERT = 0x1;
|
|
private const int WM_HSCROLL = 0x114;
|
|
private const int WM_VSCROLL = 0x115;
|
|
private const int SB_THUMBPOSITION = 4;
|
|
private const int SB_BOTTOM = 7;
|
|
private const int SB_OFFSET = 13;
|
|
//
|
|
private double _textCharWidth;
|
|
|
|
|
|
// Properties
|
|
public double TextCharWidth
|
|
{
|
|
get
|
|
{
|
|
if (_textCharWidth < 0)
|
|
{
|
|
SizeF sizeA = TextRenderer.MeasureText("A", Font);
|
|
SizeF sizeAA = TextRenderer.MeasureText("AA", Font);
|
|
//
|
|
_textCharWidth = sizeAA.Width - sizeA.Width;
|
|
}
|
|
return _textCharWidth;
|
|
}
|
|
}
|
|
|
|
// Constructors
|
|
public AutoScrollTextBox()
|
|
{
|
|
InitializeComponent();
|
|
//
|
|
_textCharWidth = -1;
|
|
}
|
|
|
|
|
|
// Methods
|
|
public void AutoScrollAppendText(string text)
|
|
{
|
|
if (text == null) return;
|
|
//
|
|
bool bottomFlag = false;
|
|
int VSmin;
|
|
int VSmax;
|
|
int sbOffset;
|
|
int savedVpos;
|
|
// Win32 magic to keep the textbox scrolling to the newest append to the textbox unless
|
|
// the user has moved the scrollbox up
|
|
sbOffset = (int)((this.ClientSize.Height - SystemInformation.HorizontalScrollBarHeight) / (this.Font.Height));
|
|
savedVpos = GetScrollPos(this.Handle, SB_VERT);
|
|
GetScrollRange(this.Handle, SB_VERT, out VSmin, out VSmax);
|
|
if (savedVpos >= (VSmax - sbOffset - 1))
|
|
bottomFlag = true;
|
|
this.AppendText(text);
|
|
if (bottomFlag)
|
|
{
|
|
GetScrollRange(this.Handle, SB_VERT, out VSmin, out VSmax);
|
|
savedVpos = VSmax - sbOffset;
|
|
bottomFlag = false;
|
|
}
|
|
SetScrollPos(this.Handle, SB_VERT, savedVpos, true);
|
|
PostMessageA(this.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * savedVpos, 0);
|
|
}
|
|
|
|
public void AutoScrollSetText(string text)
|
|
{
|
|
|
|
|
|
|
|
bool bottomFlag = false;
|
|
int VSmin;
|
|
int VSmax;
|
|
int sbOffset;
|
|
int savedVpos;
|
|
// Win32 magic to keep the textbox scrolling to the newest append to the textbox unless
|
|
// the user has moved the scrollbox up
|
|
sbOffset = (int)((this.ClientSize.Height - SystemInformation.HorizontalScrollBarHeight) / (this.Font.Height));
|
|
savedVpos = GetScrollPos(this.Handle, SB_VERT);
|
|
GetScrollRange(this.Handle, SB_VERT, out VSmin, out VSmax);
|
|
if (savedVpos >= (VSmax - sbOffset - 1))
|
|
bottomFlag = true;
|
|
//
|
|
if (text != this.Text)
|
|
this.Text = text;
|
|
//
|
|
if (bottomFlag)
|
|
{
|
|
GetScrollRange(this.Handle, SB_VERT, out VSmin, out VSmax);
|
|
savedVpos = VSmax - sbOffset;
|
|
bottomFlag = false;
|
|
}
|
|
SetScrollPos(this.Handle, SB_VERT, savedVpos, true);
|
|
PostMessageA(this.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * savedVpos, 0);
|
|
}
|
|
}
|
|
}
|