Writing dynamic label to picturebox image only drawing the last modified label - c#

Okay, to start off. I'm trying to make dynamic editable, addable, and removeable text onto a picturebox. I got that working.
When saving an image from a picturebox, it doesn't save the labels. I now got it to draw the labels as a string using Graphics. Yet, it only draws the last modified/added/edited label to the pictureBox. I'm lost.
Here's my code for drawing the labels & saving them:
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string ext = Path.GetExtension(sfd.FileName);
switch (ext)
{
case ".jpg":
format = ImageFormat.Jpeg;
break;
case ".bmp":
format = ImageFormat.Bmp;
break;
}
Bitmap bmp = new Bitmap(pictureBox1.Image);
RectangleF rectf = new RectangleF(70, 90, 90, 50);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.Flush();
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
SolidBrush brush = new SolidBrush(label.ForeColor);
for (int i = 0; i < n; i++)
{
g.DrawString(label.Text, label.Font, brush, label.Location);
label.SelectNextControl(label, false, false, true, false);
}
pictureBox1.Image = bmp;
pictureBox1.Image.Save(sfd.FileName, format);
}
Here's where the labels are defined and created:
label = new CustomLabel();
label.Name = "" + n;
label.Location = new Point(newTextbox.Location.X, newTextbox.Location.Y);
label.Text = newTextbox.Text;
label.Font = new Font("Verdana", fontSize);
label.BackColor = Color.Transparent;
label.ForeColor = textColor;
label.AutoSize = true;
label.Visible = true;
newTextbox.Visible = false;
newTextbox.Dispose();
pictureBox1.Controls.Add(label);
TextSelected = false;
label.DoubleClick += new System.EventHandler(this.label_DoubleClick);
label.MouseDown += new MouseEventHandler(this.label_MouseDown);
label.MouseUp += new MouseEventHandler(this.MouseUp);
label.MouseMove += new MouseEventHandler(this.MouseMove);
n++;
And n is defined:
public int n = 1;
Where the stroke is added to the text:
public class CustomLabel : Label
{
public CustomLabel()
{
OutlineForeColor = Color.Black;
OutlineWidth = 3;
}
public Color OutlineForeColor { get; set; }
public float OutlineWidth { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(BackColor), ClientRectangle);
using (GraphicsPath gp = new GraphicsPath())
using (Pen outline = new Pen(OutlineForeColor, OutlineWidth)
{ LineJoin = LineJoin.Round })
using (StringFormat sf = new StringFormat())
using (Brush foreBrush = new SolidBrush(ForeColor))
{
gp.AddString(Text, Font.FontFamily, (int)Font.Style,
Font.Size, ClientRectangle, sf);
e.Graphics.ScaleTransform(1.3f, 1.35f);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.DrawPath(outline, gp);
e.Graphics.FillPath(foreBrush, gp);
}
}
}

The problem is in your for loop:
for (int i = 0; i < n; i++)
{
g.DrawString(label.Text, label.Font, brush, label.Location);
label.SelectNextControl(label, false, false, true, false);
}
Here label never changes, so you are just drawing the same label n times. And I don't know what SelectNextControl does.
I suggest looping over the controls in the picture box:
foreach (var customLabel in pictureBox1.Controls.OfType<CustomLabel>()) {
g.DrawString(customLabel.Text, customLabel.Font, brush, customLabel.Location);
}

Related

C# Graphics DrawString outline

