Print with Margins While Keeping Aspect Ratio of Image C# - c#

I’m using WinForms. In my Form I got a picuturebox and 4 textboxes margin_top, margin_bottom, margin_left, and margin_right. I want to be able to create margins for the images at appear in the print preview dialog-box, but I also want to scale the image proportionately when I provide the margins. I also want the images to be enclosed in the print-preview-page, meaning not having the images cut-of. Another question, is why my image is cutting of when the print-preview page is the same size as my image? I used an 850 width by 1100 Height image and when I clicked print preview the image it got cut off without me having to re-size it.
Below is a link for an image you can test on.
http://www.filedropper.com/850x1100
Below is an image that not displaying correctly in the print-preview screen. It is missing its right and bottom borders.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Printing_Image_Center
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Image = new Bitmap(#"C:\Users\Bob\Pictures\850x1100.png");
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
var img_width = e.PageBounds.Width - e.MarginBounds.Left - Math.Abs(e.MarginBounds.Right - e.PageBounds.Width);
var img_height = e.PageBounds.Height - e.MarginBounds.Top - Math.Abs(e.MarginBounds.Bottom - e.PageBounds.Height);
e.Graphics.DrawImage(ResizeAcordingToImage(pictureBox1.Image, img_width, img_height),
e.MarginBounds.Left, e.MarginBounds.Top);
}
private void Btn_Print_Click(object sender, EventArgs e)
{
printPreviewDialog1.Document = printDocument1;
//PrintDocument.OriginAtMargins = true;
printDocument1.DefaultPageSettings.Margins.Top = Convert.ToInt32(txt_Top.Text);
printDocument1.DefaultPageSettings.Margins.Left = Convert.ToInt32(txt_Left.Text);
printDocument1.DefaultPageSettings.Margins.Right = Convert.ToInt32(txt_Right.Text);
printDocument1.DefaultPageSettings.Margins.Bottom = Convert.ToInt32(txt_bottom.Text);
printPreviewDialog1.ShowDialog();
}
private Image ResizeAcordingToImage(Image Source, int boxWidth, int boxHeight)
{
Image resizedImage;
double dbl = (double)Source.Width / (double)Source.Height;
//set height of image to boxHeight and check if resulting width is less than boxWidth,
//else set width of image to boxWidth and calculate new height
if ((int)((double)boxHeight * dbl) <= boxWidth)
{
resizedImage = new Bitmap(Source, (int)((double)boxHeight * dbl), boxHeight);
}
else
{
resizedImage = new Bitmap(Source, boxWidth, (int)((double)boxWidth / dbl));
}
return resizedImage;
}
}
}

Please provide the values of img.width and img.height in your code to resolve the problem. This is the only thing that you were missing.
var img = ResizeAcordingToImage(pictureBox1.Image, img_width, img_height);
e.Graphics.DrawImage(img, e.MarginBounds.Left, e.MarginBounds.Top, img.Width, img.Height);
Here is your result after the changes:

Related

Not able to take screenshot using C#

