打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
转:WinTab 开发说明

 

这是去年做的一个东西,老师当初打算叫一个研究生做一个画漫画的软件当作他的毕业设计,所以叫我写了这个程序,不过最后那个研究生跑去实习了(其实那个研究生很废的,怎么会有地方实习?我一直很费解)。这个程序主要功能是使用手写板画图。

下面是我自己写的开发说明:

WinTab基本函数说明

UINT WTInfo(UINT wCatgory, UINT nIndex, LPVOID lpOutput);

函数功能: 返回手写板全局信息,包括手写板坐标系,物理尺寸,性能,光标类型等。

参数 功能

wCatgory 指定返回哪种类型信息 0则返回最大类完整信息所需的缓冲区字节数

nIndex 指定 返回wCatgory类型信息中的哪些信息 0则返回上各参数指定类型的所有信息

lpOutput 指向一个缓冲区保存返回的信息。

返回值指定返回信息的字节数,如果要求返回的信息不被支持,返回0。如果没有物理设备 返回0

HCTX WTOpen(HWND hWnd, LPLOGCONTEXT lpLogCtx, BOOL fEnable)

函数功能:创建一个活动的设备环境,函数成功,应用程序开始接受手写板发来的事件消息,也可以使用返回的设备环境句柄查询消息或者调用其它函数

参数 功能

hWnd 指定拥有设备环境的窗口句柄(这个窗口接收手写板消息)

lpLogCtx 指向LOGCONTEXT数据结构,该结构定义手写板配置信息

fEnable 指定是否马上接收手写板消息,1 马上接收 0不接收

返回值 返回新的设备环境句柄,打开失败返回NULL

打开成功时 设备环境向窗口发送 WT_CTXOPEN消息

BOOL WTClose(HCTX hCtx)

关闭指定的设备环境

成功返回非0 同时窗口接收到 WT_CTXCLOSE消息。失败则返回0

BOOL WTPacket(HCTX hCtx, UINT wSerial, LPVOID lpPkt)

函数功能:将wSerial指定序号的消息包复制到lpPkt指定的缓冲区中,并将wSerial序号以及之前的消息包从消息队列中删除。

参数 功能

hCtx 指定获取消息的设备环境

wSerial 指定要取出的消息包的编号

lpPkt 指向接收消息包缓冲区的指针 大小最小为sizeof(PACKET) bytes

返回值: 消息找到并取出返回非0失败则返回0

int WTPacketsGet(HCTX hCtx, int cMaxPkts, LPVOID lpPkts)

函数功能: 从消息包队列中复制最多cMaxPkts个消息包保存到lpPkts指向的缓冲区中,并将这些消息冲消息包队列中移出

参数 功能

cMaxPkts 指定取出的最大的消息包的数量

lpPkts 指向接收消息包的缓冲区的指针 大小最小为 cMaxPkt*sizeof(PACKET) bytes

返回值: 返回取出的消息包的数量。

BOOL WTEnable(HCTX hCtx, BOOL fEnable)

函数功能: 指定hCtx设备环境是否想窗口发送消息(即是否工作)

返回值: 设置成功返回非0 设置失败返回0

常用数据结构

LOGCONTEXT

对设备环境进行说明时使用到 函数 WTInfo() WTOpen()中使用到

typedef struct tagLOGCONTEXT {

TCHAR lcName[LC_NAMELEN]; //设备名称 NULL结尾

UINT lcOptions; // 设备环境选项 CXO_MESSAGES指定设备环境发送WT_PACKET

//息给拥有这个设备环境的窗口

UINT lcStatus; // 指定当前设备环境的状态 可以使用 or 来连接多个选项

UINT lcLocks; //

UINT lcMsgBase; // 指定设备环境消息包的编号范围

UINT lcDevice;

UINT lcPktRate;

WTPKT lcPktData; // 指定消息包中返回的数据元素 请求不支持的数据元素

//会导致WTOpen()失败 使用or 进行连接

WTPKT lcPktMode; // 指定消息包中的数据元素返回的模式,在这里指定了,

//返回的就是相对模式,没有指定则返回绝对模式 如果这个

//参数里面出现了lcPktData中没有的元素则直接忽略

WTPKT lcMoveMask;

DWORD lcBtnDnMask;

DWORD lcBtnUpMask;

LONG lcInOrgX;

LONG lcInOrgY;

LONG lcInOrgZ;

LONG lcInExtX;

LONG lcInExtY;

LONG lcInExtZ;

LONG lcOutOrgX;

LONG lcOutOrgY;

LONG lcOutOrgZ;

LONG lcOutExtX;

LONG lcOutExtY;

LONG lcOutExtZ;

FIX32 lcSensX;

FIX32 lcSensY;

FIX32 lcSensZ;

BOOL lcSysMode;

int lcSysOrgX;

int lcSysOrgY;

int lcSysExtX;

int lcSysExtY;

FIX32 lcSysSensX;

FIX32 lcSysSensY;

} LOGCONTEXT;

