|
Well, as it turns out, you're quite correct - there's an inconsistency with the Margins handling. The PrintMargins attribute on the DGVPrinter object was the original margins setting method. But, now that the PageSettings object has been exposed, the DGVPrinter.PrintMargins value conflicts with the PageSettings.Margins value. Thanks for finding this. I'll be posting a fix in a day or two.
Secondly, you can make things a little easier on yourself by directly setting the PageSettings object instead of setting all its attributes one at a time.
E.g.
private PrinterSettings printsetup = null;
private PageSettings pagesetup = null;
...
if (null != printsetup) print.printDocument.PrinterSettings = printsetup;
if (null != pagesetup) print.printDocument.DefaultPageSettings = pagesetup;
if (DialogResult.OK == print.DisplayPrintDialog())
{
printsetup = print.PrintSettings;
pagesetup = print.PageSettings;
print.PrintPreviewNoDisplay(RequestList);
}
Note the use of PrintPreviewNoDisplay . Since the Print dialog is being displayed in "your" code there's no reason to show it again by calling PrintPreviewDataGridView .
Thanks again for finding this!
Steve G.
|
|
|
|
|
Hi
On some machines I have found that doing a preview or print it would try an calculate that there were many thousands (sometimes) of pages to print, when infact there were only 6. Worked fine on my development machine and on some machines the software was deployed on. Some it went berserk on !!!
Anyway here is what I think is happening and my fix.
In the method DisplayPrintDialog() by my understanding the PrintDocument printDoc's DefaultPageSettings should inherit from the PrintDialog pd settings, in some instances I don't think this is happening. Here are my changes along with the line pd.UseEXDialog = true; I found this on the net as a fix for 64bit Vista users. Displays the dialog correctly now.
The PaperSize attribute not being set is what causes the incorrect & wierd page count.
Anyway hope this helps to those whom may have experienced it, I was tearing what little hair I have out !
Thanks again aureolin for the great code
public DialogResult DisplayPrintDialog()
{
PrintDialog pd = new PrintDialog();
pd.UseEXDialog = true;
pd.AllowSelection = printDialogSettings.AllowSelection;
pd.AllowSomePages = printDialogSettings.AllowSomePages;
pd.AllowCurrentPage = printDialogSettings.AllowCurrentPage;
pd.AllowPrintToFile = printDialogSettings.AllowPrintToFile;
pd.ShowHelp = printDialogSettings.ShowHelp;
pd.ShowNetwork = printDialogSettings.ShowNetwork;
pd.Document = printDoc;
printDoc.DefaultPageSettings.Margins = printmargins;
if (!String.IsNullOrEmpty(printerName))
printDoc.PrinterSettings.PrinterName = printerName;
printDoc.DefaultPageSettings.Landscape = pd.PrinterSettings.DefaultPageSettings.Landscape;
printDoc.DefaultPageSettings.PaperSize = new PaperSize(pd.PrinterSettings.DefaultPageSettings.PaperSize.PaperName,
pd.PrinterSettings.DefaultPageSettings.PaperSize.Width,
pd.PrinterSettings.DefaultPageSettings.PaperSize.Height);
return pd.ShowDialog();
}
|
|
|
|
|
Fascinating! I'm limited to XP (for a while at least) so I'm not able to reproduce all of your issues. I did include the lines to set the Landscape and PaperSize from the print dialog default settings as you have shown. I added the flag to override the UseEXDialog setting to the printDialogSettings, along with all the other overrides. I've also updated my documentation to identify the printDialogSettings flags and what they mean.
I've submitted the changes to Codeproject so it will be a day or two before the changes are "live".
Thanks for notifying me of these issues!
Steve G.
|
|
|
|
|
Hi!
Thanks for the great article.
I have the same issue described here. But the suggested fix is not working
I figured out that it must have something to do with the cell-size. If there is small 'content' in it (100 chars) it works as expected, but if you have 1000's of chars in it, the error appears.
Maybe there's some buffer filling up?
Thanks and regards
Jan
|
|
|
|
|
After digging deeper into this problem it only appears if the contents of the cell exceeds the page size, either in landscape or in portrait mode.
So in my case I have round about 50 entries in a cell, each in a new line. It works fine if I set it to portrait mode, but not in landscape cause it exceeds the maximum height of the page.
I don't know a fix for that but I think it should continue with the remaining elements on a new page.
Maybe someone can fix this as it is urgent to me.
Thanks and regards
Jan
|
|
|
|
|
Does this class support printing checkboxes? Not the value (true/false) but actually a checked/unchecked box.
EDIT:
It doesn't support this. Have testet. It works great though but need the checkbox result to be presentet other than true/false. It would have been better with True = "X" and False = "". is there a easy way to change this before printout?
EDIT2:
Solved this. Added new columns to the grid. Turned the checkbox columns visibility off. Made an IF-sentence checking if the value was TRUE and putting an X in the new column representing the same but this is a regular text/string column data type. and so on...
modified on Friday, May 8, 2009 8:48 AM
|
|
|
|
|
Glad to see you've managed to work this through.
Steve G.
|
|
|
|
|
I get the following error for the button click method to print the dgv:
Could not load type 'DGVPrinterHelper.DGVPrinter' from assembly 'PastDueUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the method 'get_Owner' has no implementation (no RVA).
PastDueUI is the name of the project, and I am not sure why this is happening. I have added a reference for DGVPrinter.cs, and included 'using DGVPrinterHelper' in my application. This seems like the type of error I would receive if I were calling a .dll. Any help would be appreciated. I should note that my project is in 2.0.
**edit**
Convert project to a newer version. Very handy project.
modified on Friday, April 24, 2009 9:21 AM
|
|
|
|
|
I think I know what's going on, though it took some digging ... First when you added a reference to DGVPrinter.cs, you were telling the compiler that this was a DLL that had the relevant bits to implement the object - obviously not the case, so errors abound. The specific error was simply the loader telling you that it couldn't find any implementation for 'get_Owner'; no surprise as this is a code file not a dll.
What you should do is
A) remove the reference to DGVPrinter.cs
B) add DGVPrinter.cs to your project (add -> existing item) as you would any other code file
C) add a 'Using' statement in the file where you're using the DGVPrinter object (see near the top of this page for an example)
... and you should be good to go.
Steve G.
|
|
|
|
|
Hi Steve,
I just wanted to let you know about a small bug I ran across.
Set the DGVPrinter object's ProportionalColumns property to false.
Set TitleAlignment, SubTitleAlignment and FooterAlignment to Center.
When the graphics are rendered in the private "printsection" routine, it appears to use the width of the dgv object using ProportionalColumns value of true. The dgv is centered, but the Title, SubTitle and Footer all appear to be centered on an object that would be further to the right. My guess is they are positioned relative to the dgv's graphic instead of the page's graphic.
If I understood graphics a little better, I'd get it fixed and show you my solution. But I am *not* very good with graphics right now.
Joe Pool
|
|
|
|
|
Hmmmm .... I'm not able to reproduce anything like this. The centering of the Title, SubTitle and Footer are relative to the current page's margins and the calculated PrintWidth . You can see the calls in printDoc_PrintPage. Here's the Title print as an example:
printsection(e.Graphics, ref printpos, title, titlefont,
titlecolor, titleformat, overridetitleformat,
pagesets[currentpageset].margins);
The last parameter sends the current page's margins. The margins are used as the "left" position and the global "PrintWidth " value is used for the area within which to center the text. Whether or not "porportional columns" is turned on or off is irrelevant at this point.
There is one thing that might be affecting this - in printRow, the area to print in is adjusted to the smaller of PrintWidth or the width of the columns for that pageset (pageset.coltotalwidth ) so the area that the columns are printed in can actually be *different* from the area that the header and footer text is centered in.
At this point, my guess is that something else is going on. Can you give me more information on what you're trying to do and what's actually coming out the other end?
Steve G.
|
|
|
|
|
I'll follow up this with a private message.
I'd be happy to work with you on this or even help you with it in any way that I can.
I can email you the PDF output of my printout.
Joe
|
|
|
|
|
Sure - I'd like to see the PDF, along with your settings for the DGVPrinter object. My email id is aureolin on the hotmail mail service.
Steve G.
|
|
|
|
|
Just fyi, your XML code comments are throwing some compile-time warnings.
DGVPrinter.cs(932,26): error CS1572: Warning as Error: XML comment on 'DGVPrinterHelper.DGVPrinter.SetupPrint()' has a param tag for 'pd', but there is no parameter by that name
DGVPrinter.cs(1145,26): error CS1572: Warning as Error: XML comment on 'DGVPrinterHelper.DGVPrinter.buildstringformat(ref System.Drawing.StringFormat, System.Windows.Forms.DataGridViewCellStyle, System.Drawing.StringAlignment, System.Drawing.StringAlignment, System.Drawing.StringFormatFlags, System.Drawing.StringTrimming)' has a param tag for 'overrideformat', but there is no parameter by that name
DGVPrinter.cs(1147,57): error CS1573: Warning as Error: Parameter 'format' has no matching param tag in the XML comment for 'DGVPrinterHelper.DGVPrinter.buildstringformat(ref System.Drawing.StringFormat, System.Windows.Forms.DataGridViewCellStyle, System.Drawing.StringAlignment, System.Drawing.StringAlignment, System.Drawing.StringFormatFlags, System.Drawing.StringTrimming)' (but other parameters do)
DGVPrinter.cs(1148,56): error CS1573: Warning as Error: Parameter 'linealignment' has no matching param tag in the XML comment for 'DGVPrinterHelper.DGVPrinter.buildstringformat(ref System.Drawing.StringFormat, System.Windows.Forms.DataGridViewCellStyle, System.Drawing.StringAlignment, System.Drawing.StringAlignment, System.Drawing.StringFormatFlags, System.Drawing.StringTrimming)' (but other parameters do)
DGVPrinter.cs(1149,28): error CS1573: Warning as Error: Parameter 'trim' has no matching param tag in the XML comment for 'DGVPrinterHelper.DGVPrinter.buildstringformat(ref System.Drawing.StringFormat, System.Windows.Forms.DataGridViewCellStyle, System.Drawing.StringAlignment, System.Drawing.StringAlignment, System.Drawing.StringFormatFlags, System.Drawing.StringTrimming)' (but other parameters do)
DGVPrinter.cs(1726,26): error CS1572: Warning as Error: XML comment on 'DGVPrinterHelper.DGVPrinter.printsection(System.Drawing.Graphics, ref float, string, System.Drawing.Font, System.Drawing.Color, System.Drawing.StringFormat, bool, System.Drawing.Printing.Margins)' has a param tag for 'alignment', but there is no parameter by that name
DGVPrinter.cs(1727,26): error CS1572: Warning as Error: XML comment on 'DGVPrinterHelper.DGVPrinter.printsection(System.Drawing.Graphics, ref float, string, System.Drawing.Font, System.Drawing.Color, System.Drawing.StringFormat, bool, System.Drawing.Printing.Margins)' has a param tag for 'flags', but there is no parameter by that name
DGVPrinter.cs(1731,50): error CS1573: Warning as Error: Parameter 'format' has no matching param tag in the XML comment for 'DGVPrinterHelper.DGVPrinter.printsection(System.Drawing.Graphics, ref float, string, System.Drawing.Font, System.Drawing.Color, System.Drawing.StringFormat, bool, System.Drawing.Printing.Margins)' (but other parameters do)
|
|
|
|
|
Thanks for the note - I've fixed these, they'll be included in the next update.
Steve G.
|
|
|
|
|
First, I just want to say thanks for this.
There are, however, a couple of suggestions I would like to make for future releases.
First, could you add a field for the owning form, with the default set to null?
public DGVPrinter(Form owner)
{
this.owner = owner;
}
Second, could you add the ability to set the default zoom on the preview? On my desktop (with a screen resolution of 1600 by 1200 pixels), the preview always comes up too small to see the report.
public void PrintPreviewDataGridView(DataGridView dgv)
{
this.dgv = dgv;
if (DialogResult.OK == DisplayPrintDialog())
{
SetupPrint();
PrintPreviewDialog ppdialog = new PrintPreviewDialog();
ppdialog.UseAntiAlias = true;
ppdialog.PringPreviewControl.Zoom = 1.0;
if (owner == null)
{
ppdialog.ShowDialog();
} else
{
ppdialog.MdiParent = owner;
ppdialog.Show();
}
}
}
I make these modifications for the copies that I keep on my system, but it makes it more work to update to your newer versions.
I thought I'd share what I use with you. Use it if you like; ditch it if you don't.
Thanks for the tool!
|
|
|
|
|
It took a day or two to get the changes through CodeProject's editing process, but the requested changes are in place. (It also took me a day or two to send this notice as my wife and no. 2 son were sick with the flu!)
Anyway, I've added both requested properties, and updated the print preview display to size itself more appropriately. DGVPrinter now attempts to size the print preview display dialog so that the full page is visible, whether in portrait or landscape mode.
Have fun!
Steve G.
|
|
|
|
|
Thanks Steve!
I feel good knowing that I was able to contribute.
I wish the best for your family's speedy recovery. Chicken soup, saltine crackers, and 7-Up are all this Daddy serves to his sick family.
Regards,
Joe
|
|
|
|
|
Thanks, aureolin, for making this available. It has fit in quite nicely with a project I'm working on.
One thing that was driving me crazy, though, was I could not get the Titles & subtitles to be aligned correctly on the page. The were, instead, somehow tied to the table location which caused the Titles to look bad and even cut-off. Changing this code:
if (!String.IsNullOrEmpty(title))
printsection(e.Graphics, ref printpos, title, titlefont,
titlecolor, titleformat, overridetitleformat,
pagesets[currentpageset].margins);
if (!String.IsNullOrEmpty(subtitle))
printsection(e.Graphics, ref printpos, subtitle, subtitlefont,
subtitlecolor, subtitleformat, overridesubtitleformat,
pagesets[currentpageset].margins);
to this:
if (!String.IsNullOrEmpty(title))
printsection(e.Graphics, ref printpos, title, titlefont,
titlecolor, titleformat, overridetitleformat,
if (!String.IsNullOrEmpty(subtitle))
printsection(e.Graphics, ref printpos, subtitle, subtitlefont,
subtitlecolor, subtitleformat, overridesubtitleformat,
solved that problem and now my partners & I are happy with the output.
Thanks again!
Jeff M
|
|
|
|
|
Hi and thanks a mil for this code.
I would like to know how to fit this dgv in the desired position on a page.
I would like to print about 10 lines of text and a small graphic and then at about mid page the DGV.
Thanks in advance for any tips on how to use your class.
|
|
|
|
|
I think you may need to revise how you're approaching the problem. If you look at the PrintDoc_PrintPage routine and trace it down into the printsection routine you can see that the DGV object actually prints to a Graphics object acquired from the PrintEventArgs. What this means is that you can't just imbed the printout into another process.
The DGV object does have a way to set title lines, etc. in the header and footer and print them properly, but it doesn't have a way to imbed a graphic. To print things the way you're wanting to you can try overriding the "print header" section in PrintDoc_PrintPage. You'll also have to handle tracking the vertical space that your printing uses (that's the printpos variable) so that you don't have the printout running off the bottom of the page.
Hope this helps!
Steve G.
|
|
|
|
|
Hi and thanks for your reply.
I have only been programming for 4 months so what you write is way over my league.
I have looked at the sections you refer to and see the section that prints to a Graphics object.
Prior to writing to you I had tried to feed the TITLE and SUBTITLE properties some extra text, it works but the spacing makes my result look cramped.
I am so close to getting my app's printpage sorted out, I have the text and image printing fine in the top half of a page...if only I could get the DGV to print in the right spot I would be set....even willing to give priority to the DGV and let it print where it wants to but then I need to figure out how to get the text in....the image would be a bonus.
Any spoonfeeding would be greatly appreciated.
Using basic printdocument and printpage with some dumb code :
writer.WriteLine("About ten lines");
e.Graphics.DrawImage(pictureBox1.Image, 450, 250);
Thanks again
|
|
|
|
|
>> Only been programming for 4 months ...
Yikes!! You're pretty ambitious for a beginning programmer - and you seem to have come a long long way in short period of time.
What I'm talking about is you putting e.Graphics.DrawString() and e.Graphics.DrawImage() calls to print your stuff in the "print header" section, near where (instead of?) the title and subtitle are printed. The one thing you'll need to do is update the printpos variable to 'consume' the vertical space used for your header, both print and white space.
FYI, you can't use Writer.WriteLine to print to the e.Graphics object, that's why I'm suggesting the DrawString call. The DrawString method will give you the control that you need to get things looking good on the page.
You'll also need to create a couple of custom properties to pass the text and image(s) you want to print into the DGV object.
Hope this helps!!
Steve G.
|
|
|
|
|
..."seem to have come a long long way"..."seem to" is the correct way of putting it, cos in reality I am far from understanding what custom properties and updating the printpos variable are all about !
But nevertheless thanks for your time and once again thanks for the code.
Hope to get out of my newbie clothes soon cos I am getting fustrated by my lack of understanding things however every small step till now has been a matter of celebration.
Ciao
|
|
|
|
|
Good for you! You have come a long way - farther than you think.
Anyway, I can answer two things for you:
1) What does that "printpos" variable do? If you look at a sheet of paper, the printing process happens from the top down. In order to print a lines that are spaced nicely and don't simply print one on top of another, you have to move the "print position" (ergo 'printpos' for the variable name) down the page. Remember, during the print process DGVPrinter is actually 'drawing' everything on a blank slate, and it has complete control. DGVPrinter has to account for whitespace, left and right positioning, scaling to fit items in a page, leaving room for header and footer items, etc. So, the printpos variable is my 'where am I' indicator, counting vertical space used as the drawing of items moves down the page.
2) Custom properties. This one is a bit simpler. Take a look at the top of the DGVPrinter code and you'll find a lot of things that look like this:
private String printerName;
public String PrinterName
{
get { return printerName; }
set { printerName = value; }
}
This is how you define a "property" in C# (but you knew that). If you wanted to print a graphic in the header, you would need to add a property that would allow you to set a bitmap object (rather than a String in this example). This will make your image available to the code down inside DGVPrinter so that it can draw it into the header using the DrawImage call to write the bitmap into the output.
Hope this helps!
Steve G.
|
|
|
|
|