📄 patterndlg.cpp
字号:
// patternDlg.cpp : implementation file
//
#include "stdafx.h"
#include "pattern.h"
#include "patternDlg.h"
#include "Afxwin.h"
#include "Afxdlgs.h"
#include "winuser.h"
#include "Store.h"
#include <stdio.h>
//#define _MBCS
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include<windows.h>
#include<math.h>
#define Startx 30
#define Starty 190
#define wid 192
#define lon 192
#define yu 3 //2 area
#define yu1 5 //dou dong
#define yu2 4
int num,Time;
int xmax,ymax,xmin,ymin; //随时纪录书写过程中的书写范围
//存储书写笔迹的坐标序列,按笔划存储,每个笔划最多300个点
//每个字最多15个笔划
struct
{
int x;
int y;
}store[15][300];
//备份的序列
struct
{
int x;
int y;
}storeback[15][300];
struct
{
int total;//总的笔划数
char zifu[2];//代表字符
int dian[15];//每个笔划的点数
struct{
int relate;//相对前点特征
int region;//全局位置特征
int arc;//过渡带特征
}detail[15][20];//15个笔划上的特征点,每个笔划20个特征点
}tez[2002];
struct
{
int total;
int dian[15];
struct
{
int relate;
int region;
int arc;
}detail[15][20];
}test;//意义同上,为测试点的结构
int queue[50];
int queue1[40];
int zong;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPatternDlg dialog
CPatternDlg::CPatternDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPatternDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPatternDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPatternDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPatternDlg)
DDX_Control(pDX, IDC_EDIT2, m_edit2);
DDX_Control(pDX, IDC_EDIT1, m_edit1);
DDX_Control(pDX, IDC_BUTTON4, m_escape);
DDX_Control(pDX, IDC_BUTTON3, m_clear);
DDX_Control(pDX, IDC_BUTTON1, m_recog);
DDX_Control(pDX, IDC_BUTTON2, m_study);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPatternDlg, CDialog)
//{{AFX_MSG_MAP(CPatternDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON4, OnEsp)
ON_BN_CLICKED(IDC_BUTTON1, OnRecog)
ON_WM_MOUSEMOVE()
ON_BN_CLICKED(IDC_BUTTON3, OnClear)
ON_BN_CLICKED(IDC_BUTTON2, OnStudy)
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_COMMAND(ID_EXIT_MENU, OnExitMenu)
ON_COMMAND(ID_ABOUT_MENU, OnAboutMenu)
ON_COMMAND(ID_SAVE_MENU, OnSaveMenu1)
ON_COMMAND(ID_OPEN_MENU, OnOpenMenu)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPatternDlg message handlers
BOOL CPatternDlg::OnInitDialog()
{
CFile cf;
CDialog::OnInitDialog();
mouseDown=0;
int i,j,k;
//将每个笔划上坐标初始化为空
for(i=0;i<15;i++)
{
for(j=0;j<300;j++)
{
store[i][j].x=-1;
store[i][j].y=-1;
}
}
for(i=0;i<15;i++)
{
for(j=0;j<300;j++)
{
storeback[i][j].x=-1;
storeback[i][j].y=-1;
}
}
for(i=0;i<10;i++)
{
tez[i].total=-1;
for(j=0;j<15;j++)
tez[i].dian[j]=-1;
for(j=0;j<15;j++)
{
for(k=0;k<20;k++)
{
tez[i].detail[j][k].relate=0;
tez[i].detail[j][k].arc=0;
tez[i].detail[j][k].region=0;
}
}
}
Time=0;
num=0;
zong=-1;//tez下标
xmax=0;
ymax=0;
xmin=31;
ymin=31;
for(i=0;i<50;i++)
queue[i]=-1;
for(i=0;i<40;i++)
queue1[i]=-1;
test.total=-1;
for(j=0;j<15;j++)
test.dian[j]=-1;
for(j=0;j<15;j++)
{
for(k=0;k<20;k++)
{
test.detail[j][k].relate=0;
test.detail[j][k].arc=0;
test.detail[j][k].region=0;
}
}
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
if(cf.Open("mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==NULL){
AfxMessageBox("打开文件失败,\n您最好退出程序");}
return TRUE; // return TRUE unless you set the focus to a control
}
void CPatternDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CPatternDlg::OnPaint()
{
CPaintDC dc(this);
HBRUSH hB;
hB=CreateSolidBrush(RGB(255,255,255));
SelectObject(dc,hB);
Rectangle(dc,Startx,Starty,Startx+wid-1,Starty+lon-1);
DeleteObject(hB);
if (IsIconic())
{
// device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CPatternDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CPatternDlg::OnEsp()
{
OnOK();
}
//识别函数
void CPatternDlg::OnRecog()
{
int j1,k1,m1,n1,x,y,xmod,ymod;//xmod,ymod;
int flagok2=0;
char s[20];
DealData();
//安次序检验,有点下标数
for(j1=0;j1<=zong&&test.total>=0&&flagok2==0;j1++)
{
if(tez[j1].total==test.total) //如果总条数相等
{
for(k1=0;k1<=test.total;k1++)
{
if(test.dian[k1]!=tez[j1].dian[k1])
break;
}
if(k1>test.total)
//每条得点数相同
{
for(m1=0;m1<=test.total;m1++) //每条
{
for(n1=0;n1<=test.dian[m1];n1++) //每点
{
xmod=2*(tez[j1].detail[m1][n1].region % 8); //8等分
ymod=2*((int)tez[j1].detail[m1][n1].region/8);
x=test.detail[m1][n1].region % 16;
y=(int)test.detail[m1][n1].region/16; // 5/16
if(( test.detail[m1][n1].relate!=tez[j1].detail[m1][n1].relate
&&(test.detail[m1][n1].relate-10*(int)(test.detail[m1][n1].relate/10))!=tez[j1].detail[m1][n1].relate
&&(int)(test.detail[m1][n1].relate/10)!=tez[j1].detail[m1][n1].relate)
||((tez[j1].detail[m1][n1].arc!=test.detail[m1][n1].arc)&&(test.total<4)&&(test.dian[m1]<4))
||((x<xmod-3||x>xmod+3)||(y<ymod-3||y>ymod+3)))//shi为total+1
break;
}
if(n1<=test.dian[m1])
break;
}
if(m1>test.total)
{
flagok2=1;
sprintf(s,"输入正确,可识别,为:%s, 在字库%d个",tez[j1].zifu,j1);
AfxMessageBox(s);
m_edit1.ReplaceSel(tez[j1].zifu);
OnClear();
}
}
}
}
if(flagok2==0)
{
AfxMessageBox("字库不足或输入不规范,无法识别,请学习");
OnRecogch();
}
}
//学习函数
void CPatternDlg::OnStudy()
{
int j1,k1,m1,n1,k,m,xmod,ymod,x,y;//j1代表字典中的一个字,k 表示笔划,m 表示一个点
CString z1;
int i,j;
int flagok1=0; //o无法识别,1可识别,已经识别出结果
char s[30];
Inputdialog inputdlg;
//处理数据
DealData();
if(test.total==-1)
{
AfxMessageBox("没有笔迹输入,\n请重示");
}
for(j1=0;j1<=zong&&test.total!=-1;j1++)
{
if(flagok1==1)
break;
if(tez[j1].total==test.total&&flagok1==0) //总笔划相等
{
for(k1=0;k1<=test.total;k1++)
{
if(test.dian[k1]!=tez[j1].dian[k1])
break;
}
if(k1>test.total) //每笔划点数相同下
{
for(m1=0;m1<=test.total;m1++)
{
for(n1=0;n1<=test.dian[m1];n1++)
{
if(( test.detail[m1][n1].relate!=tez[j1].detail[m1][n1].relate
&&(test.detail[m1][n1].relate % 10)!=tez[j1].detail[m1][n1].relate
&&((int)(test.detail[m1][n1].relate/10))!=tez[j1].detail[m1][n1].relate)
||(tez[j1].detail[m1][n1].arc!=test.detail[m1][n1].arc))//shi为total+1
break;
xmod=2*(tez[j1].detail[m1][n1].region % 8); //8等分
ymod=2*((int)tez[j1].detail[m1][n1].region/8);
x=test.detail[m1][n1].region % 16;
y=(int)test.detail[m1][n1].region/16;
if((x<xmod-1||x>xmod+1)||(y<ymod-1||y>ymod+1))
break; //3/16
} //对一个笔划的判断,tezheng不等,跳出n
if(n1<=test.dian[m1])
break; //ci bihua不等,跳出m循环
}
if(m1>test.total&&k1>test.total)//当前库字与输入相符合
{
flagok1=1;
sprintf(s,"您输入的是:%s,数据已有",tez[j1].zifu);
AfxMessageBox(s);
m_edit1.ReplaceSel(tez[j1].zifu);
OnClear();
}
}
}
}
if(flagok1==0&&test.total>=0&&inputdlg.DoModal()==IDOK) //shuruzifu
{
if(inputdlg.m_input1!=inputdlg.m_input2
||inputdlg.m_input1==""||inputdlg.m_input1==" ")
{
AfxMessageBox("您的输入有误(不等或空格),\n请重新输入");
for(i=0;i<50;i++)
queue[i]=-1;
for(i=0;i<40;i++)
queue1[i]=-1;
test.total=-1;
for(j=0;j<15;j++)
test.dian[j]=-1;
for(j=0;j<15;j++)
{
for(k=0;k<20;k++)
{
test.detail[j][k].relate=0;
test.detail[j][k].region=0;
}
}
}
else
{
zong++;
sprintf(tez[zong].zifu,"%s",inputdlg.m_input1);
tez[zong].total=test.total;
for(i=0;i<=test.total;i++)
{
tez[zong].dian[i]=test.dian[i];
for(j=0;j<=test.dian[i];j++)
{
tez[zong].detail[i][j].relate=(test.detail[i][j].relate % 10);
tez[zong].detail[i][j].arc=test.detail[i][j].arc;
x=(int)(test.detail[i][j].region % 16)/2;
y=(int)(test.detail[i][j].region/16)/2;
tez[zong].detail[i][j].region=8*y+x;
}
}
OnSaveMenu();
if(zong>=2000)
AfxMessageBox("版本太低,容量受限,Sorry!");
m_edit1.ReplaceSel(inputdlg.m_input1);
OnClear();
}//zong dang前库下标
}
}
void CPatternDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
mouseDown=1;
CWnd::OnLButtonDown(nFlags, point);
}
//鼠标左键抬起
void CPatternDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
mouseDown=0;
if(store[num][Time-1].x>=0&&Time>0)
{
num++;
Time=0;
}
if(num>=14)
{
AfxMessageBox("写入有误(笔划太多)",NULL,NULL);
OnClear();
}
CWnd::OnLButtonUp(nFlags, point);
}
//鼠标移动事件,模拟手写笔输入
void CPatternDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
int x,y;
CBrush Brush (RGB (0, 0 , 255) );
CBrush* pOldBrush;
CDC *pDC=GetDC();
CRgn Rgn;
Rgn.CreateRectRgn(Startx,Starty,Startx+wid-1,Starty+lon-1);
pDC->SelectClipRgn(&Rgn);
if((point.x>=Startx)&&(point.x<Startx+wid)&&(point.y>=Starty)
&&(point.y<Starty+lon))
{
HCURSOR m_HCross;
m_HCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);
SetCursor(m_HCross);
}
if((mouseDown==1)&&(point.x>=Startx)&&(point.x<Startx+wid)
&&(point.y>=Starty)&&(point.y<Starty+lon))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -