admin
2022-08-25 14db1514fec89db599766d4996b4bb1fead0eff0
'完善'
25个文件已修改
6个文件已添加
1567 ■■■■■ 已修改文件
ConsoleApplication/ConsoleApplication.vcxproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ConsoleApplication.vcxproj.filters 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/CurrentPriceCapture.cpp 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/CurrentPriceCapture.h 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/L2DataCapture.cpp 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/L2DataCapture.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/LimitUpCapture.cpp 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/LimitUpCapture.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSActionUtil.cpp 251 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSActionUtil.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSL2RepairTool.cpp 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSL2RepairTool.h 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TaskChecker.cpp 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TaskChecker.h 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TradeListCapture.cpp 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TradeListCapture.h 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/Win32Util.cpp 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/Win32Util.h 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/main.cpp 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Setup1/Setup1.vdproj 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/JsonUtil.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/SocketManager.cpp 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/SocketManager.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/app.aps 补丁 | 查看 | 原始文档 | blame | 历史
app/app.rc 补丁 | 查看 | 原始文档 | blame | 历史
app/app.vcxproj.user 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/appDlg.cpp 399 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/appDlg.h 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/resource.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/setting.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/user.txt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ConsoleApplication.vcxproj
@@ -144,7 +144,10 @@
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="CurrentPriceCapture.cpp" />
    <ClCompile Include="TaskChecker.cpp" />
    <ClCompile Include="THSGPDataCapture.cpp" />
    <ClCompile Include="THSL2RepairTool.cpp" />
    <ClCompile Include="TradeQueueCapture.cpp" />
    <ClCompile Include="TradeListCapture.cpp" />
    <ClCompile Include="CaptureUtil.cpp" />
@@ -164,7 +167,10 @@
    <ClCompile Include="win32_screen_shots.cpp" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="CurrentPriceCapture.h" />
    <ClInclude Include="TaskChecker.h" />
    <ClInclude Include="THSGPDataCapture.h" />
    <ClInclude Include="THSL2RepairTool.h" />
    <ClInclude Include="TradeQueueCapture.h" />
    <ClInclude Include="TradeListCapture.h" />
    <ClInclude Include="CaptureUtil.h" />
ConsoleApplication/ConsoleApplication.vcxproj.filters
@@ -69,6 +69,15 @@
    <ClCompile Include="THSGPDataCapture.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TaskChecker.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="CurrentPriceCapture.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="THSL2RepairTool.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="resource.h">
@@ -125,6 +134,15 @@
    <ClInclude Include="THSGPDataCapture.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TaskChecker.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="CurrentPriceCapture.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="THSL2RepairTool.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="ConsoleApplication.rc">
