I'm trying to achieve framed texts (using Windows Forms), e.g.:
Height is always the same, because my strings are less than 20 chars. What about width? Is there any way to get it automatically?
Use Graphics.MeasureString()
From MSDN: http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx
private void MeasureStringMin(PaintEventArgs e)
{
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0));
}
If you don't feel like dealing with the Paint eventhandler, you could try the TextRenderer class. It has a static method that is identical to the "MeasureString" method in the above answer. In this class it is called MeasureText however.
Related
In my application, I generate a Bitmap with a variable string.
Here is my function:
public void Image(String text, String font, int size)
{
Font font = new Font(font, size);
float res = ((font.SizeInPoints * text.Length) / 72) * 96;
using (Bitmap img = new Bitmap((int)res, font.Height))
{
Graphics g = Graphics.FromImage(img);
SolidBrush drawBrush = new SolidBrush(Color.Black);
g.DrawString(text, font, drawBrush, 1, 0);
String directory = AppDomain.CurrentDomain.BaseDirectory + "Content\\Images\\Signature\\";
string outputFileName = directory + "sign.png";
img.Save(outputFileName, ImageFormat.Png);
}
}
I would like the width of the image to match perfectly the width of the string printed in that bitmap.
As you can see, I tried to calculate the width with point size of the font.
The problem is that each letter printed has a different width so I can not get the size before creating the Bitmap.
Plus, I don't even know how to retrieve the actual size of the printed string...
Does anyone have an idea?
Use the Graphics.MeasureString function. It takes a string and a font, and returns the size of the rendered text as a SizeF. There are also additional overloads that can take formatting information, and one that takes a SizeF representing the maximum width for wrapping.
Details can be found here: https://msdn.microsoft.com/en-us/library/6xe5hazb(v=vs.110).aspx
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Set maximum layout size.
SizeF layoutSize = new SizeF(100.0F, 200.0F);
// Set string format.
StringFormat newStringFormat = new StringFormat();
newStringFormat.FormatFlags = StringFormatFlags.DirectionVertical;
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont, layoutSize, newStringFormat);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0,
I have a couple of TextBlocks in a Fixed Size Column Grid. i.e. The Grid size might change, but its column widths are all the same (e.g. 10% of the whole size) and each column contains a TextBlock.
The font size of all the TextBlocks MUST be the same.
How can I find the maximum possible font size which makes all the texts inside TextBlocks visible?
You could use Graphics.MeasureString Method (String, Font, Int32) to calculate the fontsize.
Then use some behaviour magic to bind the font size to the TextBlock.
private void MeasureStringWidth(PaintEventArgs e)
{
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Set maximum width of string.
int stringWidth = 200;
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont, stringWidth);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0));
}
Ok, so this is the problem: in C# forms I've created a new private void:
private void NewBtn(string Name, int x, int y)
Which has a purpose of creating a picturebox that imitates behavior of a button (don't ask why, I simply enjoy complicating things) and can be called as many times as I want.
Font btnFont = new Font("Tahoma", 16);
PictureBox S = new PictureBox();
S.Location = new System.Drawing.Point(x, y);
S.Paint += new PaintEventHandler((sender, e) =>
{
e.Graphics.TextRenderingHint =
System.Drawing.Text.TextRenderingHint.AntiAlias;
e.Graphics.DrawString(Name, btnFont, Brushes.Black, 0, 0);
});
Controls.Add(S);
Now, I am worried about part with Paint/Graphics (ignore rest of the code, I only gave some of it). I want to center the text that I write as "Name" in void when I call it "NewBtn(Name, x, y)". So, what should I put as
e.Graphics.DrawString(Name, btnFont, Brushes.Black, ThisX???, 0);
Suggestions?
var size = g.MeasureString(Name, btnFont);
e.Graphics.DrawString(Name, btnFont, Brushes.Black,
(S.Width - size.Width) / 2,
(S.Height - size.Height) / 2));
You can improve this by measuring the string only once, considering the font and text won't change for a specific Button/PictureBox.
And I would also suggest checking if S.Size is wider / taller than size and handling it, so graphics won't try to draw a string starting at negative coordinates.
Try using the Graphics.DrawString methods that uses the String.Drawing.StringFormat Option
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment= StringAlignment.Center;
drawFormat.LineAlignment = StringAlignment.Center;
You have two options here the first to use coordinates.
e.Graphics.DrawString(("Name", new Font("Arial", 16), Brushes.Black, 10, 10, drawFormat);
the second is to create a rectange like this:
e.Graphics.DrawString("Name", new Font("Arial", 16), Brushes.Black, new Rectangle(0,0,this.Width,this.Height), drawFormat);
I already have this code but it gives me the wrong result.
private void document_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int charPerLine = e.MarginBounds.Width / (int)e.Graphics.MeasureString("m", txtMain.Font).Width;
}
The txtMain is a textbox.
This should do the trick. Be careful when dividing by a variable cast to an integer. You are leaving yourself open to a divide-by-zero here in the event that the Width property is less than one, which will be truncated to zero. It may be unlikely that you will have such a small font in your application, but it is still good practice.
private void document_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
if( (int)e.Graphics.MeasureString("m", txtMain.Font).Width > 0 )
{
int charPerLine =
e.MarginBounds.Width / (int)e.Graphics.MeasureString("m", txtMain.Font).Width;
}
}
The real issue though is why do you even need to know the number of characters per line. Unless you are trying to do some sort of ASCII art, you can use the different overloads of Graphics.DrawString to have GDI+ layout the text for you inside a bounding rectangle without needing to know how many characters fit on a line.
This sample from MSDN shows you how to do this:
// Create string to draw.
String drawString = "Sample Text";
// Create font and brush.
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Black);
// Create rectangle for drawing.
float x = 150.0F;
float y = 150.0F;
float width = 200.0F;
float height = 50.0F;
RectangleF drawRect = new RectangleF(x, y, width, height);
// Draw rectangle to screen.
Pen blackPen = new Pen(Color.Black);
e.Graphics.DrawRectangle(blackPen, x, y, width, height);
// Set format of string.
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Center;
// Draw string to screen.
e.Graphics.DrawString(drawString, drawFont, drawBrush, drawRect, drawFormat);
So if you are trying to print a page of text, you can just set the drawRect to the e.MarginBounds and plug a page worth of text in for drawString.
Another thing, if you are trying to print tabular data, you can just partition the page into rectangles - one for each column/row (however you need it), and use e.Graphics.DrawLine overloads to print the table borders.
If you post more details on what you are actually trying to achieve we can help more.
I use this code for drawing text in a panel:
Graphics g = panel1.CreateGraphics();
g.DrawString(...);
So I want to know what size the input text will be when rendered in the panel.
Use g.MeasureString() to get the width of a string in the grapic context.
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont);
You can also use TextRenderer.MeasureText which is sometimes easier to use than MeasureString.