Master the daily print in .NET
Download this article code download this issue magazine code to see resources
Use classes in .NET Framework to create a professional report.
By Michael Eaton
Technology Toolbox: C #
You can use several ways to program the printout result (such as a report) in .NET. For Windows programmers, the Crystal Reports provided by Visual Studio is actually a tool for printing reports, but for less complex reports, this tool is small. Of course, you can call with a very good Win32 API, but although the API can make you have complete control, it also locks you to a single platform. If Microsoft or additional companies (such as Ximian companies with MONO project) transfer Framework to another platform, the programs that use the API will still be locked on Windows unless you rewrite them for the new platform.
.NET Framework allows you to use these print methods in a new way, system.drawing.printing namespace class Classes Win32 API's fine-grained control (Fine-grain control) with relatively simple Visual Basic traditional Printer object Combined (see Table 1). Here, I will focus on the main classes of the name space, which allows you to create complex levels of modes. The PrintDocument class is the most important in these classes. It allows you to define an object that sends the output result to a destination, or a printer, or a print preview (using the PrintPreviewDialog class). I will also tell the PrinterSettings class, which allows you to control the files how to print.
You can easily create a printDocument object in C # and attach it on an event handler (the code that processes the printed code):
PrintDocument doc = new
PRINTDocument ();
Doc.printpage = new
PRINTPAGEEVENTHANDLER
DOC_PrintPage);
The PrintPage event handler has a parameter for a PrintPageEventArgs type. This parameter contains data related to this event, including page settings, page margins information, and more pages that require more pages. Each page triggers the event once until ev.hasmorepages is equal to FALSE:
Private void Doc_printpage (Object)
Sender, PrintPageEventArgs EV)
The graphics is used for the Fonts and Fills EV parameters to reference the Graphics status zone you use to output data. Graphics is useful to print images, text, shapes, and lines. You can define the font (font) and brush (brush) you are using with the drawstring method. A brush defines how the interior of a graph is filled. You also need to tell the drawstring method where you want to print text. The PrintPageEventArgs class has a read and write properties --hasmorepages - it indicates whether you need to print more pages:
Font f = new font ("Arial", 12);
Ev.graphics.drawstring ("Hello,
World. "
F, brushes.black, 100, 100);
ev.hasmorepages = false;
Now, you have created a PrintDocument object and linked it with an event handler. You have added code to the event handler to print a separate string, its location is one inch from the left side, one inch from the top of the page, with 12 pounds, arial fonts. Now let's print file: doc.print ();
Under the default setting, the PrintDocument class's print method prints the result on the default printer unless you specify. You can use the PrintDialog class to separately specify, it is part of the System.Windows.Forms.commondialog name space. PrintDialog allows you to choose a printer, select which part of the print file, select the number of print cubes, come to print a file will be printed.
PrintDialog class PrinterSettings properties allow you to place properties such as COPIES, from page, and to page into a PrinterSettings object of a specific file. In other words, a separate PrintDocument object has a PrinterSettings object that specifies the number of copies of the print, the range of prints, the name of the printer to be used, and information about the printer itself.
A bug in the iPrinterSettings class will cause the Copies property to always return a value of 1, regardless of your number of copies you entered in PrintDialog. However, the PrintDocument.print () method still prints the correct number, so only when you want to use this value to other places, this bug is displayed. When you perform a Print method, the system uses these settings. You can provide an actual PrinterSettings object or provide a Document object:
PRINTDIALOG PD = New PrintDialog ();
Pd.Document = doc;
Pd.showdialog ();
Then, use the PagesetupDialog of the CommonDialog name space, you can specify the paper size, paper source, print direction, and margins. PagesetupDialog and PrintDialog need you to provide a Document object or a PageSettings object. PageSettings objects apply to a separate print page that handles margins, paper size, and whether to print pages with color:
PagesetupDialog ps = new
Pagesetupdialog ();
Ps.Document = DOC;
Ps.Showdialog ();
Print a files Of course, many applications print information stored in a file or some database, so I will now tell a more complicated example: Print a comma-separated contact list text file. You can use a data set, or even an XML file to be used here. This example of the data from the Northwind database, the format is as follows:
Name, Title, Phone, Fax
By declaring a StreamReader object at the class level, then assign a file to it, you can print the example from a text file. Open the file, modify the PrintPage event handler to print each line of the file, and format the data as needed.
The PrintDocument class has several events. You have used the PrintPage event; now let's add more events. When starting a print job (before actually printing anything), trigger the BeginPrint event. The corresponding event is endprint, which is triggered when all pages end print. Create any objects you need for the PrintPage event, or open any data sources in BeginPrint, then close or release them in EndPrint. Don't forget to bind these events to the PrintDocument object (see List 1). figure 1.
Show your report
As a selection, you can also encapsulate all print functions into a separate class derived by PrintDocument and then overload the method of triggering the corresponding event. You can use your custom class without instantification of a PrintDocument object (see
Listing 2). This is a good method, but in order to keep the same, make the code clear, I will continue to tell the event binding method.
The PrintDocument class has no drawing tool, so creates a report that takes some time - but this is worth it. The best way to create a new report is to use a blank paper. After you understand the purpose of the report, you can use the painting box in the paper to represent different regions, such as header, body and footer (see Figure 1). Then spend some time to write data from each area, and where the data will be placed in. It can be said that this is the best time that you make sure that the page seen by the end user is consistent with the page you design. Users need to be more pickful than any part of the application, so you should take it as much as possible to design it. Once you spend a lot of time to design the report and the print results of it, if you write, you will not spend a lot of time.
Writing the code Rectangle object provides the fastest and simplest way to convert your page design into code. These objects allow you to simulate your design on the screen. Define a zone on the page, specify the coordinate (have a certain height and width). Rectangle objects can give you a specified point, at this point, you can place text and graphics with the DRAW method of the Graphics class. In particular, you can use the DrawRectangle method to see where the area is on the page. This method requires a PEN object (used to draw straight lines and curves). Place all layout codes in the printpage event process:
// Print a red line around the border
// of the page
Ev.graphics.drawRectangle
Pens.red, Left Margin, Topmargin,
PageWidth, PageHeight;
.NET Framework 1.0 does not get a "hard" margins of a printer (actually printed on the outer area of the page). However, PrintPageEventArgs allows you to get a similar feature through MarginBounds properties. Unfortunately, Marginbounds does not consider Hard Margins, so your output may not end on your expectations. You must use P / Invoke and call the Win32 getDeviceCaps function to get the printer's Hard Margins (see List 3). After getting Hard Margins, you can start creating a Rectangle object and print information on your report (see List 4).
Now you have created a rectangles (Rectangles), you can print your data at this location. Print a page of data at a time, so do you need to define how big it is. Use a standard line of height to divide the printable area (this example in this example), thus calculating the number of rows of each page. Determine the height of a row by using the GetHeight method of the Font object you use. GetHeight is a method of overloading a Font class. The method you use require a Graphics object parameter. The PrintPageEventArgs parameter for the PrintPage event provides this graphics object: int linesperpage =
Convert.TOINT32 (Body.height /
Bodyfont.getHeight (ev.graphics));
Once you have determined the number of rows that make up a page, you only need to make a simple loop until a page ends. Then set ev.hasmorepages to True, or the end of the data that has been waited until the print. Use the DRAW method of the Graphics object to print your data inside the loop.
You also need to make sure the DrawString method places the text in the correct position. By multiplying the height of the font you choose to track how many rows of rows you have printed, you can calculate the location of the next line when printing. Then add a value for the top page of the top (see List 5).
The DrawString method you use also accepts a StringFormat object. The StringFormat class allows you to control text layout - including alignment and row spacing - and omitted symbol insert (if a given string is too long for your rectangular border). By creating a StringFormat object, and set its alignment property to stringAlignment.center, you can hide your text; then use the object to be used in the DrawString method you call. For your contact list page, write the following code:
StringFormat sf = new stringFormat ();
Sf.Alignment = stringalignment.center;
Ev.graphics.drawstring ("Northwinds
Customer Contacts, Headerfont,
Defaultbrush, body, sf);
As you can see, once you identify the layout of the report and create a rectangular border to contain data, the actual print is not very difficult.
figure 2.
Preview print
The PrintPreviewControl and PrintPreviewDialog are a good feature in the printing namespace. PrintPreviewDialog encapsulates the PrintPreviewControl class, and provides a good user interface to navigate, change the scales, select the number of pages that you can preview (see
figure 2). You can use PrintPreviewControl to create a print preview window consistent with other parts of your application. Once you have defined your PrintDocument, you are very simple to add a print preview for the required print events:
Private void preview_click (Object
Sender, System.EventArgs E) {
PRINTPREVIEWDIALOG PD = New
PRINTPREVIEWDIALOG ();
Pd.Document = doc;
Pd.showdialog ();
}
I hope that I have provided you with the driving force for studying the System.drawing.printing namespace. I found this name space to use the best way to generate many reproducible print items (especially reports). Try to use this method to complete a print job, I will bet after I have used it, and you will immediately use this method for all printing tasks. ?
Implement printing in the console application
Download this article code
Are you tired of printing the text selected from the console application? Here, a convenient tool will be introduced to help you implement print.
By Bill Wagner
I have introduced how to capture output results from the console command in the previous article and put it in the clipboard. I often need to print out the text output results from some console commands, so I have modified the last example to support printing.
The .NET print frame is not unfamiliar for those who use MFC: You just need to create a PrintDocument object and call its print () method. The PrintDocument object calls your established event processing to print each page. After printing all the pages, print processing will set a tag and end print.
In this new example, I did three places. First, I modified the storage method to save the captured input in an ArrayList, and each line entered is a string in the collection:
Private void grabstream (TextReader Instream)
{
String Str;
While (NULL! = (str = instream.readline ())))
{
Listostrings.Add (STR);
// pipe it to the output:
System.console.writeLine (STR);
}
}
Next, I added some command line options to allow data to send data into the clipboard or on the default printer, or simultaneously send it to these (see List 1).
Finally, I wrote two programs to print out the output (see List 2). The PrintData () method is used to create a PrintDocument object and launch the printing process. It is also responsible for adding an event handler for printing page.
PrintPage () method is used to print each page. First, I calculate the number of rows that meet the print page. The font's getHeight () method shows the height of a separate line, and the PrintPageEvent's MarginBounds property shows how much is the print space of each page. With this information, I can simply draw the page eyebus, each row of the page, and footer.
There is a small problem in the print frame: pagebounds property represents the size of the entire page, not the size of the print area. I have tried to limit the header and footer outside the print area, but there is no success. On some printers, the place below the print area cannot be printed. So I can only simply adjust the margins and put the headers and footers in the print area.