i have an ms chart control on the form and i would like to print the chart. what is the best way to do this?
This might be a bit convoluted for your purposes, but I've used the PrintDocument object to draw a background image on pages of a report. You could do something similar, where you use the Graphics object from the PrintPageEventArgs to "paint" your chart image.
This code would print a 1 page document with a small rectangle drawn in the upper corner. I would think you could replace the drawing there with the drawing of your chart
class Program
{
public class Document : System.Drawing.Printing.PrintDocument
{
protected override void OnBeginPrint(System.Drawing.Printing.PrintEventArgs e)
{
base.OnBeginPrint(e);
}
protected override void OnPrintPage(System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawRectangle(SystemPens.ActiveBorder, new Rectangle(0, 0, 20, 20));
}
}
static void Main(string[] args)
{
System.Drawing.Printing.PrintDocument pd = new Document();
pd.Print();
}
}
Another flexible solution is to export the chart to PDF and let the user print it out from Adobe Reader, and he/she will be able to save the chart or send it by email as well...
Related
I have a win form where i have some label,a datagridview and some textbox.I want to print all of my items in my form in exact format it shows in the form. I have tried it using taking snap of my form then print it. But in this way i can't have my full form as my form is large enough.It only shows half portion of my form.I don't know is it the best practice on not.Is there any other way of doing this please mention
My Sample code:
private void btnPrint_Click(object sender, EventArgs e)
{
CaptureScreen();
printDocument1.Print();
}
private void CaptureScreen()
{
Graphics myGraphics = this.CreateGraphics();
Size s = this.Size;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, s);
}
private void printDocument1_PrintPage_1(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
}
As i am new in C#,it will be great help if anyone help me with some sample code.
I think you should emulate your form layout in a page or text description language like PDF or RTF. Taking a screenshot programmatically is in a way elegant but also crude at the same time, and runs into limitations of which you encountered just one.
One thing to consider is whether you should serialize your data e.g. as XML first, and only then export to data formats suitable for printing or displaying, like PDF or HTML.
I am trying to draw a rectangle on PictureBox without using Paint event of picturebox,So i override the Onpaint method :
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics dc = pictureBox1.CreateGraphics();
Pen bPen=new Pen(Color.Blue,3);
dc.DrawRectangle(bPen,0,0,50,50);
}
}
But the rectangle doesn't appear in first time ,but when i change the size of form using mouse my rectangle is appeared why ?!!!
I understand that you do not want to use the Paint event of the PictureBox. Your code wouldn't work since the form gets rendered before its containing elements.
I offer you a solution: draw on a bitmap and then insert that bitmap into the PictureBox through its Image public member.
private void loadDrawing(){
Bitmap map = new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height);
var graph = Graphics.FromImage(map);
graph.DrawRectangle(new Pen(Color.Blue, 3), 0, 0, 50, 50);
pictureBox1.Image = map;
}
Let's say you want to make the Rectangle to show up upon load:
private void Form1_Load(object sender, EventArgs e)
{
loadDrawing();
}
The problem is that you override OnPaint method of the form instead of Paint event of the PictureBox. Form's OnPaint happens, when the form needs repainting, and that's independent of what happens with the PictureBox.
Implement OnPaint event of the PictureBox and then you will not have to create Graphics object manually - simply use one provided in the event arguments.
private void Form1_Load(object sender, EventArgs e)
{
// No need to do that
// pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(10, 10, 20, 20));
}
Edit: (in response to comments)
If you want to update the paintbox periodically, do the following:
Keep the data required to draw the scene somewhere in the form, possibly as a private field
Use these data to draw the scene in Paint event of the PictureBox
When you need to update the scene, modify the data accordingly, and then call the Invalidate method of the PictureBox. It will cause the Paint event to fire and the scene will be redrawn.
Remember though, that all calls to UI methods from the threads has to be synchronized to the main UI thread (otherwise they won't work or cause problems).
You are overriding the paint method of the form, while you paint the PictureBox. That isn't how it is meant to be. The PictureBox will still do it's own rendering.
If you really want to do painting of the PictureBox, implement the Paint event of the PictureBox or create a custom control where you draw a rectangle, and a picture.
After you draw the form refresh the form using this :-
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics dc = pictureBox1.CreateGraphics();
Pen bPen=new Pen(Color.Blue,3);
dc.DrawRectangle(bPen,0,0,50,50);
this.Refresh() ;
}
The single tooltip which shows different messages for different controls. Now the Problem is the background image is not fit/suitable to all messages. I supposed to call the draw event of the tooltip for custom size, Font etc.,
I able to successfully call the draw and Popup event of the tooltip for particular message but setting the generalized size for different messages(e.ToolTipText) is unknown to me.
public void tooltip_Popup(object sender, PopupEventArgs e)
{
e.ToolTipSize = new Size(100, 100);
}
Kindly let me know anybody have any idea about it.
you can set the size in the Popup event, like this:
private void toolTip1_Popup(object sender, PopupEventArgs e)
{
e.ToolTipSize = new Size(200, 200);
}
result of my test is this, hope it's helpful to you.
I found the answer for my Problem. The below code of POPUP event will change the tooltipsize according to the text size.
public void toolTip_Popup(object sender, PopupEventArgs e)
{
using (Font f = new Font("Arial", 12f))
{
e.ToolTipSize = TextRenderer.MeasureText(
toolTips.GetToolTip(e.AssociatedControl), f);
}
My project is to print a panel from form
but the resolution was so terrible
I checked a lot of posts
Knowing that the main problem is DPI difference between monitor and printer
I try to set my bitmap big and print it at right size i want
but it seems i cant set them well
the resolution still bad and the size change like uncontralable
if i set my bitmap size greater then 10k
it will disappear from print preview dialog
my code here
Bitmap MemoryImage;
public void GetPrintArea(Panel pnl)
{
MemoryImage = new Bitmap(9000,9000);
Rectangle rect = new Rectangle(0,0,9000,9000);
pnl.DrawToBitmap(MemoryImage, rect);
}
void doc_PrintPage(object sender, PrintPageEventArgs e)
{
GetPrintArea(flowLayoutPanel1);
Rectangle pagearea = new Rectangle(0,0,5000, 5000);
e.Graphics.DrawImage(MemoryImage,pagearea);
}
PrintDocument doc = new PrintDocument();
private void button1_Click(object sender, EventArgs e)
{
PrintDocument doc = new PrintDocument();
doc.PrintPage += new PrintPageEventHandler(doc_PrintPage);
PrintPreviewDialog dlg = new PrintPreviewDialog();
PaperSize psize = new PaperSize("A4 300DPI", 2480, 3508);
doc.PrinterSettings.DefaultPageSettings.PaperSize = psize;
dlg.Document = doc;
dlg.ShowDialog();
}
I want to get panel and print it on A4 with resolution like printing a word document
I spent almost a week try to solve this problem >"<
Plz save me ...
I spent almost a week try to solve this problem
You can't make it to work even if you try another week, because you are on the wrong track.
Knowing that the main problem is DPI difference between monitor and printer
You know the problem and know that there is no solution for that you still keep trying.
Solution:
If you want to render some data on report, i don't think printing of panel is the solution. you should consider printing report in the form of a report. Like, consider making an RDLC/Crystal report and put your desired data on that report. In short, use Reports for reporting purpose.
OR - How To Shave A Koala To Stop It Looking Squashed. (But I didn't think that would make a suitably techy title)
The Problem: You have three preview images derived from a main image. The preview images are resized for standardised picture spaces on a company website, the main image can be any size image from anywhere.
Example: The main image is a hi-res image of a koala bear measuring 2000x2250. Your previews want to render the koala at 200x200, 200x50 and 250x150.
Your utility program resizes and stretches the original image to the size of your three "actual size" previews but obviously each preview looks a bit squashy and you know everyone hates to see a squashed koala.
To resolve this you add a little cropping method to your program which shaves five pixels from the preview on the desired side. This means you should be able to resize your image and unsquash your koala by shaving off the unnecessary parts of the image.
You add four buttons to each preview image picture box and create four generic methods for sending the correct shaving instructions to the crop method. You want to associate each specific button with a specific picturebox on the form, but you want to send all the click events to four generic functions.
How do you tell the generic function which of the three preview picturebox images you want it to shave in an elegant and wonderful way?
Example Code:
//cropPict=method for cropping the picture in the relevant picturebox.
//CropSide=a little enum which tells the method which side to crop.
private void btnT_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Top);
}
private void btnB_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Bottom);
}
private void btnR_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Right);
}
private void btnL_Click(object sender, EventArgs e)
{
cropPict(/*Reference to PictureBox Goes Here*/, CropSide.Left);
}
EDIT: As it happens, inspired by Hans below, rather than just stuffing the PictureBox into the tag. Which was a great idea I actually put a KeyValuePair into the tag for each button like so:
btnCCB.Tag = new KeyValuePair<CropSide,PictureBox>(CropSide.Bottom,pbxKoala);
btnCCL.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Left, pbxKoala);
btnCCR.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Right, pbxKoala);
btnCCT.Tag = new KeyValuePair<CropSide, PictureBox>(CropSide.Top, pbxKoala);
Then I could just wire all the buttons up to a single event handler like so:
private void btnC_Click(object sender, EventArgs e)
{
Button btnSend = (Button)sender;
KeyValuePair<CropSide, PictureBox> kvCrop = (KeyValuePair<CropSide, PictureBox>)btnSend.Tag;
cropPict(kvCrop.Value,kvCrop.Key);
}
Of course, there's still plenty more to do but that pretty much sorted out my problem. Thanks Hans!
Use the Button.Tag property to store a reference to its associated PictureBox. Cast sender to Button:
public Form1()
{
InitializeComponent();
button1.Tag = pictureBox1;
button1.Click += btnT_Click;
// etc..
}
private void btnT_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
cropPict((PictureBox)btn.Tag, CropSide.Top);
}