# 拓思德点阵笔
引用
```csharp
using TStudyDigitalPen.HID;
```
代码
```csharp
#region 拓思德点阵笔
#region 值初始化
// 不同尺寸点阵纸点阵宽高尺寸计算方法为:纸张物理尺寸(毫米)/0.3 *8,详见 开发必读.pdf 文档
///
/// A4点阵纸点阵宽度
///
private const int A4_WIDTH = 5600;
///
/// A4点阵纸点阵高度
///
private const int A4_HEIGHT = 7920;
/////
///// 画板
/////
//private Graphics graphics;
///
/// 笔画坐标数组
///
//private List stroke;
///
/// 笔序列号
///
private string penSerial;
///
/// 笔是否在点
///
private bool isPenDown;
//当前点阵地址
private string currentPageSerial = string.Empty;
//不同点阵地址对应的笔迹绘制图片,用于实现在不同点阵地址书写切换时,显示书写内容自动切换
//本例图片放在内存中存储,对于大量或者需要在多个点阵地址对应图片进行切换演示,建议将图片存储到文件,以免内存溢出
private Dictionary pagesDic = new Dictionary();
#endregion 值初始化
public void InitTSDPen()
{
//stroke = new List();
//获取点阵笔实例,并绑定点阵笔事件
//将授权文件内容传入,获取点阵笔对象实例
APP.digitalPen = DigitalPenHID.GetInstance(certificates.MyLicense.Bytes);
//绑定笔连接事件
APP.digitalPen.PenConnected += OnTSDPenConnect;
//绑定笔断开事件
APP.digitalPen.PenDisconnect += OnTSDPenDisconnect;
//绑定笔书写输出坐标事件
APP.digitalPen.PenCoordinate += OnTSDPenCoordinate;
//绑定抬笔事件
APP.digitalPen.PenUp += OnTSDPenUp;
//绑定落笔事件
APP.digitalPen.PenDown += OnTSDPenDown;
APP.digitalPen.PenBatteryCapacity += OnTSDBatteryCapacity;
APP.digitalPen.PenMemoryFillLevel += OnTSDMemoryFillLevel;
//完成初始化点阵笔,开始与点阵笔通信
ERROR_CODE ER = APP.digitalPen.Start();
//启动接收笔数据,完成初始化工作
ERROR_CODE rc = APP.digitalPen.Start();
//判断是否成功
if (ER != ERROR_CODE.ERROR_OK)
{
MessageWindow.Show("初始化失败,授权过期,返回值:" + ER.ToString());
}
}
///
/// 落笔
///
///
/// 时间戳,1970年1月1日到现在的总毫秒数
///
///
/// 点阵笔序列号
///
///
/// 点阵笔型号编号
///
private void OnTSDPenDown(ulong time, string penSerial, int penType)
{
if (CheckAccess())
{
Action action = new Action(OnTSDPenDown);
Dispatcher.Invoke(action, new object[] { time, penSerial, penType });
}
else
{
isPenDown = true;
}
}
///
/// 抬笔
///
///
/// 时间戳,1970年1月1日到现在的总毫秒数
///
///
/// 点阵笔序列号
///
///
/// 点阵笔型号编号
///
private void OnTSDPenUp(ulong time, string penSerial, int penType)
{
if (CheckAccess())
{
Action action = new Action(OnTSDPenUp);
Dispatcher.Invoke(action, new object[] { time, penSerial, penType });
}
else
{
isPenDown = false;
APP.PenSerial = penSerial;
}
if (APP.PageContextData.currpage > 0)
{
Dispatcher.Invoke(new Action(() =>
{
myblackboard.changepages(0, 0, true, Color, PenSize, APP.PageContextData.currpage - 1, 0);
}));
}
}
///
/// 笔断开
///
///
/// 时间戳,1970年1月1日到现在的总毫秒数
///
///
/// 点阵笔序列号
///
///
/// 点阵笔型号编号
///
private void OnTSDPenDisconnect(ulong time, string penSerial, int penType)
{
if (CheckAccess())
{
Action action = new Action(OnTSDPenDisconnect);
Dispatcher.Invoke(action, new object[] { time, penSerial, penType });
}
else
{
APP.PenSerial = penSerial;
APP.PenStatus = false;
UpdateDevStatus();
}
}
///
/// 笔连接
///
///
/// 时间戳,1970年1月1日到现在的总毫秒数
///
///
/// 点阵笔序列号
///
///
/// 点阵笔型号编号
///
private void OnTSDPenConnect(ulong time, string penSerial, int penType)
{
if (CheckAccess())
{
Action action = new Action(OnTSDPenConnect);
Dispatcher.Invoke(action, new object[] { time, penSerial, penType });
}
else
{
APP.PenSerial = penSerial;
APP.PenStatus = true;
this.penSerial = penSerial;
//连接后,在获取笔数据前,可以清除笔内的历史数据
//APP.digitalPen.ClearMemory(penSerial);
//开始接收笔数据
APP.digitalPen.GetPenData(penSerial);
UpdateDevStatus();
}
}
///
/// 电池电量
///
///
///
///
///
///
///
///
///
private void OnTSDBatteryCapacity(ulong time, string penSerial, int penType, byte capacity)
{
if (CheckAccess())
{
Action action = new Action(OnTSDBatteryCapacity);
Dispatcher.Invoke(action, new object[] { time, penSerial, penType, capacity });
}
else
{
//System.Windows.MessageWindow.Show("电池电量:" + capacity.ToString());
}
}
///
/// 已用存储
///
///
///
///
///
///
///
///
///
private void OnTSDMemoryFillLevel(ulong time, string penSerial, int penType, byte fillLevel)
{
if (CheckAccess())
{
Action action = new Action(OnTSDMemoryFillLevel);
Dispatcher.Invoke(action, new object[] { time, penSerial, penType, fillLevel });
}
else
{
}
}
///
/// 笔书写,收到坐标
///
///
/// 时间戳,1970年1月1日到现在的总毫秒数
///
///
/// 点阵笔序列号
///
///
/// 点阵笔型号编号
///
///
/// 点阵地址
///
///
/// x坐标
///
///
/// y坐标
///
///
/// 压力值
///
private void OnTSDPenCoordinate(ulong time, string penSerial, int penType, string pageSerial, int cx, int cy, byte force)
{
if (CheckAccess())
{
Action ac = new Action(OnTSDPenCoordinate);
Dispatcher.Invoke(ac, new object[] { time, pageSerial, penType, pageSerial, cx, cy, force });
}
else
{
//判断是否是落笔后输出的坐标,在设置悬浮模式下,落笔前的悬浮坐标不绘制
if (!isPenDown)
{
return;
}
//stroke.Add(new System.Drawing.Point(cx, cy));
double PropW = blackboard_canvas.ActualWidth / A4_WIDTH;
double PropH = blackboard_canvas.ActualHeight / A4_HEIGHT;
//点
double tempX = cx * PropW;
double tempY = cy * PropH;
//pageSerial //点阵IP地址 与打印的页面关联
if (APP.PageContextData.currpage > 0)
{
Dispatcher.Invoke(new Action(() =>
{
float Pressure = force / 100f;
//myblackboard.changepages(testX, testY,false);
myblackboard.changepages(tempX, tempY, false, Color, PenSize, APP.PageContextData.currpage - 1, Pressure);
#region 设置滚动条位置
//点在显示页面上方
if (tempY < ScroMain.VerticalOffset)
{
//滚动条当前位置
double RollCurrentLocation = ScroMain.VerticalOffset;
//向上滚动至以点为中心需要滚动的距离
double UpRoll = (RollCurrentLocation - tempY) + (ScroMain.ActualHeight / 2);
//如果小于0则等于0
double RollLocation = RollCurrentLocation - UpRoll;
if (RollLocation < 0)
{
RollLocation = 0;
}
////滚动条实际偏移量
//double RollOffset = RollCurrentLocation - RollLocation;
ScroMain.ScrollToVerticalOffset(RollLocation);
}
//点在显示页面下方
if (tempY > ScroMain.VerticalOffset + ScroMain.ActualHeight)
{
//滚动条当前位置
double RollCurrentLocation = ScroMain.VerticalOffset;
//向下滚动至以点为中心需要滚动的距离
double DownRoll = (tempY - RollCurrentLocation) - (ScroMain.ActualHeight / 2);
//如果小于0则等于0
double RollLocation = RollCurrentLocation + DownRoll;
//滚动条最大滚动值
double ScrollbarMaxNum = GridM.ActualHeight - ScroMain.ActualHeight;
if (RollLocation > ScrollbarMaxNum)
{
RollLocation = ScrollbarMaxNum;
}
////滚动条实际偏移量
//double RollOffset = RollLocation-RollCurrentLocation;
ScroMain.ScrollToVerticalOffset(RollLocation);
}
#endregion 设置滚动条位置
if (tempX > 0 && tempY > 0)
{
//System.Windows.Point getP = blackboard_canvas.PointToScreen(new System.Windows.Point(testX, testY));
System.Windows.Point getP = ScroMain.PointToScreen(new System.Windows.Point(tempX, tempY - ScroMain.VerticalOffset));
SetCursorPos((int)getP.X, (int)getP.Y);
}
}));
}
}
}
///
/// 清空笔内存储
///
public void ClearPenStorage()
{
if (!string.IsNullOrEmpty(penSerial))
{
APP.digitalPen.ClearMemory(penSerial);
}
}
///
/// 获取剩余电量
///
public void GetPenElectricityQuantity()
{
if (!string.IsNullOrEmpty(penSerial))
{
APP.digitalPen.GetBatteryCapacity(penSerial);
}
}
///
/// 获取存储空间
///
public void GetUsedStorage()
{
if (!string.IsNullOrEmpty(penSerial))
{
APP.digitalPen.GetMemoryFillLevel(penSerial);
}
}
///
/// 开启悬浮
///
public void 开启悬浮()
{
if (!string.IsNullOrEmpty(penSerial))
{
APP.digitalPen.SetPenHoverMode(true, penSerial);
}
}
///
/// 关闭悬浮
///
public void 关闭悬浮()
{
if (!string.IsNullOrEmpty(penSerial))
{
APP.digitalPen.SetPenHoverMode(false, penSerial);
}
}
///
/// 引用user32.dll动态链接库(windows api), 使用库中定义 API:SetCursorPos 设置光标位置
///
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetCursorPos(int x, int y);
#endregion 拓思德点阵笔
```