I use this to write text to a bitmap:
using (Graphics graphics = Graphics.FromImage(bitmap))
{
using (Font font = new Font("Arial", 72))
{
graphics.DrawString(text, font, Brushes.Gold, location);
}
// Save & dispose
}
I would like to get an outline added. How can I do this? I tried a solution from 9 years ago using GraphicsPath, but could not get it working.
From an old project of mine:
using(Bitmap bmp = new Bitmap(1000, 1000))
{
Bitmap bmp2 = captionImage(bmp, new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)), new SolidColorBrush(Color.FromArgb(255, 0, 0, 0)), "Hello World", "Arial", 24 , 4.0f, true, false, false, 10, 10);
bmp2.Save("foo.png");
}
public System.Drawing.Bitmap captionImage(System.Drawing.Bitmap img, System.Windows.Media.Brush fontColor, System.Windows.Media.Brush strokeColor, string text, string font, float fontSize, float strokeThickness, bool bold, bool italic, bool underline, int left, int top)
{
int style;
float calculatedStrokeThickness;
System.Drawing.Brush strokeBrush;
System.Drawing.FontFamily c;
style = 0;
strokeBrush = BrushToDrawingBrush(strokeColor);
calculatedStrokeThickness = fontSize * (strokeThickness * 0.1f);
if (bold == true)
style ^= (int)System.Drawing.FontStyle.Bold;
if (italic == true)
style ^= (int)System.Drawing.FontStyle.Italic;
if (underline == true)
style ^= (int)System.Drawing.FontStyle.Underline;
c = MatchFontFamily(font);
if (c == null)
c = MatchFontFamily("Arial");
if (c != null)
{
using (System.Drawing.StringFormat sf = new System.Drawing.StringFormat())
{
sf.Alignment = System.Drawing.StringAlignment.Near;
sf.LineAlignment = System.Drawing.StringAlignment.Near;
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(img))
{
using (System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath())
{
try
{
path.AddString(text, c, style, fontSize, new System.Drawing.Point(left, top), sf);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
for (float i = 0; i < calculatedStrokeThickness; i += 5)
{
using (System.Drawing.Pen p = new System.Drawing.Pen(strokeBrush, i))
{
p.LineJoin = System.Drawing.Drawing2D.LineJoin.Round;
if (strokeThickness > 0.0f)
{
//g.FillPath(System.Drawing.Brushes.Red, path);
g.DrawPath(p, path);
}
}
}
g.FillPath(BrushToDrawingBrush(fontColor), path);
}
catch (Exception x)
{
x.ToString();
}
}
}
}
}
else
MessageBox.Show("Unable to load fonts");
return img;
}
private System.Drawing.Brush BrushToDrawingBrush(Brush brush)
{
Color color;
System.Drawing.Brush ret;
color = ((SolidColorBrush)brush).Color;
ret = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B));
return ret;
}

Color issue when drawing text on an PNG image in C#