消息包数据结构

typedef struct tagPACKET {

HCTX pkContext; // 指定产生消息的设备环境

UINT pkStatus; // 指定一系列的状态和错误情形

LONG pkTime; // 绝对模式 指定消息发出的系统时间。相对模式指定距离上一个消息的浩渺数

WTPKT pkChanged; // 指定哪些数据元素发生改变

UINT pkSerialNumber; // 包含设备环境给消息安排的序列号

UINT pkCursor; // 指定光标的类型

DWORD pkButtons; // 绝对模式包含当前按钮状态。相对模式低位包含

// 按钮编号,高位包含

//TBN_NONE(没有按钮状态发生改变)TBN_UP(按钮释放)TBN_DOWN(按钮压下) 之一

DWORD pkX; // 绝对模式 DWORD格式 包含XYZ坐标

DWORD pkY; // 相对模式LONG格式包含坐标的改变量

DWORD pkZ;

UINT pkNormalPressure;

UINT pkTangentPressure;

ORIENTATION pkOrientation;

ROTATION pkRotation;

} PACKET;

消息描述

WT_PACKET

wParam 包含消息的序列号

lParam 包含处理消息的设备环境的句柄

开发环境

visual c++ 6.0

使用MFC 框架

开发程序步骤

1 创建一个 MFC AppWizard[exe]工程(单文档,多文档随意。 本例为多文档),工程名为MFC_DEMO

2 MFC ClassWizard 中为类 CMFC_DOEMView 增加对OnCreate消息的处理函数。

3 在文件 DEMOVIEW.H中增加以下内容

// MFC_DEMOView.h : interface of the CMFC_DEMOView class

//

/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_MFC_DEMOVIEW_H__B7D0AFEE_20A7_11D2_B1B0_0040053C38B6__INCLUDED_)

#define AFX_MFC_DEMOVIEW_H__B7D0AFEE_20A7_11D2_B1B0_0040053C38B6__INCLUDED_

#include <afxmt.h>

#include <windows.h>

#include <wintab.h>

#include "point.h"

using namespace std;

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

class CMFC_DEMOView : public CView

{

CMutex *pWTMutex;

POINT csr;

HCTX hCtx;

unsigned prev_pkButtons;

LOGCONTEXT lc;

protected: // create from serialization only

CMFC_DEMOView();

DECLARE_DYNCREATE(CMFC_DEMOView)

// Attributes

public:

CMFC_DEMODoc* GetDocument();

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CMFC_DEMOView)

public:

virtual void OnDraw(CDC* pDC); // overridden to draw this view

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

protected:

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CMFC_DEMOView();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

afx_msg LRESULT OnWTPacket(WPARAM, LPARAM);

protected:

// Generated message map functions

protected:

//{{AFX_MSG(CMFC_DEMOView)

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

afx_msg void OnCancelMode();

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

#ifndef _DEBUG // debug version in MFC_DEMOView.cpp

inline CMFC_DEMODoc* CMFC_DEMOView::GetDocument()

{ return (CMFC_DEMODoc*)m_pDocument; }

#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MFC_DEMOVIEW_H__B7D0AFEE_20A7_11D2_B1B0_0040053C38B6__INCLUDED_)

4 MFC_DEMOView.cpp 文件中进行如下修改

// MFC_DEMOView.cpp : implementation of the CMFC_DEMOView class

//

#include "stdafx.h"

#include "MFC_DEMO.h"

#include "DEMODoc.h"

#include "DEMOView.h"

#include <wintab.h>

