using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
//---------------- Hello It's Me Amro Omran ---------------- \\
//---------------- Hotmail.Home@gmail.com ---------------- \\
//---------------- Visit My Youtube Channel ------------------------\\
//----------------- https://www.youtube.com/@Amro-Omran ---------------\\
//---------------- Please Like And subscribe For More useful Codes---------------- \\
namespace ImageRichTextBox
{
public class ImageRichTextBox : RichTextBox
{
private Image backgroundImage;
private Bitmap OnpaintImage;
private Color highlightColor = Color.Yellow; // You can set this to any desired highlight color
private const int WM_SETFONT = 0x30;
private const int WM_NCPAINT = 0x85;
private const int WM_CTLCOLOR = 0x0019;
private const int EM_SETOPTIONS = 0x2003;
private const int ECOOP_SET = 0x0002;
public bool ClearTextOnTransparent = false;
private StringFormat TextFormat { get; set; }
private Bitmap buffer;
public bool AutoSizeTextBoxToText = false;
public bool AutoSizeTextBoxToImage = false;
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool HideCaret(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowCaret(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, ref PARAFORMAT lParam);
private const int WM_USER = 0x0400;
private const int EM_SETPARAFORMAT = WM_USER + 71;
private const int PF_LEFT = 0x0001;
private const int PF_RIGHT = 0x0002;
private const int PF_CENTER = 0x0003;
[StructLayout(LayoutKind.Sequential)]
private struct PARAFORMAT
{
public int cbSize;
public uint dwMask;
public short wNumbering;
public short wReserved;
public int dxStartIndent;
public int dxRightIndent;
public int dxOffset;
public short wAlignment;
public short cTabCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public int[] rgxTabs;
}
public ImageRichTextBox()
{
InitializeComponent();
SetStyle(ControlStyles.UserPaint |
ControlStyles.SupportsTransparentBackColor |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer, true);
Multiline = true;
BorderStyle = BorderStyle.Fixed3D;
// Set the Font property with the desired size
Font = new Font(Font.FontFamily, 12);
BackColor = Color.FromArgb(80, 20, 60, 170);
}
[
Category("Appearance"),
Description("clear Text On Transparent Back Ground"),
Browsable(true),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
]
public new bool clearTextOnTransparent
{
get { return ClearTextOnTransparent; }
set
{
ClearTextOnTransparent = value;
Invalidate();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new Image Image
{
get { return backgroundImage; }
set
{
backgroundImage = value;
Invalidate();
}
}
// New property for text alignment
private HorizontalAlignment textAlign = HorizontalAlignment.Left;
public HorizontalAlignment TextAlign
{
get { return textAlign; }
set
{
textAlign = value;
Invalidate();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new Color HighlightColor
{
get { return highlightColor; }
set
{
highlightColor = value;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
using (var br = new SolidBrush(ForeColor))
using (var sf = new StringFormat())
{
// Set text alignment based on the TextAlign property
switch (TextAlign)
{
case HorizontalAlignment.Left:
sf.Alignment = StringAlignment.Near;
break;
case HorizontalAlignment.Center:
sf.Alignment = StringAlignment.Center;
break;
case HorizontalAlignment.Right:
sf.Alignment = StringAlignment.Far;
break;
}
if (backgroundImage != null)
{
// Draw the background image
e.Graphics.DrawImage(backgroundImage, 0, 0, Width, Height);
}
else
{
// Create a buffer for double buffering
OnpaintImage = new Bitmap(Width, Height);
e.Graphics.DrawImage(OnpaintImage, 0, 0, Width, Height);
}
// Highlight the selected text
if (SelectionLength > 0)
{
int selectionStart = SelectionStart;
int selectionEnd = SelectionStart + SelectionLength;
// Ensure that the selection is within the bounds of the text
selectionStart = Math.Max(0, Math.Min(selectionStart, Text.Length - 1));
selectionEnd = Math.Max(0, Math.Min(selectionEnd, Text.Length));
// Calculate the position and width of the selected text
float selectionX;
float selectionWidth;
switch (TextAlign)
{
case HorizontalAlignment.Left:
selectionX = e.Graphics.MeasureString(Text.Substring(0, selectionStart), Font, PointF.Empty, sf).Width;
selectionWidth = e.Graphics.MeasureString(Text.Substring(selectionStart, selectionEnd - selectionStart), Font, PointF.Empty, sf).Width;
break;
case HorizontalAlignment.Center:
float textWidth = e.Graphics.MeasureString(Text, Font, PointF.Empty, sf).Width;
selectionX = (Width - textWidth) / 2 + e.Graphics.MeasureString(Text.Substring(0, selectionStart), Font, PointF.Empty, sf).Width;
selectionWidth = e.Graphics.MeasureString(Text.Substring(selectionStart, selectionEnd - selectionStart), Font, PointF.Empty, sf).Width;
break;
case HorizontalAlignment.Right:
float textWidthRight = e.Graphics.MeasureString(Text, Font, PointF.Empty, sf).Width;
selectionX = Width - textWidthRight + e.Graphics.MeasureString(Text.Substring(0, selectionStart), Font, PointF.Empty, sf).Width;
selectionWidth = e.Graphics.MeasureString(Text.Substring(selectionStart, selectionEnd - selectionStart), Font, PointF.Empty, sf).Width;
break;
default:
selectionX = 0;
selectionWidth = 0;
break;
}
float textHeight = TextRenderer.MeasureText(Text, Font).Height;
RectangleF selectionRect = new RectangleF(
selectionX,
0,
selectionWidth,
textHeight
);
if (this.Focused)
{
using (var highlightBrush = new SolidBrush(highlightColor))
{
e.Graphics.FillRectangle(highlightBrush, selectionRect);
}
}
else
{
}
}
// Draw the text
if (!ClearTextOnTransparent)
{
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
}
else
{
e.Graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
}
e.Graphics.DrawString(Text, Font, br, ClientRectangle, sf);
//using (var brush = new SolidBrush(BackColor))
//{
// if (BorderStyle != BorderStyle.None)
// {
// e.Graphics.DrawRectangle(Pens.Green, 0, 0, Width - 5.55f, Height - 5.55f);
// }
//}
}
base.OnPaint(e);
}
//protected override CreateParams CreateParams
//{
// get
// {
// CreateParams cp = base.CreateParams;
// cp.ExStyle |= 0x20; // WS_EX_TRANSPARENT
// if (imageTextBox.LoadLibrary("msftedit.dll") != IntPtr.Zero)
// {
// cp.ClassName = "RICHEDIT50W";
// }
// else if (imageTextBox.LoadLibrary("riched20.dll") != IntPtr.Zero)
// {
// cp.ClassName = "RichEdit20W";
// }
// return cp;
// }
//}
private bool bFist = true;
private string OldText = "";
protected override void WndProc(ref Message m)
{
if ((m.Msg == WM_NCPAINT || m.Msg == 0xF) && this.Focused && backgroundImage != null)
{
IntPtr dc = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(dc))
{
// Create a buffer for double buffering
buffer = new Bitmap(Width + 1, Height + 1);
using (Graphics bufferGraphics = Graphics.FromImage(buffer))
{
using (var brush = new SolidBrush(BackColor))
{
if (BorderStyle != BorderStyle.None)
{
bufferGraphics.DrawRectangle(Pens.DeepSkyBlue, 0, 0, Width - 0.5f, Height - 0.5f);
}
bufferGraphics.FillRectangle(brush, new Rectangle(1, 1, ClientRectangle.Width, ClientRectangle.Height));
}
using (var br = new SolidBrush(ForeColor))
using (var sf = new StringFormat())
{
// Set text alignment based on the TextAlign property
switch (TextAlign)
{
case HorizontalAlignment.Left:
sf.Alignment = StringAlignment.Near;
break;
case HorizontalAlignment.Center:
sf.Alignment = StringAlignment.Center;
break;
case HorizontalAlignment.Right:
sf.Alignment = StringAlignment.Far;
break;
}
// Draw the background image
bufferGraphics.DrawImage(backgroundImage, 0, 0, Width, Height);
bufferGraphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
bufferGraphics.DrawString(Text, Font, br, ClientRectangle, sf);
}
}
if (m.Msg == 15)
{
if (this.bFist)
{
this.bFist = false;
this.OldText = this.Text;
}
if (this.OldText != this.Text)
{
this.OldText = this.Text;
//EventArgs e = new EventArgs();
//this.OnTextChanged(e);
// Handle the change here
OnTextChanged(EventArgs.Empty);
}
}
const int EN_CHANGE = 0x0300;
if (m.Msg == EN_CHANGE)
{
// Handle the change here
OnTextChanged(EventArgs.Empty);
}
// Draw the buffer onto the control's graphics
// g.DrawImage(buffer, 0, 0);
ReleaseDC(Handle, dc);
base.WndProc(ref m);
}
}
else
{
if (m.Msg == 15)
{
if (this.bFist)
{
this.bFist = false;
this.OldText = this.Text;
}
if (this.OldText != this.Text)
{
this.OldText = this.Text;
//EventArgs e = new EventArgs();
//this.OnTextChanged(e);
// Handle the change here
OnTextChanged(EventArgs.Empty);
}
}
const int EN_CHANGE = 0x0300;
if (m.Msg == EN_CHANGE)
{
// Handle the change here
OnTextChanged(EventArgs.Empty);
}
base.WndProc(ref m);
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
buffer?.Dispose();
components?.Dispose();
}
base.Dispose(disposing);
}
private System.ComponentModel.IContainer components = null;
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
public void SetMultiline(bool multiline)
{
int options = multiline ? ECOOP_SET : 0;
SendMessage(Handle, EM_SETOPTIONS, (IntPtr)options, IntPtr.Zero);
Multiline = multiline;
// Redraw the control
Invalidate();
}
public void SetFontFamily(string fontFamilyName)
{
Font newFont = new Font(fontFamilyName, Font.Size);
SendMessage(Handle, WM_SETFONT, newFont.ToHfont(), (IntPtr)1);
//// Dispose the previous font to prevent memory leaks
//Font.Dispose();
Font = newFont;
// Redraw the control
Invalidate();
}
public void SetFontSize(int newSize)
{
Font = new Font(Font.FontFamily, newSize);
SendMessage(Handle, WM_SETFONT, Font.ToHfont(), (IntPtr)1);
Invalidate();
}
private void AutoSizeTextBox(TextBox txt)
{
if (AutoSizeTextBoxToText)
{
const int x_margin = 50;
const int y_margin = 10;
Size size = TextRenderer.MeasureText(txt.Text, txt.Font);
txt.ClientSize = new Size(size.Width + x_margin, size.Height + y_margin);
}
else if (AutoSizeTextBoxToImage && backgroundImage != null)
{
const int x_margin = -2;
const int y_margin = 2;
// Size size = TextRenderer.MeasureText(txt.Text, txt.Font);
txt.ClientSize = new Size(backgroundImage.Width + x_margin, backgroundImage.Height + y_margin);
}
else
{
}
}
public void SetTextAlignment(HorizontalAlignment alignment)
{
PARAFORMAT paraFormat = new PARAFORMAT();
paraFormat.cbSize = Marshal.SizeOf(typeof(PARAFORMAT));
paraFormat.dwMask = 0x0000000A; // PFM_ALIGNMENT
paraFormat.wAlignment = GetWin32TextAlignment(alignment);
SendMessage(Handle, EM_SETPARAFORMAT, 0, ref paraFormat);
}
private short GetWin32TextAlignment(HorizontalAlignment alignment)
{
switch (alignment)
{
case HorizontalAlignment.Left:
return PF_LEFT;
case HorizontalAlignment.Center:
return PF_CENTER;
case HorizontalAlignment.Right:
return PF_RIGHT;
default:
if (TextAlign == HorizontalAlignment.Left)
{
return PF_LEFT;
}
else if (TextAlign == HorizontalAlignment.Right)
{
return PF_RIGHT;
}
else if (TextAlign == HorizontalAlignment.Center) // Fix the syntax here
{
return PF_CENTER;
}
else
{
// Handle the case when TextAlign is not one of the specified values
// You might want to return a default value or throw an exception
return PF_LEFT; // or throw new InvalidOperationException("Invalid TextAlign value");
}
}
}
private ContextMenuStrip CreateCustomContextMenu()
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
// Undo
ToolStripMenuItem undoMenuItem = new ToolStripMenuItem("Undo");
undoMenuItem.ShortcutKeys = Keys.Control | Keys.Z; // Set Ctrl+Z as the shortcut key
undoMenuItem.Click += (sender, e) => Undo();
contextMenu.Items.Add(undoMenuItem);
// Cut
ToolStripMenuItem cutMenuItem = new ToolStripMenuItem("Cut");
cutMenuItem.ShortcutKeys = Keys.Control | Keys.X; // Set Ctrl+X as the shortcut key
cutMenuItem.Click += (sender, e) => Cut();
contextMenu.Items.Add(cutMenuItem);
// Copy
ToolStripMenuItem copyMenuItem = new ToolStripMenuItem("Copy");
copyMenuItem.ShortcutKeys = Keys.Control | Keys.C; // Set Ctrl+C as the shortcut key
copyMenuItem.Click += (sender, e) => Copy();
contextMenu.Items.Add(copyMenuItem);
// Paste
ToolStripMenuItem pasteMenuItem = new ToolStripMenuItem("Paste");
pasteMenuItem.ShortcutKeys = Keys.Control | Keys.V; // Set Ctrl+V as the shortcut key
pasteMenuItem.Click += (sender, e) => Paste();
contextMenu.Items.Add(pasteMenuItem);
// Select All
ToolStripMenuItem selectAllMenuItem = new ToolStripMenuItem("Select All");
selectAllMenuItem.ShortcutKeys = Keys.Control | Keys.A; // Set Ctrl+A as the shortcut key
selectAllMenuItem.Click += (sender, e) => SelectAll();
contextMenu.Items.Add(selectAllMenuItem);
return contextMenu;
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
UpdateStyles();
if (ContextMenuStrip == null)
{
ContextMenuStrip = CreateCustomContextMenu();
}
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
// Force a repaint when leaving the control
buffer = null;
Invalidate();
}
protected override void OnEnter(EventArgs e)
{
base.OnEnter(e);
buffer = null;
Invalidate();
}
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
buffer = null;
Invalidate();
}
protected override void OnDoubleClick(EventArgs e)
{
base.OnDoubleClick(e);
buffer = null;
Invalidate();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
buffer = null;
Invalidate();
}
protected override void OnLocationChanged(EventArgs e)
{
buffer = null;
base.OnLocationChanged(e);
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
HideCaret(Handle);
//SetFontSize((int)Font.Size);
SetMultiline(true);
SetFontFamilyAndStyle((string)Font.FontFamily.Name);
SetTextAlignment(textAlign);
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
buffer = null;
SetTextAlignment(textAlign);
// Force a repaint when text changes
UpdateStyles();
Invalidate();
}
public void SetFontFamilyAndStyle(string fontFamilyName)
{
// Get the existing font style
FontStyle currentFontStyle = Font.Style;
// Create a new font with the specified font family and the existing font style
Font newFont = new Font(fontFamilyName, Font.Size, currentFontStyle);
// Set the new font
SendMessage(Handle, WM_SETFONT, newFont.ToHfont(), (IntPtr)1);
Font = newFont;
// Redraw the control
Invalidate();
}
}
}