GitHub Viewer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
namespace ST.Library.UI.STTextBox
{
public partial class STTextBox : Control
{
[Browsable(false)]
public float XDPIZoom { get; private set; }
[Browsable(false)]
public float YDPIZoom { get; private set; }
private int _BorderWidth = 1;
public int BorderWidth {
get { return _BorderWidth; }
set { _BorderWidth = value; }
}
private int _LineSpacing = 0;
public int LineSpacing {
get { return _LineSpacing; }
set {
if (value < 0) {
throw new ArgumentException("The value must be more than zero");
}
_LineSpacing = value;
this.Invalidate();
}
}
private int _CharSpacing = 0;
public int CharSpacing {
get { return _CharSpacing; }
set {
if (value < 0) {
throw new ArgumentException("The value must be more than zero");
}
_CharSpacing = value;
this.Invalidate();
}
}
private Color _BorderColor = Color.FromArgb(125, 0, 0, 0);
public Color BorderColor {
get { return _BorderColor; }
set {
if (_BorderColor == value) {
return;
}
_BorderColor = value;
this.Invalidate();
}
}
private Color _SelectionColor = Color.FromArgb(125, Color.DarkGray);
public Color SelectionColor {
get { return _SelectionColor; }
set {
if (value == _SelectionColor) {
return;
}
_SelectionColor = value;
if (!m_core.Selection.IsEmptySelection) {
this.Invalidate();
}
}
}
private bool _AllowScrollBar = true;
public bool AllowScrollBar {
get { return _AllowScrollBar; }
set { _AllowScrollBar = value; }
}
private Color _ScrollbarBackColor = Color.FromArgb(40, Color.Gray);
public Color ScrollbarBackColor {
get { return _ScrollbarBackColor; }
set { _ScrollbarBackColor = value; }
}
private Color _ScrollBarCornerColor = Color.FromArgb(80, Color.Gray);
public Color ScrollBarCornerColor {
get { return _ScrollBarCornerColor; }
set { _ScrollBarCornerColor = value; }
}
private Color _ScrollbarThumbHoverColor = Color.FromArgb(80, Color.Gray);
public Color ScrollbarThumbHoverColor {
get { return _ScrollbarThumbHoverColor; }
set { _ScrollbarThumbHoverColor = value; }
}
private Color _ScrollbarThumbBackColor = Color.FromArgb(80, Color.Black);
public Color ScrollbarThumbBackColor {
get { return _ScrollbarThumbBackColor; }
set { _ScrollbarThumbBackColor = value; }
}
private int _TabSize = 4;
private bool _AutoIndent = true;
private bool _TabToSpace = false;
private const int WM_MOUSEHWHEEL = 0x020E;
private object m_obj_sync = new object();
private Timer m_timer;
private IntPtr m_hIMC;
protected Core m_core;
public STTextBox() {
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.White;
m_timer = new Timer();
m_timer.Interval = 1000;
m_timer.Tick += new EventHandler(m_timer_Tick);
m_core = new Core(this);
}
#region override
protected override void OnCreateControl() {
base.OnCreateControl();
using (Graphics g = this.CreateGraphics()) {
this.XDPIZoom = g.DpiX / 96;
this.YDPIZoom = g.DpiY / 96;
}
}
protected override void WndProc(ref Message m) {
switch (m.Msg) {
case Win32.WM_IME_STARTCOMPOSITION:
m_hIMC = Win32.ImmGetContext(this.Handle);
this.OnImeStartPrivate(m_hIMC);
break;
case Win32.WM_IME_ENDCOMPOSITION:
this.OnImeEndPrivate(m_hIMC);
break;
case Win32.WM_IME_COMPOSITION:
if (((int)m.LParam & Win32.GCS_RESULTSTR) == Win32.GCS_RESULTSTR) {
m.Result = (IntPtr)1;
this.OnImeResultStrPrivate(m_hIMC, Win32.ImmGetCompositionString(m_hIMC, Win32.GCS_RESULTSTR));
return;//Interrupt, WM_CHAR, WM_IME_CHAR messages will not be generated.
}
if (((int)m.LParam & Win32.GCS_COMPSTR) == Win32.GCS_COMPSTR) {
this.OnImeCompStr(m_hIMC, Win32.ImmGetCompositionString(m_hIMC, Win32.GCS_COMPSTR));
}
break;
case WM_MOUSEHWHEEL:
Point pt = new Point(((int)m.LParam) >> 16, (ushort)m.LParam);
pt = this.PointToClient(pt);
MouseButtons mb = MouseButtons.None;
int n = (ushort)m.WParam;
if ((n & 0x0001) == 0x0001) mb |= MouseButtons.Left;
if ((n & 0x0010) == 0x0010) mb |= MouseButtons.Middle;
if ((n & 0x0002) == 0x0002) mb |= MouseButtons.Right;
if ((n & 0x0020) == 0x0020) mb |= MouseButtons.XButton1;
if ((n & 0x0040) == 0x0040) mb |= MouseButtons.XButton2;
this.OnMouseHWheel(new MouseEventArgs(mb, 0, pt.X, pt.Y, ((int)m.WParam) >> 16));
break;
}
base.WndProc(ref m);
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
//System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
//sw.Start();
this.XDPIZoom = e.Graphics.DpiX / 96;
this.YDPIZoom = e.Graphics.DpiY / 96;
var render = m_core.ITextBoxRender;
//try {
render.OnBeginPaint(e.Graphics);
m_core.ITextView.OnDrawView(render);
if (this._AllowScrollBar && m_core.Scroll.CountDown != 0) {
this.OnCalcScrollRectangle(m_core.Scroll);
bool bFlag = true;
if (m_core.Scroll.HBackRect != m_core.Scroll.HThumbRect) {
this.OnDrawHScrollBar(render, m_core.Scroll);
} else { bFlag = false; }
if (m_core.Scroll.VBackRect != m_core.Scroll.VThumbRect) {
this.OnDrawVScrollBar(render, m_core.Scroll);
} else { bFlag = false; }
if (bFlag) this.OnDrawScrollBarCorner(render, m_core.Scroll);
}
this.OnDrawBorder(render);
render.OnEndPaint(e.Graphics);
//} catch (Exception ex) {
// MessageBox.Show(ex.Message + "\r\n\r\n" + ex.StackTrace);
//}
//sw.Stop();
//Console.WriteLine("OnPaint - " + sw.ElapsedMilliseconds + "ms");
}
protected virtual void OnDrawBorder(ISTTextBoxRender render) {
if (this._BorderWidth scroll.HBackRect.Width) {
rect_h_thumb.Width = scroll.HBackRect.Width;
} else if (rect_h_thumb.Width < this.GetIntXSize(4)) {
rect_h_thumb.Width = this.GetIntXSize(4);
}
fScale = ((float)rectV.Height / c.LineHeight) / (rectV.Height / c.LineHeight + scroll.MaxYValue);
rect_v_thumb.Height = (int)(rectV.Height * fScale);
if (rect_v_thumb.Height > scroll.VBackRect.Height) {
rect_v_thumb.Height = scroll.VBackRect.Height;
} else if (rect_v_thumb.Height < this.GetIntYSize(4)) {
rect_v_thumb.Height = this.GetIntYSize(4);
}
rect_h_thumb.X = rectV.X;
if (scroll.MaxXValue > 0) {
fScale = (float)scroll.XValue / scroll.MaxXValue;
rect_h_thumb.X += (int)((scroll.HBackRect.Width - rect_h_thumb.Width) * fScale);
}
rect_v_thumb.Y = rectV.Y;
if (scroll.MaxYValue > 0) {
fScale = (float)scroll.YValue / scroll.MaxYValue;
rect_v_thumb.Y += (int)((scroll.VBackRect.Height - rect_v_thumb.Height) * fScale);
}
scroll.HThumbRect = rect_h_thumb;
scroll.VThumbRect = rect_v_thumb;
if (scroll.VBackRect == rect_v_thumb) {
rect_h_thumb.Width += nSW;
scroll.HThumbRect = rect_h_thumb;
var temp = scroll.HBackRect;
temp.Width += nSW;
scroll.HBackRect = temp;
} else if (scroll.HBackRect == rect_h_thumb) {
rect_v_thumb.Height += nSH;
scroll.VThumbRect = rect_v_thumb;
var temp = scroll.VBackRect;
temp.Height += nSH;
scroll.VBackRect = temp;
} else {
}
//scroll.HThumbRect = rect_h_thumb;
//scroll.VThumbRect = rect_v_thumb;
}
protected virtual void OnDrawVScrollBar(ISTTextBoxRender render, STTextBoxScrollInfo scroll) {
var clr = scroll.HoverScrollBar == STTextBoxScrollInfo.ScrollBarType.V ? this._ScrollbarThumbHoverColor : this._ScrollbarBackColor;
render.FillRectangle(clr, scroll.VBackRect);
render.FillRectangle(clr, scroll.VBackRect.X, scroll.VBackRect.Y, this.GetIntXSize(1), scroll.VBackRect.Height);
render.FillRectangle(this._ScrollbarThumbBackColor, scroll.VThumbRect);
}
protected virtual void OnDrawHScrollBar(ISTTextBoxRender render, STTextBoxScrollInfo scroll) {
var clr = scroll.HoverScrollBar == STTextBoxScrollInfo.ScrollBarType.H ? this._ScrollbarThumbHoverColor : this._ScrollbarBackColor;
render.FillRectangle(clr, scroll.HBackRect);
render.FillRectangle(clr, scroll.HBackRect.X, scroll.HBackRect.Y, scroll.HBackRect.Width, this.GetIntYSize(1));
render.FillRectangle(this._ScrollbarThumbBackColor, scroll.HThumbRect);
}
protected virtual void OnDrawScrollBarCorner(ISTTextBoxRender render, STTextBoxScrollInfo scroll) {
int nWidth = this.GetIntXSize(scroll.Size);
int nHeight = this.GetIntYSize(scroll.Size);
render.FillRectangle(
this._ScrollBarCornerColor, m_core.ViewRectangle.Right - nWidth,
m_core.ViewRectangle.Bottom - nHeight,
nWidth,
nHeight);
}
#endregion
#region private
private bool SetCursor(Cursor c) {
if (this.Cursor == c) {
return false;
}
this.Cursor = c;
return true;
}
private void OnImeStartPrivate(IntPtr hIMC) {
var CandidateForm = new Win32.CANDIDATEFORM() {
dwStyle = Win32.CFS_CANDIDATEPOS,
ptCurrentPos = m_core.Caret.Location
};
Win32.ImmSetCandidateWindow(hIMC, ref CandidateForm);
var CompositionForm = new Win32.COMPOSITIONFORM() {
dwStyle = Win32.CFS_FORCE_POSITION,
ptCurrentPos = m_core.Caret.Location
};
Win32.ImmSetCompositionWindow(hIMC, ref CompositionForm);
var logFont = new Win32.LOGFONT() {
lfHeight = m_core.FontHeight,
lfFaceName = this.Font.Name + "\0"
};
Win32.ImmSetCompositionFont(hIMC, ref logFont);
this.OnImeStart(hIMC);
}
private void OnImeEndPrivate(IntPtr hIMC) {
Win32.ImmReleaseContext(this.Handle, hIMC);
this.OnImeEnd(hIMC);
}
private void OnImeResultStrPrivate(IntPtr hIMC, string strResult) {
var CompositionForm = new Win32.COMPOSITIONFORM() {
dwStyle = Win32.CFS_FORCE_POSITION,
ptCurrentPos = m_core.Caret.Location
};
Win32.ImmSetCompositionWindow(hIMC, ref CompositionForm);
this.OnImeResultStr(hIMC, strResult);
}
private void m_timer_Tick(object sender, EventArgs e) {
if (m_core.Scroll.HoverScrollBar != STTextBoxScrollInfo.ScrollBarType.None) {
return;
}
lock (m_obj_sync) {
m_core.Scroll.CountDown--;
}
if (m_core.Scroll.CountDown