Compact Framework 的智能设备打印引擎






4.59/5 (44投票s)
.NET Compact Framework 的打印支持。
引言
我在开发 Microsoft .NET Framework 应用程序时遇到了一个问题。问题在于 .NET Framework 的打印和打印预览支持。由于某些资源原因,.NET Framework 在打印和打印预览支持方面存在不足。因此,我开始为 Compact Framework 开发一个打印引擎。事实上,Pocket PC 2003 通过串行端口提供了打印支持的 API,这对于希望使用 Compact Framework 开发具有打印支持的应用程序的开发人员来说非常有用。
在开发串行通信类时,我使用了 MSDN 上的“在 Compact Framework 中 P/Invoke 串行 API”示例代码。正如我们所知,点阵打印机使用 COM 或 LPT 端口与系统进行通信。如果要通过 COM 端口发送数据,您应该使用字节流。
在我的例子中,我使用了以下值:
波特率 = 9600 数据位 = 8 校验位 = 0 停止位 = 0 |
我的类也支持打印预览。它是基于动态创建的窗口,如下所示:
图 1
我使用了多行、锁定的文本框来显示打印预览。由于其特性,文本框对象对于这项工作至关重要。事实上,通过将页面从字节数组形成,我可以轻松地将文本属性设置为打印缓冲区以显示预览。您可以看到,预览中还包含“上一页”和“下一页”按钮以及页码标签。所有控件都是动态创建的。
背景
Smart Device Print Engine 由两个主要层组成:打印类和串行通信类。我将详细、逐步地描述它是如何工作的。
图 2
使用代码
正如我之前提到的,串行端口通信基于字节流。因此,您需要以字节数组的形式发送数据。我使用了 CEWriteFile
API 函数来通过 COM 端口发送数据。您可以将数据放入一个 (n) 大小的数组中并发送到端口。例如
int iNumberOfBytesRead=0;
uint iNumberOfBytesToRead=1024;
byte[] Output = new byte[1024];
CEWriteFile(hPort, Output, iNumberOfBytesToRead,
ref iNumberOfBytesRead, IntPtr.Zero);
前面提到的 API 函数一次发送 1024 字节的数据,这对于最大限度地减少智能设备和串行端口之间的通信次数至关重要。例如,您想从行式打印机打印“hello world”字符串。这会如何实现?首先,您需要创建一个页面,如下所示:
// Create SDPE instance
SDPE = new SmartDevicePrintEngine();
// Set COM port for SDPE
SDPE.Port="COM1:";
// Create page with size parameters
SDPE.CreatePage(36,46);
上面提到的代码块创建了一个 SmartDevicePrintEngine 对象实例,并将串行端口号设置为 COM1,并在内存中创建了一个逻辑页面,该页面是一个二维 36x46 字节数组。然后它创建了 CommDevice 实例以与打印机通信。在 CommDevice 构造函数中,我将包大小设置为默认值 1024。这意味着每次将发送 1024 字节。然后,我创建了 Device Control Block 实例来设置串行端口属性。众所周知,Compact Framework 不支持线程的 Abort()
方法。因此,我使用事件机制来停止线程执行。我在 SmartDevicePrintEngine 构造函数中使用了 ArrayList
来存储用于打印预览的页面。这些操作发生在 Form_Load
事件中。现在,我们可以用我们的字符串填充逻辑页面了。
我将如何编写我的字符串并在纸上定位?我开发了 WriteToLogicalPage()
方法,因为它将字符串放置在打印区域。该方法有两个重载,分别是已对齐字符串和未对齐字符串。我将在后面的部分中描述它是如何工作的。
在页面上编写和定位字符串非常容易。请看下面的代码块示例:
SDPE.WriteToLogicalPage(17, 2, "Hello World");
X 和 Y 坐标从值 1 开始。我们想将“Hello World”字符串放置在 17, 2 的位置。 WriteToLogicalPage()
方法中的第一步是检查页面边界并将字符串(“Hello World”)转换为 PageBuffer
,这是一个字节数组。我们创建了一个逻辑页面,设置了字符串并将其定位在页面上。现在,我们需要调用最重要的 Print()
方法。
我通过 OpenPort
, SetupCommSetDCB
, SetConnectionTimeout
和 CreateCommThread
初始化了串行端口。这些方法初始化并打开串行端口设备通信。初始化后,我们需要将字节数组发送到串行端口。因此,我们应该调用 Send()
方法。在 Send()
方法中,我们需要每次发送 1024 字节的数据包。在此过程结束时,所有数据都以 1024 字节的数据包形式发送到串行端口。我们需要发送换页符(“0x0c”)来进行分页。如果我们有多页,我们需要调用 NewPage()
方法来刷新旧页面并创建一个新页面。现在,打印过程已成功完成,我们应该通过 Close()
方法关闭端口。就是这样。
现在,我们将研究 Smart Device Print Engine 中的预览支持。直到 AddToPreview()
的所有步骤都与 Print()
方法相同。在 AddToPreview()
方法中;我们需要创建一个 StringBuilder
对象实例,以便连接行来构建新的预览页面。我们将新页面插入到页面数组中。NewPage()
方法刷新旧页面并创建一个新页面。预览页面是动态形成的。它有一个文本框来表示页面的打印输出。
我想在下面描述类的方法和属性;
类:
|
签名:SmartDevicePrintEngine() 描述:构造函数。 |
签名:public bool CreatePage(int Width, int Height) 描述:创建一个逻辑页面,这是一个二维字节数组。 |
签名:public void WriteToLogicalPage(int x, int y, string Value) 描述:在给定位置将字符串写入页面。字符串不应溢出页面。 |
签名:public void WriteToLogicalPage(int x, int y, int Length, int Alignment, string Value) 描述:在给定位置按对齐方式和固定长度将字符串写入页面。字符串不应溢出页面。例如,您可能希望写入一个应右对齐的数值。 |
签名:public void FormFeed() 描述:这很简单。将 0x0c 发送到串行端口。 |
签名:private string ReadLogicalPageByRow(int RowNumber) 描述:逐行读取字节数组并将其作为字符串变量返回。 |
签名:public void Dispose() 描述:将对象从内存中刷新。 |
签名:public void NewPage() 描述:创建新页面。 |
签名:public void Print() 描述:打印文档页面或页面。 |
签名:public void AddToPreview() 描述:将您的预览页面添加到数组中,以便在打印预览屏幕上显示。 |
签名:public void Preview() 描述:调用预览窗口并显示页面的预览。 |
签名:public int PageWidth 描述:页面宽度。 |
签名:public int PageHeight 描述:页面高度。 |
签名:public string Port 描述:COM 端口号。 |
类:
|
签名:public CommDevice() 描述:构造函数 |
签名:private IntPtr OpenPort() 描述:打开端口以执行串行通信。 |
签名:private void SetupComm() 描述:设置缓冲区大小。 |
签名:private void SetConnectionTimeOut() 描述:设置串行通信的连接超时。 |
签名:private void SetDCB() 描述:设备控制块 |
签名:private void CreateCommThread() 描述:创建一个线程以处理事件。 |
签名:public void Init() 描述:串行端口初始化例程。 |
签名:public void Send(char[,] Data) 描述:以 1024 字节的片段发送字节数组。 |
签名:public void Send(byte Data) 描述:将一个字符发送到串行端口。 |
签名:public void ClosePort() 描述:关闭 COM 端口。 |
签名:public void Dispose() 描述:刷新对象。 |
签名:public string Port 描述:COM 端口号。 |
签名:public uint BaudRate 描述:通信波特率。 |
您可以在连续表格(如销售单、订单单、发票单等)中使用 **Smart Device Print Engine**。该类支持 ASCII 打印。但是,我计划在不久的将来为该类添加蓝牙支持。我希望它能满足那些希望为其项目添加打印输出支持的开发人员的需求。此外,本文还提供了有关通过 Pocket Device 进行串行通信的信息。
我在需要现场打印发票的移动销售项目中使用 **Smart Device Print Engine** 类。我们仍在成功使用该类。
历史
- 版本 1.0 - 首次发布