c#- How can I past PointF in to DrawString?
I try to past PointF into DrawString but it is not provide me.This is the code but ti is not provide me how can I do?
string txt = "A long line we're trying to fit inside a rectangle with custom line spacing";
Font font = new Font("Microsoft Sans Serif", 10, FontStyle.Bold);
SizeF fit = new SizeF(200, font.Height);
StringFormat fmt = StringFormat.GenericTypographic;
PointF pointf = new PointF(55,21);
//Rectangle ss = new Rectangle(new PointF(155.0F, 225.0F),txt);
int spacing = (int)(1.5 * font.Height);
int line = 0;
for (int ix = 0; ix < txt.Length; ) {
int chars, lines;
e.Graphics.MeasureString(txt.Substring(ix), font, fit, fmt, out chars, out lines);
e.Graphics.DrawString(txt.Substring(ix, chars), font, Brushes.Black, pointf, spacing * line);
++line;
ix += chars;
}
Please show me by code!
I think what you want is:
e.Graphics.DrawString(txt.Substring(ix, chars), font, Brushes.Black, pointf);
++line;
ix += chars;
// Set up for the next line.
pointf.Y = pointf.Y + (lines*font.Height) + spacing;
Note that I removed the last parameter to the DrawString call, and added code to update pointf.Y.
Related
I'm trying to add multiple watermarks to an image with some gap in between. I have been able to achieve this with two small caveats though.
What I want is:
Watermark should be vertically center aligned.
The program need to stop adding watermark when there is no sufficient width and/or height left in the image (so that there is no cutting of text).
My code is:
static void WatermarkedImage(string path, string fileName, string message, string destFileName)
{
using (Image image = Image.FromFile(path + fileName))
{
Graphics graphics = Graphics.FromImage(image);
Font font = new Font("Arial", 20, FontStyle.Bold);
SolidBrush brush = new SolidBrush(Color.FromArgb(150, 255, 0, 0));
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
int index = 0;
float offsetX = image.Width / 3;
float offsetY = image.Height / 3;
int increment = Convert.ToInt32(image.Height * 0.15);
while (offsetY * 1.25 < image.Height)
{
Matrix matrix = new Matrix();
matrix.Translate(offsetX, offsetY);
matrix.Rotate(-45.0f);
graphics.Transform = matrix;
graphics.DrawString(message, font, brush, 0, 50, format);
offsetX += increment;
offsetY += increment;
index++;
}
image.Save(path + destFileName);
}
}
This is what I'm getting with this:
Desired Output.
Any help is much appreciated.
Thank You!
Update-1
To check if all of the text is inside the image, use MeasureString to see how large the string will be. From this you can construct a rectangle, transform each corner of said rectangle using the matrix, and check if they are all inside the image.
Your desired output does not have any offset on the x-axis, so you shouldn't increment x offset at all.
offsetY += increment;
index++;
}
while (offsetY * 1.25 < image.Height);
image.Save(path + destFileName);
Hello I am printing a text on Receipt printer
on which I have to print Product name But products name get overwrites on Qty field can i get that name string in new line after particular length I am using following Code.
column 3 have a Product name Like (Almond Kesar Kanti Body Cleanser) How to get this text in new line and manage space of Invoice.
while (i < dataGridView2.Rows.Count)
{
if (height > e.MarginBounds.Height)
{
height = 500;
width = 500;
//e.HasMorePages = true;
return;
}
//height += dataGridView1.Rows[i].Height;
// e.Graphics.DrawRectangle(Pens.Black, 20, height, dataGridView1.Columns[0].Width, dataGridView1.Rows[0].Height);
e.Graphics.DrawString(dataGridView2.Rows[i].Cells["Column3"].FormattedValue.ToString(), dataGridView2.Font, Brushes.Black, CurrentX, CurrentY + 20);
e.Graphics.DrawString(dataGridView2.Rows[i].Cells["Column4"].FormattedValue.ToString(), dataGridView2.Font, Brushes.Black, CurrentX + 150, CurrentY + 20);
// e.Graphics.DrawString(dataGridView2.Rows[i].Cells["Column5"].FormattedValue.ToString(), dataGridView2.Font, Brushes.Black, CurrentX + 150, CurrentY + 20);
e.Graphics.DrawString(dataGridView2.Rows[i].Cells["Column10"].FormattedValue.ToString(), dataGridView2.Font, Brushes.Black, CurrentX + 200, CurrentY + 20);
i++;
CurrentY = CurrentY + 20;
}
You are not actually incrementing your CurrentY variable between the calls to DrawString. Therefore each line is printed at the same Y-coordinate.
Add CurrentY = CurrentY + 20; between each call to DrawString and just use
e.Graphics.DrawString(dataGridView2.Rows[i].Cells["Column3"].FormattedValue.ToString(), dataGridView2.Font, Brushes.Black, CurrentX, CurrentY);
Better yet, don't increment it by a fixed value but use e.Graphics.MeasureString to calculate the actual height of each line and increment by this value+spacing, like in this example:
Bitmap bmp = new Bitmap(200, 200);
using (Graphics g = Graphics.FromImage(bmp)) {
//The individual lines to draw
string[] lines = {
"Foo1",
"Foo2",
"Foo3"
};
int y = 1; //The starting Y-coordinate
int spacing = 10; //The space between each line in pixels
for (i = 0; i <= lines.Count - 1; i++) {
g.DrawString(lines[i], this.Font, Brushes.Black, 1, y);
//Increment the coordinate after drawing each line
y += Convert.ToInt32(g.MeasureString(lines[i], this.Font).Height) + spacing;
}
}
PictureBox1.Image = bmp;
Results:
Edit
To fit text into a given area you need to use a different overload of DrawString. You need to draw the string with a given LayoutRectangle like this:
Bitmap bmp = new Bitmap(200, 200);
using (Graphics g = Graphics.FromImage(bmp)) {
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
string LongText = "This is a really long text that should be automatically wrapped to a certain rectangle.";
Rectangle DestinationRectangle = new Rectangle(10, 10, 100, 150);
g.DrawRectangle(Pens.Red, DestinationRectangle);
using (StringFormat sf = new StringFormat()) {
g.DrawString(LongText, new Font("Arial", 9), Brushes.Black, DestinationRectangle, sf);
}
}
PictureBox1.Image = bmp;
The DestinationRectangle defines where the text is printed and it is automatically wrapped. The problem is, that the line spacing is defined by the Font you use, as you can see in this example with different fonts:
If you can't find a font that works for you (or define your own) you would need to split the text into words and fit them yourself into the given rectangle by drawing them word for word, measuring each with the MeasureString function and break the line when you would go over the limit.
But beware, text layout is hard, very very hard, to get all the corner cases right.
I am using netDXF (https://netdxf.codeplex.com/) to generate a DXF file for use with AutoCAD. However, I have an issue with getting the width of MText correct. I want to be able to define a width that the text should fit into, and change the width factor of the text (squash it horizontally) so that it fits in the defined area. So if I have a 40mm width to fit the text into and the text is 80mm long, it needs to have a width factor of 0.5. The only problem is that I don't know how to accurately determine the width of the text. I have tried the following methods and was unsuccessful in getting the correct result:
Why is Graphics.MeasureString() returning a higher than expected number?
Measure a String without using a Graphics object?
http://www.codeproject.com/Articles/2118/Bypass-Graphics-MeasureString-limitations
I have attached my code. I am basically printing a horizontal line using each of the 3 methods to calculate text width and comparing it to the actual text width. If I change the font, I get varying results. I have attached two images. One using the code with Calibri and one with Arial. I need the line to be on the edges of the text no matter what font I use.
Here is my code:
public void TestMethod1()
{
Application.SetCompatibleTextRenderingDefault(false);
//text width in mm
float textWidth = 40;
float textHeight = 200;
string labelText = "HELLO WORLD!";
TextStyle textStyle = new TextStyle("Calibri");
DxfDocument dxf = new DxfDocument();
Layer layer1 = new Layer("layer1");
layer1.Color = new AciColor(0, 0, 255);
layer1.Name = "Text";
MText text1 = new MText(new Vector2(0, 0), textHeight, 0, textStyle);
text1.Layer = layer1;
text1.AttachmentPoint = MTextAttachmentPoint.MiddleCenter;
//Will the text fit in the bounds of the rectangle? If not change width factor so it does.
Font f = new Font(textStyle.FontName, textHeight);
Size size = TextRenderer.MeasureText(labelText, f);
SizeF sizeF = graphicsMeasureString(labelText, f);
int width = MeasureDisplayStringWidth(labelText, f);
float widthFactor = Math.Min(1, textWidth / sizeF.Width);
MTextFormattingOptions mtextOptions = new MTextFormattingOptions(text1.Style);
//mtextOptions.WidthFactor = widthFactor;
text1.Write(labelText, mtextOptions);
//Red, g.MeasureString
Line line1 = new Line(new Vector2(0 - sizeF.Width / 2, 0), new Vector2(0 + sizeF.Width / 2, 0));
line1.Color = new AciColor(255, 0, 0);
//Green, TextRenderer
Line line2 = new Line(new Vector2(0 - size.Width / 2, 5), new Vector2(0 + size.Width / 2, 5));
line2.Color = new AciColor(0, 255, 0);
//Yellow, MeasureDisplayStringWidth
Line line3 = new Line(new Vector2(0 - width / 2, -5), new Vector2(0 + width / 2, -5));
line3.Color = new AciColor(255, 255, 0);
dxf.AddEntity(text1);
dxf.AddEntity(line1);
dxf.AddEntity(line2);
dxf.AddEntity(line3);
dxf.Save("Text Width Test.dxf");
}
public SizeF graphicsMeasureString(string text, Font f)
{
Bitmap fakeImage = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(fakeImage);
SizeF sizeF = g.MeasureString(text, f, new PointF(100, 0), StringFormat.GenericTypographic);
return sizeF;
}
public int MeasureDisplayStringWidth(string text, Font f)
{
Size size = TextRenderer.MeasureText(text, f);
Bitmap fakeImage = new Bitmap(1, 1);
Graphics g = Graphics.FromImage(fakeImage);
System.Drawing.StringFormat format = new System.Drawing.StringFormat();
System.Drawing.RectangleF rect = new System.Drawing.RectangleF(0, 0, 1000, 1000);
System.Drawing.CharacterRange[] ranges = { new System.Drawing.CharacterRange(0, text.Length) };
System.Drawing.Region[] regions = new System.Drawing.Region[1];
format.SetMeasurableCharacterRanges(ranges);
regions = g.MeasureCharacterRanges(text, f, rect, format);
rect = regions[0].GetBounds(g);
return (int)(rect.Right + 1.0f);
}
I am trying to create a captcha image. I am generating a random string and rotating the text with a random angle and trying to create a byte array. Below is my code snippet:
Image img = Image.FromFile(#"C:\Images\BackGround.jpg");
RectangleF myRect = new RectangleF(0, 0, width, height);
objGraphics.DrawImage(img, myRect);
Matrix myMatrix = new Matrix();
int i = 0;
StringFormat formatter = new StringFormat();
formatter.Alignment = StringAlignment.Center;
for (i = 0; i <= myString.Length - 1; i++)
{
myMatrix.Reset();
int charLenght = myString.Length;
float x = width / (charLenght + 1) * i;
float y = height / 30F;
myMatrix.RotateAt(oRandom.Next(-40, 40), new PointF(x, y));
objGraphics.Transform = myMatrix;
objGraphics.DrawString(myString.Substring(i, 1), MyFont, MyFontEmSizes, MyFontStyles,
MySolidBrush, x, Math.Max(width, height) / 50, formatter );
objGraphics.ResetTransform();
}
Every thing is working fine, except that, the first character in my final image on the web page is crossing my left border of the rectangle. How can I align my text to the center of the rectangle?
Thanks.
I have a label with unknown text. the text contains \n. I want a bigger space between the \n lines. How can I set it?
You can create custom label component and override it's measuring and painting, here you can find a snippet of a paint method which implements line spacing.
Edit: adding a snippet here in case the link is dead:
string text = "Sri Lanka";
Graphics g = e.Graphics;
Font font = new Font("Arial", 10);
Brush brush = new SolidBrush(Color.Black);
float lineSpacing = 0.5f;
SizeF size = g.MeasureString("A", font);
float pos = 0.0f;
for ( int i = 0; i < text.Length; ++i )
{
string charToDraw = new string(textIdea, 1);
g.DrawString(charToDraw, font, brush, pos, 0.0f);
SizeF sizeChar = g.MeasureString(charToDraw, font);
pos += sizeChar.Width + size.Width * lineSpacing;
}