Chia sẻ: Lại Văn Nghĩa | Ngày: | Loại File: DOC | Số trang:18

lượt xem


Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

The PrintPreviewDialog is convenient and easy to use. All you need to do is create an instance of the dialog class, assign your PrintDocument object to the Document property, and call the ShowDialog method.

Chủ đề:

Nội dung Text: Background

  1. Introduction This article describes the implementation of an enhanced PrintPreviewDialog class. Background The PrintPreviewDialog is convenient and easy to use. All you need to do is create an instance of the dialog class, assign your PrintDocument object to the Document property, and call the ShowDialog method. However, PrintPreviewDialog has some shortcomings, including the following: • The entire document must be rendered before the preview appears. This is annoying for long documents. • There are no options for choosing the printer, adjusting the page layout, or selecting specific pages to print. • The dialog looks outdated. It hasn't changed since .NET 1.0, and it wasn't exactly cutting-edge even back then. • The dialog allows little or no customization. • There is no option to export the document to other formats such as PDF. • Page images are cached in the control, which limits the size of the documents that can be previewed. The CoolPrintPreviewDialog class presented here addresses these shortcomings. It is just as easy to use as the standard PrintPreviewDialog, but has the following enhancements: • Pages can be previewed as soon as they are rendered. The first page is shown almost instantly and subsequent pages become available while the user browses the first ones. • The "Print" button shows a dialog that allows users to select the printer and page ranges to print. A "Page Layout" button is also available so users can change page size, orientation, and margins. • The dialog uses a ToolStrip control instead of the old toolbar. • You have the source and can customize everything from appearance to behavior. • The control creates a list of images which can be exported to other formats including PDF (although the version presented here doesn't actually do that). Using the Code Using the CoolPrintPreviewDialog is as easy as using the traditional PrintPreviewDialog. You instantiate the control, set the Document property to the PrintDocument you want to preview, then call the dialog's Show method.
  2. If you have code that uses the PrintPreviewDialog class, switching to the CoolPrintPreviewDialog only requires changing one line of code. For example: Collapse // using a PrintPreviewDialog using (var dlg = new PrintPreviewDialog()) { dlg.Document = this.printDocument1; dlg.ShowDialog(this); } // using a CoolPrintPreviewDialog using (var dlg = new CoolPrintPreview.CoolPrintPreviewDialog()) { dlg.Document = this.printDocument1; dlg.ShowDialog(this); } Generating the Preview Images The core of the CoolPrintPreviewDialog class is a CoolPreviewControl that generates and shows the page previews. The PrintDocument object has a PrintController property that specifies an object responsible for creating the Graphics objects where the document is rendered. The default print controller creates Graphics objects for the default printer and is not interesting in this case. But .NET also defines a PreviewPrintController class that creates metafiles instead. These remain available to the caller to be shown in the preview area. The CoolPreviewControl works by temporarily replacing the document's original print controller with a PreviewPrintController, calling the document's Print method, and getting the page images while the document is rendered. The images represent pages in the document, and are scaled and displayed in the control just like any regular Image object. The code that creates the page previews looks like this (this code is simplified for clarity, refer to the source for a better version): Collapse // list of page images List _imgList = new List(); // generate page images public void GeneratePreview(PrintDocument doc) { // save original print controller PrintController savePC = doc.PrintController; // replace it with a preview print controller
  3. doc.PrintController = new PreviewPrintController(); // hook up event handlers doc.PrintPage += _doc_PrintPage; doc.EndPrint += _doc_EndPrint; // render the document _imgList.Clear(); doc.Print(); // disconnect event handlers doc.PrintPage -= _doc_PrintPage; doc.EndPrint -= _doc_EndPrint; // restore original print controller doc.PrintController = savePC; } The code installs the controller and hooks up the event handlers, then calls the Print method to generate the pages, and cleans up when it's done. When the Print method is invoked, the document starts firing events. The PrintPage and EndPrint event handlers capture the pages as soon as they are rendered and add them to an internal image list. The event handlers also call the Application.DoEvents method to keep the dialog responsive to user actions while the document renders. This allows users to switch pages, adjust the zoom factor, or cancel the document generation process. Without this call, the dialog would stop operating until the whole document finishes rendering. This is the code that does all this: Collapse void _doc_PrintPage(object sender, PrintPageEventArgs e) { SyncPageImages(); if (_cancel) { e.Cancel = true; } } void _doc_EndPrint(object sender, PrintEventArgs e) { SyncPageImages(); } void SyncPageImages() { // get page previews from print controller var pv = (PreviewPrintController)_doc.PrintController; var pageInfo = pv.GetPreviewPageInfo(); // add whatever images are missing from our internal list for (int i = _img.Count; i < pageInfo.Length; i++)
  4. { // add to internal list _img.Add(pageInfo[i].Image); // fire event to indicate we have more pages OnPageCountChanged(EventArgs.Empty); // if the page being previewed changed, refresh to show it if (StartPage < 0) StartPage = 0; if (i == StartPage || i == StartPage + 1) { Refresh(); } // keep application responsive Application.DoEvents(); } } This is the core of the preview code. The rest is concerned with housekeeping tasks such as scaling the preview images, updating the scrollbars, handling navigation buttons, mouse, keyboard, and so on. Please refer to the source code for the implementation details. Updating the Page Layout The preview dialog allows users to update the print layout. This is very easy to implement, thanks to the .NET PageSetupDialog class. Here is the code that gets called when users click the "Page Layout" button: Collapse void _btnPageSetup_Click(object sender, EventArgs e) { using (var dlg = new PageSetupDialog()) { dlg.Document = Document; if (dlg.ShowDialog(this) == DialogResult.OK) { // user changed the page layout, refresh preview images _preview.RefreshPreview(); } } } The code shows a PageSetupDialog that allows the user to change the paper size, orientation, and margins. Changes made by the user are reflected in the document's DefaultPageSettings property. If the user clicks OK, then we assume that the page layout has been modified, and call the RefreshPreview method on the preview control. This method regenerates all preview
  5. images using the new settings, so the user can see the changes applied to margins, page orientation, and so on. Printing the Document When the user clicks the "Print" button, the dialog shows a PrintDialog so the user can select the printer, page range, or change his mind and cancel the printing. Unfortunately, page range selections are not honored if you simply call the Print method directly on the document. To remedy this, the dialog calls the Print method on the enhanced preview control instead. That implementation uses the page images already stored in the control, and honors page ranges defined in the document's PrinterSettings properties. This is the code that gets called when the user clicks the "Print" button: Collapse void _btnPrint_Click(object sender, EventArgs e) { using (var dlg = new PrintDialog()) { // configure dialog dlg.AllowSomePages = true; dlg.AllowSelection = true; dlg.Document = Document; // show allowed page range var ps = dlg.PrinterSettings; ps.MinimumPage = ps.FromPage = 1; ps.MaximumPage = ps.ToPage = _preview.PageCount; // show dialog if (dlg.ShowDialog(this) == DialogResult.OK) { // print selected page range _preview.Print(); } } } The Print method in the preview control starts by determining the range of pages that should be rendered. This may be the full document, a specific range, or the current selection (page being previewed). Once the page range has been determined, the code creates a DocumentPrinter helper class to perform the actual printing: Collapse public void Print() { // select pages to print var ps = _doc.PrinterSettings;
  6. int first = ps.MinimumPage - 1; int last = ps.MaximumPage - 1; switch (ps.PrintRange) { case PrintRange.CurrentPage: first = last = StartPage; break; case PrintRange.Selection: first = last = StartPage; if (ZoomMode == ZoomMode.TwoPages) last = Math.Min(first + 1, PageCount - 1); break; case PrintRange.SomePages: first = ps.FromPage - 1; last = ps.ToPage - 1; break; } // print using helper class var dp = new DocumentPrinter(this, first, last); dp.Print(); } } The DocumentPrinter class is simple. It inherits from PrintDocument and overrides the OnPrintPage method to print only the pages selected by the user: Collapse internal class DocumentPrinter : PrintDocument { int _first, _last, _index; List _imgList; public DocumentPrinter(CoolPrintPreviewControl preview, int first, int last) { // save page range and image list _first = first; _last = last; _imgList = preview.PageImages; // copy page and printer settings from original document DefaultPageSettings = preview.Document.DefaultPageSettings; PrinterSettings = preview.Document.PrinterSettings; } protected override void OnBeginPrint(PrintEventArgs e) { // start from the first page _index = _first; } protected override void OnPrintPage(PrintPageEventArgs e) { // render the current page and increment the index e.Graphics.PageUnit = GraphicsUnit.Display;
  7. e.Graphics.DrawImage(_imgList[_index++], e.PageBounds); // stop when we reach the last page in the range e.HasMorePages = _index
  8. public int Count { get { return _list.Count; } } public void Add(Image img) { _list.Add(GetBytes(img)); // stored image data, now dispose of original img.Dispose(); } public Image this[int index] { get { return GetImage(_list[index]); } set { _list[index] = GetBytes(value); } } // implementation byte[] GetBytes(Image img) { Metafile mf = img as Metafile; var enhMetafileHandle = mf.GetHenhmetafile().ToInt32(); var bufferSize = GetEnhMetaFileBits(enhMetafileHandle, 0, null); var buffer = new byte[bufferSize]; GetEnhMetaFileBits(enhMetafileHandle, bufferSize, buffer); // return bits return buffer; } Image GetImage(byte[] data) { MemoryStream ms = new MemoryStream(data); return Image.FromStream(ms); } // use interop to get the metafile bits [System.Runtime.InteropServices.DllImport("gdi32")] static extern int GetEnhMetaFileBits(int hemf, int cbBuffer, byte[] lpbBuffer); } Note that the Add method disposes of the image after storing it. I normally would not do it this way; the caller owns the image and should be responsible for disposing of it. But in this project, this arrangement allows me to swap the PageImageList implementation with a regular List, which is convenient for testing and benchmarking. Note also that the GetBytes uses the GetHenhmetafile API. This API makes the metafile invalid, so the original image cannot be used after this method is called. In this case, it is not an issue since the image is destroyed after the conversion anyway. But if you want to use this code in other applications, remember that you cannot use the metafile after this call. If you need the image, re-create it using code similar to the GetImage method above.
  9. If you are concerned about performance, the extra conversion causes a performance hit of about 10% while generating the document. I think this is a reasonable price for the benefit if your documents have hundreds or thousands of pages. If you are concerned about memory usage, consider compressing the byte arrays when you store them. I did that in my original implementation; metafiles tend to compress really well. Of course, there would be a small additional performance penalty involved. History This is the third version of the CoolPrintPreviewDialog article. This version has a shorter and more efficient implementation of the PageImageList class, and includes a Visual Basic implementaion as well. After I published the first version, someone pointed out another article that deals with the PrintPreviewDialog but somehow escaped me when I decided to write this one. It has a slightly different focus and describes localization very nicely. Hopefully, you can get some good ideas from both. Check it out here. Thanks for the feedback so far. If you have other requests, or suggestions for further improvements, please let me know. Happy previewing! Giới thiệu Bài viết này mô tả việc thực hiện một lớp PrintPreviewDialog nâng cao. N ền Các PrintPreviewDialog tiện lợi và dễ sử dụng. Tất cả bạn cần làm là tạo ra một thể của lớp thoại, phân công PrintDocument của bạn đến các đối tượng sở hữu tài liệu, và gọi phương thức ShowDialog. Tuy nhiên, PrintPreviewDialog có một số hạn chế, bao gồm sau đây: * Các tài liệu phải được kết xuất toàn bộ trước khi xem trước sẽ xuất hiện. Điều này gây phiền nhiễu cho các văn bản dài. * Không có tùy chọn cho việc lựa chọn máy in, điều chỉnh cách bố trí trang, hoặc lựa chọn các trang cụ thể để in. * Các hộp thoại sẽ lỗi thời. Nó đã không thay đổi kể từ NET 1.0., Và nó không được chính xác cắt-cạnh ngay cả khi trở lại sau đó. * Các hộp thoại cho phép ít hoặc không chỉnh. * Không có tùy chọn để xuất khẩu sang các định dạng tài liệu khác như PDF. * Trang hình ảnh được lưu trữ trong kiểm soát, như là giới hạn kích thước của tài liệu có thể được xem trước. Lớp CoolPrintPreviewDialog trình bày ở đây địa chỉ những thiếu sót. Nó chỉ là dễ sử dụng như là PrintPreviewDialog tiêu chuẩn, nhưng có những cải tiến sau đây:
  10. * Các trang có thể được xem trước ngay sau khi chúng được trả lại. Trang đầu tiên được thể hiện gần như ngay lập tức và các trang tiếp theo trở nên có sẵn trong khi người dùng duyệt những cái đầu tiên. * The "In" nút hiển thị một hộp thoại mà cho phép người dùng lựa chọn máy in và các phạm vi trang in. Một "Trang Giao diện" nút cũng có sẵn để người dùng có thể thay đổi kích thước trang, định hướng, và lợi nhuận. * Các hộp thoại sử dụng một điều khiển ToolStrip thay vì thanh công cụ cũ. * Quý vị có nguồn và có thể tùy chỉnh tất cả mọi thứ từ xuất hiện đến hành vi. * Việc kiểm soát tạo ra một danh sách các hình ảnh có thể được xuất khẩu sang các định dạng khác như PDF (mặc dù các phiên bản trình bày ở đây không thực sự làm điều đó). Sử dụng Mã Sử dụng CoolPrintPreviewDialog dễ dàng như việc sử dụng PrintPreviewDialog truyền thống. Bạn nhanh chóng sự kiểm soát, thiết lập các tài sản tài liệu cho PrintDocument bạn muốn xem trước, sau đó gọi phương thức hiển thị của hộp thoại. Nếu bạn có mã có sử dụng các lớp PrintPreviewDialog, chuyển đổi sang CoolPrintPreviewDialog chỉ đòi hỏi phải thay đổi một dòng mã. Ví dụ: Sụp đổ / / Cách sử dụng một PrintPreviewDialog bằng cách sử dụng (var DLG = PrintPreviewDialog mới ()) ( dlg.Document = this.printDocument1; dlg.ShowDialog (này); ) / / Cách sử dụng một CoolPrintPreviewDialog bằng cách sử dụng (var DLG = CoolPrintPreview.CoolPrintPreviewDialog mới ()) ( dlg.Document = this.printDocument1; dlg.ShowDialog (này); ) Tạo ra những hình ảnh Xem thử Cốt lõi của lớp CoolPrintPreviewDialog là một CoolPreviewControl mà tạo ra và hiển thị các trang xem trước. Các đối tượng PrintDocument có một tài sản PrintController rằng chỉ định một đối tượng chịu trách nhiệm cho việc tạo các đối tượng đồ họa, nơi tài liệu được trả lại. Bộ điều khiển in mặc định tạo ra các đối tượng đồ họa cho máy in mặc định và không phải là thú vị trong trường hợp này. Nhưng. NET cũng định nghĩa một lớp
  11. PreviewPrintController tạo metafiles thay thế. Những vẫn sẵn cho người gọi sẽ được hiển thị trong vùng xem trước. CoolPreviewControl Các hoạt động bằng cách thay thế tạm thời điều khiển in bản gốc của tài liệu với một PreviewPrintController, gọi phương pháp in của tài liệu, và nhận được những hình ảnh trang trong khi tài liệu được trả lại. Các hình ảnh đại diện cho các trang trong tài liệu này, và được thu nhỏ lại và hiển thị trong kiểm soát giống như bất kỳ đối tượng hình thường xuyên. Mã này tạo ra các trang xem trước hình như mã này (đây là đơn giản hóa cho rõ ràng, tham khảo các nguồn cho một phiên bản tốt hơn): Sụp đổ / / Danh sách các hình ảnh trang Danh sách _imgList = mới Danh sách (); / / Tạo ra những hình ảnh trang public void GeneratePreview (PrintDocument doc) ( / / Lưu bộ điều khiển in ấn bản gốc PrintController savePC = doc.PrintController; / / Thay thế bằng một bộ điều khiển in xem trước doc.PrintController = mới PreviewPrintController (); / / Treo lên sự kiện xử lý doc.PrintPage + = _doc_PrintPage; doc.EndPrint + = _doc_EndPrint; / / Render các tài liệu _imgList.Clear (); doc.Print (); / / Ngắt kết nối xử lý sự kiện doc.PrintPage -= _doc_PrintPage; doc.EndPrint -= _doc_EndPrint; / / Khôi phục lại bộ điều khiển in ấn bản gốc doc.PrintController = savePC; ) Mã này cài đặt các bộ điều khiển và móc lên các bộ xử lý sự kiện, sau đó gọi các phương pháp in để tạo ra các trang, và diệt khi nó được thực hiện. Khi gọi là phương pháp in, tài liệu bắt đầu bắn ra sự kiện. Các PrintPage và xử lý sự kiện EndPrint chụp các trang ngay sau khi chúng được kết xuất và thêm chúng vào một
  12. danh sách hình ảnh nội bộ. Việc xử lý sự kiện cũng gọi phương thức Application.DoEvents để giữ cho hộp thoại đáp ứng với hành động của người sử dụng, trong khi các tài liệu ám. Điều này cho phép người dùng chuyển sang trang, điều chỉnh zoom yếu tố, hay hủy bỏ quá trình tạo tài liệu. Nếu không có cuộc gọi này, hộp thoại sẽ ngừng hoạt động cho đến khi toàn bộ tài liệu hoàn tất rendering. Đây là mã mà hiện tất cả điều này: Sụp đổ void _doc_PrintPage (object sender, PrintPageEventArgs e) ( SyncPageImages (); nếu (_cancel) ( e.Cancel = true; ) ) void _doc_EndPrint (object sender, PrintEventArgs e) ( SyncPageImages (); ) void SyncPageImages () ( / / Nhận được xem trước trang từ bộ điều khiển in var pv = (PreviewPrintController) _doc.PrintController; var pageInfo = pv.GetPreviewPageInfo (); / / Thêm bất kỳ hình ảnh bị thiếu trong danh sách nội bộ của chúng tôi ; i + for (int _img.Count = i; i
  13. Application.DoEvents (); ) ) Đây là cốt lõi của mã xem trước. Phần còn lại là có liên quan với các công việc vệ sinh như nhân rộng những hình ảnh xem trước, cập nhật scrollbars, xử lý các nút chuyển hướng, chuột, bàn phím, vv. Vui lòng tham khảo các mã nguồn cho các chi tiết thực hiện. Cập nhật Giao diện Trang Hộp thoại cho phép người dùng xem trước để cập nhật bố trí in ấn. Điều này là rất dễ dàng để thực hiện, nhờ có những lớp học PageSetupDialog NET.. Dưới đây là đoạn code mà được gọi là khi người dùng nhấn vào "Trang Giao diện" nút: Sụp đổ void _btnPageSetup_Click (object sender, EventArgs e) ( bằng cách sử dụng (var DLG = PageSetupDialog mới ()) ( dlg.Document = tài liệu; nếu (dlg.ShowDialog (này) == DialogResult.OK) ( / / Người dùng thay đổi cách bố trí trang, xem trước những hình ảnh làm mới _preview.RefreshPreview (); ) ) ) Mã này cho thấy một PageSetupDialog cho phép người sử dụng để thay đổi kích thước giấy, định hướng, và lợi nhuận. Thay đổi được thực hiện bởi người sử dụng được phản ánh trong tài sản DefaultPageSettings của tài liệu. Nếu người dùng nhấp OK, sau đó chúng tôi cho rằng cách bố trí trang đã được sửa đổi, và gọi phương thức RefreshPreview về kiểm soát xem trước. Phương pháp này regenerates tất cả các hình xem trước bằng cách sử dụng các thiết lập mới, do đó người dùng có thể nhìn thấy những thay đổi áp dụng đối với lợi nhuận, trang định hướng, vv. In ấn các tài liệu Khi người dùng nhấp vào "In" nút, hộp thoại hiển thị một PrintDialog vì vậy người sử dụng có thể chọn máy in, nhiều trang, hoặc thay đổi suy nghĩ của mình và hủy bỏ việc in ấn. Thật không may, trang lựa chọn phạm vi không được vinh dự nếu bạn chỉ đơn giản gọi phương thức in trực tiếp trên tài liệu. Để khắc phục điều này, hộp thoại gọi phương pháp in trên tăng cường kiểm soát xem trước để thay thế. Điều đó thực hiện
  14. sử dụng những hình ảnh trang đã được lưu trữ trong kiểm soát, và trang danh được định nghĩa trong phạm vi của tài liệu thuộc tính PrinterSettings. Đây là mã mà được gọi là khi người dùng nhấp chuột vào "In" nút: Sụp đổ void _btnPrint_Click (object sender, EventArgs e) ( bằng cách sử dụng (var DLG = PrintDialog mới ()) ( / / Cấu hình hộp thoại dlg.AllowSomePages = true; dlg.AllowSelection = true; dlg.Document = tài liệu; / / Cho phép hiển thị nhiều trang ps var = dlg.PrinterSettings; ps.MinimumPage = ps.FromPage = 1; ps.MaximumPage = ps.ToPage = _preview.PageCount; / / Hiển thị hộp thoại nếu (dlg.ShowDialog (này) == DialogResult.OK) ( / / In chọn trang loạt _preview.Print (); ) ) ) Phương pháp in trong kiểm soát xem trước bắt đầu bằng cách xác định phạm vi của các trang đó phải được trả lại. Điều này có thể là tài liệu đầy đủ, một phạm vi cụ thể, hoặc lựa chọn hiện hành (Trang đang được xem trước). Một khi nhiều trang đã được xác định, mã tạo ra một lớp helper DocumentPrinter để thực hiện việc in ấn thực tế: Sụp đổ public void In () ( / / Chọn trang để in ps var = _doc.PrinterSettings; int đầu tiên = ps.MinimumPage - 1; int cuối = ps.MaximumPage - 1; switch (ps.PrintRange) ( trường hợp PrintRange.CurrentPage: đầu tiên = cuối = Startpage; break;
  15. trường hợp PrintRange.Selection: đầu tiên = cuối = Startpage; nếu (ZoomMode == ZoomMode.TwoPages) cuối = Math.min (đầu tiên + 1, PageCount - 1); break; trường hợp PrintRange.SomePages: đầu tiên = ps.FromPage - 1; cuối = ps.ToPage - 1; break; ) / / In bằng cách sử dụng lớp helper var dp = mới DocumentPrinter (điều này, trước tiên, cuối); dp.Print (); ) ) Lớp DocumentPrinter là đơn giản. Nó được thừa hưởng từ PrintDocument và đè phương pháp OnPrintPage in chỉ các trang lựa chọn của người dùng: Sụp đổ nội bộ lớp DocumentPrinter: PrintDocument ( int _first, _last, _index; Danh sách _imgList; công DocumentPrinter (CoolPrintPreviewControl xem trước, int đầu tiên, int cuối) ( / / Lưu nhiều trang và danh sách hình ảnh _first = đầu tiên; _last = cuối; _imgList = preview.PageImages; / / Chép trang và cài đặt máy in từ tài liệu gốc DefaultPageSettings = preview.Document.DefaultPageSettings; PrinterSettings = preview.Document.PrinterSettings; ) bảo vệ override void OnBeginPrint (PrintEventArgs e) ( / / Bắt đầu từ những trang đầu tiên _index = _first; ) bảo vệ override void OnPrintPage (PrintPageEventArgs e) ( / / Render trang hiện tại và tăng chỉ số
  16. e.Graphics.PageUnit = GraphicsUnit.Display; e.Graphics.DrawImage (_imgList [_index + +], e.PageBounds); / / Dừng khi chúng tôi đến trang cuối trong khoảng e.HasMorePages = _index
  17. / / ** Đối tượng mô hình public void Clear () ( _list.Clear (); ) public int Count ( get (return _list.Count;) ) public void Thêm img Image () ( _list.Add (getBytes (img)); / / Lưu trữ dữ liệu hình ảnh, bây giờ vứt bỏ bản gốc img.Dispose (); ) Hình ảnh công cộng này [int index] ( get (return GetImage (_list [index]);) set (_list [index] = getBytes (value);) ) / / Thực hiện byte [] getBytes (Image img) ( Metafile mf = img như Metafile; var enhMetafileHandle = mf.GetHenhmetafile (). ToInt32 (); var bufferSize = GetEnhMetaFileBits (enhMetafileHandle, 0, null); var buffer = new byte [bufferSize]; GetEnhMetaFileBits (enhMetafileHandle, bufferSize, đệm); / / Bit trở lại trở về bộ đệm; ) Hình GetImage (byte [] dữ liệu) ( MemoryStream ms = MemoryStream mới (dữ liệu); trở lại Image.FromStream (ms); ) / / Sử dụng interop để có được các bit Metafile [System.Runtime.InteropServices.DllImport ( "gdi32")] static extern int GetEnhMetaFileBits (int hemf, int cbBuffer, byte [] lpbBuffer); )
  18. Lưu ý rằng phương pháp Thêm disposes của hình ảnh sau khi lưu trữ nó. Tôi thường sẽ không làm theo cách này; người gọi sở hữu hình ảnh và phải có trách nhiệm xử lý của nó. Nhưng trong dự án này, cách sắp xếp này cho phép tôi để trao đổi việc thực hiện PageImageList với một danh sách thường xuyên, là thuận tiện cho việc thử nghiệm và điểm chuẩn. Lưu ý rằng getBytes cũng sử dụng API GetHenhmetafile. API Điều này làm cho không hợp lệ Metafile, do đó, hình ảnh ban đầu không thể được sử dụng sau khi phương pháp này được gọi. Trong trường hợp này, nó không phải là một vấn đề kể từ khi hình ảnh được phá hủy sau khi chuyển đổi nào. Nhưng nếu bạn muốn sử dụng mã này trong các ứng dụng khác, hãy nhớ rằng bạn không thể sử dụng Metafile sau khi cuộc gọi này. Nếu bạn cần có hình ảnh, tái tạo lại nó bằng cách sử dụng mã tương tự như các phương pháp GetImage ở trên. Nếu bạn đang quan tâm về hiệu suất, chuyển đổi phụ gây ra một hiệu suất đạt khoảng 10% trong khi các tài liệu được tạo ra. Tôi nghĩ rằng đây là một mức giá hợp lý cho lợi ích nếu tài liệu của bạn có hàng trăm hoặc hàng ngàn trang. Nếu bạn đang quan tâm về sử dụng bộ nhớ, hãy xem xét nén các mảng byte khi bạn lưu trữ chúng. Tôi đã làm mà trong việc thực hiện ban đầu của tôi; metafiles có xu hướng để nén thực sự tốt. Tất nhiên, sẽ có một hình phạt nhỏ thêm hiệu suất tham gia. Lịch sử Đây là phiên bản thứ ba của bài viết CoolPrintPreviewDialog. Phiên bản này có thực hiện ngắn hơn và hiệu quả của lớp PageImageList, và bao gồm một implementaion Visual Basic là tốt. Sau khi tôi công bố phiên bản đầu tiên, một ai đó chỉ ra một bài viết mà thoả thuận với PrintPreviewDialog nào đó, nhưng thoát cho tôi khi tôi quyết định viết thư này. Nó có một tập trung vào hơi khác nhau và mô tả nội địa hóa rất độc đáo. Hy vọng rằng, bạn có thể nhận được một số ý tưởng tốt từ cả hai. Kiểm tra nó ra ở đây. Thanks for the feedback cho đến nay. Nếu bạn có yêu cầu khác, hoặc đề xuất để cải thiện thêm chi tiết, xin vui lòng cho tôi biết. Happy xem trước!
Đồng bộ tài khoản