分享学习
标题:
Vc_C++实现笔锋效果代码实现
[打印本页]
作者:
admin
时间:
2019-3-30 18:12
标题:
Vc_C++实现笔锋效果代码实现
C++实现笔锋效果
实现笔锋的理论可参考网上的文章:
https://www.cnblogs.com/zl03jsj/p/8051912.html
https://www.cnblogs.com/zl03jsj/p/8048102.html
本文主要介绍如何编写代码实现书写时带笔锋的功能。
为了实现模块的分割和封装,我们首先建立一个动态库项目,并向项目中添加几个文件:
HandWriteHelp.h文件
#pragma once
#include <vector>
#include "HandWriteMath.h"
class HandWriteHelp
{
public:
HandWriteHelp();
~HandWriteHelp();
int startNewTrace()
{
pointArray = h_new_fpoint_array(24, 10, 1);
return 0;
}
int addNewPoint(float x, float y,
new_point_generated callback,//生成了新的点的回调
void *context)
{
h_point pt;
pt.x = x;
pt.y = y;
h_insert_point(pointArray, pt, callback, context);
return 0;
}
int endCurrentTrace(float x, float y,
new_point_generated callback,//生成了新的点的回调
void *context)
{
h_point pt;
pt.x = x;
pt.y = y;
h_insert_last_point(pointArray, pt, callback, context);
h_drop_fpoint_array(pointArray);
pointArray = NULL;
return 0;
}
private:
h_fpoint_array *pointArray;
};
复制代码
HandWriteMath.h文件:
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct h_point_s h_point;
typedef struct h_fpoint_s h_fpoint;
typedef struct h_ipoint_s h_ipoint;
typedef struct h_fpoint_array_s h_fpoint_array;
typedef void(*new_point_generated)(float x, float y, float w, void* context);
struct h_point_s {
float x, y;
};
struct h_fpoint_s {
h_point p;
float w;
};
struct h_ipoint_s {
h_point p;
int64_t t;
};
struct h_fpoint_array_s {
h_fpoint *point;
float maxwidth;
float minwidth;
int ref;
int len;
int cap;
h_point last_point;
float last_width;
int64_t last_ms;
};
h_fpoint_array *h_keep_fpoint_array(h_fpoint_array *a);
void h_drop_fpoint_array(h_fpoint_array *a);
h_fpoint_array *h_new_fpoint_array(int initsize, float maxwidth, float minwidth);
h_fpoint_array *h_resize_fpoints_array(h_fpoint_array* a, int size);
float h_movespeed(h_ipoint s, h_ipoint e);
float h_distance(h_point s, h_point e);
void h_fpoint_add_xyw(h_fpoint_array *a, float x, float y, float w);
void h_fpoint_add(h_fpoint_array *a, h_fpoint p);
void h_fpoint_differential_add(h_fpoint_array *a, h_fpoint p);
void h_square_bezier(h_fpoint_array *a, h_fpoint b, h_point c, h_fpoint e);
float h_linewidth(h_ipoint b, h_ipoint e, float w, float step);
float h_insert_point(h_fpoint_array *arr, h_point point,
new_point_generated callback, void *context);
void h_insert_last_point(h_fpoint_array *arr, h_point e,
new_point_generated callback, void *context);
#ifdef __cplusplus
}
#endif
复制代码
HandWritLib.h文件:
#ifndef HandWrite_h_
#define HandWrite_h_
#ifdef HANDWRITE_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct HandWritPoint {
float x;
float y;
float w;
};
typedef void(*new_point_generated)(float x, float y, float w, void* context);
//获取手写处理器
DLL_EXPORT void* getHandWriteHelp();
//释放手写处理器
DLL_EXPORT void releaseHandWriteHelp(void** handWriter);
//开始一次笔迹生成
DLL_EXPORT int startNewTrace(void * handWriter);
//增加一个书写点
DLL_EXPORT int addNewPoint(float x, float y, void * handWriter,
new_point_generated callback,//生成了新的点的回调
void *context);//当前上下文,回调函数会传回来
//输入最后一个点
DLL_EXPORT int endCurrentTrace(float x, float y, void * handWriter,
new_point_generated callback,//生成了新的点的回调
void *context);
#ifdef __cplusplus
}
#endif
#endif
复制代码
HandWriteHelp.cpp文件:
HandWriteLib.cpp文件:
HandWriteMath.c文件:
然后编译这个动态库项目,生成lib文件和dll文件, 编译动态库时预定义HANDWRITE_EXPORT宏。
然后我们新建一个基于对话框的MFC程序,项目中导入上面的lib文件,HandWriteLib.h头文件,dll文件也放到exe目录下。
对话框的代码如下:
对话框的头文件:
[code]
// HandWritingDlg.h: 头文件
//
#pragma once
#include "HandWritLib.h"
#include <vector>
#define WM_RCV_NEWPOINT (WM_USER + 100)
#define MAX_WIDTH 10
class CFPoint
{
public:
float x;
float y;
CFPoint()
{
x = 0;
y = 0;
}
CFPoint(float _x, float _y)
{
x = _x;
y = _y;
}
CFPoint(const CFPoint &pt)
{
x = pt.x;
y = pt.y;
}
inline CFPoint operator-(const CFPoint &initPt)
{
return CFPoint(x - initPt.x, y - initPt.y);
}
inline CFPoint operator+(const CFPoint &initPt)
{
return CFPoint(x + initPt.x, y + initPt.y);
}
inline CFPoint operator*(float value)
{
return CFPoint(x*value, y*value);
}
};
// CHandWritingDlg 对话框
class CHandWritingDlg : public CDialogEx
{
// 构造
public:
CHandWritingDlg(CWnd* pParent = nullptr); // 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_HANDWRITING_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg HRESULT rcvNewPoint(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
public:
afx_msg void OnBnClickedButton1();
void drawLine(const CFPoint &b, const CFPoint &e, int lineWidth);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
private:
//是否开始生成
bool isStartWrite;
long lastPointTime;
std::vector<HandWritPoint> lastPoint;
void *handWriter;
public:
afx_msg void OnClose();
afx_msg void OnDestroy();
};
复制代码
对话框的cpp文件如下:
// HandWritingDlg.cpp: 实现文件
//
#include "stdafx.h"
#include "HandWriting.h"
#include "HandWritingDlg.h"
#include "afxdialogex.h"
#include <algorithm>
#include <vector>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CHandWritingDlg 对话框
CHandWritingDlg::CHandWritingDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_HANDWRITING_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CHandWritingDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CHandWritingDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONUP()
ON_BN_CLICKED(IDC_BUTTON1, &CHandWritingDlg::OnBnClickedButton1)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_MESSAGE(WM_RCV_NEWPOINT, &CHandWritingDlg::rcvNewPoint)
ON_WM_CLOSE()
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CHandWritingDlg 消息处理程序
#include <math.h>
BOOL CHandWritingDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
handWriter = getHandWriteHelp();
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CHandWritingDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CHandWritingDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CHandWritingDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CHandWritingDlg::drawLine(const CFPoint &b, const CFPoint &e, int lineWidth)
{
CRect rect;
CDC* pdc = this->GetDC();
if (pdc == NULL)
{
DWORD dw = ::GetLastError();
dw = dw;
return;
}
Graphics graphics(pdc->m_hDC);
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
static long drawtimes = 0;
Pen pen(Color(255, 255, 0, 0), lineWidth);
pen.SetStartCap(LineCapRound);
pen.SetEndCap(LineCapRound);
Gdiplus::Point points[2];
points[0].X = b.x;
points[0].Y = b.y;
points[1].X = e.x;
points[1].Y = e.y;
graphics.DrawCurve(&pen, points, 2, 0.5);
DeleteObject(pdc->m_hDC);
}
void newPointCallback(float x, float y, float w, void *context)
{
CHandWritingDlg *pThis = (CHandWritingDlg*)context;
HandWritPoint *point = new HandWritPoint();
point->x = x;
point->y = y;
point->w = w;
pThis->SendMessage(WM_RCV_NEWPOINT, 0, (LPARAM)point);
}
void CHandWritingDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
isStartWrite = false;
endCurrentTrace(point.x, point.y, handWriter, newPointCallback, this);
CDialogEx::OnLButtonUp(nFlags, point);
}
void CHandWritingDlg::OnBnClickedButton1()
{
lastPoint.clear();
Invalidate();
}
HRESULT CHandWritingDlg::rcvNewPoint(WPARAM wParam, LPARAM lParam)
{
HandWritPoint *point = (HandWritPoint*)lParam;
if (lastPoint.size() > 0)
{
HandWritPoint p = lastPoint.back();
drawLine(CFPoint(p.x, p.y),
CFPoint(point->x, point->y),
MAX_WIDTH * (p.w) + 0.5);
}
lastPoint.push_back(*point);
delete point;
return 0;
}
void CHandWritingDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
lastPoint.clear();
startNewTrace(handWriter);
addNewPoint(point.x, point.y, handWriter, newPointCallback, this);
isStartWrite = true;
CDialogEx::OnLButtonDown(nFlags, point);
}
void CHandWritingDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if (isStartWrite == true)
{
addNewPoint(point.x, point.y, handWriter, newPointCallback, this);
}
CDialogEx::OnMouseMove(nFlags, point);
}
void CHandWritingDlg::OnClose()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CDialogEx::OnClose();
}
void CHandWritingDlg::OnDestroy()
{
CDialogEx::OnDestroy();
// TODO: 在此处添加消息处理程序代码
releaseHandWriteHelp(&handWriter);
}
复制代码
程序运行的结果如下:
[attach]40[/attach]
欢迎光临 分享学习 (http://1314xuexi.com/)
Powered by Discuz! X3.3