#define PACKETDATA PK_X | PK_Y | PK_BUTTONS //定义WT_PACKET消息格式

#define PACKETMODE 0 //定义消息模式

#include <pktdef.h> //包含消息定义头文件

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMOView

IMPLEMENT_DYNCREATE(CMFC_DEMOView, CView)

BEGIN_MESSAGE_MAP(CMFC_DEMOView, CView)

ON_MESSAGE(WT_PACKET, OnWTPacket) //定义WT_PACKET消息

//处理函数为OnWTPacket

//{{AFX_MSG_MAP(CMFC_DEMOView)

ON_WM_CREATE()

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMOView construction/destruction

CMFC_DEMOView::CMFC_DEMOView()

{

csr.x = -1;

prev_pkButtons = 0;

pWTMutex = new CMutex( TRUE, NULL, NULL );

hCtx = 0;

}

CMFC_DEMOView::~CMFC_DEMOView()

{

delete pWTMutex;

if( hCtx )

WTClose( hCtx );

}

BOOL CMFC_DEMOView::PreCreateWindow(CREATESTRUCT& cs)

{

return CView::PreCreateWindow(cs);

}

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMOView drawing

void CMFC_DEMOView::OnDraw(CDC* pDC)

{

CMFC_DEMODoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

csr.x = -1;

//对之前保存的线条进行渲染

list<point> * lst = pDoc->GetLst();

list<point>::iterator i = lst->begin();

while( i != lst->end() ) {

if( i->x >= 0 )

pDC->LineTo(i->x,i->y);

else

pDC->MoveTo(abs(i->x),abs(i->y));

i++;

}

}

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMOView diagnostics

#ifdef _DEBUG

void CMFC_DEMOView::AssertValid() const

{

CView::AssertValid();

}

void CMFC_DEMOView::Dump(CDumpContext& dc) const

{

CView::Dump(dc);

}

CMFC_DEMODoc* CMFC_DEMOView::GetDocument() // non-debug version is inline

{

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFC_DEMODoc)));

return (CMFC_DEMODoc*)m_pDocument;

}

#endif //_DEBUG

//定义消息处理函数

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMOView message handlers

LRESULT CMFC_DEMOView::OnWTPacket(WPARAM wSerial, LPARAM hCtx)

{

// Read the packet

PACKET pkt;

WTPacket( (HCTX)hCtx, wSerial, &pkt ); //获取消息包

// Process packets in order, one at a time

CSingleLock lock( pWTMutex, TRUE ); //锁定,一次只能进行处理一个消息

CDC *pDC = GetDC();

// Get window size

RECT window_rect;

GetWindowRect( &window_rect );

POINT size;

size.x = window_rect.right - window_rect.left;

size.y = window_rect.bottom - window_rect.top;

// Erase the old cursor

if( csr.x >= 0 ) {

CRgn r;

r.CreateRectRgn( csr.x - 2, csr.y - 2, csr.x + 2, csr.y + 2 );

pDC->InvertRgn( &r );

}

csr.x = (size.x * pkt.pkX) / lc.lcInExtX;

csr.y = size.y - (size.y * pkt.pkY) / lc.lcInExtY;

if( pkt.pkButtons ) {

CMFC_DEMODoc *pDoc = GetDocument();

list<point> * lst = pDoc->GetLst();

if( prev_pkButtons ) {

list<point>::iterator i = lst->end();

i--;

pDC->MoveTo(abs(i->x),abs(i->y));

lst->push_back(csr);

pDC->LineTo(csr);

} else {

POINT pt;

pt.x = -csr.x;

pt.y = -csr.y;

lst->push_back(pt);

}

}

prev_pkButtons = pkt.pkButtons;

// Draw a new cursor

CRgn r;

r.CreateRectRgn( csr.x - 2, csr.y - 2, csr.x + 2, csr.y + 2 );

pDC->InvertRgn( &r );

ReleaseDC( pDC );

return TRUE;

}

OnCreate函数中进行手写板的初始化

int CMFC_DEMOView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CView::OnCreate(lpCreateStruct) == -1)

return -1;

// Open a Wintab context

// Get default context information

WTInfo( WTI_DEFCONTEXT, 0, &lc );

// Open the context

//设定手写板消息格式

