水晶报表攻克系列3-如何在程序中自定义纸张
水晶报表攻克系列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 }
这样,就可以完整的获取用户自定义的纸张了。
下一节,会为大家分享如何使用子报表。