I am having a hard time with this C# application I am trying to modify.
The code originates from:
http://www.codeproject.com/Articles/485883/Create-your-own-Snipping-Tool
When I run the code it executes fine, you see the marker which should let you mark a sector of your screen that you want to take a screenshot of, but I am not able to mark any sector of the screen.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace copy
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Hide the Form
this.Hide();
//Create the Bitmap
Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height);
//Create the Graphic Variable with screen Dimensions
Graphics graphics = Graphics.FromImage(printscreen as Image);
//Copy Image from the screen
graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
//Create a temporal memory stream for the image
using (MemoryStream s = new MemoryStream())
{
//save graphic variable into memory
printscreen.Save(s, ImageFormat.Bmp);
pictureBox1.Size = new System.Drawing.Size(this.Width, this.Height);
//set the picture box with temporary stream
pictureBox1.Image = Image.FromStream(s);
}
//Show Form
this.Show();
//Cross Cursor
Cursor = Cursors.Cross;
}
//These variables control the mouse position
int selectX;
int selectY;
int selectWidth;
int selectHeight;
public Pen selectPen;
//This variable control when you start the right click
bool start = false;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
//validate if there is an image
if (pictureBox1.Image == null)
return;
//validate if right-click was trigger
if(start)
{
//refresh picture box
pictureBox1.Refresh();
//set corner square to mouse coordinates
selectWidth = e.X - selectX;
selectHeight = e.Y - selectY;
//draw dotted rectangle
pictureBox1.CreateGraphics().DrawRectangle(selectPen,
selectX, selectY, selectWidth, selectHeight);
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
//validate when user right-click
if (!start)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
//starts coordinates for rectangle
selectX = e.X;
selectY = e.Y;
selectPen = new Pen(Color.Red, 1);
selectPen.DashStyle = DashStyle.DashDotDot;
}
//refresh picture box
pictureBox1.Refresh();
//start control variable for draw rectangle
start = true;
}
else
{
//validate if there is image
if (pictureBox1.Image == null)
return;
//same functionality when mouse is over
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
pictureBox1.Refresh();
selectWidth = e.X - selectX;
selectHeight = e.Y - selectY;
pictureBox1.CreateGraphics().DrawRectangle(selectPen, selectX,
selectY, selectWidth, selectHeight);
}
start = false;
//function save image to clipboard
SaveToClipboard();
}
}
private void SaveToClipboard()
{
//validate if something selected
if (selectWidth > 0)
{
Rectangle rect = new Rectangle(selectX, selectY, selectWidth, selectHeight);
//create bitmap with original dimensions
Bitmap OriginalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
//create bitmap with selected dimensions
Bitmap _img = new Bitmap(selectWidth, selectHeight);
//create graphic variable
Graphics g = Graphics.FromImage(_img);
//set graphic attributes
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(OriginalImage, 0, 0, rect, GraphicsUnit.Pixel);
//insert image stream into clipboard
Clipboard.SetImage(_img);
}
//End application
Application.Exit();
}
}
}
As the comments on the linked page already suggest you have to enable the event handlers you created:
public Form1()
{
InitializeComponent();
pictureBox1.MouseDown += new MouseEventHandler(pictureBox1_MouseDown);
pictureBox1.MouseMove += new MouseEventHandler(pictureBox1_MouseMove);
}

How can i save the desktop window but in half size? [duplicate]