I want to draw black text over with grey opacity PNG file so text is BLACK.
What I am getting is the text is some % of grey:
Even if I use Brushes.Black the text is still grey;
My code is following:
List<string> GenerateDeviceIcon(string backgroundImageFile, string deviceImageFile, string deviceNumber, int deviceID, string saveNewFilePath, string fontName, int fontSize, Brush textColor)
{
var r = new List<string>();
try
{
Image background = Image.FromFile(backgroundImageFile);
Image logo = Image.FromFile(deviceImageFile);
PointF firstLocation = new PointF(2f, 2f);
using (background)
{
using (var bitmap = new Bitmap(background.Width, background.Height))
{
using (var canvas = Graphics.FromImage(bitmap))
{
using (Font arialFont = new Font(fontName, fontSize))
{
canvas.DrawString(deviceNumber, arialFont, textColor, firstLocation);
}
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
canvas.DrawImage(background, new Rectangle(0, 0, background.Width, background.Height), new Rectangle(0, 0, background.Width, background.Height), GraphicsUnit.Pixel);
canvas.DrawImage(logo, (bitmap.Width / 2) - (logo.Width / 2), (bitmap.Height / 2) - (logo.Height / 2));
canvas.Save();
}
try
{
var filename = Path.Combine(saveNewFilePath, deviceID.ToString() + ".png");
if (File.Exists(filename))
{
File.Delete(filename);
}
bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
}
catch (Exception ex)
{
r.Add(ex.Message);
}
}
}
}
catch (Exception ex)
{
r.Add(ex.Message);
}
return r;
}
How to fix it?
Many thanks!
Well I found the bug: dont draw text BEFORE you draw a background!
And I've improved the code so it draws multiple lines of a transport ID.
Enjoy if you need create complex icons in .NET!
Code:
static List<string> GenerateDeviceIcon2(string backgroundImageFile, string deviceImageFile,
string deviceNumber, int deviceID, string saveNewFilePath, string fontName, int fontSize, Color textColor)
{
var r = new List<string>();
try
{
Image background = Image.FromFile(backgroundImageFile);
Image logo = Image.FromFile(deviceImageFile);
PointF firstLocation = new PointF(2f, 2f);
#region Create text as Image with Transparancy
//first, create a dummy bitmap just to get a graphics object
Image img = new Bitmap(1, 1);
Graphics drawingText = Graphics.FromImage(img);
//measure the string to see how big the image needs to be
int maxWidth = background.Width - 2;
var font = new Font(fontName, fontSize, new FontStyle());
SizeF textSize = drawingText.MeasureString(deviceNumber, font, maxWidth);
//set the stringformat flags to rtl
StringFormat sf = new StringFormat
{
//uncomment the next line for right to left languages
//sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
Trimming = StringTrimming.Word
};
//free up the dummy image and old graphics object
img.Dispose();
drawingText.Dispose();
//create a new image of the right size
img = new Bitmap((int)textSize.Width, (int)textSize.Height);
// drawingText = Graphics.FromImage(img);
#endregion
//create a brush for the text
Brush textBrush = new SolidBrush(textColor);
using (background)
{
using (var bitmap = new Bitmap(background.Width, background.Height))
{
using (var canvas = Graphics.FromImage(bitmap))
{
//Adjust for high quality
canvas.CompositingQuality = CompositingQuality.HighQuality;
canvas.InterpolationMode = InterpolationMode.HighQualityBilinear;
canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
canvas.SmoothingMode = SmoothingMode.HighQuality;
canvas.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
//paint the background
canvas.Clear(Color.Transparent);
// First - draw a background!
canvas.DrawImage(background, new Rectangle(0, 0, background.Width, background.Height),
new Rectangle(0, 0, background.Width, background.Height), GraphicsUnit.Pixel);
// Second - draw the text in multiple rows over background
canvas.DrawImage(logo, (bitmap.Width / 2) - (logo.Width / 2), (bitmap.Height / 2) - (logo.Height / 2));
// Third - draw the logo over background
canvas.DrawString(deviceNumber, font, textBrush, new RectangleF(0, 0, textSize.Width, textSize.Height), sf);
canvas.Save();
}
try
{
var filename = Path.Combine(saveNewFilePath, deviceID.ToString() + ".png");
if (File.Exists(filename))
{
File.Delete(filename);
}
bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Png);
}
catch (Exception ex)
{
r.Add(ex.Message);
}
}
}
textBrush.Dispose();
img.Dispose();
}
catch (Exception ex)
{
r.Add(ex.Message);
}
return r;
}

Why doesn't Graphics show up?

