打印的时候纸张设置在.net中是蛮麻烦的,并不像msdn上说的那样简单,如果都是A4的纸还好,要是不同的打印机要设置不同的打印纸张那更是令人头疼。最近帮一同学做毕业设计,其中正好涉及到打印操作,在csdn上查了一下,发现很多人都遇到我同样的问题,现在我把我的解决方案与大家共享。
开始在vs2003下,DefaultPageSettings.PageSize 、PrnterSettings.PageSize 无论你怎么设置打印A4以外的纸就是有问题,在网上查了一下竟然有人说是.net的漏洞(当然不信了),百般无赖之下想到了vs2005,或许2005下面会给我一些惊喜。转战到2005下后一运行,期待的惊喜并有出现,打算要放弃了,这时我发现要是先更改打印机的默认纸张设置为A3运行程序打印A3时竟然可以,“可不可以把打印机的PageSettings对象存储起来”? 在2003里面PageSettings对象不能序列化,但在2005里面可以。 复制点soap序列化后的代码:
<a1:PageSettings id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/System.Drawing.Printing/System.Drawing%2C%20Version%3D2.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a">
<printerSettings href="#ref-3" />
- <color>
<value>1</value>
</color>
<paperSize href="#ref-4" />
<paperSource href="#ref-5" />
<printerResolution href="#ref-6" />
- <landscape>
<value>1</value>
</landscape>
<margins href="#ref-7" />
</a1:PageSettings>
大家看看,<printerSettings href="#ref-3" /> 这是打印机的设置,<paperSize href="#ref-4" />paperSize的设置,还有其他都在里面了。好了,我们先成功存储了PageSettings对象,然后就是反序列化调用对象了。反序列化之前还要都PageSettings对象的xml文件进行一些操作以满足我们的需要。
public void changeSettings(string printerName, string paperName, int paperWidth, int paperHeight)
{
XmlDocument xd = new XmlDocument();
xd.Load(@_filePath);
XPathNavigator navi = xd.CreateNavigator();
XmlNamespaceManager nameManager = new XmlNamespaceManager(navi.NameTable);
nameManager.AddNamespace("SOAP-ENV","http://schemas.xmlsoap.org/soap/envelope/");
nameManager.AddNamespace("a1", "http://schemas.microsoft.com/clr/nsassem/System.Drawing.Printing/System.Drawing%2C%20Version%3D2.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db03f5f7f11d50a3a");
XPathNavigator node1 = navi.SelectSingleNode("/SOAP-ENV:Envelope/SOAP-ENV:Body/a1:PrinterSettings/printerName", nameManager);
node1.SetValue(printerName);
XPathNavigator node2 = navi.SelectSingleNode("/SOAP-ENV:Envelope/SOAP-ENV:Body/a1:PaperSize", nameManager);
node2.SelectSingleNode("name").SetValue(paperName);
node2.SelectSingleNode("width").SetValue(paperWidth.ToString());
node2.SelectSingleNode("height").SetValue(paperHeight.ToString());
// MemoryStream ms = new MemoryStream();
xd.Save(@_filePath);
}
这个函数就是改动 xml文件的(本来想定义一个内存流,修改后的xml文件直接保存在其中再反序列化,但总不成功,希望网友们研究一下),按我们的要求该好后就可以反序列化了:
SoapFormatter sf = new SoapFormatter();//创建soap序列化对象
SoapFile xmlFile = new SoapFile(@_xmlFilePath);//创建 soapFile 对象
xmlFile.changeSettings(this._printerName, this._paperSize.PaperName, this._paperSize.Width, this._paperSize.Height);
FileStream fs = new FileStream(@_xmlFilePath, FileMode.Open, FileAccess.Read);
PageSettings ps = (PageSettings)sf.Deserialize(fs);// 反序列化修改后的流为pageSetting对象
pd.DefaultPageSettings = ps;
fs.Close();
这样就可以打印我们想要的纸张类型了,当然,运行程序前要先生成对应的打印机的PageSettings对象的xml文件,我也为此写了一个小程序。
总的来说,这样有点麻烦,但基本可以实现功能(网上看到过一篇用API实现的,看了感觉就是两个字“头晕”),如果大家有什么其它好的解决方案请也发上来交流。 ( Email:wade311@126.com )