This question already has answers here:
How to resize an Image C#
(16 answers)
Closed 8 years ago.
This is the code in form1 i'm using now.
I'm capturing the desktop window using a timer each second.
In the end i have a button click event and if i click on it, it will create animated gif file on my hard disk from all the saved gif files.
But when i'm loading/running the animated gif on internet explorer for example i see the animation on the whole screen even bigger so i need to use and move the scrollbars to see it all each time.
How can i save the desktop window but half size for example ?
Now on my hard disk i have about 100 gif files each one at size 380-407kb.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using System.IO;
using unfreez_wrapper;
namespace CapturedDesktop
{
public partial class Form1 : Form
{
int screens;
string gifsdirectory;
UnFreezWrapper unfreez;
public Form1()
{
InitializeComponent();
unfreez = new UnFreezWrapper();
timer1.Enabled = false;
screens = 0;
gifsdirectory = #"C:\Temp\CapturedDesktop\";
}
private void CaptureScreenshot()
{
screens++;
screenshots(gifsdirectory + screens.ToString("D6") + ".gif");
}
public static void screenshots(string filename)
{
//Create a new bitmap.
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
// Save the screenshot to the specified path that the user has chosen.
bmpScreenshot.Save(filename, ImageFormat.Gif);
bmpScreenshot.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
CaptureScreenshot();
}
private void AnimatedGifButton_Click(object sender, EventArgs e)
{
List<string> myGifList = new List<string>();
FileInfo[] fi;
DirectoryInfo dir1 = new DirectoryInfo(gifsdirectory);
fi = dir1.GetFiles("*.gif");
for (int i = 0; i < fi.Length; i++)
{
myGifList.Add(fi[i].FullName);
}
unfreez.MakeGIF(myGifList, gifsdirectory + "agif", 100, true);
}
}
}
I want to capture take screenshots of the whole desktop window but when displaying it to show it not so big.
You can change the size from here
public static void screenshots(string filename)
{
//Create a new bitmap.
var bmpScreenshot = new Bitmap(
(Screen.PrimaryScreen.Bounds.Width - 100),
(Screen.PrimaryScreen.Bounds.Height - 100),
PixelFormat.Format32bppArgb
);
// other code
}
This will create a Bitmap object which is 100px shorter than the screen.
You can change your screenshots function like this:
public static void screenshots(string filename)
{
//Create a new bitmap.
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
// Save the screenshot to the specified path that the user has chosen.
//bmpScreenshot.Save(filename, ImageFormat.Gif);
//bmpScreenshot.Dispose();
var bmpHalfSize = new Bitmap(Screen.PrimaryScreen.Bounds.Width / 2,
Screen.PrimaryScreen.Bounds.Height / 2,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var g = Graphics.FromImage(bmpHalfSize);
g.DrawImage(bmpScreenshot, 0, 0, CInt(Screen.PrimaryScreen.Bounds.Width / 2), CInt(Screen.PrimaryScreen.Bounds.Height / 2));
bmpHalfSize.Save(filename, ImageFormat.Gif);
bmpHalfSize.Dispose();
bmpScreenshot.Dispose();
}
Just a quick note: when playing with Graphics is better adopt Using statement in order to provides a convenient syntax that ensures the correct use of IDisposable objects.
For example:
using (Graphics g = Graphics.FromImage(bmpHalfSize)) {
g.DrawImage(bmpScreenshot, 0, 0, CInt(Screen.PrimaryScreen.Bounds.Width / 2), CInt(Screen.PrimaryScreen.Bounds.Height / 2));
}

c# Custom control click event

I've made a custom control and I want to add a click event so when the user clicks anywhere on the control it will return the position of where the user has clicked on the control. For example if the user clicks in the middle of the bar it would essentially return me enough information for me to calculate 50% and that the user has clicked in the middle.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace CustomRangeBar
{
public partial class RangeBar : UserControl
{
public RangeBar()
{
InitializeComponent();
label1.ForeColor = Color.Black;
this.ForeColor = SystemColors.Highlight; // set the default color the rangeBar
this.Click += new EventHandler(RangeBar_Click);
}
protected float percent = 0.0f; // Protected because we don't want this to be accessed from the outside
// Create a Value property for the rangeBar
public float Value
{
get
{
return percent;
}
set
{
// Maintain the value between 0 and 100
if (value < 0) value = 0;
else if (value > 100) value = 100;
percent = value;
label1.Text = value.ToString();
//redraw the rangeBar every time the value changes
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Brush b = new SolidBrush(this.ForeColor); //create brush that will draw the background of the range bar
// create a linear gradient that will be drawn over the background. FromArgb means you can use the Alpha value which is the transparency
LinearGradientBrush lb = new LinearGradientBrush(new Rectangle(0, 0, this.Width, this.Height), Color.FromArgb(255, Color.White), Color.FromArgb(50, Color.White), LinearGradientMode.Vertical);
// calculate how much has the rangeBar to be filled for 'x' %
int width = (int)((percent / 100) * this.Width);
e.Graphics.FillRectangle(b, 0, 0, width, this.Height);
e.Graphics.FillRectangle(lb, 0, 0, width, this.Height);
b.Dispose(); lb.Dispose();
}
private void RangeBar_SizeChanged(object sender, EventArgs e)
{
// maintain the label in the center of the rangeBar
label1.Location = new Point(this.Width / 2 - 21 / 2 - 4, this.Height / 2 - 15 / 2);
}
}
}
public void RangeBar_Click(object obj, EventArgs ea)
{
// This get executed if the pictureBox gets clicked
label1.text = "Increment 1";
}
OnClick is not a good function to override or subscribe to because it does not tell you the position where the click happened which is what you are looking for.
What you want is OnMouseClick which includes the x,y of the click point.
protected override void OnMouseClick(MouseEventArgs e)
{
int x = e.X;
int y = e.Y;
//Do your calculation here.
}

how to allow g.drawstring in c# to be adjusted after it is placed in picturebox

I am trying to use a picturebox and pick out 2 points(eyes in a photo). I would pick out the two points with g.DrawString where I will draw 2 different 'x'. The problem now is I am stuck as what if the user has placed the 'x' on a wrong position and I would like to adjust it. Is there any codes which will allow the g.DrawString 'x' to be able to be moved?
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;
namespace Camera
{
public partial class CamDisplay : Form
{
public CamDisplay()
{
InitializeComponent();
this.pictureBox1.ImageLocation = #"C:\center90\center90(1).jpg";
}
bool MousedClicked = true;
bool MouseClicked2 = true;
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
base.OnMouseClick(e);
if (MousedClicked == true)
{
txtXaxis.Text = e.X.ToString();
txtYaxis.Text = e.Y.ToString();
MousedClicked = false;
using (Graphics g = Graphics.FromHwnd(pictureBox1.Handle))
{
using (Font myFont = new Font("Calibri", 8))
{
g.DrawString("X", myFont, Brushes.Red, new PointF(e.X, e.Y));
}
}
}
else if (MouseClicked2 == true)
{
txtRXaxis.Text = e.X.ToString();
txtRYaxis.Text = e.Y.ToString();
MouseClicked2 = false;
using (Graphics g = Graphics.FromHwnd(pictureBox1.Handle))
{
using (Font myFont = new Font("Calibri", 8))
{
g.DrawString("X", myFont, Brushes.Red, new PointF(e.X, e.Y));
}
}
}
else
{
MousedClicked = false;
MouseClicked2 = false;
}
}
private void CamDisplay_MouseEnter(object sender, EventArgs e)
{
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.Cursor = Cursors.Hand;
}
}
}
Your question is unclear. As I understand your problem you have two options:
If you are using your Graphics object to directly manipulate the BMP (ie. you DrawString directly to the bitmap) there is no way to "undo" a previous operation. You could instead keep a local copy of the original bitmap in memory, duplicate it to a second bitmap and perform the operations only on the copy, which is the one you show in your form. When you need to "undo" you just go back to the original copy.
Do not manipulate the bitmap directly, but instead perform your drawing operations in the OnPaint() event of the PictureBox. In that way you only draw to the screen, leaving the original Bmp intact. See example here: http://msdn.microsoft.com/en-us/library/b818z6z6%28v=vs.110%29.aspx

How to print rectangle with exact size in c#?

I am new to Dot Net, I want to print a rectangle with 20mm width and 8mm height exactly if I measure with scale. I also want to print text exactly in the middle of rectangle.Can anyone suggest me how can I achieve this?
I am really sorry for not being clear earlier. I have tried using "PageUnits" its working fine. However, I have problem with the margins.
I am able to print correct margins(8.8mm left and 22mm Top) if I am using the printer "HP LaserJet P2035n". If print using "Canon iR2020 PCL5e" I am getting incorrect margins(8.1mm left and 8.0mm Top) where I should get 8.8mm left and 22mm top margins. Can someone explain me where I am doing wrong.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Printing;
namespace ConsoleApplication6
{
class DrawShape
{
public static void DrawRec()
{
PrintDocument doc = new PrintDocument();
doc.PrintPage += doc_PrintPage;
doc.Print();
}
static void doc_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
PageSettings PageSet = new PageSettings();
float MarginX = PageSet.PrintableArea.X;
float MarginY = PageSet.PrintableArea.Y;
float x = (float)(8.8-((MarginX/100)*25.4));
float y = (float)(22-((MarginY/100)*25.4));
g.PageUnit = GraphicsUnit.Millimeter;
g.DrawRectangle(Pens.Black, x, y, 20, 8);
}
}
}
You may want to start with this:
private void button1_Click(object sender, EventArgs e)
{
using (Graphics formGraphics = this.CreateGraphics())
{
formGraphics.PageUnit = GraphicsUnit.Millimeter;
formGraphics.DrawRectangle(Pens.Blue, 0, 0, 20, 80);
}
}
You can then using DrawString on the Graphics object to draw text inside your rectangle.

Categories

Resources