C#自定义晶报表纸张大小

Technorati 标签:

本文来源:http://hi.baidu.com/jackeyrain/blog/item/15f506bfc81c020f18d81f35.html

因为水晶报表的PaperSize是enum类型,但有时客户用的纸张不在其定义范围内,虽然在设计报表时可以选择目的打印机和纸型,但如果重新配置过该打印机则报表默认纸型不再有效,报表将按A4进行预览且会失真。

//获取本机所有打印机将其名称填充到comboBoxPrinters中:包含本地和网络打印机
foreach(string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
this.comboBoxPrinters.Items.Add(printer);
}
//当从comboBoxPrinters中选择打印机时获取其支持的纸张大小将其填充到listBoxPapers
this.listBoxPapers.Items.Clear();
string printer = this.comboBoxPrinters.Text;
this.m_printer = printer;
Microsoft.Win32.RegistryKey rk;
if(!this.comboBoxPrinters.Text.StartsWith(@"//")) //本地打印机
     rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE//Microsoft//Windows NT//CurrentVersion//Print//Printers//" + this.comboBoxPrinters.Text + "//DsDriver");
else //网络打印机
{
string[] p = printer.Remove(0,2).Split(new char[] { '//' });
string path = "SOFTWARE//Microsoft//Windows NT//CurrentVersion//Print//Providers//LanMan Print Services//Servers//" + p[0] + "//Printers//" + p[1] + "//DsDriver";
     rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(path);
}
string[] papers = (string[])(rk.GetValue("printMediaSupported"));
for(int i=0;i
   
   
{
this.listBoxPapers.Items.Add(papers[i]);
}
//根据纸张名称获取其所在本地机上的PaperSize:调用的是PaperSizeGetter.Get_PaperSizes静态方法(是从水晶报表中reflect精简出来的,版权归原作者所有)
public class PaperSizeGetter
{
public static string OutputPort = String.Empty;
[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DeviceCapabilities(string pDevice, string pPort, short fwCapabilities, IntPtr pOutput, IntPtr pDevMode);
public static int[] Get_PaperSizes(string printer)
{
string text1 = printer;
int num1 = FastDeviceCapabilities(0x10, IntPtr.Zero, -1, text1);
if (num1 == -1)
{
return new int[0];
}
int num2 = Marshal.SystemDefaultCharSize * 0x40;
IntPtr ptr1 = Marshal.AllocCoTaskMem(num2 * num1);
             FastDeviceCapabilities(0x10, ptr1, -1, text1);
IntPtr ptr2 = Marshal.AllocCoTaskMem(2 * num1);
             FastDeviceCapabilities(2, ptr2, -1, text1);
IntPtr ptr3 = Marshal.AllocCoTaskMem(8 * num1);
             FastDeviceCapabilities(3, ptr3, -1, text1);
int[] sizeArray1 = new int[num1];
for (int num3 = 0; num3 < num1; num3++)
{
string text2 = Marshal.PtrToStringAuto((IntPtr) (((long) ptr1) + (num2 * num3)), 0x40);
int num4 = text2.IndexOf('/0');
if (num4 > -1)
{
                     text2 = text2.Substring(0, num4);
}
short num5 = Marshal.ReadInt16((IntPtr) (((long) ptr2) + (num3 * 2)));
int num6 = Marshal.ReadInt32((IntPtr) (((long) ptr3) + (num3 * 8)));
int num7 = Marshal.ReadInt32((IntPtr) ((((long) ptr3) + (num3 * 8)) + 4));
                 sizeArray1[num3] = System.Convert.ToInt32(num5);
}
Marshal.FreeCoTaskMem(ptr1);
Marshal.FreeCoTaskMem(ptr2);
Marshal.FreeCoTaskMem(ptr3);
return sizeArray1;
}
private static int FastDeviceCapabilities(short capability, IntPtr pointerToBuffer, int defaultValue, string printerName)
{
int num1 = DeviceCapabilities(printerName, OutputPort, capability, pointerToBuffer, IntPtr.Zero);
if (num1 == -1)
{
return defaultValue;
}
return num1;
}
}
//根据纸型名称在其名称列表中的索引,获取该索引在调用Get_PaperSizes后的size数组中的对应值
int[] sizes = PaperSizeGetter.Get_PaperSizes(printerName);
int paperSizeid = sizes[this.listBoxPapers.SelectedIndex];
//将该size赋值给报表对象
report.PrintOptions.PaperSize = (CrystalDecisions.Shared.PaperSize)(paperSizeid);
 
 

本地机的每种纸型在每个支持的打印机上都对应了个id值,不同的配置顺序,不同的客户机相同纸型名称对都会导致不同的id,怎么获取这个id是关键,例如本机的
Letter      1
Tabloid     3
Legal       5
A3           8
A4          9
A5          11
B4          119
B5          120
11x17       121
25x25       122 //自定义
PostScript 自定义页面大小 32767
从打印机服务器属性中删除25x25,增加26x26,再增加25x25
Letter      1
Tabloid     3
Legal       5
A3          8
A4          9
A5          11
B4           119
B5          120
11x17       121
26x26      122 //自定义
25x25      123 //自定义
PostScript 自定义页面大小 32767
通过reflect水晶报表的PaperSize属性得知水晶报表通过这个id来设置其纸张大小,所以才想出这么个笨方法暂时解决了客户的要求。
Get_PaperSizes方法,以及这个id真实涵义自己还没弄懂,还请高人指点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值