Printing Basics (Tutorials)

  • Thread starter Thread starter Tomas Vera
  • Start date Start date
T

Tomas Vera

Hello All,
Don't know how I've managed to escape this but:

I need to learn how to print from my app.

I've worked through the examples in the Docs and have a good idea of
how to print text and InvokePaint on controls. But now I need to
understand how to print things such as
1. The non-Visible part of a datagrid (not just the data in the
cells, but the lines, headers, etc.).
2. RTF (multiple font/color) text objects.
3. Mixed items text with pictures, etc.
4. Screenshots, etc.

Can anyone point to a good tutorial (online or paper) that covers
these types of things? Or at least covers the concepts?

Thanks,

-tomas
 
This works well:
Add a PrintDocument, PrintPreview to your form. Set the PrintPreviews
document property to the PrintDocument, and set the PrintDocuments
PrintPage procedure to the pd_PrintPage item below. This code presumes
a PrintDocument named Pd, a print preview named ppv, and a print button
named cmPrintForm. You'll have to adjust the scaling and other factors
to fit your form, and generally make this your own. This is for the
purpose of printing your actual form as the user sees it. I owe credit
to Lion Shi for originally posting this code.

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
Int32 dwRop // raster operation code
);
private Bitmap memoryImage;

private void CaptureScreen() {
string myUser =
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(System.Environment.UserName.ToLower());
System.Drawing.Font mFont = new System.Drawing.Font("Arial", 12);
Graphics mygraphics = this.CreateGraphics();
Size s = this.Size;
string strOne = "Add Style or Component Form, Printed By: " + myUser
+ " On: " + System.DateTime.Now.ToShortDateString() + " At: " +
System.DateTime.Now.ToShortTimeString();
memoryImage = new Bitmap(s.Width, s.Height + 50, mygraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.DrawString(strOne, mFont, Brushes.Black, 50, 25);
IntPtr dc1 = mygraphics.GetHdc();
IntPtr dc2 = memoryGraphics.GetHdc();
BitBlt(dc2, 0, 50, this.ClientRectangle.Width,
this.ClientRectangle.Height, dc1, 0, 0, 13369376);
mygraphics.ReleaseHdc(dc1);
memoryGraphics.ReleaseHdc(dc2);
}

private void pd_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e) {
e.Graphics.DrawImage(memoryImage, 15, 15);
}

private void cmPrintForm_Click(System.Object sender, System.EventArgs
e) {
if (this.Width > this.Height) {
pd.DefaultPageSettings.Landscape = true;
}
CaptureScreen();
//printDocument1.Print();
ppv.Width=1024;
ppv.Height=768;
ppv.ShowDialog();
}
 
Thanks for the BitBlt. I'd seen it before, in the "old days" and was
hoping that there was something more "native" in .Net.

Thanks,

-tomas
This works well:
Add a PrintDocument, PrintPreview to your form. Set the PrintPreviews
document property to the PrintDocument, and set the PrintDocuments
PrintPage procedure to the pd_PrintPage item below. This code presumes
a PrintDocument named Pd, a print preview named ppv, and a print button
named cmPrintForm. You'll have to adjust the scaling and other factors
to fit your form, and generally make this your own. This is for the
purpose of printing your actual form as the user sees it. I owe credit
to Lion Shi for originally posting this code.

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
Int32 dwRop // raster operation code
);
private Bitmap memoryImage;

private void CaptureScreen() {
string myUser =
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(System.Environment.UserName.ToLower());
System.Drawing.Font mFont = new System.Drawing.Font("Arial", 12);
Graphics mygraphics = this.CreateGraphics();
Size s = this.Size;
string strOne = "Add Style or Component Form, Printed By: " + myUser
+ " On: " + System.DateTime.Now.ToShortDateString() + " At: " +
System.DateTime.Now.ToShortTimeString();
memoryImage = new Bitmap(s.Width, s.Height + 50, mygraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.DrawString(strOne, mFont, Brushes.Black, 50, 25);
IntPtr dc1 = mygraphics.GetHdc();
IntPtr dc2 = memoryGraphics.GetHdc();
BitBlt(dc2, 0, 50, this.ClientRectangle.Width,
this.ClientRectangle.Height, dc1, 0, 0, 13369376);
mygraphics.ReleaseHdc(dc1);
memoryGraphics.ReleaseHdc(dc2);
}

private void pd_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e) {
e.Graphics.DrawImage(memoryImage, 15, 15);
}

private void cmPrintForm_Click(System.Object sender, System.EventArgs
e) {
if (this.Width > this.Height) {
pd.DefaultPageSettings.Landscape = true;
}
CaptureScreen();
//printDocument1.Print();
ppv.Width=1024;
ppv.Height=768;
ppv.ShowDialog();
}


Tomas said:
Hello All,
snip
1. The non-Visible part of a datagrid (not just the data in the
cells, but the lines, headers, etc.).
2. RTF (multiple font/color) text objects.
3. Mixed items text with pictures, etc.
4. Screenshots, etc.

Can anyone point to a good tutorial (online or paper) that covers
these types of things? Or at least covers the concepts?

Thanks,

-tomas
 
I'm just finishing up a check printing app, and I certainly didn't take that
approach. In fact, it's 100% managed code and uses images (from jpeg, some
drawn dynamically, even a screen shot section, etc), lots of strings,
various fonts, etc. The example below is very "old school". I got the
managed screen shot code from CodeProject.com, and everything else is in the
framework and works great.

