Reputation: 1
I'm trying to draw the same text from textBox to Panel char By Char For both Arabic & English with the same char size and position also style and color my code works perfectly if the text is English language but for Arabic its printing separated chars . I Know if i use DrawString , DrawTextBox or TextRenderer.DrawText strate forward i will get the result but it will show only the first visible liens and can't move through the liens if multiline true or move to the end if multiline false
my problem only in drawing Arabic chars these are what I tried
enum CaseMap { End = 0, Middle = 1, Beginning = 2, Isolated = 3 };
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Microsoft_TextBox
{
public partial class Arabic_English_Draw_TextBox : Form
{
private TextBox textBox1;
private Panel panel1;
private Label TexeLabel;
private Label PanelLabel;
public Arabic_English_Draw_TextBox()
{
InitializeComponent();
textBox1 = new TextBox();
this.Controls.Add(textBox1);
textBox1.Text = "مرحبا بالعالم Hello شكرا I'm trying to draw the same text from textBox to Panel char By Char For Arabic & English ";
textBox1.Font = new Font("Tahoma", 18, FontStyle.Bold);
textBox1.Multiline = true;
textBox1.BorderStyle = BorderStyle.Fixed3D;
textBox1.Size = new Size(200, 150);
textBox1.Location = new Point(50, 50);
textBox1.TextAlign = HorizontalAlignment.Center;
textBox1.ForeColor = Color.DeepSkyBlue;
textBox1.TextChanged += textBox1_TextChanged;
textBox1.KeyDown += textBox1_KeyDown;
TexeLabel = new Label();
this.Controls.Add(TexeLabel);
TexeLabel.Location = new Point(50, 20);
TexeLabel.Text = "Text Box";
panel1 = new Panel();
this.Controls.Add(panel1);
panel1.BorderStyle = BorderStyle.Fixed3D;
panel1.Size = new Size(200, 150);
panel1.Location = new Point(textBox1.Width+ 50, 50);
panel1.Paint += panel1_Paint; // Hook up the Paint event handler
PanelLabel = new Label();
this.Controls.Add(PanelLabel);
PanelLabel.Location = new Point(panel1.Location.X, 20);
PanelLabel.Text = "Panel To Draw";
this.Width = 500;
this.Height = 300;
StartPosition = FormStartPosition.CenterScreen;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
panel1.Invalidate();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
panel1.Invalidate();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
using (SolidBrush br = new SolidBrush(textBox1.ForeColor))
using (StringFormat sf = new StringFormat())
{
// Calculate the width of the text
SizeF textSize = e.Graphics.MeasureString(textBox1.Text, textBox1.Font, textBox1.ClientSize, sf);
// Draw each character
int firstCharIndex = textBox1.GetCharIndexFromPosition(new Point(0, 0));
int lastCharIndex = textBox1.GetCharIndexFromPosition(new Point(textBox1.ClientSize.Width - 1, textBox1.ClientSize.Height - 1));
StringBuilder stringBuilder = new StringBuilder(); // Initialize StringBuilder
int csizeH = 0;
int csizeW = 0;
int CCount = 0;
List<RectangleF> charRects = new List<RectangleF>(); // Store rectangles for each character
for (int i = firstCharIndex; i <= lastCharIndex && i < textBox1.Text.Length; i++)
{
char Char = textBox1.Text[i];
Size charSize = TextRenderer.MeasureText(Char.ToString(), textBox1.Font);
// Append each character to the StringBuilder
stringBuilder.Append(Char);
csizeH = (int)charSize.Height;
csizeW = (int)charSize.Width;
RectangleF charRect = new RectangleF(
textBox1.GetPositionFromCharIndex(i),
charSize);
switch (textBox1.TextAlign)
{
case HorizontalAlignment.Left:
charRect.Offset(-(int)textBox1.Font.Size / 5f, 0);
break;
case HorizontalAlignment.Center:
charRect.Offset(-(int)textBox1.Font.Size / 2.8f, 0);
break;
case HorizontalAlignment.Right:
charRect.Offset(-(int)textBox1.Font.Size / 2.05f, 0);
break;
}
charRects.Add(charRect); // Store the rectangle for each character
CCount = charRects.Count;
}
// Determine the start position for drawing the concatenated string
PointF startPosition = charRects.Count > 0 ? charRects[0].Location : PointF.Empty;
// Draw each character individually at their respective positions
for (int i = 0; i < stringBuilder.Length; i++)
{
e.Graphics.DrawString(stringBuilder[i].ToString(), textBox1.Font, br, charRects[i], sf);
}
}
}
}
}
Upvotes: 0
Views: 109
Reputation: 154
Oke two thing one TextBox is ignoring the "\n" character. if you put "\r\n" then it will create a new line.
Draw method:
private void panel1_Paint(object sender, PaintEventArgs e)
{
using (SolidBrush br = new SolidBrush(textBox1.ForeColor))
using (StringFormat sf = new StringFormat())
{
//sf.Alignment = StringAlignment.Center;
sf.Trimming = StringTrimming.EllipsisCharacter;
sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces ;
// Draw each character
int firstCharIndex = textBox1.GetCharIndexFromPosition(new Point(1, 1));
int lastCharIndex = textBox1.GetCharIndexFromPosition(new Point(textBox1.ClientSize.Width - 1, textBox1.ClientSize.Height - 1));
StringBuilder stringBuilder = new StringBuilder(); // Initialize StringBuilder
List<RectangleF> charRects = new List<RectangleF>(); // Store rectangles for each character
for (int i = firstCharIndex; i <= lastCharIndex && i < textBox1.Text.Length; i++)
{
char Char = textBox1.Text[i];
Size charSize = TextRenderer.MeasureText(Char.ToString(), textBox1.Font);
var isCharVisible = textBox1.GetPositionFromCharIndex(i);
if (isCharVisible.Y < 0 || isCharVisible.Y > (textBox1.Height-charSize.Height/2))
{
continue;
}
// Append each character to the StringBuilder
stringBuilder.Append(Char);
RectangleF charRect = new RectangleF(
textBox1.GetPositionFromCharIndex(i),
charSize);
charRects.Add(charRect); // Store the rectangle for each character
}
int j = 0;
int count = 0;
var LineRect = charRects[0];
for (int i = 1; i < charRects.Count; i++)
{
if (charRects[i-1].Y != charRects[i].Y || i == charRects.Count-1)
{
// last char
if(i == charRects.Count - 1)
{
// set the location for the minimum X
// set the line Rectangel
if (LineRect.X < charRects[i].X)
{
LineRect = new RectangleF(LineRect.X, LineRect.Y, LineRect.Width + charRects[i].Width, LineRect.Height);
}
else
{
LineRect = new RectangleF(charRects[i].X, LineRect.Y, LineRect.Width + charRects[i].Width, LineRect.Height);
}
count++;
}
// Drawstring line by line
e.Graphics.DrawString(stringBuilder.ToString().Substring(j,count), textBox1.Font, br, LineRect, sf);
j = i;
count = 0;
LineRect = charRects[i];
}
else
{
// set the location for the minimum X
// set the line Rectangel
if (LineRect.X < charRects[i].X)
{
LineRect = new RectangleF(LineRect.X, LineRect.Y, LineRect.Width + charRects[i].Width, LineRect.Height);
}
else
{
LineRect = new RectangleF(charRects[i].X, LineRect.Y, LineRect.Width + charRects[i].Width, LineRect.Height);
}
}
count++;
}
}
}
This draw the text line by line from the TextBox. Not perfect but i think is 99% good.
Upvotes: 0