lc.lcPktData = PACKETDATA;

//设定手写板消息模式

lc.lcPktMode = PACKETMODE;

//设定手写板,要求其发送WT_PACKET消息

lc.lcOptions = CXO_MESSAGES;

//打开手写板设备环境

//hCtx = WTOpen( m_hWnd, &lc, TRUE );

hCtx = WTOpen( m_hWnd, &lc, TRUE );

return 0;

}

5DEMODoc.h 文件中增加以下红色内容

// MFC_DEMODoc.h : interface of the CMFC_DEMODoc class

//

/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_MFC_DEMODOC_H__B7D0AFEC_20A7_11D2_B1B0_0040053C38B6__INCLUDED_)

#define AFX_MFC_DEMODOC_H__B7D0AFEC_20A7_11D2_B1B0_0040053C38B6__INCLUDED_

#if _MSC_VER >= 1000

#pragma once

#endif // _MSC_VER >= 1000

#include <list>

#include "point.H"

using namespace std;

class CMFC_DEMODoc : public CDocument

{

list<point> * pt_lst;

protected: // create from serialization only

CMFC_DEMODoc();

DECLARE_DYNCREATE(CMFC_DEMODoc)

// Attributes

public:

list<point> * GetLst( void ) { return pt_lst; };

// Operations

public:

// Overrides

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CMFC_DEMODoc)

public:

virtual BOOL OnNewDocument();

virtual void Serialize(CArchive& ar);

//}}AFX_VIRTUAL

// Implementation

public:

virtual ~CMFC_DEMODoc();

#ifdef _DEBUG

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

#endif

protected:

// Generated message map functions

protected:

//{{AFX_MSG(CMFC_DEMODoc)

// NOTE - the ClassWizard will add and remove member functions here.

// DO NOT EDIT what you see in these blocks of generated code !

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MFC_DEMODOC_H__B7D0AFEC_20A7_11D2_B1B0_0040053C38B6__INCLUDED_)

6DEMODoc.cpp 文件中进行如下修改

// MFC_DEMODoc.cpp : implementation of the CMFC_DEMODoc class

//

#include "stdafx.h"

#include "MFC_DEMO.h"

#include "point.h"

#include "DEMODoc.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMODoc

IMPLEMENT_DYNCREATE(CMFC_DEMODoc, CDocument)

BEGIN_MESSAGE_MAP(CMFC_DEMODoc, CDocument)

//{{AFX_MSG_MAP(CMFC_DEMODoc)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMODoc construction/destruction

CMFC_DEMODoc::CMFC_DEMODoc()

{

pt_lst = new list<point>;

}

CMFC_DEMODoc::~CMFC_DEMODoc()

{

delete pt_lst;

}

BOOL CMFC_DEMODoc::OnNewDocument()

{

if (!CDocument::OnNewDocument())

return FALSE;

// Clear the point list

delete pt_lst;

pt_lst = new list<point>;

return TRUE;

}

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMODoc serialization

void CMFC_DEMODoc::Serialize(CArchive& ar)

{

if (ar.IsStoring())

{

// TODO: add storing code here

}

else

{

// TODO: add loading code here

}

}

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMODoc diagnostics

#ifdef _DEBUG

void CMFC_DEMODoc::AssertValid() const

{

CDocument::AssertValid();

}

void CMFC_DEMODoc::Dump(CDumpContext& dc) const

{

CDocument::Dump(dc);

}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////

// CMFC_DEMODoc commands

7 Point.h 文件内容

#ifndef POINT_H

#define POINT_H

class point

{

public:

long x, y;

point( void ) { ; };

point( point const & p ) { x = p.x; y = p.y; };

point( POINT const & p ) { x = p.x; y = p.y; };

bool operator < ( point const & r ) const { return x < r.x || (x == r.x && y < r.y); };

bool operator > ( point const & r ) const { return !(*this < r); };

bool operator == ( point const & r ) const { return x == r.x && y == r.y; };

bool operator != ( point const & r ) const { return !(*this == r); };

};

#endif POINT_H

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
在函数前加Afx和::以及函数后加const的意义
·教程:轻松玩转MFC文档视图架构编程
How Message Maps Work
消息映射和命令传递(转)
MFC COM 笔记
从VC6到VC9移植代码问题总结
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服