From a17738e1545ff7dbef6398b8ec1eab93ab59c9a1 Mon Sep 17 00:00:00 2001
From: admin <weikou2014>
Date: 星期四, 30 六月 2022 19:14:47 +0800
Subject: [PATCH] '功能完善'

---
 ConsoleApplication/THSActionUtil.cpp |  536 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 456 insertions(+), 80 deletions(-)

diff --git a/ConsoleApplication/THSActionUtil.cpp b/ConsoleApplication/THSActionUtil.cpp
index 3506f84..331e092 100644
--- a/ConsoleApplication/THSActionUtil.cpp
+++ b/ConsoleApplication/THSActionUtil.cpp
@@ -2,6 +2,23 @@
 #include "ImgDivider.h"
 #include "Win32Util.h"
 
+RecognitionManager* THSActionUtil::recognitionManager;
+
+bool isMainScreen(string str) {
+	if (str.find("同花顺(") != string::npos) {
+		cout << str << endl;
+		if (str.find("副屏") == string::npos) {
+			if (str.find("热门股") != string::npos || str.find("我的板块") != string::npos) {
+				return true;
+			}
+		}
+	}
+	return	false;
+}
+
+bool isSecondScreen(string str) {
+	return	str.find("同花顺(") != string::npos && str.find("副屏") != string::npos;
+}
 
 //获取副屏
 HWND getSecondWindow() {
@@ -10,12 +27,59 @@
 	for (ele = wlist.begin();ele != wlist.end();ele++) {
 		HWND hwnd = *ele;
 		string str = Win32Util::getWindowName(hwnd);
-		if (str.find("同花顺") != string::npos && str.find("副屏") != string::npos)
+		if (isSecondScreen(str))
 		{
 			return hwnd;
 		}
 	}
 	return 0;
+}
+
+HWND THSActionUtil::getL2Win() {
+	list<HWND> wlist = Win32Util::searchWindow("同花顺(");
+	list<HWND>::iterator ele;
+	for (ele = wlist.begin();ele != wlist.end();ele++) {
+		HWND hwnd = *ele;
+		string str = Win32Util::getWindowName(hwnd);
+
+
+		if (isMainScreen(str)) {
+			return hwnd;
+		}
+
+	}
+	return 0;
+}
+bool THSActionUtil::checkEnv() {
+
+	list<HWND> wlist = Win32Util::searchWindow("同花顺(");
+	list<HWND>::iterator ele;
+	bool fp = false;
+	bool zp = false;
+	for (ele = wlist.begin();ele != wlist.end();ele++) {
+		HWND hwnd = *ele;
+		string str = Win32Util::getWindowName(hwnd);
+		if (isSecondScreen(str))
+		{
+			fp = true;
+		}
+
+		if (isMainScreen(str)) {
+			zp = true;
+		}
+
+	}
+
+	if (!zp) {
+		throw string("同花顺主屏L2窗口未打开");
+	}
+
+
+	if (!fp) {
+		throw string("同花顺副屏没有打开");
+	}
+
+	return true;
 }
 
 void THSActionUtil::openSecondScreen() {
@@ -29,7 +93,7 @@
 	for (ele = wlist.begin();ele != wlist.end();ele++) {
 		HWND hwnd = *ele;
 		string str = Win32Util::getWindowName(hwnd);
-		if (str.find("同花顺") != string::npos && str.find("副屏") != string::npos)
+		if (isSecondScreen(str))
 		{
 			cout << str << endl;
 			SetForegroundWindow(hwnd);
@@ -38,7 +102,7 @@
 			break;
 		}
 
-		if (str.find("同花顺") != string::npos && str.find("热门股") != string::npos) {
+		if (isMainScreen(str)) {
 			cout << hwnd << endl;
 			//获取尺寸
 			RECT rc;
@@ -51,6 +115,10 @@
 	}
 
 	if (!open) {
+		if (mainPage <= 0) {
+			throw("未找到首页");
+		}
+
 		Win32Util::focus(mainPage);
 		//查找主窗口的工具栏
 		HWND tool = FindWindowExA(mainPage, NULL, "AfxControlBar100s", NULL);
@@ -72,7 +140,13 @@
 	}
 }
 //添加股票
-void THSActionUtil::setGP(std::string quickCode, list<std::string> codeList) {
+bool THSActionUtil::setGP(std::string quickCode, list<std::string> codeList) {
+
+	list<std::string> tempCodeList;
+	for (std::list<string>::iterator e = codeList.begin();e != codeList.end();e++) {
+		tempCodeList.push_back(*e);
+	}
+
 	//打开副屏
 	HWND sw = getSecondWindow();
 	if (sw <= 0)
@@ -84,32 +158,37 @@
 	if (sw <= 0) {
 		throw("未打开副屏");
 	}
-
+	Win32Util::focus(sw);
 	//打开板块
-	Win32Util::keyboardNum(quickCode);
+	Win32Util::keyboardNum(quickCode, 100);
 	Win32Util::keyboard(VK_RETURN, 200);
-	Sleep(1000);
+
+	Sleep(2000);
 	//设置板块中的股票
 
 	//获取板块内容句柄
 
 	HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL);
-	cv::Mat img = CaptureUtil::capture(content);
-	if (img.cols <= 0 || img.rows <= 0) {
-		throw("板块截屏内容为空");
+	cv::Mat oimg = CaptureUtil::capture(content);
+	cout << "副屏截图:" << oimg.rows << "-" << oimg.cols << endl;
+
+	if (oimg.cols <= 0 || oimg.rows <= 0) {
+		throw string("板块截屏内容为空");
 	}
 
+	cv::Mat img = ImgUtil::grayImage(oimg);
+	oimg.release();
 	std::list<GPCodeArea>  areaList = recognitionGPArea(img);
 
 	std::list<string> addList;
 	std::list<GPCodeArea> delList;
 	std::list<GPCodeArea> resultList = recognitionNum(img, areaList);
 
-	for (std::list<GPCodeArea>::reverse_iterator ele= resultList.rbegin();ele != resultList.rend();++ele) {
+	for (std::list<GPCodeArea>::reverse_iterator ele = resultList.rbegin();ele != resultList.rend();++ele) {
 
 		bool contains = false;
 		std::list<string>::iterator e;
-		for (e = codeList.begin();e != codeList.end();e++) {
+		for (e = tempCodeList.begin();e != tempCodeList.end();e++) {
 			if (*e == (*ele).code) {
 				contains = true;
 				break;
@@ -121,33 +200,70 @@
 		}
 		else
 		{
-			codeList.remove((*ele).code);
+			tempCodeList.remove((*ele).code);
 		}
-	
+
 	}
 	//-----先删除需要删除的
 	//获取内容板块坐标
-	RECT rect;
-	GetWindowRect(content, &rect);
-	
 
-	for (std::list<GPCodeArea>::iterator ele = delList.begin();ele != delList.end();++ele) {     
+
+	RECT rect;
+	GetWindowRect(sw, &rect);
+	Win32Util::mouseMove(rect.left + 10, rect.top + 5, 1);
+	Win32Util::click(10);
+
+	for (std::list<GPCodeArea>::iterator ele = delList.begin();ele != delList.end();++ele) {
+		RECT rect;
+		GetWindowRect(content, &rect);
+		Win32Util::focus(sw);
 		int x = rect.left;
 		int y = rect.top;
-		x += (*ele).startx+5;
-		y += (*ele).starty+5;
-	    //选中删除
-		Win32Util::click(x,y,50);
+		x += (*ele).startx + 5;
+		y += (*ele).starty + 5;		//选中删除
+		Win32Util::mouseMove(x, y, 50);
+		Win32Util::click(10);
 		Win32Util::keyboard(VK_DELETE, 50);
 	}
+	img.release();
 
 	//----增加
 	//截图,识别出增加按钮位置,点击增加,输入内容
+	for (std::list<string>::iterator ele = tempCodeList.begin();ele != tempCodeList.end();++ele) {
+		addGP(*ele);
+		Sleep(100);
+	}
 
+	oimg = CaptureUtil::capture(content);
+	if (oimg.cols <= 0 || oimg.rows <= 0) {
+		throw("板块截屏内容为空");
+	}
+	img = ImgUtil::grayImage(oimg);
+	areaList = recognitionGPArea(img);
+	resultList = recognitionNum(img, areaList);
+	for (std::list<GPCodeArea>::iterator ele = resultList.begin();ele != resultList.end();++ele) {
+		bool contains = false;
+		std::list<string>::iterator e;
+		for (e = codeList.begin();e != codeList.end();e++) {
+			if (*e == (*ele).code) {
+				contains = true;
+				break;
+			}
+		}
+		if (contains) {
+			codeList.remove((*ele).code);
+		}
+	}
+
+	if (codeList.size() == 0) {
+		return true;
+	}
+
+	return false;
 }
 
 
-void add(string code) {
+void THSActionUtil::addGP(string code) {
 	//打开副屏
 	HWND sw = getSecondWindow();
 	if (sw <= 0)
@@ -161,7 +277,8 @@
 	}
 
 	HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL);
-	cv::Mat img = CaptureUtil::capture(content);
+	cv::Mat oimg = CaptureUtil::capture(content);
+	cv::Mat img = ImgUtil::grayImage(oimg);
 	if (img.cols <= 0 || img.rows <= 0) {
 		throw("板块截屏内容为空");
 	}
@@ -169,13 +286,18 @@
 	for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();++ele) {
 		GPCodeArea codeArea = *ele;
 		if (codeArea.type == IMG_TYPE_ADD) {
+			Win32Util::focus(sw);
 			RECT rc;
-			GetWindowRect(HWND(0x00161728), &rc);
+			GetWindowRect(content, &rc);
 			int y = rc.top + codeArea.starty + (codeArea.endy - codeArea.starty) / 2;
 			int x = rc.left + codeArea.startx + (codeArea.endx - codeArea.startx) / 2;
 			Win32Util::click(x, y, 50);
+			Sleep(10);
+			Win32Util::click(x, y, 50);
+			Sleep(10);
+			Win32Util::click(x, y, 50);
 			//输入股票代码
-			Win32Util::keyboardNum(code,1000);
+			Win32Util::keyboardNum(code, 1000);
 			Win32Util::keyboard(VK_RETURN, 1500);
 			//关闭按钮
 			Sleep(100);
@@ -186,56 +308,9 @@
 	}
 }
 
-//识别股票代码
-std::list<GPCodeArea>  THSActionUtil::recognitionGPArea(cv::Mat img) {
-	//获取title分隔线
-	int rows = img.rows;
-	int cols = img.cols;
-	int r;
-	int contentStartRow = -1;
-	for (r = 5;r < img.rows;r++) {
-		if (ImgDivider::isRowFull(img, r, cols - 100, cols - 5, 2)) {
-			contentStartRow = r;
-		}
+list<GPCodeArea> splitGPCodeArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col) {
 
-		if (contentStartRow > -1) {
-			break;
-		}
-	}
-
-	if (contentStartRow < 0) {
-		throw("起始行分隔出错");
-	}
-
-	//分隔列
-	int c = 0;
-	int startC = -1;
-	int endC = -1;
-	for (c = 50;c < cols;c++) {
-		if (ImgDivider::isColFull(img, c, contentStartRow + 5, contentStartRow + 100, 2)) {
-			if (startC < 0) {
-				startC = c;
-			}
-			else {
-				if (c - startC < 20) {
-					startC = c;
-				}
-				else {
-					endC = c;
-					break;
-				}
-			}
-		}
-	}
-
-	if (startC < 0 || endC < 0) {
-		throw("内容框分隔出错");
-	}
-	//cv::imshow("内容", cv::Mat(img, cv::Rect(startC, contentStartRow, endC - startC, rows - contentStartRow)));
-	std::list<GPCodeArea> resultList;
-
-	startC += 1;
-	endC -= 1;
+	list<GPCodeArea> resultList;
 
 	//分隔行内容
 	int emptyStartRow = -1;
@@ -244,8 +319,8 @@
 	int endf = -1;
 	std::list<int*> dataItemList;
 
-	for (int i = contentStartRow + 30;i < rows;i++) {
-		bool empty = ImgDivider::isRowEmpty(img, i, startC, startC + 50, 1, 64) && ImgDivider::isRowEmpty(img, i, startC + (endC - startC) / 2 - 40, startC + (endC - startC) / 2 + 40, 1, 64);
+	for (int i = start_row;i < end_row;i++) {
+		bool empty = ImgDivider::isRowEmpty(img, i, start_col, start_col + 50, 1, _IMG_BINARY_THRESHOLD) && ImgDivider::isRowEmpty(img, i, start_col + (end_col - start_col) / 2 - 40, start_col + (end_col - start_col) / 2 + 40, 1, _IMG_BINARY_THRESHOLD);
 		if (empty) {
 			if (emptyStartRow < 0) {
 				emptyStartRow = i;
@@ -264,9 +339,9 @@
 				//内容坐标
 				   //LogUtil::debug("内容的高度为:%d \n", endf - startf);
 				int* dd = (int*)malloc(sizeof(int) * 4);
-				*dd = startC;
+				*dd = start_col;
 				*(dd + 1) = startf;
-				*(dd + 2) = endC;
+				*(dd + 2) = end_col;
 				*(dd + 3) = endf;
 				//行数据高大于6才为有效的行高
 				if (endf - startf > 6)
@@ -427,6 +502,62 @@
 
 }
 
+//识别股票代码
+std::list<GPCodeArea>  THSActionUtil::recognitionGPArea(cv::Mat img) {
+
+	//imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\test.jpg", img);
+	//获取title分隔线
+	int rows = img.rows;
+	int cols = img.cols;
+	int r;
+	int contentStartRow = -1;
+	for (r = 5;r < img.rows;r++) {
+		if (ImgDivider::isRowFull(img, r, cols - 100, cols - 5, 2)) {
+			contentStartRow = r;
+		}
+
+		if (contentStartRow > -1) {
+			break;
+		}
+	}
+
+	if (contentStartRow < 0) {
+		throw("起始行分隔出错");
+	}
+
+	//分隔列
+	int c = 0;
+	int startC = -1;
+	int endC = -1;
+	for (c = 50;c < cols;c++) {
+		if (ImgDivider::isColFull(img, c, contentStartRow + 5, contentStartRow + 100, 2)) {
+			if (startC < 0) {
+				startC = c;
+			}
+			else {
+				if (c - startC < 20) {
+					startC = c;
+				}
+				else {
+					endC = c;
+					break;
+				}
+			}
+		}
+	}
+
+	if (startC < 0 || endC < 0) {
+		throw("内容框分隔出错");
+	}
+	//cv::imshow("内容", cv::Mat(img, cv::Rect(startC, contentStartRow, endC - startC, rows - contentStartRow)));
+
+	startC += 1;
+	endC -= 1;
+	std::list<GPCodeArea> resultList = splitGPCodeArea(img, contentStartRow + 30, startC, rows, endC);
+	return resultList;
+
+}
+
 std::list<GPCodeArea>   THSActionUtil::recognitionNum(cv::Mat img, std::list<GPCodeArea> areaList) {
 
 	if (!recognitionManager) {
@@ -437,11 +568,34 @@
 
 	std::list<GPCodeArea>::iterator ele;
 
+	int index = 0;
 	for (ele = areaList.begin();ele != areaList.end();ele++) {
+		index++;
 		GPCodeArea codeArea = *ele;
 		if (codeArea.type == IMG_TYPE_GP) {
 			cv::Mat nums = cv::Mat(img, cv::Rect(codeArea.startx, codeArea.starty, codeArea.endx - codeArea.startx + 1, codeArea.endy - codeArea.starty + 1));
-			std::list<cv::Mat> list2 = ImgUtil::splitNum(nums);
+			//保存分隔的数据
+			if (false) {
+				string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\";
+				path.append(to_string(index));
+				path.append(".jpg");
+				cv::imwrite(path, nums);
+			}
+
+			std::list<cv::Mat> list2 = ImgUtil::splitNum(nums, 96);
+			if (false) {
+				std::list<cv::Mat>::iterator e;
+				int ci = 0;
+				for (e = list2.begin();e != list2.end();e++) {
+					ci++;
+					string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\";
+					path.append(to_string(index)).append("_").append(to_string(ci));
+					path.append(".jpg");
+					cv::imwrite(path, *e);
+				}
+
+			}
+
 			std::list<uchar> resultList = recognitionManager->recognitionGPCode(list2);
 			std::list<uchar>::iterator ele1;
 			string code = "";
@@ -449,9 +603,231 @@
 				code.append(to_string(*ele1));
 			}
 			codeArea.code = code;
+			cout << code << endl;
 			codeList.push_back(codeArea);
 		}
 	}
 
 	return codeList;
+}
+
+
+//分隔L2数据的目录
+std::list<GPCodeArea> splitL2Cate(cv::Mat img) {
+	int cols = img.cols;
+	int contentStartRow = -1;
+	int contentEndRow = -1;
+	for (int r = 5;r < img.rows;r++) {
+		if (ImgDivider::isRowFull(img, r, 10, 200, 2, 10, 30) && ImgDivider::isRowFull(img, r, img.cols - 200, img.cols - 1, 2, 10, 30)) {
+			if (contentStartRow < 0)
+			{
+				contentStartRow = r;
+			}
+			else {
+				if (r - contentStartRow > 10) {
+					contentEndRow = r;
+
+				}
+
+			}
+		}
+
+		if (contentStartRow > -1 && contentEndRow > -1) {
+			break;
+		}
+	}
+
+	if (contentStartRow < 0 || contentEndRow < 0) {
+		throw("起始行或结束行分隔出错");
+	}
+
+	//分隔列
+	list<int*> dataColIndexs;
+	int startf = -1;
+	int endf = -1;
+	int startIndex = -1;
+	for (int i = 10;i < cols;i++) {
+		if (startIndex == -1) {
+			startIndex = i;
+		}
+
+		bool full = ImgDivider::isColFull(img, i, contentStartRow, contentEndRow, 2);
+		if (full) {
+			if (startf < 0)
+			{
+				startf = i;
+				endf = i;
+			}
+			else {
+				endf = i;
+			}
+		}
+		else {
+			if (startf > -1 && endf > -1) {
+				int width = endf - startf + 1;
+				int* dd = (int*)malloc(sizeof(int) * 2);
+
+				*dd = startIndex;
+				*(dd + 1) = startf - 1;
+
+				dataColIndexs.push_back(dd);
+				startIndex = i;
+			}
+			startf = -1;
+			endf = -1;
+		}
+
+	}
+
+	if (startf > -1 && endf > -1) {
+		int width = endf - startf + 1;
+		int* dd = (int*)malloc(sizeof(int) * 2);
+
+		*dd = startIndex;
+		*(dd + 1) = startf - 1;
+		LogUtil::debug("列数据:%d-%d\n", *dd, *(dd + 1));
+
+		dataColIndexs.push_back(dd);
+
+		startf = -1;
+		endf = -1;
+	}
+
+	if (cols - startIndex > 50) {
+
+		int* dd = (int*)malloc(sizeof(int) * 2);
+
+		*dd = startIndex;
+		*(dd + 1) = cols - 1;
+
+		dataColIndexs.push_back(dd);
+	}
+
+
+
+
+	std::list<GPCodeArea> areaList;
+	list<int*>::iterator ele;
+	for (ele = dataColIndexs.begin();ele != dataColIndexs.end();ele++) {
+		int* p = *ele;
+		int startx = *p;
+		int endx = *(p + 1);
+
+		GPCodeArea area = GPCodeArea();
+		area.startx = startx;
+		area.endx = endx;
+		area.starty = contentStartRow;
+		area.endy = contentEndRow;
+		areaList.push_back(area);
+	}
+	return areaList;
+}
+
+
+
+std::map<int,string> THSActionUtil::getListenL2GPCodes() {
+	std::list<GPCodeArea> areaList = getListenL2GP();
+	std::map<int, string> map;
+	for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();ele++) {
+		GPCodeArea data = (*ele);
+		if (map.count(data.cateIndex)==0&&data.type== IMG_TYPE_GP) {
+			map[data.cateIndex] = data.code;
+		}
+	}
+
+	return map;
+}
+
+
+std::list<GPCodeArea> THSActionUtil::getListenL2GP() {
+	//截图当前有哪些股票代码
+	list<HWND> wlist = Win32Util::searchWindow("同花顺(");
+	HWND mainPage = 0;
+	list<HWND>::iterator ele;
+	for (ele = wlist.begin();ele != wlist.end();ele++) {
+		HWND hwnd = *ele;
+		string str = Win32Util::getWindowName(hwnd);
+		if (isMainScreen(str)) {
+			cout << hwnd << endl;
+			//获取尺寸
+			RECT rc;
+			GetWindowRect(hwnd, &rc);
+			if (rc.right - rc.left > 200 && rc.bottom - rc.top > 200) {
+				mainPage = hwnd;
+				break;
+			}
+		}
+	}
+	if (mainPage <= 0) {
+		throw string("L2监听未打开");
+	}
+
+	HWND content = FindWindowExA(mainPage, NULL, "AfxFrameOrView100s", NULL);
+	//截图
+	cv::Mat oimg = CaptureUtil::capture(content);
+	cv::Mat img = ImgUtil::grayImage(oimg);
+	oimg.release();
+	//分隔图片
+
+	std::list<GPCodeArea>  areaList = splitL2Cate(img);
+
+	int index = 0;
+	for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();ele++) {
+		GPCodeArea area = *ele;
+		index++;
+		std::list<GPCodeArea> resultList = splitGPCodeArea(img, area.starty + 20, area.startx, area.endy, area.endx);
+		if (false) {
+			std::string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\";
+			path.append(std::to_string(index)).append("_listen.jpg");
+			imwrite(path, cv::Mat(img, cv::Rect(area.startx, area.starty, area.endx - area.startx + 1, area.endy - area.starty + 1)));
+		}
+
+		for (std::list<GPCodeArea>::iterator ele1 = resultList.begin();ele1 != resultList.end();ele1++) {
+			GPCodeArea areaC = *ele1;
+			if (areaC.type == IMG_TYPE_GP) {
+				list<cv::Mat> nums = ImgUtil::splitNum(cv::Mat(img, cv::Rect(areaC.startx, areaC.starty, areaC.endx - areaC.startx + 1, areaC.endy - areaC.starty + 1)), 96);
+				if (!recognitionManager) {
+					recognitionManager = new RecognitionManager();
+				}
+				if (nums.size() != 6) {
+					throw string("代码分隔出错");
+				}
+
+
+				list<uchar>  rresult = recognitionManager->recognitionGPCode(nums);
+				string num;
+				for (std::list<uchar>::iterator e = rresult.begin();e != rresult.end();e++) {
+					num.append(to_string(*e));
+				}
+				(*ele1).code = num;
+				(*ele1).cateIndex = index-1;
+			}
+		}
+
+		return resultList;
+	}
+
+}
+bool THSActionUtil::setListenL2GP(int p, string code) {
+
+
+	std::list<GPCodeArea> resultList = getListenL2GP();
+
+	HWND content = FindWindowExA(getL2Win(), NULL, "AfxFrameOrView100s", NULL);
+
+	int index = 0;
+	for (std::list<GPCodeArea>::iterator ele = resultList.begin();ele != resultList.end();ele++) {
+		GPCodeArea result = *ele;
+		if (result.code == code) {
+			//点击
+			RECT rc;
+			GetWindowRect(content, &rc);
+			int x = rc.left + result.startx + 5;
+			int y = rc.top + result.starty + 5;
+			Win32Util::focus(content);
+			Win32Util::click(x, y, 50);
+			return true;
+		}
+	}
+	return false;
 }
\ No newline at end of file

--
Gitblit v1.8.0