I want to save all drawstring which is done with the codes at the bottom half. I am saving it by saving the "Points" in a List type. The purpose of saving is because I want to have the ability to delete a particular drawing. All other drawings will be retained and only the one which wants to be deleted will be removed. My main query is why can't I use the same code with some minor editing(Top half of the code is the code I use to add new drawstring) that I use to draw to redraw when I am deleting a particular drawing.
Side_pictureBox.ImageLocation = AppDomain.CurrentDomain.BaseDirectory + #"pictures for app\Bus_Nearside.png";
Side_pictureBox.Image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + #"\pictures for app\Bus_Nearside.png");
Bitmap bm = new Bitmap(Side_pictureBox.Image);
if (Tagged_Remarks_listBox.SelectedIndex == 0)
{
for (int x = 0; x <= NumberingPosition.Count - 1; x++)
{
if (x != 0)
{
using (Graphics gr = Graphics.FromImage(bm))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
Font drawFont = new Font("Calibri (Body)", 15);
SolidBrush drawBrush = new SolidBrush(Color.Blue);
//MessageBox.Show(Numbering[u] + NumberingPosition[u]);
gr.DrawString(Numbering[x], drawFont, drawBrush, NumberingPosition[x]);
}
}
Side_pictureBox.Image = bm;
Side_pictureBox.Invalidate();
}
//Above code is when I first drawstring ,Below Code is to redraw when deleting particular drawing//
Bitmap bm = new Bitmap(Side_pictureBox.Image);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
String drawString = numbering_for_digram.ToString();
Font drawFont = new Font("Calibri (Body)", 15);
SolidBrush drawBrush = new SolidBrush(Color.Blue);
gr.DrawString(drawString, drawFont, drawBrush, lastPoint);
Numbering.Add(drawString);
drawFont.Dispose();
drawBrush.Dispose();
}
Side_pictureBox.Image = bm;
If we're in the Paint() event, then I'd expect to see something more like this:
if (Tagged_Remarks_listBox.SelectedIndex == 0)
{
Graphics gr = e.Graphics;
gr.SmoothingMode = SmoothingMode.AntiAlias;
Font drawFont = new Font("Calibri (Body)", 15);
SolidBrush drawBrush = new SolidBrush(Color.Blue);
for (int x = 1; x <= NumberingPosition.Count - 1; x++)
{
//MessageBox.Show(Numbering[u] + NumberingPosition[u]);
gr.DrawString(Numbering[x], drawFont, drawBrush, NumberingPosition[x]);
}
drawFont.Dispose();
drawBrush.Dispose();
}
Note that calling Invalidate() in the Paint() would cause it to repaint itself REPEATEDLY and FOREVER...which might be part of the problem.
I found a way to make it work(Maybe not the best, most effective, efficient way), by using Bitmap to take in all the drawings. This bitmap will then be saved as a Png file. Once all drawings are done, I declare the picturebox.image as the bitmap's Png file.
private void Side_pictureBox_Paint(object sender, PaintEventArgs e)
{
if (Tagged_Remarks_listBox.SelectedIndex == 0 && selectedindexreset == true)
{
//Side_pictureBox.ImageLocation = AppDomain.CurrentDomain.BaseDirectory + #"pictures for app\Bus_Nearside.png";
Side_pictureBox.Image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + #"\pictures for app\Bus_Nearside.png");
Bitmap bmforedit = new Bitmap(Side_pictureBox.Image);
//MessageBox.Show("inside");
using (Graphics gr = Graphics.FromImage(bmforedit))
{
for (int x = 0; x <= NumberingPosition.Count - 1; x++)
{
//MessageBox.Show(x.ToString());
if (Numbering[x] != "1") // change accordingly
{
//MessageBox.Show(Numbering[x]);
gr.SmoothingMode = SmoothingMode.AntiAlias;
Font drawFont = new Font("Calibri (Body)", 15);
SolidBrush drawBrush = new SolidBrush(Color.Blue);
//MessageBox.Show(Numbering[x] + NumberingPosition[x]);
gr.DrawString(Numbering[x], drawFont, drawBrush, NumberingPosition[x]);
drawFont.Dispose();
drawBrush.Dispose();
}
}
// bmforedit.Save(#"C:\Users\user\Desktop\PDI_APP_EDIT_FOR_TO\PDIPROTOTYPE2\bin\Debug\pictures for app\TestImage.png");
Side_pictureBox.Image.Dispose();
//bmforedit.Save(#"C:\Users\user\Desktop\PDI_APP_EDIT_FOR_TO\PDIPROTOTYPE2\bin\Debug\pictures for app\TestImage1.png");
Side_pictureBox.Image = bmforedit;
}
for (int u = 0; u <= PrevStore.Count - 1; u++)
{
using (Graphics g = Graphics.FromImage(bmforedit))
{
if (u < StartDrawCount[0] || u > StopDrawCount[0])
{
g.DrawLine(new Pen(Color.DarkRed, 2), PrevStore[u], NowStore[u]);
g.SmoothingMode = SmoothingMode.AntiAlias;
}
}
}
bmforedit.Save(#"C:\Users\user\Desktop\PDI_APP_EDIT_FOR_TO\PDIPROTOTYPE2\bin\Debug\pictures for app\TestImage2.png");
selectedindexreset = false;
Side_pictureBox.ImageLocation = AppDomain.CurrentDomain.BaseDirectory + #"pictures for app\TestImage2.png";
Side_pictureBox.Refresh();
}
}

C# Tabs Rotate Text

I am having some issues rotating the text on a tab. The tabs originally worked just fine, but then I wanted to bold the text when selected, so I used the Draw Item Event. I added a RotateTransform and a TranslateTransform, but its not working. The text just doesn't show up. I have troubleshot it and if I take the rotation away, the text is visible, but when I use the rotate to make the text vertical, it disappears. Here's my code:
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
string tabText = tabControl1.TabPages[e.Index].Text;
SizeF textSize = g.MeasureString(tabText, tabControl1.Font);
Brush _textBrush = Brushes.Black;
TabPage _tabPage = tabControl1.TabPages[e.Index];
System.Drawing.Rectangle _tabBounds = tabControl1.GetTabRect(e.Index);
StringFormat _stringFlags = new StringFormat();
_stringFlags.Alignment = StringAlignment.Center;
_stringFlags.LineAlignment = StringAlignment.Center;
PointF tabPt = new PointF(_tabBounds.Left+(_tabBounds.Width), _tabBounds.Top+(_tabBounds.Height));
if (e.Index == tabControl1.SelectedIndex)
{
g.RotateTransform(-90);
g.TranslateTransform(tabPt.X, tabPt.Y);
g.DrawString(tabControl1.TabPages[e.Index].Text,
new Font(tabControl1.Font, FontStyle.Bold),
_textBrush,
new PointF(tabPt.X, tabPt.Y));
g.ResetTransform();
}
else
{
g.TranslateTransform(tabPt.X, tabPt.Y);
g.RotateTransform(-90);
g.DrawString(tabControl1.TabPages[e.Index].Text,
tabControl1.Font,
_textBrush,
new PointF(tabPt.X,tabPt.Y));
g.ResetTransform();
}
}
}
Any help would be greatly appreciated.
EDIT
Here's the image:
Here's the new code:
Graphics g = e.Graphics;
string tabText = tabControl1.TabPages[e.Index].Text;
SizeF textSize = g.MeasureString(tabText, tabControl1.Font);
Brush _textBrush = Brushes.Black;
TabPage _tabPage = tabControl1.TabPages[e.Index];
System.Drawing.Rectangle _tabBounds = tabControl1.GetTabRect(e.Index);
PointF rotPt = new PointF(_tabBounds.Left + (_tabBounds.Width / 2) - (2.75F), _tabBounds.Top + (_tabBounds.Height / 2) + (textSize.Width/2));
PointF tabPt = new PointF(_tabBounds.Left + (_tabBounds.Width / 2) - (2.75F), _tabBounds.Top + (_tabBounds.Height / 2) + (textSize.Width)/2);
if (e.Index == tabControl1.SelectedIndex)
{
g.TranslateTransform(rotPt.X, rotPt.Y);
g.RotateTransform(-90);
g.TranslateTransform(-(rotPt.X), -(rotPt.Y));
g.DrawString(tabText,
new Font(tabControl1.Font, FontStyle.Bold),
_textBrush,
new PointF(rotPt.X, rotPt.Y));
}
else
{
g.TranslateTransform(rotPt.X, rotPt.Y);
g.RotateTransform(-90);
g.TranslateTransform(-rotPt.X, -rotPt.Y);
g.DrawString(tabText,
tabControl1.Font,
_textBrush,
new PointF(rotPt.X,rotPt.Y));
}
Thanks TaW for your help. Here's the final code and its working.
public form1()
{
InitializeComponent();
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.DrawItem += new DrawItemEventHandler(tabControl1_DrawItem);
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
string tabText = tabControl1.TabPages[e.Index].Text;
SizeF textSize = g.MeasureString(tabText, tabControl1.Font);
Brush _textBrush = Brushes.Black;
TabPage _tabPage = tabControl1.TabPages[e.Index];
System.Drawing.Rectangle _tabBounds = tabControl1.GetTabRect(e.Index);
PointF rotPt = new PointF(_tabBounds.Left + (_tabBounds.Width / 2) - (textSize.Height / 2), _tabBounds.Top + (_tabBounds.Height / 2) + (textSize.Width/2));
if (e.State.HasFlag(DrawItemState.Selected))
{
g.TranslateTransform(rotPt.X, rotPt.Y);
g.RotateTransform(-90);
g.TranslateTransform(-(rotPt.X), -(rotPt.Y));
g.DrawString(tabText,
new Font(tabControl1.Font, FontStyle.Bold),
_textBrush,
new PointF(rotPt.X, rotPt.Y));
g.ResetTransform();
}
else
{
g.TranslateTransform(rotPt.X, rotPt.Y);
g.RotateTransform(-90);
g.TranslateTransform(-rotPt.X, -rotPt.Y);
g.DrawString(tabText,
tabControl1.Font,
_textBrush,
new PointF(rotPt.X,rotPt.Y));
g.ResetTransform();
}
}
P.S. I never did get the e.Bounds rather than GetTabRect (i'm not sure how to set it to the selected tab).

How to print one large image in many pages?

I want to print one tall (long) image in many pages. So in every page, I take a suitable part from the image and I draw it in the page.
the problem is that I have got the image shrunk (its shape is compressed) in the page,so I added an scale that its value is 1500 .
I think that I can solve the problem if I knew the height of the page (e.Graphics) in pixels.
to convert Inches to Pixel, Do I have to multiply by (e.Graphics.DpiX = 600) or multiply by 96 .
void printdocument_PrintPage(object sender, PrintPageEventArgs e)
{
if (pageImage == null)
return;
e.Graphics.PageUnit = GraphicsUnit.Pixel;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
float a = (e.MarginBounds.Width / 100) * e.Graphics.DpiX;
float b = ((e.MarginBounds.Height / 100) * e.Graphics.DpiY);
int scale = 1500;
scale = 0; //try to comment this
RectangleF srcRect = new RectangleF(0, startY, pageImage.Width, b - scale);
RectangleF destRect = new RectangleF(0, 0, a, b);
e.Graphics.DrawImage(pageImage, destRect, srcRect, GraphicsUnit.Pixel);
startY = Convert.ToInt32(startY + b - scale);
e.HasMorePages = (startY < pageImage.Height);
}
could you please make it works correctly.
you can download the source code from (here).
thanks in advanced.
I tried to complete your task.
Here you go. Hope it helps.
This method prints the image on several pages (or one if image is small).
private void printImage_Btn_Click(object sender, EventArgs e)
{
list = new List<Image>();
Graphics g = Graphics.FromImage(image_PctrBx.Image);
Brush redBrush = new SolidBrush(Color.Red);
Pen pen = new Pen(redBrush, 3);
decimal xdivider = image_PctrBx.Image.Width / 595m;
int xdiv = Convert.ToInt32(Math.Ceiling(xdivider));
decimal ydivider = image_PctrBx.Image.Height / 841m;
int ydiv = Convert.ToInt32(Math.Ceiling(ydivider));
/*int xdiv = image_PctrBx.Image.Width / 595; //This is the xsize in pt (A4)
int ydiv = image_PctrBx.Image.Height / 841; //This is the ysize in pt (A4)
// # 72 dots-per-inch - taken from Adobe Illustrator
if (xdiv >= 1 && ydiv >= 1)
{*/
for (int i = 0; i < xdiv; i++)
{
for (int y = 0; y < ydiv; y++)
{
Rectangle r;
try
{
r = new Rectangle(i * Convert.ToInt32(image_PctrBx.Image.Width / xdiv),
y * Convert.ToInt32(image_PctrBx.Image.Height / ydiv),
image_PctrBx.Image.Width / xdiv,
image_PctrBx.Image.Height / ydiv);
}
catch (Exception)
{
r = new Rectangle(i * Convert.ToInt32(image_PctrBx.Image.Width / xdiv),
y * Convert.ToInt32(image_PctrBx.Image.Height),
image_PctrBx.Image.Width / xdiv,
image_PctrBx.Image.Height);
}
g.DrawRectangle(pen, r);
list.Add(cropImage(image_PctrBx.Image, r));
}
}
g.Dispose();
image_PctrBx.Invalidate();
image_PctrBx.Image = list[0];
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += PrintDocument_PrintPage;
PrintPreviewDialog previewDialog = new PrintPreviewDialog();
previewDialog.Document = printDocument;
pageIndex = 0;
previewDialog.ShowDialog();
// don't forget to detach the event handler when you are done
printDocument.PrintPage -= PrintDocument_PrintPage;
}
This method prints every picture in the List in the needed dimensions (A4 size):
private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
// Draw the image for the current page index
e.Graphics.DrawImageUnscaled(list[pageIndex],
e.PageBounds.X,
e.PageBounds.Y);
// increment page index
pageIndex++;
// indicate whether there are more pages or not
e.HasMorePages = (pageIndex < list.Count);
}
This method crops the image and returns every part of the image:
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, System.Drawing.Imaging.PixelFormat.DontCare);
return (Image)(bmpCrop);
}
The Image gets loaded from the PictureBox, so make sure the image is loaded. (No exception handling yet).
internal string tempPath { get; set; }
private int pageIndex = 0;
internal List<Image> list { get; set; }
These variables are defined as global variables.
You can download a sample project here:
http://www.abouchleih.de/projects/PrintImage_multiplePages.zip // OLD Version
http://www.abouchleih.de/projects/PrintImage_multiplePages_v2.zip // NEW
I have Created a Class file for multiple page print a single large image.
Cls_PanelPrinting.Print Print =new Cls_PanelPrinting.Print(PnlContent/Image);
You have to Pass the panel or image.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Printing;
namespace Cls_PanelPrinting
{
public class Print
{
readonly PrintDocument printdoc1 = new PrintDocument();
readonly PrintPreviewDialog previewdlg = new PrintPreviewDialog();
public int page = 1;
internal string tempPath { get; set; }
private int pageIndex = 0;
internal List<Image> list { get; set; }
private int _Line = 0;
private readonly Panel panel_;
public Print(Panel pnl)
{
panel_ = pnl;
printdoc1.PrintPage += (printdoc1_PrintPage);
PrintDoc();
}
private void printdoc1_PrintPage(object sender, PrintPageEventArgs e)
{
Font myFont = new Font("Cambria", 10, FontStyle.Italic, GraphicsUnit.Point);
float lineHeight = myFont.GetHeight(e.Graphics) + 4;
float yLineTop = 1000;
int x = e.MarginBounds.Left;
int y = 25; //e.MarginBounds.Top;
e.Graphics.DrawImageUnscaled(list[pageIndex],
x,y);
pageIndex++;
e.HasMorePages = (pageIndex < list.Count);
e.Graphics.DrawString("Page No: " + pageIndex, myFont, Brushes.Black,
new PointF(e.MarginBounds.Right, yLineTop));
}
public void PrintDoc()
{
try
{
Panel grd = panel_;
Bitmap bmp = new Bitmap(grd.Width, grd.Height, grd.CreateGraphics());
grd.DrawToBitmap(bmp, new Rectangle(0, 0, grd.Width, grd.Height));
Image objImage = (Image)bmp;
Bitmap objBitmap = new Bitmap(objImage, new Size(700, objImage.Height));
Image PrintImage = (Image)objBitmap;
list = new List<Image>();
Graphics g = Graphics.FromImage(PrintImage);
Brush redBrush = new SolidBrush(Color.Red);
Pen pen = new Pen(redBrush, 3);
decimal xdivider = panel_.Width / 595m;
// int xdiv = Convert.ToInt32(Math.Ceiling(xdivider));
decimal ydivider = panel_.Height / 900m;
int ydiv = Convert.ToInt32(Math.Ceiling(ydivider));
int xdiv = panel_.Width / 595; //This is the xsize in pt (A4)
for (int i = 0; i < xdiv; i++)
{
for (int y = 0; y < ydiv; y++)
{
Rectangle r;
if (panel_.Height > 900)
{
try
{
if (list.Count > 0)
{
r = new Rectangle(0, (900 * list.Count), PrintImage.Width, PrintImage.Height - (900 * list.Count));
}
else
{
r = new Rectangle(0, 0, PrintImage.Width, 900);
}
list.Add(cropImage(PrintImage, r));
}
catch (Exception)
{
list.Add(PrintImage);
}
}
else { list.Add(PrintImage); }
}
}
g.Dispose();
PrintImage = list[0];
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += printdoc1_PrintPage;
PrintPreviewDialog previewDialog = new PrintPreviewDialog();
previewDialog.Document = printDocument;
pageIndex = 0;
printDocument.DefaultPageSettings.PrinterSettings.PrintToFile = true;
string path = "d:\\BillIng.xps";
if (File.Exists(path))
File.Delete(path);
printDocument.DefaultPageSettings.PrinterSettings.PrintFileName = "d:\\BillIng.xps";
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
printDocument.PrintPage -= printdoc1_PrintPage;
}
catch { }
}
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, System.Drawing.Imaging.PixelFormat.DontCare);
return (Image)(bmpCrop);
}
}
}

Categories