C++高仿大漠找字FindStr
字库就用大漠字库就可以了。
大家先来看看效果图:
砸门先制作一个这样的字库:
上面就是我定义的方字!当然了随你高兴写成什么字都可以。
但是最高不能超过256个字节
效果图如下:
看下调用方法
首先申请一个程序集变量:
TKdmsoft dm;//天空大漠
dm.SetPath(“d:\”);//设置操作的磁盘地址
dm.SetDict(“找字.txt”);//设置字库
int x=-1, y=-1;//申请两个返回的地址
//time_t t; time(&t);
//tm* m=localtime(&t);
//
//int sbb= m->tm_sec;
dm.FindStr(0, 1, 215, 113, "方方", "ff0000-050505", x, y);//调用方法
if (x>=0)
{
str.Format("%d", x);
SetDlgItemText(EDIT_x, str);
str.Format("%d", y);
SetDlgItemText(EDIT_y, str);
}
下面是找字类:
FindstrEx.h
#pragma once
struct MyDict
{
char* Dict; //要操作字体的点阵
char Neam[256] = {0}; //要操作的字符名称
int yxxs;//有效像数
int spxs;//竖排行数
};
struct MyDictwh
{
int w;//字体宽度
int h;//字体高度
};
class TKdmsoft
{
public:
TKdmsoft();
TKdmsoft(HWND hnd);
~TKdmsoft();
public:
int FindStr(int x1, int y1, int x2, int y2, const char* str, const char* color_format, int& X, int& Y);
long SetDict(char* file);
long SetPath(char* path);
long Sethwnd(HWND hwnd);
long CloseTk();//释放插件
long GetZtSize();//获取寻找的文字个数
private:
int GetDict(int dex, const char* str_a);//解析大漠字库
char* GetDictWh(const char* str, int& W, int& h, int& uto); //取回字符宽高
private:
char* strpath=NULL;//操作默认磁盘
MyDict* Dict=NULL;//字库文件
MyDictwh* dictwh; //当次字体大小
int DictSize = 0; //字库大小或有多少个字
HWND g_hwnd; //需要操作的窗口句柄
int ZTsize = 0; //字体大小
};
inline long TKdmsoft::CloseTk()
{
for (size_t i = 0; i < DictSize; i++)
{
delete[] Dict[i].Dict;
}
delete[] Dict;
delete[] strpath;
return 0;
}
long TKdmsoft::GetZtSize()//返回字体个数
{
if (ZTsize==0)
{
return 0;
}
return ZTsize;
}
// 天空插件
TKdmsoft::TKdmsoft(HWND hnd )
{
g_hwnd = hnd;
}
TKdmsoft::~TKdmsoft()
{
}
inline TKdmsoft::TKdmsoft()
{
}
long TKdmsoft::Sethwnd(HWND hwnd)
{
if (hwnd==0)
{
return -1;
}
g_hwnd = hwnd;
return 0;
}
//取两个十进制数的差,返回:十六进制文本
CString QCZ(int p1, int p2)
{
CString str;
str = IntToHex(abs(p1 - p2));
if (str.GetLength() == 2)
{
return str;
}
if (str.GetLength() == 1)
{
return "0" + str;
}
if (str.GetLength() == 0)
{
return "00";
}
return "";
}
//取色差
int QSC(CString str, int& c1, int& c2)
{
int strl = str.GetLength();
CString CR, CP, str1;
int strlock = 0;
for (size_t i = 0; i < strl; i++)
{
str1 = "";
str1 = str.Mid(i, 1);
if (str1 != "-")
{
if (!((str1[0] >= '0' && str1[0] <= '9') || (str1[0] >= 'a' && str1[0] <= 'f') || (str1[0] >= 'A' && str1[0] <= 'F')))
{
c1 = -1; return -1;
}//取反就是找不到上面的就返回一个错误码
}
if (str1 == "-") { strlock = 1; }//控制分离偏色和颜色的开关
if (strlock == 0)
{
CR += str1;
}
if (strlock == 1 && str1 != "-")
{
CP += str1;
}
}
CString strt;
strt.Format("%s%s%s", CR.Mid(4, 2), CR.Mid(2, 2), CR.Mid(0, 2));
c1 = Hex_Conversion_Dec(strt);//进制十六倒十
strt.Format("%s%s%s", CP.Mid(4, 2), CP.Mid(2, 2), CP.Mid(0, 2));
c2 = Hex_Conversion_Dec(strt);
return 0;
}
//图片相似度
int redToGreen(COLORREF& c, int c1, int c2)//把图片二值化
{
//int R = c;// GetRValue(c);//获取c中R的值
CString str;
int b, d;
int R, G, B;
R = GetRValue(c);//获取c中R的值
G = GetGValue(c);//获取c中R的值
B = GetBValue(c);//获取c中R的值
int r1, g1, b1, pr, pg, pb;
r1 = GetRValue(c1);//获取c中R的值
g1 = GetGValue(c1);//获取c中R的值
b1 = GetBValue(c1);//获取c中R的值
pr = GetRValue(c2);//获取c中R的值
pg = GetGValue(c2);//获取c中R的值
pb = GetBValue(c2);//获取c中R的值
{
if (pr >= 1)
{
b = r1;
r1 += pr;//最大偏移
pr = b - pr;//最小偏移
if (r1 > 255) {
r1 = 255;//控制数据溢出
}
else if (r1 < 0) {
r1 = 0;//控制数据溢出
}
if (pr > 255)
{
pr = 255;//控制数据溢出
}
else if (pr < 0) {
pr = 0;//控制数据溢出
}
if (R > r1 || R < pr)
{
return 0;
}
}
else if (pr == 0)
{
if (R != r1)
{
return 0;
}
}
}
{
if (pg >= 1)
{
if (pg >= 1)
{
b = g1;
g1 += pg;//最大偏移
pg = b - pg;//最小偏移
if (g1 > 255) {
g1 = 255;//控制数据溢出
}
else if (g1 < 0) {
g1 = 0;//控制数据溢出
}
if (pg > 255)
{
pg = 255;//控制数据溢出
}
else if (pg < 0) {
pg = 0;//控制数据溢出
}
if (G > g1 || G < pg)
{
return 0;
}
}
else if (pg == 0) { if (G != g1) { return 0; } }
}
}
{
if (pb >= 1)
{
b = b1;
b1 += pb;//最大偏移
pb = b - pb;//最小偏移
if (b1 > 255) {
b1 = 255;//控制数据溢出
}
else if (b1 < 0) {
b1 = 0;//控制数据溢出
}
if (pb > 255)
{
pb = 255;//控制数据溢出
}
else if (pb < 0) {
pb = 0;//控制数据溢出
}
if (B > b1 || B < pb)
{
return 0;
}
}
else if (pb == 0) { if (B != b1) { return 0; } }
}
return 1;
}
//原文链接:https ://blog.csdn.net/qq_43345204/article/details/83476693
void Getcol_a(CString str, int& a, int& b)
{
CString utoa, utoa1;
int inlock = 0;
CString str1;
int strl = str.GetLength();
for (size_t i = 0; i < strl; i++)
{
str1 = str.Mid(i, 1);
if (str1 == "-")
{
inlock = 1;
}
if (inlock == 0)
{
utoa += str1;
str1 = "";
}
if (inlock == 1 && str1 != "-")
{
utoa1 += str1;
str1 = "";
}
}
a = StrToInt(utoa);
b = StrToInt(utoa1);
}
int TKdmsoft::FindStr(int x1, int y1, int x2, int y2, const char* str, const char* color_format, int& X, int& Y)
{
//CBitmap, HBitmap, BITMAP.
if (g_hwnd==0)
{
return -1;
}
HDC hDC = GetWindowDC(g_hwnd);// ::GetWindowDC(hwnd);//获取DC
HDC hDCMem = ::CreateCompatibleDC(hDC);//创建兼容DC
RECT rect;
rect.right = y2 - y1;//获取屏幕高度
rect.bottom = x2 - x1;//获取屏幕宽度
HBITMAP hBitMap = ::CreateCompatibleBitmap(hDC, rect.right, rect.bottom);//创建兼容位图
HBITMAP hOldMap = (HBITMAP)::SelectObject(hDCMem, hBitMap);//将位图选入DC。并保存返回值
::BitBlt(hDCMem, 0, 0, rect.right, rect.bottom, hDC, 8+x1,31+y1, SRCCOPY);//将屏幕DC的图象拷贝到内存DC中
CImage bm;
bm.Attach(hBitMap);
//bm.Save("d:\\2345.bmp");//假设文件后缀为.bmp,则保存为为bmp格式
CDC* pDC = CDC::FromHandle(hDCMem);
int width, high;
width = x2 - x1;//bm.GetWidth();//获取图像的宽度
high = y2 - y1; //bm.GetHeight();//获取图像的高度
if (width <= 0 || high <= 0)
{
return -1;
}
int c1, c2;
char** FindStrpm = (char**) new char*[width+100]; //分配一个数组来装图片像数
for (size_t i = 0; i < width+100; i++)
{
FindStrpm[i] = new char[high+100];
}
if (QSC(color_format, c1, c2) == -1)//取回颜色和偏色的数值
{
return -1;
}
COLORREF cor;
int a = 0;
int R = 0, G = 0, B = 0;
for (size_t y = 0; y < width; y++)
{
for (size_t x = 0; x < high; x++)
{
if (x==12 && y==25)
{
x = x;
}
cor = pDC->GetPixel(x, y);
//CString str1;
int tpe;
//memcpy(&tpe,&cor,3);
tpe = redToGreen(cor, c1, c2);//转换主屏幕;
if (tpe == -1)
{
return -1;
}
if (tpe==1)
{
tpe = tpe;
}
FindStrpm[x][y] = tpe;
}
}
bm.Detach();
//释放
::DeleteObject(hBitMap);
::DeleteDC(hDCMem);
::DeleteDC(hDC);
//for (size_t i = 0; i < width+100; i++)
//{
// delete[] FindStrpm[i] ;
//}
delete[] FindStrpm;
int uot_x = -1, uot_y = -1;
int w, h;
//GetDict("C0180300600$方$0.0.8$2");
int b = 0, uto=0;
char* chh= NULL;
chh=GetDictWh(str, w, h, uto);
if (w <= 0 || h <= 0)
{
return -1;
}
a = 0;
int** FindS = (int**) new int* [w];
for (int i = 0; i < w; i++)
{
FindS[i] = new int[h];
}
int zthmax = dictwh[0].w;
int ztdex = 0;
for (size_t x = 0; x < w; x++)
{
if (zthmax==0)
{
ztdex++;
zthmax = dictwh[ztdex].w;
}
zthmax--;
for (size_t y = 0; y < h; y++)
{
char ch[2] = { 0 };
if (y<=dictwh[ztdex].h)
{
memcpy(ch, chh + a, 1);
int temp = StrToInt(ch);
FindS[x][y] = temp;
a++;
}
else
{
FindS[x][y] = 0;
}
}
}
delete[] dictwh;
int uto1=0;// = Dict.yxxs, uto1 = 0;//记录找到的有效像数
bool ret = false;
a = 0, b = 0;
for (size_t x = 0; x < width; x++)
{
if (width - x >= w)//宽度大于等于字体宽度才开始寻找不然从下一行开始
{
for (size_t y = 0; y < high; y++)
{
if (high - y >= h)//高度度大于等于字体宽度才开始寻找不然从下一行开始
{
for (size_t yy = 0; yy < w; yy++)
{
for (size_t hh = 0; hh < h; hh++)
{
int xxx = x + yy, yyy = y + hh;
int b1 = FindStrpm[xxx][yyy], b2 = FindS[yy][hh];
if (b2 == 1)
{
if (b1 != b2)
{
uto1 = 0;
a = 0;
ret = false;
uot_x = -1;
uot_y = -1;
break;;
}
else
{
ret = true;
}
if (a == 0 && ret == true)
{
uot_x = x;
uot_y = y;
}
uto1++;
a++;
if (uto1 >= uto)
{
break;
}
}
}
if (uto1 >= uto)
{
break;
}
}
}
if (uto1 >= uto)
{
break;
}
}
}
if (uto1 >= uto)
{
break;
}
}
for (int i = 0; i < w; i++)
{
delete[] FindS[i];
}
delete[] FindS;
if (uot_x >= 0)
{
X = uot_x+x1;
Y = uot_y+y1;
}
else
{
X = -1;
Y = -1;
return 1;
}
return 1;
}
long TKdmsoft::SetDict(char* file)
{
if (file == NULL|| strpath == NULL)
{
return -1;
}
char path[256] = {0};
memcpy(path, strpath,strlen(strpath));
memcpy(path+ strlen(strpath), file, strlen(file));
HANDLE hand =CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD Len = 0;
ULONGLONG size;
CFileStatus fileStatus;
if (CFile::GetStatus(path,fileStatus))
{
size = fileStatus.m_size;
}
char* str=new char[size];
memset(str, 0, sizeof(str));
ReadFile(hand, str, size, &Len, NULL);
int a = 0;
char bj[3] = {0};
for (UINT64 i = 0; i < Len; i++)
{
memcpy(bj, str + i, 2);
if (strcmp(bj,"\r\n") == 0)
{
a++;
}
}
Dict = new MyDict[a];
DictSize = a;
memset(Dict, 0, sizeof(Dict));
int b = 0,c=0;
char srz[4096] = {0};
for (QWORD i = 0; i < Len; i++)
{
memcpy(bj, str + i, 2);
if (strcmp(bj,"\r\n")!=0&&bj[0]!='\n')
{
srz[b] = str[i];
b++;
}
if (strcmp(bj, "\r\n") == 0)
{
GetDict(c,srz);
c++;
b = 0;
memset(srz,0,sizeof(srz)*sizeof(char));
}
//memset
}
SetDlgItemText(g_hwnd,EDIT_ZT, str);
CloseHandle(hand);
delete[] str;
return 0;
}
long TKdmsoft::SetPath(char* path)
{
if (path==NULL)
{
return -1;
}
if (strlen(path)<=2)
{
return -1;
}
strpath = path;
return 1;
}
int TKdmsoft::GetDict(int dex, const char* str_a)
{
char str[256] = { 0 }, str1[2] = { 0 };
int strl = strlen(str_a);
char Dict1[256] = { 0 }; //要操作字体的点阵
int dit = 0, Nett = 0, czt = 0, cht = 0;
char Neam[256] = { 0 }; //要操作的字符名称
char czs[256] = { 0 };//有效像数
char chs[256] = { 0 };//竖排行数
int strlock = 0;
for (UINT64 i = 0; i < strl; i++)
{
str1[0] = str_a[i];
if (strcmp(str1, "$") == 0)
{
strlock++;
}
if (strlock == 0 && strcmp(str1, "$") != 0)
{
Dict1[dit] = str1[0];
dit++;
str1[0] = 0;
}
if (strlock == 1 && strcmp(str1, "$") != 0)
{
Neam[Nett] = str1[0];
Nett++;
str1[0] = 0;
}
if (strlock == 2 && strcmp(str1, "$") != 0)
{
czs[czt] = str1[0];
czt++;
str1[0] = 0;
}
if (strlock == 3 && strcmp(str1, "$") != 0)
{
chs[cht] += str1[0];
cht++;
str1[0] = 0;
}
}
if (strlen(Dict1) <= 0 || strlen(Neam) <= 0 || strlen(czs) <= 0 || strlen(chs) <= 0)
{
return 0;//读取错误返回0
}
char ch[3] = { 0 };
CString SST=HexToBin(Dict1);//转换到二进制
Dict[dex].Dict = new char[SST.GetLength()];
memset(Dict[dex].Dict, 0, SST.GetLength());
memcpy(Dict[dex].Dict, SST.GetBuffer(), SST.GetLength());
memcpy(ch,Neam,2);
if (!IsChinese(ch))
{
memcpy(Dict[dex].Neam, Neam, 1);
}
else
{
memcpy(&Dict[dex].Neam, Neam, 2);
}
memcpy(ch, czs+4, 4);
Dict[dex].yxxs = StrToInt(ch);//字符转换到整数
Dict[dex].spxs = StrToInt(chs);//这是竖排行数
return 1;
}
int GetDictSize(const char* str)
{
int strl = strlen(str);
int strlock = 0;
int ret = 0;
int b = 0;
for (size_t i = 0; i < strl; i++)
{
char bj[3] = { 0 };
if (strlock==0)
{
if (strl - i >= 1)
{
memcpy(bj, str + i, 2);
}
else
{
memset(bj, 0, sizeof(bj));
memcpy(bj, str + i, 1);
}
if (IsChinese(bj))
{
b++;
ret = i;
strlock = 1;
}
}
if (strlock == 1&&i-ret==1)
{
strlock = 0;
ret = 0;
}
}
strl = strl - b * 2;
b = b + strl;
return b;
}
char* TKdmsoft::GetDictWh(const char* str, int& w, int& h,int& uto)
{
char retstr[4096] = {0};
if (str==NULL)
{
return "";
}
int strl = GetDictSize(str);
ZTsize = strl;
dictwh = new MyDictwh[strl];
int a = 0,hh=0,sst=0,dex=0,b=0;
for (size_t i = 0; i < strl; i++)
{
a = 0;
for (size_t j = 0; j < DictSize; j++)
{
char bj[3] = {0};
memcpy(bj, str , 2);
if (!IsChinese(bj))
{
memcpy(bj, str + j, 1);
}
if (strcmp(Dict[j].Neam, bj) == 0)
{
a = j + 1;
break;
}
}
if (a>0)
{
h = Dict[a-1].spxs;//字体高度
if (h < 11)
{
h = 11;
}
if (hh==0)
{
hh = h;
}
else
{
if (h>hh)
{
hh = h;
}
}
if (sst==0)
{
sst = strlen(Dict[a - 1].Dict);
memcpy(retstr, Dict[a - 1].Dict, sst);
}
else
{
memcpy(retstr+ sst, Dict[a - 1].Dict, strlen(Dict[a - 1].Dict));
sst+= strlen(Dict[a - 1].Dict);
}
b= strlen(Dict[a - 1].Dict) / h;//字体宽度
w += b;
dictwh[dex].w = b;
dictwh[dex].h = h;
uto += Dict[a - 1].yxxs;
a = 0;
}
}
if (hh==0)
{
w = 0;
h = 0;
uto = 0;
dictwh = NULL;
return "";
}
h = hh;
str = retstr;
return retstr;
}
下面是调用的CPP
// FinndstrExDlg.cpp: 实现文件
//
#include "pch.h"
#include "framework.h"
#include "FinndstrEx.h"
#include "FinndstrExDlg.h"
#include "afxdialogex.h"
#include<iostream>
#include <fstream>
#include "dlgs.h"
#include "math.h"
#include "stdlib.h"
#include "MFC进制转换.h"
#include "FindstrEx.h"
//#include <opencv2\opencv.hpp>
TKdmsoft dm;
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CFinndstrExDlg 对话框
CFinndstrExDlg::CFinndstrExDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_FINNDSTREX_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CFinndstrExDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CFinndstrExDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CFinndstrExDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CFinndstrExDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON3, &CFinndstrExDlg::OnBnClickedButton3)
END_MESSAGE_MAP()
// CFinndstrExDlg 消息处理程序
BOOL CFinndstrExDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
dm.Sethwnd(m_hWnd);//设置需要找字的窗口
CStatic* pwnd = (CStatic*)GetDlgItem(IDC_PIC1); //IDC_STATIC //pwnd->SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
pwnd->ModifyStyle(0xf, SS_BITMAP);
HBITMAP bmp = (HBITMAP)::LoadImage(GetModuleHandle(NULL), "d:\\1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
pwnd->SetBitmap(bmp);//打开图片
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CFinndstrExDlg::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 CFinndstrExDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CFinndstrExDlg::OnBnClickedButton1()
{
TODO: 在此添加控件通知处理程序代码
dm.SetPath("d:\\");
dm.SetDict("找字.txt");
CString cstr,str;
//GetDlgItemText(EDIT_x, cstr);
//cstr.Format("点阵信息:%s\r\n字符名称:%s\r\n有效像数:%d\r\n竖排行数:%d", Dict.Dict, Dict.Neam, Dict.yxxs, Dict.spxs);
//GetDlgItemText(EDIT_y, str);
int x=-1, y=-1;
//time_t t; time(&t);
//tm* m=localtime(&t);
//
//int sbb= m->tm_sec;
dm.FindStr(0, 1, 215, 113, "方方", "ff0000-050505", x, y);
if (x>=0)
{
str.Format("%d", x);
SetDlgItemText(EDIT_x, str);
str.Format("%d", y);
SetDlgItemText(EDIT_y, str);
}
//intTo101(0xC0180300600);
// time(&t);
//m = localtime(&t);
//int sbb1 = m->tm_sec;
//str.Format("%d", sbb1- sbb);
//AfxMessageBox(str);
//CString str= HexToBin("C0180300600");
//SetDlgItemText(EDIT_ZT, g_str1);
//SetDlgItemText(EDIT1_ARRAY, g_str);
//原文链接:https ://blog.csdn.net/mengsuifengc/article/details/109228725
}
void CFinndstrExDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(EDIT_ZT, str);
str=BinToHex(str);
SetDlgItemText(EDIT_ZT, str);
}
void CFinndstrExDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
dm.CloseTk();
}
还不是很完善大家自己完善了!