Draw Both Arabic And English Words Char By Char?

hotmail.home

Member
Joined
Jan 24, 2024
Messages
6
Programming Experience
5-10
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
  1. draw word by word
  2. draw two chars by two chars to make joined chars as Arabic writing but not worked as i want
  3. if the char has space or white space after it handles the chars before as one word but i faced another problem with alignment between Arabic and English and also setting the starting position for each word
  4. -also tried using enum CaseMap { End = 0, Middle = 1, Beginning = 2, Isolated = 3 };

my code works perfectly with English Chars

Screenshot 2024-03-01 033220.jpg


C#:
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 شكرا"+"\n"+ "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);
                }
            }
        }
    }
}
 
Why are you trying to render the text yourself in a Panel? Why not just use a Label and feed the complete string from the textbox into the label?

Or is this a stepping stone for you to learn how to render text yourself so that you can enhance your RichTextBox with transparent or background image?
 
Yes you are correct about the second part ;) but I'm trying to enhance Actual transparent textBox, not richTextBox but I'm stuck at drawing the text for Arabic and if the text has Both Arabic and English at the same time.
and I tried al the ways this the only way to match the text from TextBoxBase to the Actual draw to be as written to move the draw Text for both cases (Multiline == True or False) to match chars location on each line
using this way will give the advantage of showing only the visible text as on the textbox

Screenshot 2024-03-05 022537.jpg
 
The general technique is to draw line by line. To determine what fits in a line, you would use the measure text APIs. By drawing line by line, you let the GDI+ engine do the work of computing any ligatures, kerning, and alignment.
 
Back
Top Bottom