Essentially, you create a PrintDocument, wire up a OnPagePrint event, and
fire the PrintDocument.Print() method. The eventArgs of that event contain
a Graphics object. If you're familiar with GDI+, then you know you can just
use DrawImage(), DrawString(), DrawLine(), etc to make your output. At the
end of the PagePrint event, you just set e.HasMorePages = true/false to
determine if the event fires again. Of couse make sure you have some
external logic to eventually set e.HasMorePages = false when you've looped
through everything you want to put on paper.

Craig

Tomas Vera said:
Thanks for the BitBlt. I'd seen it before, in the "old days" and was
hoping that there was something more "native" in .Net.

Thanks,

-tomas
This works well:
Add a PrintDocument, PrintPreview to your form. Set the PrintPreviews
document property to the PrintDocument, and set the PrintDocuments
PrintPage procedure to the pd_PrintPage item below. This code presumes
a PrintDocument named Pd, a print preview named ppv, and a print button
named cmPrintForm. You'll have to adjust the scaling and other factors
to fit your form, and generally make this your own. This is for the
purpose of printing your actual form as the user sees it. I owe credit
to Lion Shi for originally posting this code.

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
Int32 dwRop // raster operation code
);
private Bitmap memoryImage;

private void CaptureScreen() {
string myUser =
CultureInfo.CurrentCulture.TextInfo.ToTitleCase(System.Environment.UserName.ToLower());
System.Drawing.Font mFont = new System.Drawing.Font("Arial", 12);
Graphics mygraphics = this.CreateGraphics();
Size s = this.Size;
string strOne = "Add Style or Component Form, Printed By: " + myUser
+ " On: " + System.DateTime.Now.ToShortDateString() + " At: " +
System.DateTime.Now.ToShortTimeString();
memoryImage = new Bitmap(s.Width, s.Height + 50, mygraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.DrawString(strOne, mFont, Brushes.Black, 50, 25);
IntPtr dc1 = mygraphics.GetHdc();
IntPtr dc2 = memoryGraphics.GetHdc();
BitBlt(dc2, 0, 50, this.ClientRectangle.Width,
this.ClientRectangle.Height, dc1, 0, 0, 13369376);
mygraphics.ReleaseHdc(dc1);
memoryGraphics.ReleaseHdc(dc2);
}

private void pd_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e) {
e.Graphics.DrawImage(memoryImage, 15, 15);
}

private void cmPrintForm_Click(System.Object sender, System.EventArgs
e) {
if (this.Width > this.Height) {
pd.DefaultPageSettings.Landscape = true;
}
CaptureScreen();
//printDocument1.Print();
ppv.Width=1024;
ppv.Height=768;
ppv.ShowDialog();
}


Tomas said:
Hello All,
snip
1. The non-Visible part of a datagrid (not just the data in the
cells, but the lines, headers, etc.).
2. RTF (multiple font/color) text objects.
3. Mixed items text with pictures, etc.
4. Screenshots, etc.

Can anyone point to a good tutorial (online or paper) that covers
these types of things? Or at least covers the concepts?

Thanks,

-tomas
 
Thomas... Printing on a single page is pretty straight forward. Printing
components across mulitple pages will give you a terrific headache. If
you want reusable code, I would just extend the MS controls so that they
know how to print themselves.

Here is a prototype interface for printable controls. The print engine
manages printing and knows what page you are on. The document owns the
container hierarchy of printable components. To print a page, the print
manager calls Draw on the top level component which in turn calls Draw
on its components until all components have been printed themselves.


public interface IPrintEngine
{
string DateDelimiter {get;set;}
float FirstTabStop {get;set;}
void Reset();
RectangleF PageRect {get;set;}
int CurrentPageNumber {get;set;}
int CurrentIndex {get;}
float[] TabStops {get;set;}
LineSpacing LineSpacing {get;set;}
string ReplaceTokens(string inString);
void AddToken(IReplaceToken token);
float GetXPagePos(Graphics g, IPrintElement element, ContentAlignment
alignment);
float GetXControlOffset(IPrintElement element, ContentAlignment
alignment, float width);
Document GetDocument(Control.ControlCollection collection);
bool PrintPage(Document document,
Graphics g,
Rectangle rect,
bool isSimulation);
Font Font {get;set;}
Brush Brush {get;set;}
StringFormat StringFormat {get;set;}
}
public interface IDocument
{
Version Version {get;}
string Name {get;set;}
IHeader Header {get;set;}
PrintElementCollection Body {get;set;}
IFooter Footer {get;set;}
CheckableCollection CheckCollection {get;set;}
}
public interface IPrintElement
{
void ClearDataBindings();
float LocationXPos{get;}
float LocationYPos {get;}
float ControlWidth {get;}
float VerticalMargin {get;set;}
float HorizontalMargin {get;set;}
bool UseDocumentProperties { get; set;}
float CalculateHeight(IPrintEngine pe, Graphics g);
float CalculateWidth(IPrintEngine pe, Graphics g);
bool Draw(IPrintEngine pe,
float xPos,
float yPos,
Graphics g,
RectangleF pageRect,
bool isSimulation);
}

public interface IPrintContainer : IPrintElement
{
IPrintElement[] GetElements();
bool OverrideStringProperties {get;set;}
void Add(IPrintElement element);
void Remove(IPrintElement element);
}
public interface IHeader : IPrintElement{}
public interface IFooter : IPrintElement{}


Regards,
Jeff
 
Back
Top