0.有关打印对话框的实现.txt
上传用户:jx_fiona
上传日期:2014-03-08
资源大小:1387k
文件大小:18k
源码类别:

打印编程

开发平台:

Others

  1. 开源:.NET环境下有关打印页面设置、打印机设置、打印预览对话框的实现  
  2.   我个人认为,开发MIS,首先就得解决网格的问题,而开发工具为我们提供了如DataGrid、MSHFlexGrid的控件。其次,是打印的问题,将业务单据与数据报表打印出来。可想而知,即使一个业务功能非常完美齐全的管理软件,没有打印的支持,也一定不算是一个完整的软件。
  3.   对于打印,我们总是在用户打印之前可以看看打印的效果,这时,一般的软件都提供了打印预览;如果需要调整打印的效果如纸张的大小、边距的设置,又提供了页面设置对话框让用户选择和调整;如果系统有多个打印机,当用户单击打印按钮时还可以选择输出的对象。
  4.   总之,对于打印,我们至少要提供打印页面设置、打印机设置、打印预览对话框,让用户有更多的机会参与交互。这一些,是一个打印模块比较重要也比较基本的东西,让我们一起来实现它们吧。
  5.   进入Vs2003 IDE,从文件菜单上单击新建项目,项目类型为C#,在模板中选择类库,名称估且叫GoldPrinter,确定即可。在打开的开发环境中,删除解决方案资源管理器中默认生成的Class1.cs。
  6.   现在,我们要考虑一下,对于打印,可能是在Windows下,也可能是Web下。如果将两者的方法统一起来,让调用者不用操心是什么方式下那该多好啊。因此,我们首先设计一个接口,提供两者共用的方法。
  7.   
  8.   在项目上鼠标右键单击后添加一个新类,名称为:IPrinterPageSetting,由于是接口,将class改为interface,并去掉构造函数。看上去应类似如下:
  9. using System;
  10. namespace GoldPrinter
  11. {
  12. /// <summary>
  13. /// IPrinterPageSetting 的摘要说明。
  14. /// </summary>
  15. public class IPrinterPageSetting
  16. {
  17. }
  18. }
  19. 方法中至少包含三个声明即ShowPageSetupDialog()、ShowPrintSetupDialog()、ShowPrintPreviewDialog(),也就是打开打印页面设置、打印机设置、打印预览对话框。
  20.   
  21.   Vs2003为我们提供了一个PrintDocument,名字空间是System.Drawing.Printing。PrintDocument是为打印而提供的一个类,它的概述(summary)是这样的:定义一个可再次使用的对象,该对象将输出发送到打印机。
  22.   PrintDocument为我们封装了很多复杂的细节,它有一个至关重要的事件叫PrintPage,PrintPage的概述是:当需要为当前页打的输出时发生。因此,我们只要引发了打印事件,把打印的具体输出的对象交给PrintPage,别的我们就不用操心了。
  23.   那么,我们怎么实现具体输出的过程呢?由于是封装,我们也不可能知道最终用户具体怎么去实现,这时,委托(Delegate)为我们起了大的作用。大家都知道一个函数实现某个功能的时候往往需要一些输入的数据,但是函数本身并不知道这些数据到底是哪个具体的值,只知道这个值的数据类型,这时引入了参数,调用者调用函数据的时候传入相应类型的具体值就行了。大家应该意识到了我的用意,与函数类似,我们为打印提供了关联打印机的方法,但是具体的实现只有由调用者去实现,不同之处是函数传递的是参数,而我们要做的委托传递的是方法。这时,我们只要为两者建立对应关系就可以了,这就是委托。我们需要定义一个委托,参数类型与PrintPage的一致就可以了,即(Object obj,System.Drawing.Printing.PrintPageEventArgs ev)。
  24.   由此可见,我们需要做下面的一些事情:
  25.   1、在项目的引用处添加引用,在弹出的对话框的.NET标签中选择System.Drawing.dll,
  26.      原因是PrintDocument的名字空间是System.Drawing.Printing,在System.Drawing.dll实现;
  27.   2、在IPrinterPageSetting接口中增加PrintDocument属性的声明;
  28.   3、定义委托
  29.   4、在IPrinterPageSetting接口中增加PrintPage属性的声明,类型为定义的委托;
  30. 以下是IPrinterPageSetting接口文件内容:
  31. using System;
  32. using System.Drawing;
  33. using System.Drawing.Printing;
  34. namespace GoldPrinter
  35. {
  36. /// <summary>
  37. /// PrintDocument.PrintPage的委托定义
  38. /// </summary>
  39. public delegate void PrintPageDelegate(Object obj,System.Drawing.Printing.PrintPageEventArgs ev) ;
  40. /// <summary>
  41. /// IPrinterPageSetting 的接口,显示打印纸张设置、打印机设置、打印预览对话框。
  42. /// 程序提供:周方勇;Email:flygoldfish@sina.com。
  43. /// </summary>
  44. public interface IPrinterPageSetting
  45. {
  46. /// <summary>
  47. /// 获取或设置打印文档
  48. /// </summary>
  49. System.Drawing.Printing.PrintDocument PrintDocument
  50. {
  51. get;
  52. set;
  53. }
  54. /// <summary>
  55. /// 关联一个方法,目的是让具体的打印由实例化者来操作
  56. /// 如PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler);
  57. /// </summary>
  58. PrintPageDelegate PrintPage
  59. {
  60. get;
  61. set;
  62. }
  63. /// <summary>
  64. /// 显示页面设置对话框,并返回PageSettings
  65. /// </summary>
  66. /// <returns></returns>
  67. System.Drawing.Printing.PageSettings ShowPageSetupDialog();
  68. /// <summary>
  69. /// 显示打印机设置对话框,并返回PrinterSettings
  70. /// </summary>
  71. /// <returns></returns>
  72. System.Drawing.Printing.PrinterSettings ShowPrintSetupDialog();
  73. /// <summary>
  74. /// 显示打印预览对话框
  75. /// </summary>
  76. void ShowPrintPreviewDialog();
  77. }//End Interface
  78. }//End NameSpace
  79.   下面,我们以Windows下的编程方式实现,同时也列Web编程下的框架。由于是Windows下的编程,我们可能用到对话框什么的作为错误提示,因此,我们同理要加入System.Windows.Forms.dll引用。再建立一个类文件,名称为WinPrinterPageSetting。进入文件后,在类声明后面加上:IPrinterPageSetting,实现接口功能。程序清单如下,程序中有很多注释,这里不再多说。
  80. using System;
  81. using System.Drawing;
  82. using System.Drawing.Printing;
  83. using System.Windows.Forms;
  84. namespace GoldPrinter
  85. {
  86. /// <summary>
  87. /// WinForm下的打印纸张设置、打印机设置、打印预览对话框。
  88. /// </summary>
  89. public class WinPrinterPageSetting:IPrinterPageSetting
  90. {
  91. //把PrintPage委托声明为类的一个成员变量
  92. private PrintPageDelegate _printPage;
  93. // 打印文档
  94. private PrintDocument _printDocument;
  95. #region 构造函数
  96. public WinPrinterPageSetting():this(null)
  97. {
  98. }
  99. /// <summary>
  100. /// 使用printDocument来初始化类的新实例,当printDocument为null时自动创建一个printDocument的实例
  101. /// </summary>
  102. /// <param name="printDocument"></param>
  103. public WinPrinterPageSetting(PrintDocument printDocument)
  104. {
  105. if (printDocument != null)
  106. {
  107. _printDocument = printDocument;
  108. }
  109. else
  110. {
  111. _printDocument = new PrintDocument();
  112. }
  113. }
  114. #endregion
  115. #region IPrinterPageSetting 成员
  116. /// <summary>
  117. /// 获取或设置打印文档
  118. /// </summary>
  119. public PrintDocument PrintDocument
  120. {
  121. get
  122. {
  123. return this._printDocument;
  124. }
  125. set
  126. {
  127. this._printDocument = value;
  128. }
  129. }
  130. /// <summary>
  131. /// 一定要实例化此类后在调用打印/预览之前设置此属性,使之关联一个方法,目的是让具体的打印由实例化者来操作
  132. /// 如PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler);
  133. /// </summary>
  134. public PrintPageDelegate PrintPage
  135. {
  136. set
  137. {
  138. //初始委托变量,关联方法
  139. _printPage = value;
  140. if (_printDocument==null)
  141. {
  142. throw new Exception("关联的打印文档不能为空!");
  143. }
  144. _printDocument.PrintPage +=new System.Drawing.Printing.PrintPageEventHandler(this._printPage);
  145. }
  146. get
  147. {
  148. return _printPage;
  149. }
  150. }
  151. /// <summary>
  152. /// 显示页面设置对话框,并返回PageSettings
  153. /// </summary>
  154. /// <returns></returns>
  155. public PageSettings ShowPageSetupDialog()
  156. {
  157. return ShowPageSetupDialog(this._printDocument);
  158. }
  159. /// <summary>
  160. /// 显示打印机设置对话框,并返回PrinterSettings
  161. /// </summary>
  162. /// <returns></returns>
  163. public PrinterSettings ShowPrintSetupDialog()
  164. {
  165. return ShowPrintSetupDialog(this._printDocument);
  166. }
  167. /// <summary>
  168. /// 显示打印预览对话框
  169. /// </summary>
  170. public void ShowPrintPreviewDialog()
  171. {
  172. ShowPrintPreviewDialog(this._printDocument);
  173. }
  174. #endregion
  175. //***************注意:以下几个对话框方法可以独立使用***************
  176. #region 页面设置对话框 protected virtual PageSettings ShowPageSetupDialog(PrintDocument printDocument)
  177. /// <summary>
  178. /// 页面设置对话框,可以独立使用
  179. /// </summary>
  180. /// <param name="printDocument"></param>
  181. /// <returns></returns>
  182. /// <remarks>
  183. /// 作    者:周方勇
  184. /// 修改日期:2004-08-07
  185. /// </remarks>
  186. protected virtual PageSettings ShowPageSetupDialog(PrintDocument printDocument)
  187. {
  188. //声明返回值的PageSettings
  189. PageSettings ps = new PageSettings();
  190. if (printDocument==null)
  191. {
  192. throw new Exception("关联的打印文档不能为空!");
  193. }
  194. try
  195. {
  196. //申明并实例化PageSetupDialog
  197. PageSetupDialog psDlg = new PageSetupDialog();
  198. //相关文档及文档页面默认设置
  199. psDlg.Document = printDocument;
  200. psDlg.PageSettings = printDocument.DefaultPageSettings;
  201. //显示对话框
  202. DialogResult result = psDlg.ShowDialog();
  203. if (result == DialogResult.OK)
  204. {
  205. ps = psDlg.PageSettings;
  206. printDocument.DefaultPageSettings = psDlg.PageSettings;
  207. }
  208. }
  209. catch(System.Drawing.Printing.InvalidPrinterException e)
  210. {
  211. MessageBox.Show("未安装打印机,请进入系统控制面版添加打印机!","打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  212. }
  213. catch(Exception ex)
  214. {
  215. MessageBox.Show(ex.Message,"打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  216. }
  217. return ps;
  218. }
  219. #endregion
  220. #region 打印设置对话框 protected virtual PrinterSettings ShowPrintSetupDialog(PrintDocument printDocument)
  221. /// <summary>
  222. /// 打印设置对话框,可以独立使用
  223. /// </summary>
  224. /// <param name="printDocument"></param>
  225. /// <returns></returns>
  226. /// <remarks>
  227. /// 作    者:周方勇
  228. /// 修改日期:2004-08-07
  229. /// </remarks>
  230. protected virtual PrinterSettings ShowPrintSetupDialog(PrintDocument printDocument)
  231. {
  232. //声明返回值的PrinterSettings
  233. PrinterSettings ps = new PrinterSettings();
  234. if (printDocument==null)
  235. {
  236. throw new Exception("关联的打印文档不能为空!");
  237. }
  238. try
  239. {
  240. //申明并实例化PrintDialog
  241. PrintDialog pDlg = new PrintDialog();
  242. //可以选定页
  243. pDlg.AllowSomePages = true;
  244. //指定打印文档
  245. pDlg.Document = printDocument;
  246. //显示对话框
  247. DialogResult result = pDlg.ShowDialog();
  248. if (result == DialogResult.OK)
  249. {
  250. //保存打印设置
  251. ps = pDlg.PrinterSettings;
  252. //打印
  253. printDocument.Print();
  254. }
  255. }
  256. catch(System.Drawing.Printing.InvalidPrinterException e)
  257. {
  258. MessageBox.Show("未安装打印机,请进入系统控制面版添加打印机!","打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  259. }
  260. catch(Exception ex)
  261. {
  262. MessageBox.Show(ex.Message,"打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  263. }
  264. return ps;
  265. }
  266. #endregion
  267. #region 打印预览对话框 protected virtual void ShowPrintPreviewDialog(PrintDocument printDocument)
  268. /// <summary>
  269. /// 打印预览对话框,可以独立使用
  270. /// </summary>
  271. /// <param name="printDocument"></param>
  272. /// <returns></returns>
  273. /// <remarks>
  274. /// 作    者:周方勇
  275. /// 修改日期:2004-08-07
  276. /// </remarks>
  277. protected virtual void ShowPrintPreviewDialog(PrintDocument printDocument)
  278. {
  279. if (printDocument==null)
  280. {
  281. throw new Exception("关联的打印文档不能为空!");
  282. }
  283. try
  284. {
  285. //申明并实例化PrintPreviewDialog
  286. PrintPreviewDialog ppDlg = new PrintPreviewDialog();
  287. //指定打印文档
  288. ppDlg.Document = printDocument;
  289. //显示对话框
  290. DialogResult result = ppDlg.ShowDialog();
  291. if (result == DialogResult.OK)
  292. {
  293. //...
  294. }
  295. }
  296. catch(System.Drawing.Printing.InvalidPrinterException e)
  297. {
  298. MessageBox.Show("未安装打印机,请进入系统控制面版添加打印机!","打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  299. }
  300. catch(Exception ex)
  301. {
  302. MessageBox.Show(ex.Message,"打印",MessageBoxButtons.OK,MessageBoxIcon.Warning);
  303. }
  304. }
  305. #endregion
  306. }//End Class
  307. }//End NameSpace
  308.   大家可以看到了#region指定,它与#endregion一起使用,可以把中间的文本折叠起来,很方便,需要查看的时候就单击前面的展开符号。后三个函数是比较重要的方法,同时提供它们的重载函数。ShowPageSetupDialog()与ShowPrintSetupDialog()返回用户确认的当前设置选择。
  309.   再建立一个类文件,名称为WebPrinterPageSetting。进入文件后,在类声明后面加上:IPrinterPageSetting,实现接口功能。程序清单如下:
  310. using System;
  311. namespace GoldPrinter
  312. {
  313. /// <summary>
  314. /// WebForm下的打印纸张设置、打印机设置、打印预览对话框。(***暂无具体实现***)
  315. /// </summary>
  316. public class WebPrinterPageSetting:IPrinterPageSetting
  317. {
  318. public WebPrinterPageSetting()
  319. {
  320. //
  321. // TODO: 在此处添加构造函数逻辑
  322. //
  323. }
  324. #region IPrinterPageSetting 成员
  325. public System.Drawing.Printing.PrintDocument PrintDocument
  326. {
  327. get
  328. {
  329. // TODO:  添加 WebPrinterPageSetting.PrintDocument getter 实现
  330. return null;
  331. }
  332. set
  333. {
  334. // TODO:  添加 WebPrinterPageSetting.PrintDocument setter 实现
  335. }
  336. }
  337. public PrintPageDelegate PrintPage
  338. {
  339. get
  340. {
  341. // TODO:  添加 WebPrinterPageSetting.PrintPage getter 实现
  342. return null;
  343. }
  344. set
  345. {
  346. // TODO:  添加 WebPrinterPageSetting.PrintPage setter 实现
  347. }
  348. }
  349. public System.Drawing.Printing.PageSettings ShowPageSetupDialog()
  350. {
  351. // TODO:  添加 WebPrinterPageSetting.ShowPageSetupDialog 实现
  352. return null;
  353. }
  354. public System.Drawing.Printing.PrinterSettings ShowPrintSetupDialog()
  355. {
  356. // TODO:  添加 WebPrinterPageSetting.ShowPrintSetupDialog 实现
  357. return null;
  358. }
  359. public void ShowPrintPreviewDialog()
  360. {
  361. // TODO:  添加 WebPrinterPageSetting.ShowPrintPreviewDialog 实现
  362. }
  363. #endregion
  364. }//End Class
  365. }//End NameSpace
  366.   做到了这一步,大家可能说已经可以了,确实如此。因为在调用的时候实例化WinPrinterPageSetting/WebPrinterPageSetting并调用它的方法或属性就可以了。大家再想想我为什么要提供IPrinterPageSetting呢?如果我现在调用打印对话框,我也不管是Windows下还是Web下的,这时,IPrinterPageSetting就发挥了作用。
  367. 例如:
  368. IPrinterPageSetting _printerPageSetting;
  369. 申明了一个打印接口对象,以后就可以直接调用它的方法了,但是到底是Windows模式还是Web模式呢,我们只需要让程序自己去根据系统去实例为真正的WinPrinterPageSetting或WebPrinterPageSetting了。如:
  370. //创建接口对象的新实例,使其指象真正的实现其接口的对象
  371. if (Windows模式)
  372. {
  373. _printerPageSetting = new WinPrinterPageSetting();
  374. }
  375. else if(Web模式)
  376. {
  377. _printerPageSetting = new WebPrinterPageSetting();
  378. }
  379. 在接下来的程序清单中我们可以看到这个效果。我们再建立一个PrinterPageSetting类,将WinPrinterPageSetting与WebPrinterPageSetting合二为一。在类的构造函数中增加自动判断Windows模式还是Web模式,同时也提供PrintMode属性可以让用户修改。程序清单如下:
  380. using System;
  381. using System.Drawing;
  382. using System.Drawing.Printing;
  383. using System.Windows.Forms;
  384. namespace GoldPrinter
  385. {
  386. /// <summary>
  387. /// 打印方式
  388. /// </summary>
  389. public enum PrintModeFlag
  390. {
  391. /// <summary>
  392. /// Windows窗口打印方式
  393. /// </summary>
  394. Win
  395. ,
  396. /// <summary>
  397. /// Web窗口打印方式
  398. /// </summary>
  399. Web
  400. }
  401. /// <summary>
  402. /// 封装页面设置、打印机设置、打印预览,适合于Window和Asp.Net。
  403. /// 程序提供:周方勇;Email:flygoldfish@sina.com。
  404. /// </summary>
  405. public class PrinterPageSetting
  406. {
  407. //申明一个封装页面设置、打印机设置、打印预览的接口
  408. private IPrinterPageSetting _printerPageSetting;
  409. //打印方式
  410. private PrintModeFlag _printModeFlag;
  411. public PrintModeFlag PrintMode
  412. {
  413. get
  414. {
  415. return this._printModeFlag;
  416. }
  417. set
  418. {
  419. this._printModeFlag = value;
  420. //运用了抽象模式,创建接口对象的新实例,使其指象真正的实现其接口的对象
  421. if (this._printModeFlag == PrintModeFlag.Win)
  422. {
  423. _printerPageSetting = new WinPrinterPageSetting();
  424. }
  425. else if(this._printModeFlag == PrintModeFlag.Web)
  426. {
  427. _printerPageSetting = new WebPrinterPageSetting();
  428. }
  429. }
  430. }
  431. /// <summary>
  432. /// 获取或设置打印文档
  433. /// </summary>
  434. public PrintDocument PrintDocument
  435. {
  436. get
  437. {
  438. return _printerPageSetting.PrintDocument;
  439. }
  440. set
  441. {
  442. _printerPageSetting.PrintDocument = value;
  443. }
  444. }
  445. /// <summary>
  446. /// 一定要实例化此类后在调用打印/预览初始此变量,使之关联一个方法,目的是让具体的打印由实例化者来操作
  447. /// 如PrinterPageSetting1.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler);
  448. /// </summary>
  449. public PrintPageDelegate PrintPage
  450. {
  451. set
  452. {
  453. _printerPageSetting.PrintPage = value;
  454. }
  455. get
  456. {
  457. return _printerPageSetting.PrintPage;
  458. }
  459. }
  460. #region 构造函数
  461. /// <summary>
  462. ///  封装页面设置、打印机设置、打印预览,适合于Window和Asp.Net,Web方式下请在配置文件中增加键PrintMode及值Web,也可以实例化后设置PrintMode属性为PrintModeFlag.Web。
  463. /// </summary>
  464. public PrinterPageSetting():this(null)
  465. {
  466. }
  467. /// <summary>
  468. ///  封装页面设置、打印机设置、打印预览,适合于Window和Asp.Net,Web方式下请在配置文件中增加键PrintMode及值Web,也可以实例化后设置PrintMode属性为PrintModeFlag.Web。
  469. /// </summary>
  470. /// <param name="printDocument"></param>
  471. public PrinterPageSetting(PrintDocument printDocument)
  472. {
  473. string strPrintMode = "";
  474. //配置文件中键PrintMode
  475. strPrintMode = System.Configuration.ConfigurationSettings.AppSettings["PrintMode"];
  476. if (strPrintMode == null)
  477. {
  478. //默认为Win方式
  479. strPrintMode = "Win";
  480. }
  481. //配置文件中键PrintMode的值Win/Web
  482. if (strPrintMode.ToUpper() == "WIN")
  483. {
  484. this.PrintMode = PrintModeFlag.Win;
  485. }
  486. else
  487. {
  488. this.PrintMode = PrintModeFlag.Web;
  489. }
  490. /*  //配置文件中添加键值的写法
  491. <?xml version="1.0" encoding="utf-8" ?>
  492. <configuration>
  493. <appSettings>
  494. <add key="PrintMode" value="Web"/>
  495. </appSettings>
  496. </configuration>
  497. */
  498. _printerPageSetting.PrintDocument = printDocument;
  499. }
  500. #endregion
  501. /// <summary>
  502. /// 显示页面设置对话框,并返回PageSettings
  503. /// </summary>
  504. /// <returns></returns>
  505. public PageSettings ShowPageSetupDialog()
  506. {
  507. return _printerPageSetting.ShowPageSetupDialog();
  508. }
  509. /// <summary>
  510. /// 显示打印机设置对话框,并返回PrinterSettings
  511. /// </summary>
  512. /// <returns></returns>
  513. public PrinterSettings ShowPrintSetupDialog()
  514. {
  515. return _printerPageSetting.ShowPrintSetupDialog();
  516. }
  517. /// <summary>
  518. /// 显示打印预览对话框
  519. /// </summary>
  520. public void ShowPrintPreviewDialog()
  521. {
  522. _printerPageSetting.ShowPrintPreviewDialog();
  523. }
  524. }//End Class
  525. }//End NameSpace
  526.   在这个类的构造函数中,提到了配置文件。在建立Asp.Net应用程序的时候自动会生成一个名为WebMIS.Config的文件,文件里有一些环境和其它信息的设置,可以简单的理解为为程序提供一个外部设置的接口,提高应用程序的灵活性。在建立Windows应用程序的时候默认情况下没有这样的文件,但是可以在项目上单击鼠标右键添加新项,选择应用程序配置,默认的配置文件名为App.config。在构造函数中我们默认为Win下的打印,如果是Web方式下,可以在配置文件中增加键PrintMode及值Web,也可以实例化后设置PrintMode属性为PrintModeFlag.Web。下面是在配置文件中添加键值的写法
  527.     <?xml version="1.0" encoding="utf-8" ?>
  528.     <configuration>
  529.      <appSettings>
  530.        <add key="PrintMode" value="Web"/> 
  531.      </appSettings>
  532.     </configuration>
  533.   至此,关于NET环境下有关打印页面设置、打印机设置、打印预览对话框的实现全部结束,我们可以将程序编译成一个动态库了。在接下来的文章中,我们一起看看怎么应用这个动态库,并且以一个完整的单据、报表打印程序为例进一步说明。
  534. 相关源码下载信息请访问:
  535. http://blog.csdn.net/flygoldfish
  536. 声明:本文版权为周方勇所有,欢迎转载,请保留完整的内容及出处。
  537. flygoldfish@163.com