水晶报表攻克系列3-如何在程序中自定义纸张
大家都知道电脑里会有预定义好的纸张,例如A4。但是最近做发票,快递单时,纸张大小需要自定义。
例如:
1 ReportDocument doc = new ReportDocument();
2 doc.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.PaperA4;
CrystalDecisions.Shared.PaperSize查看定义可知,是一个枚举类,里面只有41种预定义的纸张类型。而且,doc.PrintOptions.PaperSize不可以自定义纸张的宽和高。
经过查阅资料,有一种比较好的办法:
1) 在开始菜单,“打印机和传真”=》文件菜单项,服务器属性中,添加自定义纸张,设置自定义纸张的名称。
2) 在程序中就可以通过获取该自定义纸张的id,来设置PaperSize,程序如下:
1 doc.PrintOptions.PaperSize = (CrystalDecisions.Shared.PaperSize)(GetSelectedPaperSizeId());
1 /// <summary>
2 /// 获取用户自定义纸张ID
3 /// </summary>
4 public int GetSelectedPaperSizeId()
5 {
6 string printer = "";
7 string printerName = PrinterSetting.PostPrinterName;
8 string paperName = PrinterSetting.PostPrinterUserPaperSize;
9 foreach (string printerItem in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
10 {
11 if (printerItem.Contains(printerName))
12 {
13 printer = printerItem;
14 }
15 }
16 Microsoft.Win32.RegistryKey rk;
17 if (!printer.StartsWith(@"\\")) //本地打印机
18 {
19 rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers\\" + printer + "\\DsDriver");
20 }
21 else //网络打印机
22 {
23
24 string[] p = printer.Remove(0, 2).Split(new char[] { '\\' });
25 string path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Providers\\LanMan Print Services\\Servers\\" + p[0] + "\\Printers\\" + p[1] + "\\DsDriver";
26 rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path);
27 }
28
29 string[] papers = (string[])(rk.GetValue("printMediaSupported"));
30 int index = 0;
31 int paperid = 0;
32 foreach (string paper in papers)
33 {
34 if (paper == paperName)
35 {
36 paperid = index;
37 }
38 index++;
39 }
40
41 int[] sizes = PrinterHelper.Get_PaperSizes(printerName);
42 int paperSizeid = sizes[paperid];
43 return paperSizeid;
44 }
其中PrinterHelper类如下:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Runtime.InteropServices;
6
7 namespace Gasgoo.Invoice.Common
8 {
9 public class PrinterHelper
10 {
11 public static string OutputPort = String.Empty;
12
13 [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
14 public static extern int DeviceCapabilities(string pDevice, string pPort, short fwCapabilities, IntPtr pOutput, IntPtr pDevMode);
15
16 public static int[] Get_PaperSizes(string printer)
17 {
18 string text1 = printer;
19 int num1 = FastDeviceCapabilities(0x10, IntPtr.Zero, -1, text1);
20 if (num1 == -1)
21 {
22 return new int[0];
23 }
24 int num2 = Marshal.SystemDefaultCharSize * 0x40;
25 IntPtr ptr1 = Marshal.AllocCoTaskMem(num2 * num1);
26 FastDeviceCapabilities(0x10, ptr1, -1, text1);
27 IntPtr ptr2 = Marshal.AllocCoTaskMem(2 * num1);
28 FastDeviceCapabilities(2, ptr2, -1, text1);
29 IntPtr ptr3 = Marshal.AllocCoTaskMem(8 * num1);
30 FastDeviceCapabilities(3, ptr3, -1, text1);
31 int[] sizeArray1 = new int[num1];
32 for (int num3 = 0; num3 < num1; num3++)
33 {
34 string text2 = Marshal.PtrToStringAuto((IntPtr)(((long)ptr1) + (num2 * num3)), 0x40);
35 int num4 = text2.IndexOf('\0');
36 if (num4 > -1)
37 {
38 text2 = text2.Substring(0, num4);
39 }
40 short num5 = Marshal.ReadInt16((IntPtr)(((long)ptr2) + (num3 * 2)));
41 int num6 = Marshal.ReadInt32((IntPtr)(((long)ptr3) + (num3 * 8)));
42 int num7 = Marshal.ReadInt32((IntPtr)((((long)ptr3) + (num3 * 8)) + 4));
43 sizeArray1[num3] = System.Convert.ToInt32(num5);
44 }
45 Marshal.FreeCoTaskMem(ptr1);
46 Marshal.FreeCoTaskMem(ptr2);
47 Marshal.FreeCoTaskMem(ptr3);
48 return sizeArray1;
49 }
50
51 private static int FastDeviceCapabilities(short capability, IntPtr pointerToBuffer, int defaultValue, string printerName)
52 {
53 int num1 = DeviceCapabilities(printerName, OutputPort, capability, pointerToBuffer, IntPtr.Zero);
54 if (num1 == -1)
55 {
56 return defaultValue;
57 }
58 return num1;
59 }
60 }
61 }
这样,就可以完整的获取用户自定义的纸张了。
下一节,会为大家分享如何使用子报表。