ConsoleApplication/CurrentPriceCapture.cpp
New file
@@ -0,0 +1,280 @@
#include "CurrentPriceCapture.h"
#include "THSActionUtil.h"
#include <set>
#include "Win32Util.h"
#include "TaskChecker.h"
OpenCLExcuter* CurrentPriceCapture::openCLExcuter;
bool CurrentPriceCapture::inited;
//是否正在执行
bool CurrentPriceCapture::running;
bool CurrentPriceCapture::kill;
CallbackFun_Current_Price CurrentPriceCapture::data_callback;
std::list<cv::Point> CurrentPriceCapture::pointList;
void* CurrentPriceCapture::context;
HWND CurrentPriceCapture::win;
RecognitionManager* CurrentPriceCapture::recognitionManager;
void CurrentPriceCapture::_run() {
    while (true) {
        if (kill)
            break;
        TaskChecker::clientLiveTime.limitUp = clock();
        if (running && inited) {
            clock_t start = clock();
            try {
                cout << "现价识别" << endl;
                list<CurrentPriceData> codes = capture();
                cout << "现价识别耗时:" << clock() - start << "  数量:" << codes.size() << endl;
                data_callback(codes, context);
                codes.clear();
            }
            catch (...) {
                cout<<"现价识别error"<<endl;
            }
            Sleep(10);
        }
        else {
            Sleep(1000);
        }
    }
}
void CurrentPriceCapture::init(CallbackFun_Current_Price callback, void* contex) {
    data_callback = callback;
    context = contex;
    running = false;
    kill = false;
    recognitionManager = new RecognitionManager();
    openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
    thread rt(&(CurrentPriceCapture::_run));
    rt.detach();
    inited = true;
    refreshHWND();
}
void CurrentPriceCapture::reCreateRunning()
{
    kill = TRUE;
    Sleep(4000);
    kill = FALSE;
    thread rt(&(CurrentPriceCapture::_run));
    rt.detach();
}
void CurrentPriceCapture::refreshHWND() {
    HWND hwnd = THSActionUtil::getMainWin();
    if (hwnd <= 0)
        throw string("同花顺主屏未打开");
    //采用快捷键打开
    Win32Util::focus(hwnd);
    //Win32Util::keyboardNum("51", 200);
    //Win32Util::keyboard(VK_RETURN, 10);
    Sleep(1000);
    HWND content = FindWindowExA(hwnd, NULL, "AfxFrameOrView100s", NULL);
    if (content <= 0)
        throw string("未获取到内容窗口句柄");
    win = content;
}
bool CurrentPriceCapture::isRunning() {
    return running;
}
list<CurrentPriceData> CurrentPriceCapture::capture(cv::Mat oimg) {
    cv::Mat grayImg = cv::Mat::zeros(oimg.rows, oimg.cols, CV_8UC1);//ImgUtil::grayImage(oimg);
    uchar* imgData = (uchar*)malloc(sizeof(uchar) * oimg.rows * oimg.cols);
    if (oimg.channels() == 3)
    {
        openCLExcuter->rgb2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
    }
    else {
        openCLExcuter->rgba2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
    }
    grayImg.data = imgData;
    list<int*> rowData = THSActionUtil::splitPlateRowArea(grayImg);
    //每行的元素个数
    int ele_count_per_line = 2;
    int* splitResult = (int*)malloc(sizeof(int) * 4 * 4 * rowData.size());
    int* rowIndex = (int*)malloc(sizeof(int) * 4 * rowData.size());
    int count = 0;
    for (std::list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
        string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
        path.append(to_string(count)).append(".jpg");
        //cv::imwrite(path, cv::Mat(grayImg, cv::Rect((*ele)[0], (*ele)[1], (*ele)[2] - (*ele)[0] + 1, (*ele)[3] - (*ele)[1] + 1)));
        rowIndex[4 * count + 0] = (*ele)[0];
        rowIndex[4 * count + 1] = (*ele)[1];
        rowIndex[4 * count + 2] = (*ele)[2];
        rowIndex[4 * count + 3] = (*ele)[3];
        free(*ele);
        count++;
    }
    int line_number_count = ele_count_per_line * 6;
    openCLExcuter->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line,1,2,splitResult);
    /*
    *测试
    for (int i = 0;i < rowData.size();i++) {
        for (int j = 0;j < line_number_count;j++) {
            int sx = splitResult[(line_number_count * i + j) * 4 + 0];
            int sy = splitResult[(line_number_count * i + j) * 4 + 1];
            int ex = splitResult[(line_number_count * i + j) * 4 + 2];
            int ey = splitResult[(line_number_count * i + j) * 4 + 3];
            string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
            path.append(to_string(i)).append("_").append(to_string(j)).append(".jpg");
            //cv::imwrite(path, cv::Mat(grayImg, cv::Rect(sx, sy, ex - sx + 1, ey - sy + 1)));
        }
    }
    */
    int start = 4 * 4 * 1 + 4 * 1;
    string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
    path.append(to_string(start)).append(".jpg");
    //cv::imwrite(path, cv::Mat(grayImg,cv::Rect(splitResult[start], splitResult[start+1], splitResult[start+2]- splitResult[start]+1, splitResult[start+3]- splitResult[start+1]+1)));
    //cv::imwrite(path, cv::Mat(grayImg, cv::Rect(447, 102, 454-447+1,111-102+1 )));
    //分割数字
    unsigned char* zeroData = (unsigned char*)malloc(sizeof(unsigned char) * _NUMBER_GP_CODE_WIDTH * _NUMBER_GP_CODE_HEIGHT);
    for (int r = 0;r < _NUMBER_GP_CODE_HEIGHT;r++) {
        for (int c = 0;c < _NUMBER_GP_CODE_WIDTH;c++)
        {
            zeroData[r * _NUMBER_GP_CODE_WIDTH + c] = ImgUtil::NUMS_GP_CODE[0].data.ptr<uchar>(r)[c];
        }
    }
    unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * rowData.size()) * _NUMBER_GP_CODE_WIDTH * 10 * line_number_count);
    UcharDataInfo typesData = UcharDataInfo();
    unsigned char types[] = { NUM_TYPE_CODE, NUM_TYPE_PRICE };
    typesData.length = 2;
    typesData.data = types;
    int length_per_num = 6;
    openCLExcuter->splitPlateNum(grayImg, IntDataInfo({ splitResult,(int)(ele_count_per_line * rowData.size()) }), UcharDataInfo({ totalNumberData, -1 }), typesData, zeroData, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, ele_count_per_line, length_per_num);
    //识别数字
    uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * rowData.size()) * _NUMBER_GP_CODE_WIDTH * 10 * line_number_count);
    openCLExcuter->createNumberTemplates(rowData.size(), _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, line_number_count, ImgUtil::numsOneLevel_gpcode, templateNums);
    uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_GP_CODE_HEIGHT, _NUMBER_GP_CODE_WIDTH * 10 * line_number_count, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, line_number_count);
    list<CurrentPriceData> dataList;
    for (int i = 0;i < rowData.size();i++) {
        CurrentPriceData currentData = CurrentPriceData();
        string code = "";
        for (int j = 0;j < 6;j++)
        {
            code.append(to_string(numberResult[i][j]));
        }
        string price = "";
        for (int j = 0;j < 6;j++)
        {
            if (j == 4) {
                price.append(".");
            }
            price.append(to_string(numberResult[i][6 * 1 + j]));
        }
        currentData.index = i;
        currentData.code = code;
        currentData.price = price;
        if ( currentData.price != "0000.00") {
            dataList.push_back(currentData);
        }
        free(numberResult[i]);
    }
    free(numberResult);
    int* unitData = (int*)malloc(sizeof(int) * 4 * dataList.size());
    free(rowIndex);
    free(splitResult);
    free(zeroData);
    free(templateNums);
    free(unitData);
    free(imgData);
    grayImg.release();
    return dataList;
}
list<CurrentPriceData> CurrentPriceCapture::capture() {
    if (win <= 0) {
        throw string("未找到目标标的窗口");
    }
    cout << "开始运行" << endl;
    RECT wrect;
    GetWindowRect(win,&wrect);
    list<CurrentPriceData> flist;
    set<string> codesSet;
        for (int i = 0;i < 3;i++)
        {
            if (kill) {
                break;
            }
            int x = wrect.right - 50;
            int y = wrect.top + 50;
            SendMessage(win, WM_MOUSEWHEEL, 0, MAKEWORD(x, y));
            Sleep(100);
            cv::Mat oimg = CaptureUtil::capture(win);
            list<CurrentPriceData> codes = capture(oimg);
            for (list<CurrentPriceData>::iterator ele = codes.begin();ele != codes.end();ele++) {
                string code = (*ele).code;
                if (codesSet.count(code) == 0&&stof((*ele).price)>0) {
                    codesSet.insert(code);
                    flist.push_back(*ele);
                }
            }
            codes.clear();
            Sleep(50);
    }
    return flist;
}
//全部开始
void CurrentPriceCapture::start() {
    running = true;
}
//全部结束
void CurrentPriceCapture::stop() {
    running = false;
}
bool CurrentPriceCapture::isInited() {
    return inited;
}
ConsoleApplication/CurrentPriceCapture.h
New file
@@ -0,0 +1,65 @@
#pragma once
#include <string>
#include <iostream>
#include <list>
#include "ImgUtil.h"
#include "RecognitionManager.h"
#include "THSActionUtil.h"
//现价
struct CurrentPriceData
{
    string code;
    string price;
    //辅助功能
    int index;
};
//涨停获取
typedef void (*CallbackFun_Current_Price)(list<CurrentPriceData> codeList, void* contex);
class CurrentPriceCapture
{
private:
    static OpenCLExcuter* openCLExcuter;
    static RecognitionManager* recognitionManager;
    static bool inited;
    //是否正在执行
    static bool running;
    static bool kill;
    static CallbackFun_Current_Price data_callback;
    static void* context;
    static void _run();
    static HWND win;
    static HWND menuWin;
    static    std::list<cv::Point> pointList;
public:
    void init(CallbackFun_Current_Price callback, void* context);
    //重新创建运行线程
    void reCreateRunning();
    void refreshHWND();
    bool isRunning();
    static list<CurrentPriceData> capture(cv::Mat img);
    static list<CurrentPriceData> capture();
    //全部开始
    void start();
    //全部结束
    void stop();
    bool isInited();
};
ConsoleApplication/L2DataCapture.cpp
@@ -3,6 +3,7 @@
#include<fstream>
#include "THSActionUtil.h"
#include <thread>
#include "TaskChecker.h"
bool L2DataCapture::inited;
bool L2DataCapture::tradeTimeCapture;
@@ -13,6 +14,7 @@
//是否正在执行
bool L2DataCapture::running;
bool L2DataCapture::runnings[THS_FRAME_COUNT];
bool L2DataCapture::killRunnings[THS_FRAME_COUNT];
clock_t L2DataCapture::latest_running_times[THS_FRAME_COUNT];
CallbackFun L2DataCapture::data_callback;
@@ -40,7 +42,9 @@
void L2DataCapture::_run(int index)
{
    while (true) {
        if (killRunnings[index])
            break;
        TaskChecker::clientLiveTime.l2[index] = clock();
        if (tradeTimeCapture) {
            int time = getNowSecondTime();
            //9:20-11:31  12:59-15:01
@@ -134,7 +138,16 @@
        tradeQueueCapture[i] = new TradeQueueCapture();
    }
    running = false;
    int length = sizeof(runnings) / sizeof(runnings[0]);
    for (int i = 0;i < length;i++) {
        runnings[i] = false;
        thread rt(&(L2DataCapture::_run), i);
        rt.detach();
        killRunnings[i] = FALSE;
        //thread rt_trade_queue(&(L2DataCapture::_run_trade_queue), i);
        //rt_trade_queue.detach();
    }
    //获取同花顺窗口句柄
    try {
@@ -143,17 +156,18 @@
    catch (string st) {
        throw st;
    }
    running = false;
    int length = sizeof(runnings) / sizeof(runnings[0]);
    for (int i = 0;i < length;i++) {
        runnings[i] = false;
        thread rt(&(L2DataCapture::_run), i);
        rt.detach();
        //thread rt_trade_queue(&(L2DataCapture::_run_trade_queue), i);
        //rt_trade_queue.detach();
    }
void L2DataCapture::reCreateChannelRunner(int index)
{
    //先杀死原有线程
    killRunnings[index] = TRUE;
    Sleep(500);
    killRunnings[index] = FALSE;
    thread rt(&(L2DataCapture::_run), index);
    rt.detach();
}
bool L2DataCapture::isRunning() {
@@ -201,13 +215,15 @@
    clock_t  starttime = clock();
    /*
    if (1 > 0) {
     std:map<string, TradeData> map;
        return map;
    }
    */
    list<TradeData> resultList=  captureLevel2TradeData(openCLExcuter[identify], oimg, identify);
    std::cout << "-------L2行情识别结束任务: threadid-" << std::this_thread::get_id() << "  序号:" << identify << " 耗时:" << clock() - starttime  <<"  数据量:"<< resultList.size() << endl;
    return resultList;
}
list<TradeData> L2DataCapture::captureLevel2TradeData(OpenCLExcuter* openCLExcuter, cv::Mat oimg, int identify)
{
    //LogUtil::debug("截图完成");
    clock_t time_1 = clock();
@@ -225,17 +241,17 @@
    else {
        if (oimg.channels() == 3)
        {
            openCLExcuter[identify]->rgb2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
            openCLExcuter->rgb2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
        }
        else {
            openCLExcuter[identify]->rgba2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
            openCLExcuter->rgba2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
        }
        img.data = imgData;
        oimg.release();
        clock_t time_2_ = clock();
        if (identify == 0)
        {
            std::cout << "灰度完成: threadid-" << std::this_thread::get_id() << " 耗时:" << (time_2_ - time_1) << endl;
            std::cout << "灰度完成: threadid-" << std::this_thread::get_id() << " 耗时:" << (time_2_ - time_1) << "   截图尺寸:" << img.cols << "x" << img.rows << endl;
            std::cout <<"通道数:"<<oimg.channels()<<endl;
            
@@ -275,7 +291,7 @@
    }
    //一维分块图像数据
    int* rowSplitDataOneLevel = (int*)malloc(sizeof(int) * rowDataList.size() * 4 * 7);
    openCLExcuter[identify]->splitL2RowData(imgData, img.cols, img.rows, rowDataOneLevel, rowDataList.size(), rowSplitDataOneLevel);
    openCLExcuter->splitL2RowData(imgData, img.cols, img.rows, rowDataOneLevel, rowDataList.size(), rowSplitDataOneLevel);
    free(rowDataOneLevel);
    /*
@@ -326,7 +342,7 @@
    //图像识别(除开数字的部分)
    int* notNumberResult = (int*)malloc(sizeof(int) * rowDataList.size() * 3);
    openCLExcuter[identify]->recognitionNotNum(img.data, img.cols, img.rows, rowSplitDataOneLevel, 7, rowDataList.size(), notNumberResult);
    openCLExcuter->recognitionNotNum(img.data, img.cols, img.rows, rowSplitDataOneLevel, 7, rowDataList.size(), notNumberResult);
    int i = 0;
@@ -453,7 +469,7 @@
    if (identify == 0)
        std::cout << "数据准备-0数据准备: threadid-" << std::this_thread::get_id() << " 耗时:" << time_33 - time_32 << "总耗时:" << time_33 - time_1 << endl;
    openCLExcuter[identify]->splitL2Num(imgData, img.cols, img.rows, pos, 4 * rowDataList.size(), zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, totalNumberData);
    openCLExcuter->splitL2Num(imgData, img.cols, img.rows, pos, 4 * rowDataList.size(), zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, totalNumberData);
    free(zeroData);
    free(pos);
@@ -475,7 +491,7 @@
    //准备模板数字
    uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowDataList.size()) * _NUMBER_L2_WIDTH * 10 * _NUMBER_L2_TOTAL_NUMBER);
    openCLExcuter[identify]->createNumberTemplates(rowDataList.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, ImgUtil::numsOneLevel_level2, templateNums);
    openCLExcuter->createNumberTemplates(rowDataList.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, ImgUtil::numsOneLevel_level2, templateNums);
    //ImgUtil::createTemplateNumData(data.size());
    clock_t time_4 = clock();
@@ -500,7 +516,7 @@
    //数字识别
    uchar** numberResult = openCLExcuter[identify]->recognition_numbers(totalNumberData, templateNums, rowDataList.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * _NUMBER_L2_TOTAL_NUMBER, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER);
    uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowDataList.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * _NUMBER_L2_TOTAL_NUMBER, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER);
    //释放内存
    free(totalNumberData);
    free(templateNums);
@@ -555,10 +571,6 @@
    rowDataList.clear();
    list<int*>().swap(rowDataList);
    free(rowSplitDataOneLevel);
    if (identify == 0)
        std::cout << "-------L2行情识别结束任务: threadid-" << std::this_thread::get_id() << "  序号:" << identify << " 耗时:" << clock() - starttime << endl;
    return resultList;
}
ConsoleApplication/L2DataCapture.h
@@ -24,6 +24,7 @@
    //是否正在执行
    static bool running;
    static bool runnings[THS_FRAME_COUNT];
    static bool killRunnings[THS_FRAME_COUNT];
    static clock_t latest_running_times[THS_FRAME_COUNT];
    static string gpCodes[THS_FRAME_COUNT];
@@ -45,6 +46,8 @@
    //初始化
    void init(CallbackFun callback, CallbackFun_Trade_Queue trade_queue_callback, void* context);
    void reCreateChannelRunner(int index);
    void refreshHWND();
    
@@ -68,6 +71,7 @@
    //捕获level2的盘口数据
    static list<TradeData>  captureLevel2TradeData(HWND hwnd,int index) throw(int);
    static list<TradeData>  captureLevel2TradeData(cv::Mat oimg,int identify);
    static list<TradeData>  captureLevel2TradeData(OpenCLExcuter *openCLExcuter, cv::Mat oimg, int identify);
    //设置代码
    static void setGPCode(int index, string code);
    //获取代码
ConsoleApplication/LimitUpCapture.cpp
@@ -2,10 +2,13 @@
#include "THSActionUtil.h"
#include <set>
#include "Win32Util.h"
#include "TaskChecker.h"
OpenCLExcuter* LimitUpCapture::openCLExcuter;
bool LimitUpCapture::inited;
//是否正在执行
bool LimitUpCapture::running;
bool LimitUpCapture::kill;
CallbackFun_Limit_Up LimitUpCapture::data_callback;
@@ -27,6 +30,9 @@
void LimitUpCapture::_run() {
    while (true) {
        if (kill)
            break;
        TaskChecker::clientLiveTime.limitUp = clock();
        if (running && inited) {
            clock_t start = clock();
            list<LimitUpData> codes = captureLimitUpCodes();
@@ -34,6 +40,9 @@
            data_callback(codes, context);
            codes.clear();
            Sleep(3000);
        }
        else {
            Sleep(1000);
        }
    }
}
@@ -44,6 +53,7 @@
    data_callback = callback;
    context = contex;
    running = false;
    kill = false;
    recognitionManager = new RecognitionManager();
    openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
@@ -51,6 +61,14 @@
    rt.detach();
    inited = true;
    refreshHWND();
}
void LimitUpCapture::reCreateRunning()
{
    kill = TRUE;
    Sleep(4000);
    kill = FALSE;
    thread rt(&(LimitUpCapture::_run));
    rt.detach();
}
void LimitUpCapture::refreshHWND() {
    HWND hwnd = getWindow();
@@ -180,7 +198,6 @@
    int* rowIndex = (int*)malloc(sizeof(int) * 4 * rowData.size());
    int count = 0;
    for (std::list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
        string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
        path.append(to_string(count)).append(".jpg");
        //cv::imwrite(path, cv::Mat(grayImg, cv::Rect((*ele)[0], (*ele)[1], (*ele)[2] - (*ele)[0] + 1, (*ele)[3] - (*ele)[1] + 1)));
@@ -346,6 +363,9 @@
    list<cv::Point>::iterator ele;
    for (ele = pointList.begin();ele != pointList.end();ele++) {
        if (kill) {
            break;
        }
        int x = (*ele).x;//+ menuRect.left;
        int y = (*ele).y;//+ menuRect.top;
        printf("x:%d y:%d\n", x, y);
@@ -359,6 +379,9 @@
        
        for (int i = 0;i < 3;i++)
        {
            if (kill) {
                break;
            }
            int x = wrect.right - 50;
            int y = wrect.top + 50;
            SendMessage(win, WM_MOUSEWHEEL, 0, MAKEWORD(x, y));
ConsoleApplication/LimitUpCapture.h
@@ -30,6 +30,8 @@
    //是否正在执行
    static bool running;
    static bool kill;
    static CallbackFun_Limit_Up data_callback;
    static void* context;
@@ -45,6 +47,10 @@
public:
    void init(CallbackFun_Limit_Up callback, void* context);
    //重新创建运行线程
    void reCreateRunning();
    void refreshHWND();
    bool isRunning();
ConsoleApplication/THSActionUtil.cpp
@@ -1,6 +1,8 @@
#include "THSActionUtil.h"
#include "ImgDivider.h"
#include "Win32Util.h"
#include <fstream>
bool isL2Screen(string str) {
    if (str.find("同花顺(") != string::npos) {
@@ -49,7 +51,7 @@
        std::string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\";
        path.append(std::to_string(rand())).append("_listen.jpg");
        imwrite(path, img);
        throw string("代码数字分隔出错");
        throw string("代码数字分隔出错(32)");
    }
    return    nums;
}
@@ -181,19 +183,36 @@
    }
    if (!zp) {
        throw string("同花顺主屏L2窗口未打开");
        throw string("同花顺主屏L2窗口未打开(01)");
    }
    if (!fp) {
        throw string("同花顺副屏1没有打开");
        throw string("同花顺副屏1没有打开(02)");
    }
    if (!fp2) {
        throw string("同花顺副屏2没有打开");
        throw string("同花顺副屏2没有打开(03)");
    }
    return true;
}
void THSActionUtil::openL2Screen() {
    HWND l2 = getL2Win();
    if (l2 <= 0) {
        //尝试打开主屏
        HWND main = THSActionUtil::getMainWin();
        if (main > 0)
        {
            Win32Util::focus(main);
            Win32Util::keyboardNum(".00", 200);
            Win32Util::keyboard(13, 10);
            Sleep(1000);
        }
    }
}
void THSActionUtil::openSecondScreen() {
@@ -230,7 +249,7 @@
    if (!open) {
        if (mainPage <= 0) {
            throw string("未找到首页");
            throw string("未找到首页(04)");
        }
        Win32Util::focus(mainPage);
@@ -290,7 +309,7 @@
    if (!open) {
        if (mainPage <= 0) {
            throw string("未找到首页");
            throw string("未找到首页(05)");
        }
        Win32Util::focus(mainPage);
@@ -315,6 +334,26 @@
    }
}
void THSActionUtil::openTradeSuccessScreen()
{
    HWND hwnd = getTradeSuccessWindow();
    if (hwnd <= 0) {
        throw string("交易窗口未打开(06)");
    }
    hwnd = FindWindowExA(hwnd, NULL, "AfxMDIFrame140s", NULL);
    hwnd = FindWindowExA(hwnd, NULL, "AfxWnd140s", NULL);
    hwnd = FindWindowExA(hwnd, NULL, NULL, "HexinScrollWnd");
    hwnd = FindWindowExA(hwnd, NULL, NULL, "HexinScrollWnd2");
    hwnd = FindWindowExA(hwnd, NULL, "SysTreeView32", NULL);
    if (hwnd <= 0) {
        throw string("未找到交易窗口菜单(07)");
    }
    //点击当日委托
    SendMessage(hwnd, WM_LBUTTONDOWN, 0x00000001, 0x00E70047);
    SendMessage(hwnd, WM_LBUTTONUP, 0x00000000, 0x00E70047);
}
//添加股票
bool THSActionUtil::setGP(std::string quickCode, list<std::string> codeList, RecognitionManager* recognitionManager) {
@@ -333,7 +372,7 @@
        sw = getSecondWindow();
    }
    if (sw <= 0) {
        throw string("未打开副屏");
        throw string("未打开副屏(11)");
    }
    //打开板块
@@ -354,7 +393,7 @@
    cout << "副屏截图:" << oimg.rows << "-" << oimg.cols << endl;
    if (oimg.cols <= 0 || oimg.rows <= 0) {
        throw string("板块截屏内容为空");
        throw string("板块截屏内容为空(12)");
    }
    cv::Mat img = ImgUtil::grayImage(oimg);
@@ -419,7 +458,7 @@
    oimg = CaptureUtil::capture(content);
    if (oimg.cols <= 0 || oimg.rows <= 0) {
        throw string("板块截屏内容为空");
        throw string("板块截屏内容为空(13)");
    }
    img = ImgUtil::grayImage(oimg);
    areaList = recognitionGPArea(img);
@@ -456,14 +495,14 @@
        sw = getSecondWindow();
    }
    if (sw <= 0) {
        throw string("未打开副屏");
        throw string("未打开副屏(14)");
    }
    HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL);
    cv::Mat oimg = CaptureUtil::capture(content);
    cv::Mat img = ImgUtil::grayImage(oimg);
    if (img.cols <= 0 || img.rows <= 0) {
        throw string("板块截屏内容为空");
        throw string("板块截屏内容为空(15)");
    }
    std::list<GPCodeArea>  areaList = recognitionGPArea(img);
    for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();++ele) {
@@ -585,7 +624,7 @@
    }
    if (contentStartRow < 0|| contentEndRow<0) {
        throw string("起始行分隔出错");
        throw string("起始行分隔出错(16)");
    }
    //分隔列
@@ -601,7 +640,7 @@
    }
    if (startC < 0) {
        throw string("内容框分隔出错");
        throw string("内容框分隔出错(17)");
    }
    GPCodeArea area = GPCodeArea();
    area.startx = 0;
@@ -629,7 +668,7 @@
    }
    if (contentStartRow < 0) {
        throw string("起始行分隔出错");
        throw string("起始行分隔出错(18)");
    }
    //分隔列
@@ -654,7 +693,7 @@
    }
    if (startC < 0 || endC < 0) {
        throw string("内容框分隔出错");
        throw string("内容框分隔出错(19)");
    }
    //再次分隔内容框,排除干扰
@@ -864,7 +903,7 @@
    }
    if (contentStartRow < 0) {
        throw string("起始行分隔出错");
        throw string("起始行分隔出错(20)");
    }
    //分隔列
@@ -889,7 +928,7 @@
    }
    if (startC < 0 || endC < 0) {
        throw string("内容框分隔出错");
        throw string("内容框分隔出错(21)");
    }
    //cv::imshow("内容", cv::Mat(img, cv::Rect(startC, contentStartRow, endC - startC, rows - contentStartRow)));
@@ -900,7 +939,7 @@
        resultList = splitGPCodeArea(img, contentStartRow + 25, startC, rows, endC);
    }
    catch (...) {
        throw string("分隔代码区域出错");
        throw string("分隔代码区域出错(22)");
    }
    return resultList;
}
@@ -996,7 +1035,7 @@
    }
    //contentStartRow < 0 || contentEndRow < 0
    if (contentStartRow < 0) {
        throw string("起始行或结束行分隔出错");
        throw string("起始行或结束行分隔出错(23)");
    }
    contentEndRow = contentStartRow + 50;
@@ -1115,7 +1154,7 @@
    }
    //contentStartRow < 0 || contentEndRow < 0
    if (contentStartRow < 0) {
        throw string("起始行或结束行分隔出错");
        throw string("起始行或结束行分隔出错(24)");
    }
    contentEndRow = contentStartRow + 50;
@@ -1231,6 +1270,61 @@
}
void THSActionUtil::betchAddGP(HWND addDialog, list<string> codeList)
{
    //将代码写入txt文件
    string path = "D:\\gpcode\\gp.txt";
    ofstream ofs;
    ofs.open(path, ios::trunc);
    int index = 0;
    for (list<string>::iterator ele = codeList.begin();ele != codeList.end();++ele)
    {
        index++;
        ofs << *ele;
        if (index < codeList.size())
            ofs << "\n";
    }
    Sleep(200);
    addDialog = FindWindowExA(addDialog, NULL,"AfxWnd100s","CEFBrowser" );
    addDialog = FindWindowExA(addDialog, NULL, "CefBrowserWindow", NULL);
    addDialog = FindWindowExA(addDialog, NULL, "Chrome_WidgetWin_0", NULL);
    addDialog = FindWindowExA(addDialog, NULL, "Chrome_RenderWidgetHostHWND", NULL);
    cout << "添加股票弹框:"<< addDialog << endl;
    Win32Util::focus(addDialog);
    //图片选择按钮
    SendMessage(addDialog, WM_LBUTTONDOWN, 0x00000001, 0x00370141);
    SendMessage(addDialog, WM_LBUTTONUP, 0x00000000, 0x00370141);
    Sleep(100);
    //上传文件按钮
    SendMessage(addDialog, WM_LBUTTONDOWN, 0x00000001, 0x016000B1);
    SendMessage(addDialog, WM_LBUTTONUP, 0x00000000, 0x016000B1);
    HWND hwnd = HWND(0);
    for (int i = 0;i < 10;i++)
    {
        HWND temp = FindWindowA("#32770", "打开");
        if (temp > 0) {
            hwnd = temp;
            break;
        }
        Sleep(1000);
    }
    Win32Util::selectTexFileWin10(hwnd, "D:\\gpcode\\");
    Sleep(500);
    Win32Util::focus(addDialog);
    //点击添加全部按钮
    SendMessage(addDialog, WM_LBUTTONDOWN, 0x00000001, 0x00570139);
    SendMessage(addDialog, WM_LBUTTONUP, 0x00000000, 0x00570139);
    //关闭弹框
    HWND close = FindWindowA(0, "添加股票");
    SendMessage(close, WM_CLOSE, 0, 0);
}
std::list<GPCodeArea> THSActionUtil::getListenL2GPAreaAndCode(RecognitionManager* recognitionManager) {
    //截图当前有哪些股票代码
    list<HWND> wlist = Win32Util::searchWindow("同花顺(");
@@ -1251,7 +1345,7 @@
        }
    }
    if (mainPage <= 0) {
        throw string("L2监听未打开");
        throw string("L2监听未打开(25)");
    }
    HWND content = FindWindowExA(mainPage, NULL, "AfxFrameOrView100s", NULL);
@@ -1308,7 +1402,66 @@
    return fresultList;
}void THSActionUtil::clearPlateCodes(HWND hwnd)
{
    HWND content = FindWindowExA(hwnd, NULL, "AfxFrameOrView100s", NULL);
    for (int i = 0;i < 15;i++)
    {
        //截图识别是否还有代码
        cv::Mat oimg = CaptureUtil::capture(content);
        if (oimg.cols <= 0 || oimg.rows <= 0) {
            throw string("板块截屏内容为空(26)");
}
        cv::Mat img = ImgUtil::grayImage(oimg);
        oimg.release();
        std::list<GPCodeArea>  areaList = recognitionGPArea(img);
        cout << "数据数量:" << areaList.size() << endl;
        if (areaList.size() <= 2) {
            //执行最后一次删除
            Win32Util::focus(hwnd);
            Win32Util::keyboard(VK_DELETE, 30);
            break;
        }
        //执行删除事件
        for (int j = 0;j < 20;j++) {
            Win32Util::focus(hwnd);
            Win32Util::keyboard(VK_DELETE, 30);
        }
    }
}
RECT THSActionUtil::getPlateAddCodeBtnPostion(HWND win)
{
    //获取添加按钮位置
    HWND content = FindWindowExA(win, NULL, "AfxFrameOrView100s", NULL);
    RECT contentRect;
    GetWindowRect(content, &contentRect);
    cv::Mat oimg = CaptureUtil::capture(content);
    if (oimg.cols <= 0 || oimg.rows <= 0) {
        throw string("板块截屏内容为空(27)");
    }
    cv::Mat img = ImgUtil::grayImage(oimg);
    oimg.release();
    std::list<GPCodeArea>  areaList = recognitionGPArea(img);
    for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();ele++) {
        cout << "添加按钮位置:" << (*ele).startx << "," << (*ele).starty << "," << (*ele).endx << "," << (*ele).endy << endl;
        if ((*ele).type == IMG_TYPE_ADD) {
            RECT rect;
            rect.left = contentRect.left + (*ele).startx;
            rect.right = contentRect.left + (*ele).endx;
            rect.top = contentRect.top + (*ele).starty;
            rect.bottom = contentRect.top + (*ele).endy;
            return rect;
        }
    }
    throw string("尚未找到添加按钮(28)");
}
bool THSActionUtil::setListenL2GP(int p, string code, RecognitionManager* recognitionManager) {
@@ -1352,7 +1505,7 @@
    }
    if (contentStartRow < 0) {
        throw string("起始行分隔出错");
        throw string("起始行分隔出错(29)");
    }
    //分隔列
@@ -1377,7 +1530,7 @@
    }
    if (startC < 0 || endC < 0) {
        throw string("内容框分隔出错");
        throw string("内容框分隔出错(30)");
    }
    GPCodeArea area = GPCodeArea();
@@ -1388,3 +1541,55 @@
    return area;
}
void THSActionUtil::addTargetCodes(list<std::string> codeList, RecognitionManager* recognitionManager)
{
    //获取同花顺主页
    HWND win = getMainWin();
    Win32Util::focus(win);
    //快捷键打开板块
    Win32Util::keyboardNum("51", 200);
    Win32Util::keyboard(13, 10);
    Sleep(1000);
    //删除板块内的所有内容
    clearPlateCodes(win);
    //获取添加按钮位置
    RECT codeArea = getPlateAddCodeBtnPostion(win);
    //点击添加按钮
    Win32Util::click(codeArea.left + 5, codeArea.top + 3);
    //批量添加代码
    HWND addDLG;
    for (int i = 0;i < 10;i++) {
        addDLG = FindWindowA("#32770", "添加股票");
        if (addDLG > 0) {
            break;
        }
        Sleep(1000);
    }
    if (addDLG <= 0) {
        throw string("添加股票窗口打开失败(31)");
    }
    if (codeList.size() >= 100)
    {
        betchAddGP(addDLG, codeList);
    }
    else {
        //逐个添加
        for (list<std::string>::iterator ele = codeList.begin();ele != codeList.end();++ele) {
            string code = *ele;
            Win32Util::focus(addDLG);
            for (int i = 0;i < 6;i++)
            {
                Win32Util::keyboard(VK_BACK, 10);
            }
            Win32Util::focus(addDLG);
            Win32Util::keyboardNum(code, 1000);
            Win32Util::focus(addDLG);
            Win32Util::keyboard(VK_RETURN, 1500);
        }
        Sleep(100);
        SendMessage(addDLG, WM_CLOSE, 0, 0);
    }
    //TODO 校验代码的正确性
}
ConsoleApplication/THSActionUtil.h
@@ -35,7 +35,14 @@
{
private:
    static void addGP(string code);
    //批量添加股票
    static void betchAddGP(HWND addDialog,list<string> codeList);
    static std::list<GPCodeArea> getListenL2GPAreaAndCode(RecognitionManager* recognitionManager);
    //删除板块内的所有代码
    static void clearPlateCodes(HWND hwnd);
    //获取板块中代码添加按钮的位置
    static RECT getPlateAddCodeBtnPostion(HWND win);
public:
    static HWND getMainWin();
@@ -66,8 +73,10 @@
    static std::list<int*> splitPlateRowArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col);
    //打开同花顺的副屏幕
    static void openL2Screen();
    static void openSecondScreen();
    static void openThirdScreen();
    static void openTradeSuccessScreen();
    //设置股票
    static bool setGP(std::string quickCode, list<std::string> codeList,RecognitionManager* recognitionManager);
@@ -91,7 +100,8 @@
    static GPCodeArea recognitionPlateContentArea(cv::Mat grayImg);
    //添加目标标的(目标标的的数量必须大于9个才行)
    static void addTargetCodes(list<std::string> codeList, RecognitionManager* recognitionManager);
ConsoleApplication/THSL2RepairTool.cpp
New file
@@ -0,0 +1,86 @@
#include "THSL2RepairTool.h"
#include "Win32Util.h"
#include "THSActionUtil.h"
THSL2RepairTool::THSL2RepairTool()
{
    openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
}
void THSL2RepairTool::repairL2Data(RecognitionManager *recognitionManager, int index, string code, double min_price, double max_price)
{
    try {
        list<TradeData> dataList;
        try {
            dataList = L2DataCapture::captureLevel2TradeData(openCLExcuter, CaptureUtil::capture(index, CAPTURE_TYPE_L2), index);
        }
        catch (int c) {
            cout << "获取L2数据出错:code-" << c << endl;
        }
        cout << "获取到的数据:" << dataList.size() << endl;
        if (dataList.size() == 0) {//修正数据
            //上下滚动鼠标滚轮1次
            HWND win = CaptureUtil::getHWND(index, CAPTURE_TYPE_L2);
            cout << "L2 win:" << win << endl;
            RECT rect;
            Win32Util::getWindowRect(win, &rect);
            cout << "L2 rect:" << rect.left << rect.top << endl;
            Win32Util::rollMouseWheel(false, win, rect.left + 20, rect.top + 10);
            Sleep(100);
            Win32Util::rollMouseWheel(true, win, rect.left + 20, rect.top + 10);
            Sleep(500);
            try {
                dataList = L2DataCapture::captureLevel2TradeData(openCLExcuter, CaptureUtil::capture(index, CAPTURE_TYPE_L2), index);
                cout << "获取到的数据:" << dataList.size() << endl;
            }
            catch (int c) {
                cout << "获取L2数据出错:code-" << c << endl;
            }
        }
        //打开L2监控屏幕
        THSActionUtil::openL2Screen();
        bool success = false;
        int retryCount = 0;
        while (!success)
        {
            if (retryCount > 3) {
                break;
            }
            //点击代码
            retryCount++;
            THSActionUtil::setListenL2GP(index, code, recognitionManager);
            Sleep(1000);
            bool normal = true;
            for (list<TradeData>::iterator ele = dataList.begin();ele != dataList.end();++ele) {
                double price = stod((*ele).price);
                if (price >= max_price + 0.0001) {
                    normal = false;
                    break;
                }
                else if (price <= min_price - 0.0001) {
                    normal = false;
                    break;
                }
            }
            cout << code << "-repairL2Data是否修复成功:" << normal << endl;
            success = normal;
        }
    }
    catch (int code) {
        throw string("错误码:" + code);
    }
    catch (string st) {
        throw st;
    }
    catch (...) {
        std::exception_ptr p = std::current_exception();
        throw string("未知错误(unknown error)");
    }
}
ConsoleApplication/THSL2RepairTool.h
New file
@@ -0,0 +1,19 @@
#pragma once
//L2修复工具
#include "L2DataCapture.h"
class THSL2RepairTool
{
public:
    THSL2RepairTool();
    void repairL2Data(RecognitionManager* recognitionManager, int index,string code, double min_price, double max_price);
private:
    OpenCLExcuter* openCLExcuter;
};
ConsoleApplication/TaskChecker.cpp
New file
@@ -0,0 +1,2 @@
#include "TaskChecker.h"
 ClientTaskLiveTime TaskChecker::clientLiveTime;
ConsoleApplication/TaskChecker.h
New file
@@ -0,0 +1,46 @@
#pragma once
//任务检测器
#include <time.h>
#include "L2DataCapture.h"
//任务生存时间
//客户端环境状态
struct ClientEnvState {
    //l2屏幕
    bool ths_l2_win;
    //副屏1
    bool ths_fp_1;
    //副屏2
    bool ths_fp_2;
    //交易成功界面
    bool ths_trade_success;
    int l2_channel_valid_count;
    int l2_channel_invalid_count;
    //今日涨停
    bool limitUp;
    //交易成功
    bool tradeSuccess;
};
struct ClientTaskLiveTime
{
    clock_t l2[THS_FRAME_COUNT];
    clock_t tradeSuccess;
    clock_t limitUp;
};
class TaskChecker
{
public:
    static ClientTaskLiveTime clientLiveTime;
};
ConsoleApplication/TradeListCapture.cpp
@@ -1,8 +1,11 @@
#include "TradeListCapture.h"
#include <set>
#include "Win32Util.h"
#include "TaskChecker.h"
OpenCLExcuter* TradeListCapture::openCLExcuter;
bool TradeListCapture::inited;
bool TradeListCapture::kill_d;
bool TradeListCapture::kill_s;
HWND TradeListCapture::trade_delegate_win;
HWND TradeListCapture::trade_success_win;
RecognitionManager* TradeListCapture::recognitionManager;
@@ -22,7 +25,9 @@
void TradeListCapture::_run_s() {
    while (true) {
        //1s一次
        if (kill_s)
            break;
        TaskChecker::clientLiveTime.tradeSuccess = clock();
        if (running_s && inited) {
            clock_t start = clock();
            try {
@@ -45,6 +50,8 @@
void TradeListCapture::_run_d() {
    while (true) {
        if (kill_d)
            break;
        //1s一次
        if (running_d && inited) {
            clock_t start = clock();
@@ -122,6 +129,23 @@
}
void TradeListCapture::reCreateTradeSuccessRunning()
{
    kill_s = TRUE;
    Sleep(3000);
    kill_s = FALSE;
    thread rt(&(TradeListCapture::_run_s));
    rt.detach();
}
void TradeListCapture::reCreateTradeDelegateRunning()
{
    kill_d = TRUE;
    Sleep(3000);
    kill_d = FALSE;
    thread rt(&(TradeListCapture::_run_d));
    rt.detach();
}
void TradeListCapture::refreshTradeDelegateHWND() {
    HWND hwnd = THSActionUtil::getTradeDelegateWindow();
    if (hwnd <= 0)
ConsoleApplication/TradeListCapture.h
@@ -56,6 +56,8 @@
    //是否正在执行
    static bool running_s;
    static bool running_d;
    static bool kill_d;
    static bool kill_s;
    static CallbackFun_Trade_Success data_callback_success;
    static CallbackFun_Trade_Delegate data_callback_delegate;
    static void* context;
@@ -72,6 +74,11 @@
public:
    void init(CallbackFun_Trade_Success callback_s, CallbackFun_Trade_Delegate callback_d, void* context);
    //重新创建线程
    void reCreateTradeSuccessRunning();
    void reCreateTradeDelegateRunning();
    void refreshTradeDelegateHWND();
    void refreshTradeSuccessHWND();
    static cv::Mat grayImgs(cv::Mat img);
ConsoleApplication/Win32Util.cpp
@@ -101,6 +101,19 @@
    SetFocus(hwnd);
}
void Win32Util::copy(string text)
{
    HWND hWnd = NULL;
    OpenClipboard(hWnd);//打开剪切板
    EmptyClipboard();//清空剪切板
    HANDLE hHandle = GlobalAlloc(GMEM_FIXED, 1000);//分配内存
    char* pData = (char*)GlobalLock(hHandle);//锁定内存,返回申请内存的首地址
    strcpy(pData, text.c_str());
    SetClipboardData(CF_TEXT, hHandle);//设置剪切板数据
    GlobalUnlock(hHandle);//解除锁定
    CloseClipboard();//关闭剪切板
}
//键盘输入数字
void Win32Util::keyboardNum(string num, int delay) {
    thread runner(kbNumRunner, num, delay);
@@ -111,6 +124,15 @@
void Win32Util::keyboard(int code, int delay) {
    thread runner(kbKeyRunner, code, delay);
    runner.join();
}
void Win32Util::keyboardPaste()
{
    keybd_event(VK_CONTROL, 0, 0, 0);    // 按下CTRL键
    keybd_event('V', 0, 0, 0);    // 按下a键
    Sleep(50);
    keybd_event('V', 0, KEYEVENTF_KEYUP, 0);// 松开a键
    keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);// 松开CTRL键
}
DEVMODE Win32Util::getL2ScreenInfo()
@@ -149,5 +171,80 @@
    ShowWindow(hwnd, SW_SHOWNORMAL);
}
void Win32Util::selectTexFileWin10(HWND hwnd, string path)
{
    //选择路径
    HWND pathWin = FindWindowExA(hwnd, NULL, "WorkerW", NULL);
    pathWin = FindWindowExA(pathWin, NULL, "ReBarWindow32", NULL);
    pathWin = FindWindowExA(pathWin, NULL, "Address Band Root", NULL);
    pathWin = FindWindowExA(pathWin, NULL, "msctls_progress32", NULL);
    pathWin = FindWindowExA(pathWin, NULL, "Breadcrumb Parent", NULL);
    pathWin = FindWindowExA(pathWin, NULL, "ToolbarWindow32", NULL);
    RECT p;
    GetWindowRect(pathWin, &p);
    Win32Util::focus(hwnd);
    Win32Util::click(p.right - 5, p.top + 5, 10);
    Sleep(1000);
    //复制路径
    Win32Util::copy(path);
    //粘贴路径
    keyboardPaste();
    //按enter按键
    keybd_event(VK_RETURN, 0, 0, 0);
    keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
    //选着导入Txt
    HWND typeWin = FindWindowExA(hwnd, NULL, "ComboBox", NULL);
    GetWindowRect(typeWin, &p);
    Win32Util::focus(typeWin);
    Win32Util::click(p.right - 5, p.top + 5, 10);
    Win32Util::click(p.right - 5, p.bottom + 30, 100);
    Sleep(500);
    //选中文件
    HWND contentWin = FindWindowExA(hwnd, NULL, "DUIViewWndClassName", NULL);
    contentWin = FindWindowExA(contentWin, NULL, "DirectUIHWND", NULL);
    HWND contentWin_ = FindWindowExA(contentWin, NULL, "CtrlNotifySink", NULL);
    for (int i = 0;i < 5;i++)
    {
        if (FindWindowExA(contentWin_, NULL, "SHELLDLL_DefView", NULL) > 0)
            break;
        contentWin_ = FindWindowExA(contentWin, contentWin_, "CtrlNotifySink", NULL);
    }
    GetWindowRect(contentWin_, &p);
    Win32Util::click(p.left + 20, p.top + 10, 10);
    Win32Util::click(p.left + 20, p.top + 10, 10);
    Win32Util::click(p.left + 20, p.top + 10, 10);
    //Sleep(100);
    //点击打开
    //HWND openWin = FindWindowExA(hwnd, NULL, NULL, "打开(&O)");
    //GetWindowRect(openWin, &p);
    //return;
    //Win32Util::click((p.left + p.right) / 2, (p.top + p.bottom) / 2, 100);
}
void Win32Util::rollMouseWheel(bool back, HWND win,int x, int y)
{
    //back-是否往后滚
    SendMessage(win, WM_MOUSEWHEEL, back?0xFF880000:0x00780000, MAKEWORD(x, y));
}
void Win32Util::getWindowRect(HWND hwnd, RECT *rect)
{
    GetWindowRect(hwnd, rect);
}
ConsoleApplication/Win32Util.h
@@ -24,11 +24,17 @@
    //获取焦点
    static void focus(HWND hwnd);
    //复制到粘贴板
    static void copy(string text);
    //键盘输入数字
    static void keyboardNum(string num, int delay=0);
    //键盘输入其他键
    static void keyboard(int code, int delay=0);
    //键盘键入粘贴
    static void keyboardPaste();
    //获取L2屏幕数据
    static DEVMODE getL2ScreenInfo();
@@ -40,5 +46,14 @@
    static bool isWindowShow(HWND hwnd);
    //显示窗口
    static void showWindow(HWND hwnd);
    //选择txt文件
    static void selectTexFileWin10(HWND hwnd, string path);
    //鼠标滚动
    static void rollMouseWheel(bool back,HWND win,int x, int y);
    //获取位置
    static void getWindowRect(HWND hwnd,RECT *rect);
};
ConsoleApplication/main.cpp
@@ -5,6 +5,7 @@
#include "LimitUpCapture.h"
#include "IndustryCapture.h"
#include "TradeListCapture.h"
#include "CurrentPriceCapture.h"
void gray();
void ths();
/*
@@ -131,38 +132,24 @@
    char tmp_s[64];
    strftime(tmp_s, sizeof(tmp_s), "%S", localtime(&timep));
    cout << string(tmp_h) << endl;
    cout << string(tmp_m) << endl;
    cout << string(tmp_s) << endl;
    cout << string(tmp_m) << endl;    cout << string(tmp_s) << endl;
    return stoi(string(tmp_h)) * 3600 + stoi(string(tmp_m)) * 60 + stoi(string(tmp_s));
}
int main() {
    cout << "开始程序" << endl;
    //SetDlgItemText(HWND(0x0002269E), 0x0000040A, TEXT("100"));
    //SetWindowText(GetDlgItem(HWND(0x0002269E), 0x0000040A),TEXT("100"));
    //Win32Util::focus(GetDlgItem(HWND(0x0002269E), 0x00000408));
    //Win32Util::keyboardNum("000333", 10);
    ImgUtil::init();
    //int result= getNowSecondTime1();
    CurrentPriceCapture* currentPriceCapture = new CurrentPriceCapture();
    currentPriceCapture->init(NULL,NULL);
    list<CurrentPriceData> resultList= currentPriceCapture->capture();
    for (list<CurrentPriceData>::iterator ele = resultList.begin();ele != resultList.end();++ele) {
        cout<<(*ele).code<<":"<< (*ele).price <<endl;
    }
    //TradeListCapture* tradeListCapture = new TradeListCapture();
    //tradeListCapture->init(NULL,NULL,NULL);
    //tradeListCapture->refreshTradeDelegateHWND();
    //cv::Mat img= tradeListCapture->grayImgs(CaptureUtil::capture(HWND(0x00055B0E)));
    //cv::imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\trade\\gray_1.png",img);
    //list<TradeDelegateData> dataList = tradeListCapture->captureTradeDelegateInfo();
    cv::waitKey(0);
    cv::destroyAllWindows();
    return 0;
    ImgUtil::init();
Setup1/Setup1.vdproj
@@ -2650,15 +2650,15 @@
        {
        "Name" = "8:Microsoft Visual Studio"
        "ProductName" = "8:GP"
        "ProductCode" = "8:{AD2DB9B9-91FB-4E17-ABA5-8C2DB663ACE2}"
        "PackageCode" = "8:{33D97017-BA1B-4775-922F-FE62DB48947E}"
        "ProductCode" = "8:{5C7E235C-AF45-420E-8568-E6BC84A5DAF7}"
        "PackageCode" = "8:{74B1A9AE-7307-48A1-9E1E-E9CC63BCD059}"
        "UpgradeCode" = "8:{746B406D-2250-4EC9-AC73-44489EBE2279}"
        "AspNetVersion" = "8:2.0.50727.0"
        "RestartWWWService" = "11:FALSE"
        "RemovePreviousVersions" = "11:TRUE"
        "DetectNewerInstalledVersion" = "11:TRUE"
        "InstallAllUsers" = "11:FALSE"
        "ProductVersion" = "8:1.0.0"
        "ProductVersion" = "8:1.0.1"
        "Manufacturer" = "8:yeshi"
        "ARPHELPTELEPHONE" = "8:"
        "ARPHELPLINK" = "8:"
app/JsonUtil.h
@@ -6,6 +6,8 @@
#include "LimitUpCapture.h"
#include "TradeListCapture.h"
#include "IndustryCapture.h"
#include "CurrentPriceCapture.h"
#include "TaskChecker.h"
class JsonUtil {
@@ -198,6 +200,23 @@
        return toJsonStr(root);
    }
    static  std::string loadGPPriceData(std::list<CurrentPriceData> dataList) {
        Json::Value root;
        root["type"] = 40;
        Json::Value data;
        std::list<CurrentPriceData>::iterator ele;
        int index = 0;
        for (ele = dataList.begin();ele != dataList.end();ele++) {
            Json::Value item;
            item["code"] = (*ele).code;
            item["price"] = (*ele).price;
            data[index++] = item;
        }
        root["data"] = data;
        return toJsonStr(root);
    }
    static  std::string loadGPCodeData(std::list<IndustryData> codeList) {
        Json::Value root;
@@ -217,12 +236,13 @@
        return toJsonStr(root);
    }
    static  std::string loadHeartbeatData(int client,string memery) {
    static  std::string loadHeartbeatData(int client,string memery,string ownMemery) {
        Json::Value root;
        root["type"] = 30;
        Json::Value data;
        data["client"] = client;
        data["memery"] = memery;
        data["own_memery"] = ownMemery;
        root["data"] = data;
        return toJsonStr(root);
    }
@@ -252,6 +272,19 @@
        return toJsonStr(root);
    }
    static std::string toJson(ClientEnvState state) {
        Json::Value root;
        root["ths_l2_win"] = state.ths_l2_win;
        root["ths_fp_1"] = state.ths_fp_1;
        root["ths_fp_2"] = state.ths_fp_2;
        root["ths_trade_success"] = state.ths_trade_success;
        root["l2_channel_valid_count"] = state.l2_channel_valid_count;
        root["l2_channel_invalid_count"] = state.l2_channel_invalid_count;
        root["limitUp"] = state.limitUp;
        root["tradeSuccess"] = state.tradeSuccess;
        return toJsonStr(root);
    }
    
app/SocketManager.cpp
@@ -4,6 +4,7 @@
#include <thread>
#include <string>
SOCKET SocketManager::socketServer;
ActionCallback SocketManager::actionCallback;
@@ -31,26 +32,13 @@
        if (recv_len > 0)
        {
            cout << "接受到操作指令:" << recvBuff << endl;
            try {
                bool success = actionCallback(string(recvBuff), callbackContext);
            string result = actionCallback(string(recvBuff), callbackContext);
                //发送操作结果
                if (success)
                {
                    char buff[] = "OK";
                    int iSend = send(client, buff, sizeof(buff), 0);
                    cout << "返回给客户端数据:" << buff << endl;
                }
                else {
                    char buff[] = "FAIL";
                    int iSend = send(client, buff, sizeof(buff), 0);
                    cout << "返回给客户端数据:" << buff << endl;
                }
            }
            catch (string st) {
                char buff[] = "FAIL";
                int iSend = send(client, buff, sizeof(buff), 0);
                cout << "设置采集代码出错:" << st << endl;
            }
            int iSend = send(client, result.c_str(), result.size(), 0);
            cout << "返回给客户端数据:" << result << endl;
        }
        else {
            cout << "客户端退出" << endl;
app/SocketManager.h
@@ -14,7 +14,7 @@
#define LOCAL_SERVER_ADDR "127.0.0.1"
#define LOCAL_SERVER_PORT 9006
typedef bool (*ActionCallback)(string data, void* contex);
typedef string (*ActionCallback)(string data, void* contex);
class SocketManager
{
app/app.aps
Binary files differ
app/app.rc
Binary files differ
app/app.vcxproj.user
@@ -3,4 +3,11 @@
  <PropertyGroup>
    <RESOURCE_FILE>app.rc</RESOURCE_FILE>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
    <RemoteDebuggerCommand>\\192.168.3.242\FXDMounter\Debug\DataCapture.exe</RemoteDebuggerCommand>
    <RemoteDebuggerWorkingDirectory>\\192.168.3.242\FXDMounter\</RemoteDebuggerWorkingDirectory>
    <RemoteDebuggerServerName>192.168.3.242</RemoteDebuggerServerName>
    <RemoteDebuggerConnection>RemoteWithoutAuthentication</RemoteDebuggerConnection>
  </PropertyGroup>
</Project>
app/appDlg.cpp
@@ -12,8 +12,10 @@
#ifndef _TOOL_H
#define _TOOL_H 1
#include "tool.h"
#include "TaskChecker.h"
#endif 
#include "JsonUtil.h"
#include <exception>
#ifdef _DEBUG
@@ -26,6 +28,8 @@
#endif
#include <Win32Util.h>
#include "loginDlg.h"
#include <psapi.h>
#pragma comment(lib,"psapi.lib")
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
@@ -98,6 +102,8 @@
    tradeListCapture = new TradeListCapture();
    industryCapture = new IndustryCapture();
    gpDataCapture = new THSGPDataCapture();
    currentPriceCapture = new CurrentPriceCapture();
    thsL2RepairTool = new THSL2RepairTool();
}
void CappDlg::DoDataExchange(CDataExchange* pDX)
@@ -114,6 +120,8 @@
    DDX_Control(pDX, IDC_BUTTON22, refreshHWNDBtn);
    DDX_Control(pDX, IDC_BUTTON21, resetTHSBtn);
    DDX_Control(pDX, IDC_CHECK6, autoL2Check);
    DDX_Control(pDX, IDC_CURRENT_PRICE, currentPriceBtn);
    DDX_Control(pDX, IDC_STATIC_AUTO_MSG, autoMsgStatic);
}
BEGIN_MESSAGE_MAP(CappDlg, CDialogEx)
@@ -138,6 +146,7 @@
    ON_BN_CLICKED(IDC_BUTTON22, &CappDlg::OnBnClickedButton22)
    ON_BN_CLICKED(IDC_LOGOUT_BTN, &CappDlg::OnBnClickedLogoutBtn)
    ON_BN_CLICKED(IDC_CHECK6, &CappDlg::OnBnClickedCheck6)
    ON_BN_CLICKED(IDC_CURRENT_PRICE, &CappDlg::OnBnClickedCurrentPrice)
END_MESSAGE_MAP()
@@ -191,11 +200,13 @@
        if (settings.size() > 0) {
            string c= *(settings.begin());
            if (c == "1") {
                autoMsgStatic.SetWindowTextW(_T("正在自动启动中..."));
                autoL2Check.SetCheck(TRUE);
                thread rt(&(CappDlg::autoStartL2),this);
                rt.detach();
            }
            else {
                autoMsgStatic.SetWindowTextW(_T(""));
                autoL2Check.SetCheck(FALSE);
            }
        }
@@ -223,9 +234,11 @@
    if (authoritySet.count(AUTHORITY_TRADE_DELEGATE) > 0) {
        delegateBtn.EnableWindow(TRUE);
        currentPriceBtn.EnableWindow(TRUE);
    }
    else {
        delegateBtn.EnableWindow(FALSE);
        currentPriceBtn.EnableWindow(FALSE);
    }
@@ -465,9 +478,27 @@
    _list.clear();
}
void CappDlg::OnCurrentPriceCallback(list<CurrentPriceData> dataList, void* context)
{
    //转为json
    CappDlg* app = (CappDlg*)context;
bool  CappDlg::OnActionCallback(string data, void* context) {
    string data = JsonUtil::loadGPPriceData(dataList);
    try {
        app->socketManager->sendMsg(8, data.c_str());
        //AfxMessageBox(_T("上传成功"));
    }
    catch (string st) {
        //重新连接服务器
        app->socketManager->resetClient(8);
        app->socketManager->Connect(8);
    }
    dataList.clear();
}
string CappDlg::OnActionProcess(string data, void* context)
{
    //转为json
    CappDlg* app = (CappDlg*)context;
    cout << "action回调:" << std::this_thread::get_id() << ":" << data << endl;
@@ -488,7 +519,7 @@
        try {
            if (!app->capture->isInited()) {
                throw string("采集器尚未初始化");
                app->initCapture(false);
            }
            //暂停采集
@@ -498,8 +529,10 @@
            if (!result) {
                throw string("设置版块监控的GP失败");
            }
            //刷新句柄
            THSActionUtil::setListenL2GP(index, code, recognitionManager);
            //打开Level2监控屏幕
            THSActionUtil::openL2Screen();
            map<int, string> results = THSActionUtil::getListenL2GPCodes(recognitionManager);
            //设置代码
            for (map<int, string>::iterator ele = results.begin();ele != results.end();ele++) {
@@ -509,21 +542,20 @@
            }
        }
        catch (string e) {
            //CString msg(e.c_str());
            //AfxMessageBox(msg);
            throw e;
        }
        catch (...) {
            throw string("未知错误");
            throw string("未知错误(unknown error)");
        }
        //恢复采集
        app->capture->start(index);
    }
    else if (action == "repairL2Data") {
        //修正代码与L2行情代码不对应 或者 L2行情无数据的情况
        cout << "修复L2数据" << endl;
        if (!app->capture->isInited()) {
            throw string("采集器尚未初始化");
            app->initCapture(false);
        }
        try {
            //修正L2的数据
@@ -531,43 +563,144 @@
            string code = root["data"]["code"].asString();
            double min_price = root["data"]["min_price"].asDouble();
            double max_price = root["data"]["max_price"].asDouble();
            list<TradeData> dataList = app->capture->captureLevel2TradeData(CaptureUtil::capture(index, CAPTURE_TYPE_L2), index);
            cout << index << ":" << code << ":" << min_price << ":" << max_price << endl;
            app->thsL2RepairTool->repairL2Data(recognitionManager, index, code, min_price, max_price);
        }catch (string st) {
            throw st;
        }
            bool success = false;
            int retryCount = 0;
            while (!success)
    }
    else if (action == "getEnvState") {
        app->initCapture(false);
        ClientEnvState state;
        //获取同花顺的环境
        HWND l2 = THSActionUtil::getL2Win();
        HWND second = THSActionUtil::getSecondWindow();
        HWND third = THSActionUtil::getThirdWindow();
        HWND trade_success = THSActionUtil::getTradeSuccessWindow();
        if (l2 > 0 && Win32Util::isWindowShow(l2)) {
            state.ths_l2_win = TRUE;
        }
        else {
            state.ths_l2_win = FALSE;
        }
        if (second > 0 && Win32Util::isWindowShow(second)) {
            state.ths_fp_1 = TRUE;
        }
        else {
            state.ths_fp_1 = FALSE;
        }
        if (third > 0 && Win32Util::isWindowShow(third)) {
            state.ths_fp_2 = TRUE;
        }
        else {
            state.ths_fp_2 = FALSE;
        }
        if (trade_success > 0 && Win32Util::isWindowShow(trade_success)) {
            state.ths_trade_success = TRUE;
        }
        else {
            state.ths_trade_success = FALSE;
        }
        //获取环境状态
        int l2_valid_count = 0;
        int l2_invalid_count = 0;
        for (int i = 0;i < THS_FRAME_COUNT;i++)
            {
                if (retryCount > 3) {
                    break;
            clock_t latestTime = TaskChecker::clientLiveTime.l2[i];
            if (clock() - latestTime > 5000) {
                //5s内不再活跃
                l2_invalid_count++;
                }
                //点击代码
                retryCount++;
                THSActionUtil::setListenL2GP(index, code, recognitionManager);
                Sleep(1);
                bool normal = true;
            else {
                l2_valid_count++;
            }
        }
        state.l2_channel_valid_count = l2_valid_count;
        state.l2_channel_invalid_count = l2_invalid_count;
                for (list<TradeData>::iterator ele = dataList.begin();ele != dataList.end();++ele) {
                    double price = stod((*ele).price);
                    if (price >= max_price + 0.0001) {
                        normal = false;
                        break;
        if (clock() - TaskChecker::clientLiveTime.limitUp > 5000) {
            state.limitUp = false;
                    }
                    else if (price <= min_price - 0.0001) {
                        normal = false;
                        break;
        else {
            state.limitUp = true;
        }
        if (clock() - TaskChecker::clientLiveTime.tradeSuccess > 5000) {
            state.tradeSuccess = false;
        }
        else {
            state.tradeSuccess = true;
        }
        return JsonUtil::toJson(state);
    }
    else if (action == "repairEnv") {
        app->initCapture(false);
        //同花顺环境修复
        app->OnBnClickedButton21();
        //l2采集环境修复
        for (int i = 0;i < THS_FRAME_COUNT;i++)
        {
            clock_t latestTime = TaskChecker::clientLiveTime.l2[i];
            if (clock() - latestTime > 5000) {
                //5s内不再活跃
                app->capture->reCreateChannelRunner(i);
                    }
                }
                cout << code << "-repairL2Data是否修复成功:" << normal << endl;
                success = normal;
        if (clock() - TaskChecker::clientLiveTime.tradeSuccess > 5000) {
            app->tradeListCapture->captureTradeSuccessInfo();
            }
        if (clock() - TaskChecker::clientLiveTime.limitUp > 5000) {
            app->limitUpCapture->reCreateRunning();
        }
    }
    else if (action == "syncTargetCodes") {
        Json::Value data = root["data"];
        list<string> codeList;
        for (int i = 0;i < data.size();i++) {
            string code = data[i].asString();
            codeList.push_back(code);
        }
        THSActionUtil::addTargetCodes(codeList, app->recognitionManager);
    }
    return "";
}
string  CappDlg::OnActionCallback(string data, void* context) {
    Json::Value root;
    try {
        string result = OnActionProcess(data, context);
        root["code"] = 0;
        root["data"] = result;
    }
    catch (string st) {
        root["code"] = 1;
        root["msg"] = st;
        }
        catch (...) {
            throw string("未知错误");
        root["code"] = 2;
        root["msg"] = "未知错误";
        }
    }
    return true;
    return  JsonUtil::jsonValue2String(root);
}
//心跳信号
@@ -575,24 +708,36 @@
    //5s一次心跳
    while (true)
    {
        if (clientNum >= 0)
        {
            //用户已经登录
        MEMORYSTATUS ms;
        ::GlobalMemoryStatus(&ms);
        DWORD mer = ms.dwMemoryLoad;
        cout << "内存使用率:" << mer << endl;
            //获取当前进程的内存使用情况
            HANDLE handle = GetCurrentProcess();
            PROCESS_MEMORY_COUNTERS pmc;
            GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
            float memoryUsage_M = pmc.WorkingSetSize / (1024.0 * 1024.0);
            string ownMemory = to_string(memoryUsage_M);
            ownMemory.append("MB");
        try {
            string msg = JsonUtil::loadHeartbeatData(clientNum,to_string(mer));
                string msg = JsonUtil::loadHeartbeatData(clientNum, to_string(mer), ownMemory);
            SocketManager::sendMsg(msg.c_str());
            //cout << "心跳信号" << endl;
        }
        catch (...) {
            cout << "心跳信号异常" << endl;
        }
        }
        Sleep(5000);
    }
}
void CappDlg::initCapture()
void CappDlg::initCapture(bool notify)
{
    if (!capture->isInited())
    {
@@ -600,21 +745,141 @@
            capture->init(OnL2DataCallback, OnTradeQueueDataCallback, this);
        }
        catch (string st) {
            if (notify)
            {
            CString msg(st.c_str());
            AfxMessageBox(msg);
        }
    }
}
    if (!limitUpCapture->isInited())
    {
        try {
            limitUpCapture->init(OnLimitUpDataCallback, this);
        }
        catch (string st) {
            if (notify)
            {
                CString msg(st.c_str());
                AfxMessageBox(msg);
            }
        }
    }
    if (!tradeListCapture->isInited())
    {
        try {
            tradeListCapture->init(OnTradeSuccessDataCallback, OnTradeDelegateDataCallback, this);
        }
        catch (string st) {
            if (notify)
            {
                CString msg(st.c_str());
                AfxMessageBox(msg);
            }
        }
    }
    if (!currentPriceCapture->isInited())
    {
        try {
            currentPriceCapture->init(OnCurrentPriceCallback, this);
        }
        catch (string st) {
            if (notify)
            {
                CString msg(st.c_str());
                AfxMessageBox(msg);
            }
        }
    }
}
void CappDlg::checkTHSEnv(CappDlg *app)
{
    try {
        THSActionUtil::checkEnv();
    }
    catch (string e) {
        //打开同花顺的所有屏幕
        try {
            THSActionUtil::openL2Screen();
            THSActionUtil::openSecondScreen();
            Sleep(1000);
            THSActionUtil::openThirdScreen();
            Sleep(1000);
        }
        catch (...) {
        }
    }
        HWND l2 = THSActionUtil::getL2Win();
        if (l2 > 0)
        {
            Win32Util::showWindow(l2);
            //初始化l2的各个窗口句柄
            app->capture->refreshHWND();
        }
        HWND  second = THSActionUtil::getSecondWindow();
        if (second <= 0) {
            throw string("同花顺副屏1未打开");
        }
        Win32Util::showWindow(second);
        HWND  third = THSActionUtil::getThirdWindow();
        if (third <= 0) {
            throw string("同花顺副屏2未打开");
        }
        Win32Util::showWindow(third);
        //设置
        DEVMODE device = Win32Util::getL2ScreenInfo();
        int device_width = device.dmPelsWidth;
        int device_height = device.dmPelsHeight;
        POINTL device_pos = device.dmPosition;
        //最大化L2
        Win32Util::moveWin(l2, device_pos.x, device_pos.y, device_width, device_height);
        //将副屏1与副屏2缩小为屏幕的一半
        Win32Util::moveWin(second, device_pos.x, device_pos.y + device_height / 2, device_width / 2 - 50, device_height / 2);
        Win32Util::moveWin(third, device_pos.x + device_width / 2 + 30, device_pos.y + device_height / 2, device_width / 2 - 50, device_height / 2);
}
void CappDlg::autoStartL2(void* context)
{
    Sleep(1500);
    CappDlg* app =(CappDlg*) context;
    app->autoMsgStatic.SetWindowTextW(_T("开始检测同花顺环境..."));
    //点击检查同花顺
    app->OnBnClickedButton21();
    for (int i = 0;i < 10;i++)
    {
        try {
            checkTHSEnv(app);
            app->autoMsgStatic.SetWindowTextW(_T("同花顺环境检测通过..."));
            break;
        }
        catch (string st) {
            Sleep(2000);
            CString msg(st.c_str());
            app->autoMsgStatic.SetWindowTextW(msg);
        }
    }
    Sleep(1000);
    app->autoMsgStatic.SetWindowTextW(_T("开始启动L2行情识别..."));
    //启动L2行情识别
    app->OnBnClickedButton5();
    app->autoMsgStatic.SetWindowTextW(_T("L2行情识别启动完成..."));
    //启动交易成功识别
    app->OnBnClickedButtonTrade();
    //启动涨停识别
@@ -1184,19 +1449,7 @@
    catch (string e) {
        //打开同花顺的所有屏幕
        try {
            HWND l2 = THSActionUtil::getL2Win();
            if (l2 <= 0) {
                //尝试打开主屏
                HWND main = THSActionUtil::getMainWin();
                if (main > 0)
                {
                    Win32Util::focus(main);
                    Win32Util::keyboardNum(".00", 200);
                    Win32Util::keyboard(13, 10);
                    Sleep(1000);
                }
            }
            THSActionUtil::openL2Screen();
            THSActionUtil::openSecondScreen();
            Sleep(1000);
            THSActionUtil::openThirdScreen();
@@ -1214,6 +1467,8 @@
        if (l2 > 0)
        {
            Win32Util::showWindow(l2);
            //初始化l2的各个窗口句柄
            capture->refreshHWND();
        }
        HWND  second = THSActionUtil::getSecondWindow();
@@ -1259,7 +1514,17 @@
    try {
        //刷新L2窗口句柄
        capture->refreshHWND();
        //刷新涨停句柄
    }
    catch (string e) {
        CString msg(e.c_str());
        AfxMessageBox(msg);
    }
    catch (...) {
        AfxMessageBox(_T("未知错误"));
    }
    try {
        //刷新L2窗口句柄
        limitUpCapture->refreshHWND();
    }
    catch (string e) {
@@ -1275,6 +1540,8 @@
//退出登录
void CappDlg::OnBnClickedLogoutBtn()
{
    clientNum = -1;
    SendMessage(WM_CLOSE);
    loginDlg dlg(this);
    dlg.setReLogin(true);
@@ -1294,3 +1561,35 @@
    }
    Tool::saveSettings("setting.txt", settings);
}
//线价识别
void CappDlg::OnBnClickedCurrentPrice()
{
    if (!currentPriceCapture->isInited()) {
        try {
            currentPriceCapture->init(OnCurrentPriceCallback, this);
        }
        catch (string e) {
            CString msg(e.c_str());
            AfxMessageBox(msg);
        }
    }
    if (currentPriceCapture->isRunning()) {
        currentPriceCapture->stop();
        currentPriceBtn.SetWindowTextW(_T("启动现价识别"));
    }
    else {
        try {
            currentPriceCapture->refreshHWND();
        }
        catch (string e) {
            CString msg(e.c_str());
            AfxMessageBox(msg);
        }
        currentPriceCapture->start();
        currentPriceBtn.SetWindowTextW(_T("暂停现价识别"));
    }
}
app/appDlg.h
@@ -11,6 +11,8 @@
#include "TradeListCapture.h"
#include "IndustryCapture.h"
#include "THSGPDataCapture.h"
#include "CurrentPriceCapture.h"
#include "THSL2RepairTool.h"
#include "pthread.h"
#pragma comment(lib, "pthreadVC2.lib")
@@ -37,6 +39,8 @@
    TradeListCapture* tradeListCapture;
    IndustryCapture* industryCapture;
    THSGPDataCapture* gpDataCapture;
    CurrentPriceCapture *currentPriceCapture;
    THSL2RepairTool *thsL2RepairTool;
    void OnDataCallback(int index, list<TradeData> dataList);
    static void  OnL2DataCallback(int index,string code, list<TradeData> dataList, void* context);
@@ -45,7 +49,11 @@
    static void  OnTradeSuccessDataCallback(list<TradeSuccessData> dataList, void* context);
    static void  OnTradeDelegateDataCallback(list<TradeDelegateData> dataList,string money, void* context);
    static void OnIndustryDataCallback(list<IndustryData>  dataList, void* context);
    static bool  OnActionCallback(string data, void* context);
    static void OnCurrentPriceCallback(list<CurrentPriceData>  dataList, void* context);
    static string  OnActionProcess(string data, void* context);
    static string  OnActionCallback(string data, void* context);
    static void *runCaptureIndustryCodes(void* context);
@@ -55,7 +63,10 @@
    static void  onHeartbeat();
    void initCapture();
    void initCapture(bool notify=true);
    //检查
    static void checkTHSEnv(CappDlg* app);
    static void autoStartL2(void* context);
@@ -124,4 +135,7 @@
    afx_msg void OnBnClickedLogoutBtn();
    CButton autoL2Check;
    afx_msg void OnBnClickedCheck6();
    CButton currentPriceBtn;
    afx_msg void OnBnClickedCurrentPrice();
    CStatic autoMsgStatic;
};
app/resource.h
@@ -42,6 +42,8 @@
#define IDC_LOGOUT_BTN                  1035
#define IDC_CHECK_AUTO_LOGIN            1036
#define IDC_CHECK6                      1037
#define IDC_CURRENT_PRICE               1038
#define IDC_STATIC_AUTO_MSG             1040
// Next default values for new objects
// 
@@ -49,7 +51,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        136
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1038
#define _APS_NEXT_CONTROL_VALUE         1041
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
app/setting.txt
@@ -1 +1 @@
0
1
app/user.txt
@@ -1,3 +1,3 @@
client2
client3
123456
0