#region Imports using DPumpHydr.WinFrmUI.RLT.Design.Metro; using DPumpHydr.WinFrmUI.RLT.Enum.Metro; using DPumpHydr.WinFrmUI.RLT.Extension.Metro; using DPumpHydr.WinFrmUI.RLT.Interface.Metro; using DPumpHydr.WinFrmUI.RLT.Manager; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Text; using System.Runtime.InteropServices; using System.Windows.Forms; #endregion namespace DPumpHydr.WinFrmUI.RLT.Controls { #region MetroRichTextBox [ToolboxItem(true)] [ToolboxBitmap(typeof(MetroRichTextBox), "Bitmaps.RichTextBox.bmp")] [Designer(typeof(MetroRichTextBoxDesigner))] [DefaultProperty("Text")] [DefaultEvent("TextChanged")] [ComVisible(true)] public class MetroRichTextBox : Control, IMetroControl { #region Interfaces [Category("Metro"), Description("Gets or sets the style associated with the control.")] public Style Style { get => StyleManager?.Style ?? _style; set { _style = value; switch (value) { case Style.Light: ApplyTheme(); break; case Style.Dark: ApplyTheme(Style.Dark); break; case Style.Custom: ApplyTheme(Style.Custom); break; default: ApplyTheme(); break; } Invalidate(); } } [Category("Metro"), Description("Gets or sets the Style Manager associated with the control.")] public MetroStyleManager StyleManager { get => _styleManager; set { _styleManager = value; Invalidate(); } } [Category("Metro"), Description("Gets or sets the The Author name associated with the theme.")] public string ThemeAuthor { get; set; } [Category("Metro"), Description("Gets or sets the The Theme name associated with the theme.")] public string ThemeName { get; set; } #endregion Interfaces #region Global Vars private Utilites _utl; #endregion Global Vars #region Internal Vars private Style _style; private MetroStyleManager _styleManager; private int _maxLength; private bool _readOnly; private MouseMode _state; private bool _wordWrap; private bool _autoWordSelection; private string[] _lines; private Color _foreColor; private Color _backColor; private Color _borderColor; private Color _hoverColor; private bool _isDerivedStyle = true; private Color _disabledBackColor = Color.FromArgb(204, 204, 204); private Color _disabledForeColor = Color.FromArgb(136, 136, 136); private Color _disabledBorderColor = Color.FromArgb(155, 155, 155); #region Base RichTextBox private readonly RichTextBox _richTextBox = new(); #endregion Base RichTextBox #endregion Internal Vars #region Constructors public MetroRichTextBox() { SetStyle ( ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true ); UpdateStyles(); base.Font = MetroFonts.Regular(10); EvaluateVars(); ApplyTheme(); T_Defaults(); } private void EvaluateVars() { _utl = new Utilites(); } private void T_Defaults() { _wordWrap = true; _autoWordSelection = false; _foreColor = Color.FromArgb(20, 20, 20); _borderColor = Color.FromArgb(155, 155, 155); _hoverColor = Color.FromArgb(102, 102, 102); _backColor = Color.FromArgb(238, 238, 238); _richTextBox.BackColor = BackColor; _richTextBox.ForeColor = ForeColor; _readOnly = false; _maxLength = 32767; _state = MouseMode.Normal; _lines = null; _richTextBox.Cursor = Cursors.IBeam; _richTextBox.BorderStyle = BorderStyle.None; _richTextBox.Location = new(7, 8); _richTextBox.Font = Font; _richTextBox.Size = new(Width, Height); _richTextBox.MouseHover += T_MouseHover; _richTextBox.MouseUp += T_MouseUp; _richTextBox.Leave += T_Leave; _richTextBox.Enter += T_Enter; _richTextBox.KeyDown += T_KeyDown; _richTextBox.TextChanged += T_TextChanged; } #endregion Constructors #region Draw Control protected override void OnPaint(PaintEventArgs e) { Graphics g = e.Graphics; Rectangle rect = new(0, 0, Width - 1, Height - 1); g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; if (Enabled) { using SolidBrush bg = new(BackColor); using Pen p = new(BorderColor); using Pen ph = new(HoverColor); g.FillRectangle(bg, rect); switch (_state) { case MouseMode.Normal: g.DrawRectangle(p, rect); break; case MouseMode.Hovered: g.DrawRectangle(ph, rect); break; } _richTextBox.BackColor = BackColor; _richTextBox.ForeColor = ForeColor; } else { using SolidBrush bg = new(DisabledBackColor); using Pen p = new(DisabledBorderColor); g.FillRectangle(bg, rect); g.DrawRectangle(p, rect); _richTextBox.BackColor = DisabledBackColor; _richTextBox.ForeColor = DisabledForeColor; } _richTextBox.Location = new(7, 4); _richTextBox.Width = Width - 10; } #endregion Draw Control #region ApplyTheme private void ApplyTheme(Style style = Style.Light) { if (!IsDerivedStyle) { return; } switch (style) { case Style.Light: ForeColor = Color.FromArgb(20, 20, 20); BackColor = Color.FromArgb(238, 238, 238); HoverColor = Color.FromArgb(102, 102, 102); BorderColor = Color.FromArgb(155, 155, 155); DisabledBackColor = Color.FromArgb(204, 204, 204); DisabledBorderColor = Color.FromArgb(155, 155, 155); DisabledForeColor = Color.FromArgb(136, 136, 136); ThemeAuthor = "Taiizor"; ThemeName = "MetroLight"; UpdateProperties(); break; case Style.Dark: ForeColor = Color.FromArgb(204, 204, 204); BackColor = Color.FromArgb(34, 34, 34); HoverColor = Color.FromArgb(170, 170, 170); BorderColor = Color.FromArgb(110, 110, 110); DisabledBackColor = Color.FromArgb(80, 80, 80); DisabledBorderColor = Color.FromArgb(109, 109, 109); DisabledForeColor = Color.FromArgb(109, 109, 109); ThemeAuthor = "Taiizor"; ThemeName = "MetroDark"; UpdateProperties(); break; case Style.Custom: if (StyleManager != null) { foreach (System.Collections.Generic.KeyValuePair varkey in StyleManager.RichTextBoxDictionary) { switch (varkey.Key) { case "ForeColor": ForeColor = _utl.HexColor((string)varkey.Value); break; case "BackColor": BackColor = _utl.HexColor((string)varkey.Value); break; case "HoverColor": HoverColor = _utl.HexColor((string)varkey.Value); break; case "BorderColor": BorderColor = _utl.HexColor((string)varkey.Value); break; case "DisabledBackColor": DisabledBackColor = _utl.HexColor((string)varkey.Value); break; case "DisabledBorderColor": DisabledBorderColor = _utl.HexColor((string)varkey.Value); break; case "DisabledForeColor": DisabledForeColor = _utl.HexColor((string)varkey.Value); break; default: return; } } } UpdateProperties(); break; default: throw new ArgumentOutOfRangeException(nameof(style), style, null); } } private void UpdateProperties() { Invalidate(); _richTextBox.Invalidate(); } #endregion ApplyTheme #region Events public new event TextChangedEventHandler TextChanged; public delegate void TextChangedEventHandler(object sender); public event SelectionChangedEventHandler SelectionChanged; public delegate void SelectionChangedEventHandler(object sender, EventArgs e); public event LinkClickedEventHandler LinkClicked; public delegate void LinkClickedEventHandler(object sender, EventArgs e); public event ProtectedEventHandler Protected; public delegate void ProtectedEventHandler(object sender, EventArgs e); private void T_SelectionChanged(object sender, EventArgs e) { SelectionChanged?.Invoke(sender, e); } private void T_LinkClicked(object sender, EventArgs e) { LinkClicked?.Invoke(sender, e); } private void T_Protected(object sender, EventArgs e) { Protected?.Invoke(sender, e); } public void T_Leave(object sender, EventArgs e) { base.OnMouseLeave(e); Invalidate(); } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); _state = MouseMode.Normal; Invalidate(); } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); _state = MouseMode.Hovered; Invalidate(); } public void T_MouseUp(object sender, MouseEventArgs e) { base.OnMouseUp(e); if (e.Button == MouseButtons.Right) { if (ContextMenuStrip != null) { ContextMenuStrip.Show(_richTextBox, new Point(e.X, e.Y)); } } Invalidate(); } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); _state = MouseMode.Hovered; Invalidate(); } protected override void OnMouseHover(EventArgs e) { base.OnMouseHover(e); _state = MouseMode.Hovered; Invalidate(); } public void T_MouseHover(object sender, EventArgs e) { base.OnMouseHover(e); Invalidate(); } protected override void OnResize(EventArgs e) { base.OnResize(e); _richTextBox.Size = new(Width - 10, Height - 10); } public void T_Enter(object sender, EventArgs e) { base.OnMouseEnter(e); Invalidate(); } private void T_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.A) { e.SuppressKeyPress = true; } if (e.Control && e.KeyCode == Keys.C) { _richTextBox.Copy(); e.SuppressKeyPress = true; } } private void T_TextChanged(object sender, EventArgs e) { Text = _richTextBox.Text; TextChanged?.Invoke(this); Invalidate(); } protected override void OnCreateControl() { base.OnCreateControl(); if (!Controls.Contains(_richTextBox)) { Controls.Add(_richTextBox); } } public void AppendText(string text) { if (_richTextBox != null) { _richTextBox.AppendText(text); } } public void Undo() { if (_richTextBox != null) { if (_richTextBox.CanUndo) { _richTextBox.Undo(); } } } public int GetLineFromCharIndex(int index) { if (_richTextBox != null) { return _richTextBox.GetLineFromCharIndex(index); } else { return 0; } } public Point GetPositionFromCharIndex(int index) { return _richTextBox.GetPositionFromCharIndex(index); } public int GetCharIndexFromPosition(Point pt) { if (_richTextBox == null) { return 0; } return _richTextBox.GetCharIndexFromPosition(pt); } public void ClearUndo() { if (_richTextBox == null) { return; } _richTextBox.ClearUndo(); } public void Copy() { if (_richTextBox == null) { return; } _richTextBox.Copy(); } public void Cut() { if (_richTextBox == null) { return; } _richTextBox.Cut(); } public void SelectAll() { if (_richTextBox == null) { return; } _richTextBox.SelectAll(); } public void DeselectAll() { if (_richTextBox == null) { return; } _richTextBox.DeselectAll(); } public void Select(int start, int length) { if (_richTextBox == null) { return; } _richTextBox.Select(start, length); } public void Paste(DataFormats.Format clipFormat) { if (_richTextBox == null) { return; } _richTextBox.Paste(clipFormat); } public void LoadFile(string path) { if (_richTextBox == null) { return; } _richTextBox.LoadFile(path); } public void LoadFile(string path, RichTextBoxStreamType fileType) { if (_richTextBox == null) { return; } _richTextBox.LoadFile(path, fileType); } public void LoadFile(System.IO.Stream data, RichTextBoxStreamType fileType) { if (_richTextBox == null) { return; } _richTextBox.LoadFile(data, fileType); } public void SaveFile(string path) { if (_richTextBox == null) { return; } _richTextBox.SaveFile(path); } public void SaveFile(string path, RichTextBoxStreamType fileType) { if (_richTextBox == null) { return; } _richTextBox.SaveFile(path, fileType); } public void SaveFile(System.IO.Stream data, RichTextBoxStreamType fileType) { if (_richTextBox == null) { return; } _richTextBox.SaveFile(data, fileType); } public bool CanPaste(DataFormats.Format clipFormat) { return _richTextBox.CanPaste(clipFormat); } public int Find(char[] characterSet) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(characterSet); } public int Find(char[] characterSet, int start) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(characterSet, start); } public int Find(char[] characterSet, int start, int ends) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(characterSet, start, ends); } public int Find(string str) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(str); } public int Find(string str, int start, int ends, RichTextBoxFinds options) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(str, start, ends, options); } public int Find(string str, RichTextBoxFinds options) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(str, options); } public int Find(string str, int start, RichTextBoxFinds options) { if (_richTextBox == null) { return 0; } return _richTextBox.Find(str, start, options); } #endregion Events #region Properties [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public BorderStyle BorderStyle => BorderStyle.None; [Category("Metro"), Description("Gets or sets how text is aligned in a RichTextBox control.")] public int MaxLength { get => _maxLength; set { _maxLength = value; if (_richTextBox != null) { _richTextBox.MaxLength = value; } Invalidate(); } } [Category("Metro")] [Description("Gets or sets the background color of the control.")] public override Color BackColor { get => _backColor; set { _backColor = value; _richTextBox.BackColor = value; Invalidate(); } } [Category("Metro")] [Description("Gets or sets the color of the control whenever hovered.")] public Color HoverColor { get => _hoverColor; set { _hoverColor = value; Invalidate(); } } [Category("Metro")] [Description("Gets or sets the border color of the control.")] public Color BorderColor { get => _borderColor; set { _borderColor = value; Invalidate(); } } [Category("Metro")] [Description("Gets or sets the foreground color of the control.")] [Browsable(false)] public override Color ForeColor { get => _foreColor; set { _foreColor = value; _richTextBox.ForeColor = value; Invalidate(); } } [Category("Metro"), Description("Gets or sets a value indicating whether text in the RichTextBox is read-only.")] public bool ReadOnly { get => _readOnly; set { _readOnly = value; if (_richTextBox != null) { _richTextBox.ReadOnly = value; } } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public override Image BackgroundImage => null; [Category("Metro"), Description("Gets or sets the current text in the RichTextBox.")] public override string Text { get => _richTextBox.Text; set { base.Text = value; if (_richTextBox != null) { _richTextBox.Text = value; } } } [Category("Metro"), Description("Gets or sets the font of the text displayed by the control.")] public override Font Font { get => base.Font; set { base.Font = value; if (_richTextBox == null) { return; } _richTextBox.Font = value; _richTextBox.Location = new(5, 5); _richTextBox.Width = Width - 8; } } [Category("Metro"), Description("Indicates whether a multiline text box control automatically wraps words to the beginning of the next line when necessary.")] public bool WordWrap { get => _wordWrap; set { _wordWrap = value; if (_richTextBox != null) { _richTextBox.WordWrap = value; } } } [Category("Metro"), Description("Gets or sets a value indicating whether automatic word selection is enabled.")] public bool AutoWordSelection { get => _autoWordSelection; set { _autoWordSelection = value; if (_richTextBox != null) { _richTextBox.AutoWordSelection = value; } } } [Category("Metro"), Description("Gets or sets the lines of text in the control.")] public string[] Lines { get => _lines; set { _lines = value; if (_richTextBox != null) { _richTextBox.Lines = value; } Invalidate(); } } [Category("Metro"), Description("Gets or sets the ContextMenuStrip associated with this control.")] public override ContextMenuStrip ContextMenuStrip { get => base.ContextMenuStrip; set { base.ContextMenuStrip = value; if (_richTextBox == null) { return; } _richTextBox.ContextMenuStrip = value; Invalidate(); } } [Category("Metro")] [Description("Gets or sets back color used by the control while disabled.")] public Color DisabledBackColor { get => _disabledBackColor; set { _disabledBackColor = value; Refresh(); } } [Category("Metro")] [Description("Gets or sets the fore color of the control whenever while disabled")] public Color DisabledForeColor { get => _disabledForeColor; set { _disabledForeColor = value; Refresh(); } } [Category("Metro")] [Description("Gets or sets the border color of the control while disabled.")] public Color DisabledBorderColor { get => _disabledBorderColor; set { _disabledBorderColor = value; Refresh(); } } [Category("Metro")] [Description("Gets or sets the whether this control reflect to parent(s) style. \n " + "Set it to false if you want the style of this control be independent. ")] public bool IsDerivedStyle { get => _isDerivedStyle; set { _isDerivedStyle = value; Refresh(); } } #endregion Properties } #endregion }