I draw text on a picturebox with:
Point text_point = new Point(0, i);
Font drawFont = new Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Pixel);
SolidBrush drawBrush = new SolidBrush(Color.Black);
g.DrawString(Convert.ToString(i), drawFont, drawBrush, text_point);
... but the text is always drawn 'thick' like this:
84
How can I get it to look like: 84 ?
Try:
Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
Related
i created a function which is drawing a circle with a letter inside.
i write it into a stream and set it to picture box in Zoom Mode.
It looks nice but some pieces of the circle are cut off.
Here is the Code for the Circle:
public MemoryStream GenerateCircle(string name)
{
var avatarString = string.Format("{0}", name[0]).ToUpper();
var bgColour = ColorTranslator.FromHtml("#007FBC");
var bmp = new Bitmap(70, 70);
var sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
var font = new Font("Arial", 34, FontStyle.Bold, GraphicsUnit.Pixel);
var graphics = Graphics.FromImage(bmp);
graphics.Clear(Color.White);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
Rectangle rect = new Rectangle(0, 0, 70, 70);
Brush b = new SolidBrush(bgColour);
Pen pen = new Pen(bgColour);
graphics.DrawEllipse(pen, rect);
graphics.FillEllipse(b, rect);
graphics.DrawString(avatarString, font, new SolidBrush(Color.WhiteSmoke), 35, 35, sf);
graphics.Flush();
var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Png);
return ms;
}
i set it like that:
avatarpicturebox.Image = Image.FromStream(GenerateCircle("Test"));
That is what it looks like:
Circle Cuts Off
Can someone help here please?
Just reduce the circle's width and height 1 pixel each to avoid clipping the right and bottom sides due to the pixels offset. Use Rectangle.Inflate method and pass negative width and height values to shrink the destination rectangle to fit.
Modifying your function to return a Bitmap instead of MemoryStream.
public Bitmap GenerateCircle(string name)
{
var bgColour = ColorTranslator.FromHtml("#007FBC");
var bmp = new Bitmap(70, 70, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (var graphics = Graphics.FromImage(bmp))
using (var sf = new StringFormat())
using (var font = new Font("Arial", 34, FontStyle.Bold, GraphicsUnit.Pixel))
using (var b = new SolidBrush(bgColour))
using (var pen = new Pen(bgColour))
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
graphics.Clear(Color.White);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
graphics.PixelOffsetMode = PixelOffsetMode.Half;
Rectangle rect = new Rectangle(Point.Empty, bmp.Size);
rect.Inflate(-2, -2);
graphics.DrawEllipse(pen, rect);
graphics.FillEllipse(b, rect);
graphics.DrawString(name.ToUpper(), font, Brushes.WhiteSmoke, rect, sf);
}
return bmp;
}
And the caller:
private void SomeButton_Click(object sender, EventArgs e)
{
avatarpicturebox.Image?.Dispose();
avatarpicturebox.Image = GenerateCircle("T");
}
Side Notes
Always dispose of the graphics objects you create either by calling explicitly the .Dispose method or by creating them with using keyword.
Use the Graphics.DrawString overloads that take a Rectangle and StringFormat params to draw the strings. Use the later to dictate how and where the string should be drawn in the given Rectangle. See also StringFormatFlags enum.
I have faced underline missing issue with if I only draw text (only spaces) with underline style. Please refer the below tried code at my end and let me know the solution to resolve this.
Bitmap bitmap = new Bitmap(400, 200);
Graphics graphics = Graphics.FromImage(bitmap);
Brush brush = new SolidBrush(Color.White);
graphics.FillRectangle(brush, 0, 0, 400, 200);
System.Drawing.Font font = new System.Drawing.Font("Arial", 12, FontStyle.Underline);
brush = new SolidBrush(Color.Black);
StringFormat stringformat = new StringFormat(StringFormat.GenericTypographic);
stringformat.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
string text = "Hello";
SizeF sizeF = m_graphics.MeasureString(text, font, new PointF(0, 0), stringformat);
graphics.DrawString(text, font, brush, new RectangleF(0, 0, sizeF.Width, sizeF.Height), stringformat);
text = " ";
float width = sizeF.Width;
sizeF = m_graphics.MeasureString(text, font, new PointF(0, 0), stringformat);
graphics.DrawString(text, font, brush, new RectangleF(width, 0, sizeF.Width, sizeF.Height), stringformat);
text = "World";
width += sizeF.Width;
sizeF = m_graphics.MeasureString(text, font, new PointF(0, 0), stringformat);
graphics.DrawString(text, font, brush, new RectangleF(width, 0, sizeF.Width, sizeF.Height), stringformat);
As far as I can see you have three options:
Use a monospaced font (Courier New and Lucida Sans Typewriter). More info on the monospaced fonts here and here.
System.Drawing.Font font =
new System.Drawing.Font("Courier New", 12, FontStyle.Underline);
Write the text at once. If you only write the spaces then the method won't work, even if you use TextRenderer to draw the string. So if you receive the strings separately then I suggest add them in a StringBuilder and draw the whole text or sentence.
var sb = new StringBuilder();
sb.Append("Hello");
sb.Append(" ");
sb.Append("World!");
var bitmap = new Bitmap(400, 200);
var graphics = Graphics.FromImage(bitmap);
Brush brush = new SolidBrush(Color.White);
graphics.FillRectangle(brush, 0, 0, 400, 200);
var font = new Font("Arial", 12, FontStyle.Underline);
brush = new SolidBrush(Color.Black);
var stringformat = new StringFormat(StringFormat.GenericTypographic);
stringformat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
stringformat.Trimming = StringTrimming.None;
var text = sb.ToString();
var sizeF = graphics.MeasureString(text, font, new PointF(0, 0), stringformat);
graphics.DrawString(text, font, brush,
new RectangleF(5, 0, sizeF.Width, sizeF.Height), stringformat);
The hack version: You can draw an invisible character such as (char)127 which is the delete character, like this (you can use the code from point 2 and add this line when initializing the StringBuilder):
sb.Append(new string ((char)127, 5)); //this will create approx. five spaces.
You can use other invisible characters if you need.
The 3rd options is a hack and should be considered as such, I would recommend option 1 if you can change the font otherwise option 2.
This question already has answers here:
How to set line spacing Graphics.DrawString
(2 answers)
Closed 6 years ago.
CodeA:
Image imageChipsetName = new System.Drawing.Bitmap(photoWidth, photoHeight);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
Graphics graphics = Graphics.FromImage(imageChipsetName);
graphics.DrawString(stringA + "\n",
new Font("Tahoma", 14, FontStyle.Underline), Brushes.Black,
new RectangleF(0, 0, photoWidth, photoHeight), strFormat);
graphics.DrawString( stringB,
new Font("Tahoma", 14), Brushes.Black,
new RectangleF(0, 0, photoWidth, photoHeight), strFormat);
CodeB:
Image imageChipsetName = new System.Drawing.Bitmap(photoWidth, photoHeight);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
Graphics graphics = Graphics.FromImage(imageChipsetName);
graphics.DrawString(stringA + "\n"+stringB,
new Font("Tahoma", 14, FontStyle.Underline), Brushes.Black,
new RectangleF(0, 0, photoWidth, photoHeight), strFormat);
I need to draw 2 string within a box. StringA with underline style while StringB don't.
CodeB almost achieve what I want but stringA and stringB sharing the same style. So I tested with CodeA but the program with it is that both string overlapping each other. May I know
The problem with codeA is that both stringA and stringB are drawn at the exact same position.
graphics.DrawString turns string into image and print it on the paper.
"\n" doesn't have any meaning once the string is turned into image. It will not be printed nor will it create a new line. In fact, there is no "lines" on the paper. Just image.
You need to give stringB different position. Use Graphics.MeasureString (String, Font) to measure the size of stringA, then adjust stringB's position according to the result.
Image imageChipsetName = new System.Drawing.Bitmap(photoWidth, photoHeight);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
Font strFontA = new Font("Tahoma", 14, FontStyle.Underline);//Font used by stringA
Graphics graphics = Graphics.FromImage(imageChipsetName);
graphics.DrawString(stringA + "\n",
strFont_A, Brushes.Black,
new RectangleF(0, 0, photoWidth, photoHeight), strFormat);
SizeF stringSizeA = new SizeF();
stringSizeA = Graphics.MeasureString(stringA, strFont_A);//Measuring the size of stringA
graphics.DrawString(stringB,
new Font("Tahoma", 14), Brushes.Black,
new RectangleF(0, stringSizeA.Height, photoWidth, photoHeight - stringSizeA.Height), strFormat);
I'm trying to draw text, which contains symbols from "Combining Diacritical Marcs" unicode subrange (U+0300 - U+FE23). For example i tried to draw string "T̅", wich contains of two characters: 'T' and '\u0305'.
I've got that:
Is there any way to get correct text?
Addition: I need to draw rotated text too.
PS: my code:
private void Form1_Paint(object sender, PaintEventArgs e) {
Graphics g = e.Graphics;
Font fontTahoma = new Font("Tahoma", 16);
Font fontTimesNewRom = new Font("Times New Romulan", 16);
Font fontArial = new Font("Arial", 16);
Brush brush = new SolidBrush(Color.Red);
g.DrawString("Test1 T̅ T\u0305", fontTahoma, brush, new PointF(20, 20));
g.DrawString("Test1 T̅ T\u0305", fontTimesNewRom, brush, new PointF(20, 40));
g.DrawString("Test1 T̅ N\u0305", fontArial, brush, new PointF(20, 60));
}
TextRenderer seems to draw it better:
TextRenderer.DrawText(g, "Test1 T̅ T\u0305", fontTahoma,
new Point(120, 20), Color.Black);
I am generating ICards for employees.
I have to write address of the employee on the ICard.
Image blankICard = Image.FromFile(#"C:\Users\admin\Pictures\filename.jpg");
Bitmap outputImage = new Bitmap(blankICard.Width, blankICard.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.SolidBrush b = new SolidBrush(Color.FromArgb(255, 88, 89, 91));
using (Graphics graphics = Graphics.FromImage(outputImage))
{
graphics.DrawImage(blankICard, new Rectangle(0, 0, blankICard.Width, blankICard.Height),
new Rectangle(new Point(), blankICard.Size), GraphicsUnit.Pixel);
Font stringFont = new Font("FreightSans Medium", 20, FontStyle.Regular);
string address = "Address goes here";
graphics.DrawString(address, new Font("FreightSans Medium", 20, FontStyle.Regular), b, new Point(621, 234));
graphics.DrawString("Employee Code:12345678", new Font("FreightSans Medium", 26, FontStyle.Regular), b, new Point(350, 407));
}
Current Output is shown in the left side of the image.
Here what happens that my string goes out of the box.
I want to bind it in the fix size box.
Example is shown in the right side of the Image.
Use Graphics.DrawString overload that takes Rectangle instead of a point. That way you'll wrap text to fit within specified width.
using (Graphics graphics = Graphics.FromImage(outputImage)){
// Draw whatever you need first
// ....
// Create font...
graphics.DrawString(employeeCode, font, Brushes.Black,
new Rectangle(0, 25, maxWidth, maxHeight);
}
Simple as that :)
I made some changes to your code, commenting 2 lines - I did not have the file C:\Users\admin\Pictures\filename.jpg on my pc - That's why blankICard was disabled and so was its Rectangle:
You must set maxWidth in order to wrap your employee code, for example.
// Image blankICard = Image.FromFile(#"C:\Users\admin\Pictures\filename.jpg");
int width = 500;
int height = 500;
Bitmap outputImage = new Bitmap(width, height,PixelFormat.Format32bppArgb);
SolidBrush b = new SolidBrush(Color.FromArgb(255, 88, 89, 91));
SolidBrush blackBrush = new SolidBrush(Color.Black);
using (Graphics graphics = Graphics.FromImage(outputImage))
{
graphics.DrawRectangle(new Pen(blackBrush), new Rectangle(0, 0, width, height));
// new Rectangle(new Point(), blankICard.Size), GraphicsUnit.Pixel);
Font stringFont = new Font("FreightSans Medium", 20, FontStyle.Regular);
string address = "Address goes here";
string employeeCode = "Employee Code:12345678";
int maxWidth = 30;
SizeF sf = graphics.MeasureString(employeeCode, new Font(new FontFamily("FreightSans Medium"), 26), maxWidth);
graphics.DrawString(address, new Font("FreightSans Medium", 20, FontStyle.Regular), b, new Point(0, 0));
graphics.DrawString(employeeCode, new Font(new FontFamily("FreightSans Medium"), 26), Brushes.Black,new RectangleF(new PointF(0, 25), sf),StringFormat.GenericTypographic);
//graphics.DrawString(, new Font("FreightSans Medium", 26, FontStyle.Regular), b, new Point(10, 20));
}