您好,登錄后才能下訂單哦!
我個人認為,開發MIS,首先就得解決網格的問題,而開發工具為我們提供了如DataGrid、MSHFlexGrid的控件。其次,是打印的問題,將業務單據與數據報表打印出來。可想而知,即使一個業務功能非常完美齊全的管理軟件,沒有打印的支持,也一定不算是一個完整的軟件。
對于打印,我們總是在用戶打印之前可以看看打印的效果,這時,一般的軟件都提供了打印預覽;如果需要調整打印的效果如紙張的大小、邊距的設置,又提供了頁面設置對話框讓用戶選擇和調整;如果系統有多個打印機,當用戶單擊打印按鈕時還可以選擇輸出的對象。
總之,對于打印,我們至少要提供打印頁面設置、打印機設置、打印預覽對話框,讓用戶有更多的機會參與交互。這一些,是一個打印模塊比較重要也比較基本的東西,讓我們一起來實現它們吧。
進入Vs2003 IDE,從文件菜單上單擊新建項目,項目類型為C#,在模板中選擇類庫,名稱估且叫GoldPrinter,確定即可。在打開的開發環境中,刪除解決方案資源管理器中默認生成的Class1.cs。
現在,我們要考慮一下,對于打印,可能是在Windows下,也可能是Web下。如果將兩者的方法統一起來,讓調用者不用操心是什么方式下那該多好啊。因此,我們首先設計一個接口,提供兩者共用的方法。
在項目上鼠標右鍵單擊后添加一個新類,名稱為:IPrinterPageSetting,由于是接口,將class改為interface,并去掉構造函數。看上去應類似如下:
using System;
namespace GoldPrinter
{
/// <summary>
/// IPrinterPageSetting 的摘要說明。
/// </summary>
public class IPrinterPageSetting
{
}
}
方法中至少包含三個聲明即ShowPageSetupDialog()、ShowPrintSetupDialog()、ShowPrintPreviewDialog(),也就是打開打印頁面設置、打印機設置、打印預覽對話框。
Vs2003為我們提供了一個PrintDocument,名字空間是System.Drawing.Printing。PrintDocument是為打印而提供的一個類,它的概述(summary)是這樣的:定義一個可再次使用的對象,該對象將輸出發送到打印機。
PrintDocument為我們封裝了很多復雜的細節,它有一個至關重要的事件叫PrintPage,PrintPage的概述是:當需要為當前頁打的輸出時發生。因此,我們只要引發了打印事件,把打印的具體輸出的對象交給PrintPage,別的我們就不用操心了。
那么,我們怎么實現具體輸出的過程呢?由于是封裝,我們也不可能知道最終用戶具體怎么去實現,這時,委托(Delegate)為我們起了大的作用。大家都知道一個函數實現某個功能的時候往往需要一些輸入的數據,但是函數本身并不知道這些數據到底是哪個具體的值,只知道這個值的數據類型,這時引入了參數,調用者調用函數據的時候傳入相應類型的具體值就行了。大家應該意識到了我的用意,與函數類似,我們為打印提供了關聯打印機的方法,但是具體的實現只有由調用者去實現,不同之處是函數傳遞的是參數,而我們要做的委托傳遞的是方法。這時,我們只要為兩者建立對應關系就可以了,這就是委托。我們需要定義一個委托,參數類型與PrintPage的一致就可以了,即(Object obj,System.Drawing.Printing.PrintPageEventArgs ev)。
由此可見,我們需要做下面的一些事情:
1、在項目的引用處添加引用,在彈出的對話框的.NET標簽中選擇System.Drawing.dll,
原因是PrintDocument的名字空間是System.Drawing.Printing,在System.Drawing.dll實現;
2、在IPrinterPageSetting接口中增加PrintDocument屬性的聲明;
3、定義委托
4、在IPrinterPageSetting接口中增加PrintPage屬性的聲明,類型為定義的委托;
以下是IPrinterPageSetting接口文件內容:
using System;
using System.Drawing;
using System.Drawing.Printing;
namespace GoldPrinter
{
/// <summary>
/// PrintDocument.PrintPage的委托定義
/// </summary>
public delegate void PrintPageDelegate(Object obj,System.Drawing.Printing.PrintPageEventArgs ev) ;
/// <summary>
/// IPrinterPageSetting 的接口,顯示打印紙張設置、打印機設置、打印預覽對話框。
/// 程序提供:周方勇;Email:flygoldfish@sina.com。
/// </summary>
public interface IPrinterPageSetting
{
/// <summary>
/// 獲取或設置打印文檔
/// </summary>
System.Drawing.Printing.PrintDocument PrintDocument
{
get;
set;
}
/// <summary>
/// 關聯一個方法,目的是讓具體的打印由實例化者來操作
/// 如PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler);
/// </summary>
PrintPageDelegate PrintPage
{
get;
set;
}
/// <summary>
/// 顯示頁面設置對話框,并返回PageSettings
/// </summary>
/// <returns></returns>
System.Drawing.Printing.PageSettings ShowPageSetupDialog();
/// <summary>
/// 顯示打印機設置對話框,并返回PrinterSettings
/// </summary>
/// <returns></returns>
System.Drawing.Printing.PrinterSettings ShowPrintSetupDialog();
/// <summary>
/// 顯示打印預覽對話框
/// </summary>
void ShowPrintPreviewDialog();
}//End Interface
}//End NameSpace
下面,我們以Windows下的編程方式實現,同時也列Web編程下的框架。由于是Windows下的編程,我們可能用到對話框什么的作為錯誤提示,因此,我們同理要加入System.Windows.Forms.dll引用。再建立一個類文件,名稱為WinPrinterPageSetting。進入文件后,在類聲明后面加上:IPrinterPageSetting,實現接口功能。程序清單如下,程序中有很多注釋,這里不再多說。
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
namespace GoldPrinter
{
/// <summary>
/// WinForm下的打印紙張設置、打印機設置、打印預覽對話框。
/// </summary>
public class WinPrinterPageSetting:IPrinterPageSetting
{
//把PrintPage委托聲明為類的一個成員變量
private PrintPageDelegate _printPage;
// 打印文檔
private PrintDocument _printDocument;
#region 構造函數
public WinPrinterPageSetting():this(null)
{
}
/// <summary>
/// 使用printDocument來初始化類的新實例,當printDocument為null時自動創建一個printDocument的實例
/// </summary>
/// <param name="printDocument"></param>
public WinPrinterPageSetting(PrintDocument printDocument)
{
if (printDocument != null)
{
_printDocument = printDocument;
}
else
{
_printDocument = new PrintDocument();
}
}
#endregion
#region IPrinterPageSetting 成員
/// <summary>
/// 獲取或設置打印文檔
/// </summary>
public PrintDocument PrintDocument
{
get
{
return this._printDocument;
}
set
{
this._printDocument = value;
}
}
/// <summary>
/// 一定要實例化此類后在調用打印/預覽之前設置此屬性,使之關聯一個方法,目的是讓具體的打印由實例化者來操作
/// 如PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler);
/// </summary>
public PrintPageDelegate PrintPage
{
set
{
//初始委托變量,關聯方法
_printPage = value;
if (_printDocument==null)
{
throw new Exception("關聯的打印文檔不能為空!");
}
_printDocument.PrintPage +=new System.Drawing.Printing.PrintPageEventHandler(this._printPage);
}
get
{
return _printPage;
}
}
/// <summary>
/// 顯示頁面設置對話框,并返回PageSettings
/// </summary>
/// <returns></returns>
public PageSettings ShowPageSetupDialog()
{
return ShowPageSetupDialog(this._printDocument);
}
/// <summary>
/// 顯示打印機設置對話框,并返回PrinterSettings
/// </summary>
/// <returns></returns>
public PrinterSettings ShowPrintSetupDialog()
{
return ShowPrintSetupDialog(this._printDocument);
}
/// <summary>
/// 顯示打印預覽對話框
/// </summary>
public void ShowPrintPreviewDialog()
{
ShowPrintPreviewDialog(this._printDocument);
}
#endregion
//***************注意:以下幾個對話框方法可以獨立使用***************
#region 頁面設置對話框 protected virtual PageSettings ShowPageSetupDialog(PrintDocument printDocument)
/// <summary>
/// 頁面設置對話框,可以獨立使用
/// </summary>
/// <param name="printDocument"></param>
/// <returns></returns>
/// <remarks>
/// 作 者:周方勇
/// 修改日期:2004-08-07
/// </remarks>
protected virtual PageSettings ShowPageSetupDialog(PrintDocument printDocument)
{
//聲明返回值的PageSettings
PageSettings ps = new PageSettings();
if (printDocument==null)
{
throw new Exception("關聯的打印文檔不能為空!");
}
try
{
//申明并實例化PageSetupDialog
PageSetupDialog psDlg = new PageSetupDialog();
//相關文檔及文檔頁面默認設置
psDlg.Document = printDocument;
psDlg.PageSettings = printDocument.DefaultPageSettings;
//顯示對話框
DialogResult result = psDlg.ShowDialog();
if (result == DialogResult.OK)
{
ps = psDlg.PageSettings;
printDocument.DefaultPageSettings = psDlg.PageSettings;
}
}
catch(System.Drawing.Printing.InvalidPrinterException e)
{
MessageBox.Show("未安裝打印機,請進入系統控制面版添加打印機!","打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message,"打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
return ps;
}
#endregion
#region 打印設置對話框 protected virtual PrinterSettings ShowPrintSetupDialog(PrintDocument printDocument)
/// <summary>
/// 打印設置對話框,可以獨立使用
/// </summary>
/// <param name="printDocument"></param>
/// <returns></returns>
/// <remarks>
/// 作 者:周方勇
/// 修改日期:2004-08-07
/// </remarks>
protected virtual PrinterSettings ShowPrintSetupDialog(PrintDocument printDocument)
{
//聲明返回值的PrinterSettings
PrinterSettings ps = new PrinterSettings();
if (printDocument==null)
{
throw new Exception("關聯的打印文檔不能為空!");
}
try
{
//申明并實例化PrintDialog
PrintDialog pDlg = new PrintDialog();
//可以選定頁
pDlg.AllowSomePages = true;
//指定打印文檔
pDlg.Document = printDocument;
//顯示對話框
DialogResult result = pDlg.ShowDialog();
if (result == DialogResult.OK)
{
//保存打印設置
ps = pDlg.PrinterSettings;
//打印
printDocument.Print();
}
}
catch(System.Drawing.Printing.InvalidPrinterException e)
{
MessageBox.Show("未安裝打印機,請進入系統控制面版添加打印機!","打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message,"打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
return ps;
}
#endregion
#region 打印預覽對話框 protected virtual void ShowPrintPreviewDialog(PrintDocument printDocument)
/// <summary>
/// 打印預覽對話框,可以獨立使用
/// </summary>
/// <param name="printDocument"></param>
/// <returns></returns>
/// <remarks>
/// 作 者:周方勇
/// 修改日期:2004-08-07
/// </remarks>
protected virtual void ShowPrintPreviewDialog(PrintDocument printDocument)
{
if (printDocument==null)
{
throw new Exception("關聯的打印文檔不能為空!");
}
try
{
//申明并實例化PrintPreviewDialog
PrintPreviewDialog ppDlg = new PrintPreviewDialog();
//指定打印文檔
ppDlg.Document = printDocument;
//顯示對話框
DialogResult result = ppDlg.ShowDialog();
if (result == DialogResult.OK)
{
//...
}
}
catch(System.Drawing.Printing.InvalidPrinterException e)
{
MessageBox.Show("未安裝打印機,請進入系統控制面版添加打印機!","打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message,"打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
}
}
#endregion
}//End Class
}//End NameSpace
大家可以看到了#region指定,它與#endregion一起使用,可以把中間的文本折疊起來,很方便,需要查看的時候就單擊前面的展開符號。后三個函數是比較重要的方法,同時提供它們的重載函數。ShowPageSetupDialog()與ShowPrintSetupDialog()返回用戶確認的當前設置選擇。
再建立一個類文件,名稱為WebPrinterPageSetting。進入文件后,在類聲明后面加上:IPrinterPageSetting,實現接口功能。程序清單如下:
using System;
namespace GoldPrinter
{
/// <summary>
/// WebForm下的打印紙張設置、打印機設置、打印預覽對話框。(***暫無具體實現***)
/// </summary>
public class WebPrinterPageSetting:IPrinterPageSetting
{
public WebPrinterPageSetting()
{
//
// TODO: 在此處添加構造函數邏輯
//
}
#region IPrinterPageSetting 成員
public System.Drawing.Printing.PrintDocument PrintDocument
{
get
{
// TODO: 添加 WebPrinterPageSetting.PrintDocument getter 實現
return null;
}
set
{
// TODO: 添加 WebPrinterPageSetting.PrintDocument setter 實現
}
}
public PrintPageDelegate PrintPage
{
get
{
// TODO: 添加 WebPrinterPageSetting.PrintPage getter 實現
return null;
}
set
{
// TODO: 添加 WebPrinterPageSetting.PrintPage setter 實現
}
}
public System.Drawing.Printing.PageSettings ShowPageSetupDialog()
{
// TODO: 添加 WebPrinterPageSetting.ShowPageSetupDialog 實現
return null;
}
public System.Drawing.Printing.PrinterSettings ShowPrintSetupDialog()
{
// TODO: 添加 WebPrinterPageSetting.ShowPrintSetupDialog 實現
return null;
}
public void ShowPrintPreviewDialog()
{
// TODO: 添加 WebPrinterPageSetting.ShowPrintPreviewDialog 實現
}
#endregion
}//End Class
}//End NameSpace
做到了這一步,大家可能說已經可以了,確實如此。因為在調用的時候實例化WinPrinterPageSetting/WebPrinterPageSetting并調用它的方法或屬性就可以了。大家再想想我為什么要提供IPrinterPageSetting呢?如果我現在調用打印對話框,我也不管是Windows下還是Web下的,這時,IPrinterPageSetting就發揮了作用。
例如:
IPrinterPageSetting _printerPageSetting;
申明了一個打印接口對象,以后就可以直接調用它的方法了,但是到底是Windows模式還是Web模式呢,我們只需要讓程序自己去根據系統去實例為真正的WinPrinterPageSetting或WebPrinterPageSetting了。如:
//創建接口對象的新實例,使其指象真正的實現其接口的對象
if (Windows模式)
{
_printerPageSetting = new WinPrinterPageSetting();
}
else if(Web模式)
{
_printerPageSetting = new WebPrinterPageSetting();
}
在接下來的程序清單中我們可以看到這個效果。我們再建立一個PrinterPageSetting類,將WinPrinterPageSetting與WebPrinterPageSetting合二為一。在類的構造函數中增加自動判斷Windows模式還是Web模式,同時也提供PrintMode屬性可以讓用戶修改。程序清單如下:
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
namespace GoldPrinter
{
/// <summary>
/// 打印方式
/// </summary>
public enum PrintModeFlag
{
/// <summary>
/// Windows窗口打印方式
/// </summary>
Win
,
/// <summary>
/// Web窗口打印方式
/// </summary>
Web
}
/// <summary>
/// 封裝頁面設置、打印機設置、打印預覽,適合于Window和Asp.Net。
/// 程序提供:周方勇;Email:flygoldfish@sina.com。
/// </summary>
public class PrinterPageSetting
{
//申明一個封裝頁面設置、打印機設置、打印預覽的接口
private IPrinterPageSetting _printerPageSetting;
//打印方式
private PrintModeFlag _printModeFlag;
public PrintModeFlag PrintMode
{
get
{
return this._printModeFlag;
}
set
{
this._printModeFlag = value;
//運用了抽象模式,創建接口對象的新實例,使其指象真正的實現其接口的對象
if (this._printModeFlag == PrintModeFlag.Win)
{
_printerPageSetting = new WinPrinterPageSetting();
}
else if(this._printModeFlag == PrintModeFlag.Web)
{
_printerPageSetting = new WebPrinterPageSetting();
}
}
}
/// <summary>
/// 獲取或設置打印文檔
/// </summary>
public PrintDocument PrintDocument
{
get
{
return _printerPageSetting.PrintDocument;
}
set
{
_printerPageSetting.PrintDocument = value;
}
}
/// <summary>
/// 一定要實例化此類后在調用打印/預覽初始此變量,使之關聯一個方法,目的是讓具體的打印由實例化者來操作
/// 如PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler);
/// </summary>
public PrintPageDelegate PrintPage
{
set
{
_printerPageSetting.PrintPage = value;
}
get
{
return _printerPageSetting.PrintPage;
}
}
#region 構造函數
/// <summary>
/// 封裝頁面設置、打印機設置、打印預覽,適合于Window和Asp.Net,Web方式下請在配置文件中增加鍵PrintMode及值Web,也可以實例化后設置PrintMode屬性為PrintModeFlag.Web。
/// </summary>
public PrinterPageSetting():this(null)
{
}
/// <summary>
/// 封裝頁面設置、打印機設置、打印預覽,適合于Window和Asp.Net,Web方式下請在配置文件中增加鍵PrintMode及值Web,也可以實例化后設置PrintMode屬性為PrintModeFlag.Web。
/// </summary>
/// <param name="printDocument"></param>
public PrinterPageSetting(PrintDocument printDocument)
{
string strPrintMode = "";
//配置文件中鍵PrintMode
strPrintMode = System.Configuration.ConfigurationSettings.AppSettings["PrintMode"];
if (strPrintMode == null)
{
//默認為Win方式
strPrintMode = "Win";
}
//配置文件中鍵PrintMode的值Win/Web
if (strPrintMode.ToUpper() == "WIN")
{
this.PrintMode = PrintModeFlag.Win;
}
else
{
this.PrintMode = PrintModeFlag.Web;
}
/* //配置文件中添加鍵值的寫法
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="PrintMode" value="Web"/>
</appSettings>
</configuration>
*/
_printerPageSetting.PrintDocument = printDocument;
}
#endregion
/// <summary>
/// 顯示頁面設置對話框,并返回PageSettings
/// </summary>
/// <returns></returns>
public PageSettings ShowPageSetupDialog()
{
return _printerPageSetting.ShowPageSetupDialog();
}
/// <summary>
/// 顯示打印機設置對話框,并返回PrinterSettings
/// </summary>
/// <returns></returns>
public PrinterSettings ShowPrintSetupDialog()
{
return _printerPageSetting.ShowPrintSetupDialog();
}
/// <summary>
/// 顯示打印預覽對話框
/// </summary>
public void ShowPrintPreviewDialog()
{
_printerPageSetting.ShowPrintPreviewDialog();
}
}//End Class
}//End NameSpace
在這個類的構造函數中,提到了配置文件。在建立Asp.Net應用程序的時候自動會生成一個名為WebMIS.Config的文件,文件里有一些環境和其它信息的設置,可以簡單的理解為為程序提供一個外部設置的接口,提高應用程序的靈活性。在建立Windows應用程序的時候默認情況下沒有這樣的文件,但是可以在項目上單擊鼠標右鍵添加新項,選擇應用程序配置,默認的配置文件名為App.config。在構造函數中我們默認為Win下的打印,如果是Web方式下,可以在配置文件中增加鍵PrintMode及值Web,也可以實例化后設置PrintMode屬性為PrintModeFlag.Web。下面是在配置文件中添加鍵值的寫法
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="PrintMode" value="Web"/>
</appSettings>
</configuration>
至此,關于NET環境下有關打印頁面設置、打印機設置、打印預覽對話框的實現全部結束,我們可以將程序編譯成一個動態庫了。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。