📄 handwritingview.cpp
字号:
// HandwritingView.cpp : implementation of the CHandwritingView class
//
#include "stdafx.h"
#include "Handwriting.h"
#include <math.h>
#include "HandwritingDoc.h"
#include "HandwritingView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CHandwritingView
IMPLEMENT_DYNCREATE(CHandwritingView, CView)
BEGIN_MESSAGE_MAP(CHandwritingView, CView)
//{{AFX_MSG_MAP(CHandwritingView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_btnCoordinate, OnbtnCoordinate)
ON_COMMAND(ID_btnPlay, OnbtnPlay)
ON_COMMAND(ID_btnRecord, OnbtnRecord)
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_btnOpenBmp, OnbtnOpenBmp)
ON_COMMAND(ID_btnSample, OnbtnSample)
ON_UPDATE_COMMAND_UI(ID_btnCoordinate, OnUpdatebtnCoordinate)
ON_COMMAND(ID_btnEnd, OnbtnEnd)
ON_UPDATE_COMMAND_UI(ID_btnEnd, OnUpdatebtnEnd)
ON_UPDATE_COMMAND_UI(ID_btnOpenBmp, OnUpdatebtnOpenBmp)
ON_UPDATE_COMMAND_UI(ID_btnPlay, OnUpdatebtnPlay)
ON_UPDATE_COMMAND_UI(ID_btnRecord, OnUpdatebtnRecord)
ON_UPDATE_COMMAND_UI(ID_btnSample, OnUpdatebtnSample)
ON_COMMAND(IDC_btnRefresh, OnbtnRefresh)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHandwritingView construction/destruction
///////////////////////////////////////
//构造函数:置初值
//
CHandwritingView::CHandwritingView()
{
sOperated=sReady;
Strokes=NULL;
pCurrentStroke=NULL;
pBuff=NULL;
uLines=0;
Stepth=0;
bLining=FALSE;
m_hCursor=AfxGetApp()->LoadStandardCursor (IDC_CROSS);
m_pDC=NULL;
bmp=true;
bErase=false;
}
CHandwritingView::~CHandwritingView()
{
}
BOOL CHandwritingView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CHandwritingView drawing
void CHandwritingView::OnDraw(CDC* pDC)
{
CHandwritingDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//初始化或者显示字体
//
if(!m_pDC)
Init();
Draw();
}
/////////////////////////////////////////////////////////////////////////////
// CHandwritingView printing
BOOL CHandwritingView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
/////////////////////////////////////////////////////////////////////////////
// CHandwritingView diagnostics
#ifdef _DEBUG
void CHandwritingView::AssertValid() const
{
CView::AssertValid();
}
void CHandwritingView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CHandwritingDoc* CHandwritingView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHandwritingDoc)));
return (CHandwritingDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CHandwritingView message handlers
///////////////////////////////////////////////////////////////
//鼠标左按钮按下消息函数:启动通过沿字符笔划画线来进行笔划录制
//的过程
//
void CHandwritingView::OnLButtonDown(UINT nFlags, CPoint point)
{
RECT rect;
//设置画线的起点
//
if(sOperated==sRecording)
{
Stepth++;
if(Stepth%3==1)
oneStroke.Speed =1;
m_pOld=point;
m_pOrigin=point;
SetCapture();
bLining=true;
GetClientRect(&rect);
ClientToScreen(&rect);
ClipCursor(&rect);
}
CView::OnLButtonDown(nFlags, point);
}
///////////////////////////////////////////////////////////////
//鼠标左按钮释放消息函数:一次画线结束,如果当次画线类型是指定
//笔划轨迹(三步循环周期中的第一步,即Stepth的值为3的倍数余1)或者
//指定笔划起始宽度(三步循环周期中的第二步,即Stepth的值为3的
//倍数余2),则保留相应数据,并准备继续画线;若为指定终端笔划
//宽度(三步循环周期中的第三步,即Stepth的值为3的倍数),则
//保存数据并生成一个新的笔划节点插入到字符笔划链表中。
//
void CHandwritingView::OnLButtonUp(UINT nFlags, CPoint point)
{
UINT tmp;
RECT rect,rectTip;
double dWidth;
UINT uWidth;
STROKES *pTmp;
//根据步骤索引值决定进行存储当前笔划等操作
//
m_pDC->SetTextColor(RGB(0,0,0));
if(bLining)
{
dWidth=sqrt((m_pOld.x-m_pOrigin.x)*(m_pOld.x-m_pOrigin.x)+(m_pOld.y-m_pOrigin.y)*(m_pOld.y-m_pOrigin.y));
uWidth=dWidth;
uWidth=uWidth?uWidth:1;
GetClientRect(&rect);
rectTip=rect;
rectTip.top=rect.bottom -20;
tmp=Stepth%3;
switch(tmp)
{
//完成一个笔划所有属性的指定,则生成笔划节点并插入字符链表
//
case 0:oneStroke.Width2=uWidth;
pTmp= new _STROKES;
if(pTmp==NULL)
{
MessageBox( "不能获取所需要的内存", _T(""),MB_OK );
exit(0);
}
pTmp->Stroke.x1=oneStroke.x1 ;
pTmp->Stroke.y1=oneStroke.y1 ;
pTmp->Stroke.x2=oneStroke.x2 ;
pTmp->Stroke.y2=oneStroke.y2 ;
pTmp->Stroke.x1=oneStroke.x1 ;
pTmp->Stroke.Width1=oneStroke.Width1;
pTmp->Stroke.Width2=oneStroke.Width2;
pTmp->Stroke.Speed=oneStroke.Speed;
pTmp->pStroke =NULL;
//字符节点链接到字符笔划单链表中
if(pCurrentStroke)
{
pCurrentStroke->pStroke=pTmp;
pCurrentStroke=pTmp;
}
if(Strokes==NULL)
{
Strokes=pTmp;
pCurrentStroke=pTmp;
}
m_pDC->LineTo (m_pOrigin);
m_pDC->TextOut (rectTip.left,rectTip.top,"操作提示:请指定下一个笔划线段...... ");
break;
//完成一个笔划轨迹的指定
//
case 1:oneStroke.x1=m_pOrigin.x;
oneStroke.y1=m_pOrigin.y;
oneStroke.x2=m_pOld.x;
oneStroke.y2=m_pOld.y;
m_pDC->TextOut (rectTip.left,rectTip.top,"操作提示:请指定笔划线段起始端宽度...... ");
break;
//完成一个笔划起始宽度的指定
//
case 2:oneStroke.Width1=uWidth;
m_pDC->LineTo (m_pOrigin);
m_pDC->TextOut (rectTip.left,rectTip.top,"操作提示:请指定笔划线段终止端宽度...... ");
break;
default:;
}
//释放鼠标和光标
bLining=FALSE;
ReleaseCapture();
ClipCursor(NULL);
}
CView::OnLButtonUp(nFlags, point);
}
/////////////////////////////////////////////////////////////////
//鼠标右按钮单击消息函数:在一个笔划的录制过程中,每单击一次,笔
//划绘制速度提高一个因子
//
void CHandwritingView::OnRButtonDown(UINT nFlags, CPoint point)
{
//为当前笔划指定绘制速度因子
//
oneStroke.Speed++;
CView::OnRButtonDown(nFlags, point);
}
////////////////////////////////////////////
//数据显示消息:将当前录制的字符笔划属性数据
//显示出来
//
void CHandwritingView::OnbtnCoordinate()
{
RECT rect;
int x,y;
int Num;
char x1[5],y1[5],x2[5],y2[5],w1[5],w2[5],s[5],No[5];
CString strResult,strStroke(" ");
//分四列依笔划定义结构的顺序显示当前录制的字符的笔划数据
//
bErase=false;
GetClientRect(&rect);
x=0;
Num=0;
y=rect.bottom/2;
y=0;
STROKES *p=Strokes;
while(p)
{
//显示数据
//
_itoa(p->Stroke.x1 ,x1,10);
_itoa(p->Stroke.y1 ,y1,10);
_itoa(p->Stroke.x2 ,x2,10);
_itoa(p->Stroke.y2 ,y2,10);
_itoa(p->Stroke.Width1 ,w1,10);
_itoa(p->Stroke.Width2,w2,10);
_itoa(p->Stroke.Speed,s,10);
_itoa(Num,No,10);
strResult=strStroke+No+":"+x1+","+y1+"-"+x2+","+y2+";"+w1+"-"+w2+";"+s;
m_pDC->TextOut (x,y,strResult);
//调整下一个数据显示位置
Num++;
if(Num%4)
{
x+=rect.right/4;
}
else
{
x=0;
y+=15;
}
p=p->pStroke;
}
}
/////////////////////////////////////////////////////////
//手写展示命令函数:启动动态显示当前录制的手写字符的过程
//
void CHandwritingView::OnbtnPlay()
{
//播放录制的字符
//
bErase=true;
sOperated=sPlaying;
Writing(Strokes,1,5,false,1,10,10,m_pDC,false);
bErase=false;
bmp=false;
sOperated=sPlayed;
}
/////////////////////////////////////////////////
//录制按钮函数:启动字符录制过程
//
void CHandwritingView::OnbtnRecord()
{
//启动字符笔划的录制过程
//
if(m_pDC==NULL)
Init();
sOperated=sRecording;
Stepth=0;
//删除存在的字符笔划链表
DeleteStrokes();
}
//////////////////////////////////////////////////////////////
//鼠标移动消息函数:动态显示或者擦除鼠标的画线
//
void CHandwritingView::OnMouseMove(UINT nFlags, CPoint point)
{
//消除或者显示笔划及其宽度轨迹
//
if(bLining)
{
SetCursor(m_hCursor);
m_pDC->SetROP2 (R2_NOT);
m_pDC->MoveTo (m_pOrigin);
m_pDC->LineTo (m_pOld);
m_pDC->MoveTo (m_pOrigin);
m_pDC->LineTo (point);
m_pOld=point;
}
CView::OnMouseMove(nFlags, point);
}
///////////////////////////////
//初始函数
//
void CHandwritingView::Init()
{
m_pDC=new CClientDC(this);
sOperated=sReady;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//手写字符动态显示函数:遍历字符链表的笔划,并根据笔划信息
//将笔划直线段象素化,然后根据笔划的宽度创建相应的画笔,按
//增量绘制直线的方式逐个绘制象素,并根据速度因子进行必要延
//时。
//
void CHandwritingView::Writing(STROKES *Strokes, BYTE Style, BYTE Interval, bool Fast, BYTE Ratio,int x0, int y0,CClientDC *dc,bool bFlash)
{
int dx,dy;
int sx,sy;
int t1,t2,e;
int x1,y1,x2,y2;
int x,y;
int i;
BYTE Width1,Width2;
BYTE bStyle,bRatio;
int iWidth;
float dWidth;
DWORD Delay,Upper,Now;
CPen Pen;
STROKES *pStroke,*pTemp;
//根据指定的各种属性实际逐象素绘制手写字符
//
dc->SetROP2 (R2_COPYPEN);
Upper=Fast?100000:1000000;
Upper=bFlash?0:Upper;
bStyle=Style%10?Style%10:1;
bRatio=Ratio%10?Ratio%10:1;
pStroke=Strokes;
//展示笔划书写过程
//
while(pStroke!=NULL)
{
//字符放大ratio倍
//
x1=pStroke->Stroke.x1*bRatio+x0 ;
y1=pStroke->Stroke.y1*bRatio+y0 ;
x2=pStroke->Stroke.x2*bRatio+x0 ;
y2=pStroke->Stroke.y2*bRatio+y0;
Width1=pStroke->Stroke.Width1 *bStyle;
Width2=pStroke->Stroke.Width2 *bStyle;
//笔划段象素化
//
dx=abs(x2-x1);
dy=abs(y2-y1);
sx=-1;
if(x2>x1)
sx=1;
sy=-1;
if(y2>y1)
sy=1;
x=x1;
y=y1;
dc->MoveTo (x,y);
if(dx>dy)
{
t1=2*dy;
t2=2*(dy-dx);
e=2*dy-dx;
dWidth=1.0*(Width2-Width1)/dx;
for(i=0;i<dx;i++)
{
//创建相应宽度的笔
//
iWidth=Width1+dWidth*i;
Pen.CreatePen (PS_SOLID,iWidth,RGB(0,0,0));
dc->SelectObject(&Pen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -