本文介绍Windows Mobile或CE平台下的企业应用中的打印的实现方法和部分打印机指令参考。
Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ipAddress = IPAddress.Parse(“192.168.1.4”);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 9100);
//异步连接
mySocket.BeginConnect(ipEndPoint, new AsyncCallback(OnConnect), null);
//异步发送打印数据及指令
mySocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
为了更好的通用性最好封装一个异步Socket类,这样不仅可以用在发送打印指令下,发送其他数据给主机也可以使用:
下面是我封装的一个异步socket类:
namespace PDA.Net
{
/// <summary>
/// 通知事件类型
/// </summary>
public enum NotifyEvents
{
Connected,
DataSent,
DataReceived,
Disconnected,
ConnectError,
SendError,
ReceiveError,
DisconnectError,
OtherError
}
/// <summary>
/// 通知事件委托
/// </summary>
/// <param name="notifyEvent">事件类型</param>
/// <param name="eventMessage">事件消息</param>
/// <param name="data">数据内容</param>
public delegate void NotifyEventHandler(NotifyEvents notifyEvent, string eventMessage, object data);
//socket异步通讯类
public class DeviceSocket
{
public Socket mySocket = null;
// 处理同步
ManualResetEvent asyncEvent = new ManualResetEvent(true);
public string receiveBuf = null;
private const int BUFFER_SIZE = 1024;
//通知事件
public event NotifyEventHandler Notify;
// Closing flag
private bool closing = false;
byte[] bRcvd = new byte[BUFFER_SIZE];
/// <summary>
///连接到一个网络地址
/// </summary>
public void Connect(String ip, int port)
{
mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 将事件状态设置为非终止状态,导致线程阻止
asyncEvent.Reset();
// 准备异步socket
IPAddress ipAddress = IPAddress.Parse(ip);
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);
//开始异步连接主机
mySocket.BeginConnect(ipEndPoint, new AsyncCallback(OnConnect), null);
// 等待所有异步操作都完成
//asyncEvent.WaitOne();
}
/// <summary>
/// 确定Socket是否连接,有时Socket的Connected是true,但不能一定保证已连接
///需通过poll已确认是否真的已连接
///
/// 连接返回true,否则false;
/// </summary>
public bool IsConnected
{
get
{
if (mySocket == null) return false;
if (!mySocket.Connected) return false;
//确保socket已连接,即使Conected属性已连接
try
{
// 确定socket是否连接
return !mySocket.Poll(1, SelectMode.SelectError);
}
catch
{
return false;
}
}
}
/// <summary>
/// Async connect callback
/// </summary>
private void OnConnect(IAsyncResult ar)
{
try
{
// 接收挂起的异步连接请求
mySocket.EndConnect(ar);
// 通知主线程已连接
NotifyCaller(NotifyEvents.Connected, null);
}
catch (Exception ex)
{
NotifyCaller(NotifyEvents.ConnectError, ex.Message);
}
}
/// <summary>
/// 断开已连接的socket
/// </summary>
public void Disconnect()
{
// 如果socket没有被创建,直接返回
if (mySocket == null) return;
closing = true;
try
{
mySocket.Shutdown(SocketShutdown.Both);
}
catch { }
try
{
mySocket.Close();
// 等待所有异步操作直至完成
//asyncEvent.WaitOne();
}
catch { }
closing = false;
NotifyCaller(NotifyEvents.Disconnected, "断开成功");
}
/// <summary>
/// 发送数据
/// </summary>
public void Send(String data)
{
// String to byet
byte[] byteArray = Encoding.Default.GetBytes(data);
Send(byteArray);
}
public void Send(byte[] byteData)
{
try
{
//发送数据给已连接的socket
mySocket.BeginSend(byteData, 0, byteData.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
asyncEvent.Reset();
}
catch (Exception ex)
{
NotifyCaller(NotifyEvents.SendError, ex.Message, byteData);
}
}
/// <summary>
/// 异步通知发送数据的主线程
/// </summary>
private void OnSend(IAsyncResult ar)
{
try
{
int sendLen = mySocket.EndSend(ar);
//通知发送成功和发送的数据长度
NotifyCaller(NotifyEvents.DataSent, sendLen.ToString());
}
catch (Exception ex)
{
NotifyCaller(NotifyEvents.SendError, ex.Message);
}
}
/// <summary>
/// 接收数据
/// </summary>
public void Receive()
{
try
{
asyncEvent.Reset();
mySocket.BeginReceive(bRcvd, 0, BUFFER_SIZE, SocketFlags.None, new AsyncCallback(OnReceive), null);
//Thread.Sleep(1000);
}
catch (Exception ex)
{
NotifyCaller(NotifyEvents.ReceiveError, ex.Message);
}
}
/// <summary>
/// 异步回传接收到的数据
/// </summary>
private void OnReceive(IAsyncResult ar)
{
try
{
int len = mySocket.EndReceive(ar);
receiveBuf = ASCIIEncoding.ASCII.GetString(bRcvd, 0, len);
//通知数据接收成功,并返回接收的数据给接收数据的线程
NotifyCaller(NotifyEvents.DataReceived, null, receiveBuf);
}
catch (Exception ex)
{
NotifyCaller(NotifyEvents.ReceiveError, ex.Message);
}
}
/// <summary>
/// 通知发送数据的线程
/// </summary>
private void NotifyCaller(NotifyEvents nEvent, string message, object data)
{
asyncEvent.Set();
//当没有绑定事件和已断开连接时不发送通知
if ((this.Notify != null) && !closing)
Notify(nEvent, message, data);
}
public void NotifyCaller(NotifyEvents nEvent, string message)
{
asyncEvent.Set();
//当没有绑定事件和已断开连接时不发送通知
if ((this.Notify != null) && !closing)
Notify(nEvent, message, null);
}
}
}
在UI中调用DeviceSoket
DeviceSocket=socket = new DeviceSocket();
socket.Notify += new NotifyEventHandler(socket_Notify);
//socket异步通知
void socket_Notify(NotifyEvents nEvent, string message, object data)
{
//返回给UI进程
this.Invoke(new NotifyEventHandler(OnSocketNofity),
new object[] { nEvent, message, data});
}
//在UI进程中显示Socket通知
private void OnSocketNofity(NotifyEvents eventType, string message, object data)
{
switch (eventType)
{
case NotifyEvents.DataReceived:
// 接收到数据:data
break;
case NotifyEvents.Connected:
//连接成功
break;
case NotifyEvents.ConnectError:
//连接错误
break;
case NotifyEvents.Disconnected:
//断开连接
break;
case NotifyEvents.SendError:
//发送数据错误
break;
case NotifyEvents.OtherError:
//其他错误
break;
}
}
连接成功后可以根据PDA扫描的数据动态生成打印的直接通过socket 发送给打印机就可以了。
类似:
byte[] buffer = commandBuilder.GetPrintCommands(barcode);
socket.Send(buffer);
Zebra打印指令
public byte[] ZebraCommands(string code)
{
int x, y;
StringBuilder str = new StringBuilder("^XA");
str.Append("^CW1,DOWNLD1");
str.Append("^CW2,DOWNLD2");
str.Append("^CW4,DOWNLD4");
str.Append("^COY,0^MMT^MD+0^JUS");
str.Append("^XZ");
str.Append("^XA");
str.Append("^PR3^FS");
//打条形码
str.Append("^BY3,1,0,20^FS");
x = 80;
y = 180;
str.Append(string.Format("^FT{0},{1}^BCN,120,N,N,N^FD{2}^FS", x, y, code));
str.Append("^CI0");
str.Append(string.Format("^FT{0},{1}^A0N,70,80^FD{2}^FS", x + 15, y + 75, code));
// ******设为中文打印 * ****************
str.Append("^CI14");
str.Append("^SEE:GB.DAT");
str.Append("^CW1,E:MSUNG24.FNT");
str.Append("^CI14");
str.Append(string.Format("^FT{0},{1}^A1N,70,80^FD{2}^FS", x + 15, y + 175, "中文测试A"));
//str.Append("^FT350,270^A1N,36,36^FD中文^FS");
//str.Append("^CI14");
str.Append("^CI0");
str.Append(string.Format("^FT{0},{1}^A0N,70,80^FD{2}^FS", x + 15, y + 275, "123"));
str.Append("^XZ");
return Encoding.Default.GetBytes(str.ToString());
}
Intermes打印指令
public byte[] IntermecPrintCommands()
{
StringBuilder str = new StringBuilder();
str.Append("\nN\n");
str.Append("A200,100,2,4,1,1,N,\"Example 1\"\n");
str.Append("A250,150,2,4,1,1,N,\"Example 2\"\n");
str.Append("A200,200,2,8,2,2,N,\"中文测试\"\n");
str.Append("B50,60,0,3,2,4,50,B,\"G100102010\"\n");
str.Append("P1\n");
return Encoding.Default.GetBytes(str.ToString());
}
1.判断是否打印成功
要看打印机是否支持,就是在打印成功后会有相应的指令发出,通过接收打印机的指令,就可以判断是否成功。
2.判断没有打印成功的数据,并在网络恢复是能自动打印。