diff --git a/MeoAssistance/include/WinMacro.h b/MeoAssistance/include/WinMacro.h index b351872ca5..964d4cae24 100644 --- a/MeoAssistance/include/WinMacro.h +++ b/MeoAssistance/include/WinMacro.h @@ -16,11 +16,11 @@ namespace MeoAssistance { bool findHandle(); bool resizeWindow(int Width, int Height); - bool click(Point p); - bool clickRange(Rect rect); - cv::Mat getImage(Rect rect); + bool click(const Point & p); + bool clickRange(const Rect & rect); + cv::Mat getImage(const Rect& rect); Rect getWindowRect(); - double getScreenScale(); + static double getScreenScale(); private: HandleType m_handle_type; diff --git a/MeoAssistance/src/WinMacro.cpp b/MeoAssistance/src/WinMacro.cpp index e395f096f2..93183c66a1 100644 --- a/MeoAssistance/src/WinMacro.cpp +++ b/MeoAssistance/src/WinMacro.cpp @@ -16,196 +16,177 @@ using namespace MeoAssistance; WinMacro::WinMacro(HandleType type) - : m_handle_type(type), - m_rand_engine(time(NULL)) + : m_handle_type(type), + m_rand_engine(time(NULL)) { } bool WinMacro::findHandle() { - json::array handle_arr; - switch (m_handle_type) { - case HandleType::BlueStacksControl: - handle_arr = Configer::handleObj["BlueStacksControl"].as_array(); - break; - case HandleType::BlueStacksView: - handle_arr = Configer::handleObj["BlueStacksView"].as_array(); - break; - case HandleType::BlueStacksWindow: - handle_arr = Configer::handleObj["BlueStacksWindow"].as_array(); - break; - default: - std::cerr << "handle type error! " << static_cast(m_handle_type) << std::endl; - return false; - } + json::array handle_arr; + switch (m_handle_type) { + case HandleType::BlueStacksControl: + handle_arr = Configer::handleObj["BlueStacksControl"].as_array(); + break; + case HandleType::BlueStacksView: + handle_arr = Configer::handleObj["BlueStacksView"].as_array(); + break; + case HandleType::BlueStacksWindow: + handle_arr = Configer::handleObj["BlueStacksWindow"].as_array(); + break; + default: + std::cerr << "handle type error! " << static_cast(m_handle_type) << std::endl; + return false; + } - m_handle = NULL; - for (auto&& obj : handle_arr) - { - m_handle = ::FindWindowExA(m_handle, NULL, obj["class"].as_string().c_str(), obj["window"].as_string().c_str()); - } + m_handle = NULL; + for (auto&& obj : handle_arr) + { + m_handle = ::FindWindowExA(m_handle, NULL, obj["class"].as_string().c_str(), obj["window"].as_string().c_str()); + } #ifdef _DEBUG - std::cout << "type: " << static_cast(m_handle_type) << ", handle: " << m_handle << std::endl; + std::cout << "type: " << static_cast(m_handle_type) << ", handle: " << m_handle << std::endl; #endif - if (m_handle != NULL) { - return true; - } - else { - return false; - } + if (m_handle != NULL) { + return true; + } + else { + return false; + } } bool WinMacro::resizeWindow(int width, int height) { - if (!(static_cast(m_handle_type) & static_cast(HandleType::Window))) { - return false; - } + if (!(static_cast(m_handle_type) & static_cast(HandleType::Window))) { + return false; + } - return ::MoveWindow(m_handle, 0, 0, width, height, true); + return ::MoveWindow(m_handle, 0, 0, width / getScreenScale(), height / getScreenScale(), true); } double WinMacro::getScreenScale() { - // 获取窗口当前显示的监视器 - // 使用桌面的句柄. - HWND hWnd = GetDesktopWindow(); - HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); + static double scale = 0; + if (scale == 0) { + // 获取窗口当前显示的监视器 + // 使用桌面的句柄. + HWND hWnd = GetDesktopWindow(); + HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); - // 获取监视器逻辑宽度与高度 - MONITORINFOEX miex; - miex.cbSize = sizeof(miex); - GetMonitorInfo(hMonitor, &miex); - int cxLogical = (miex.rcMonitor.right - miex.rcMonitor.left); - int cyLogical = (miex.rcMonitor.bottom - miex.rcMonitor.top); + // 获取监视器逻辑宽度与高度 + MONITORINFOEX miex; + miex.cbSize = sizeof(miex); + GetMonitorInfo(hMonitor, &miex); + int cxLogical = (miex.rcMonitor.right - miex.rcMonitor.left); + int cyLogical = (miex.rcMonitor.bottom - miex.rcMonitor.top); - // 获取监视器物理宽度与高度 - DEVMODE dm; - dm.dmSize = sizeof(dm); - dm.dmDriverExtra = 0; - EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm); - int cxPhysical = dm.dmPelsWidth; - int cyPhysical = dm.dmPelsHeight; + // 获取监视器物理宽度与高度 + DEVMODE dm; + dm.dmSize = sizeof(dm); + dm.dmDriverExtra = 0; + EnumDisplaySettings(miex.szDevice, ENUM_CURRENT_SETTINGS, &dm); + int cxPhysical = dm.dmPelsWidth; + int cyPhysical = dm.dmPelsHeight; - // 考虑状态栏大小,逻辑尺寸会比实际小 - double horzScale = ((double)cxPhysical / (double)cxLogical); - double vertScale = ((double)cyPhysical / (double)cyLogical); + // 考虑状态栏大小,逻辑尺寸会比实际小 + double horzScale = ((double)cxPhysical / (double)cxLogical); + double vertScale = ((double)cyPhysical / (double)cyLogical); - // 考虑状态栏大小,选择里面大的那个 - return std::max(horzScale, vertScale); + // 考虑状态栏大小,选择里面大的那个 + scale = std::max(horzScale, vertScale); + } + return scale; } -bool WinMacro::click(Point p) +bool WinMacro::click(const Point& p) { - if (!(static_cast(m_handle_type) & static_cast(HandleType::Control))) { - return false; - } + if (!(static_cast(m_handle_type) & static_cast(HandleType::Control))) { + return false; + } + int x = p.x / getScreenScale(); + int y = p.y / getScreenScale(); #ifdef _DEBUG - std::cout << "click: " << p.x << ", " << p.y << std::endl; + std::cout << "click: " << x << ", " << y << std::endl; #endif - LPARAM lparam = MAKELPARAM(p.x, p.y); + LPARAM lparam = MAKELPARAM(x, y); ::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam); ::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam); - return true; + return true; } -bool WinMacro::clickRange(Rect rect) +bool WinMacro::clickRange(const Rect& rect) { - if (!(static_cast(m_handle_type) & static_cast(HandleType::Control))) { - return false; - } + if (!(static_cast(m_handle_type) & static_cast(HandleType::Control))) { + return false; + } - int x = 0, y = 0; - if (rect.width == 0) { - x = rect.x; - } - else { - std::poisson_distribution x_rand(rect.width); - x = x_rand(m_rand_engine) + rect.x; - } + int x = 0, y = 0; + if (rect.width == 0) { + x = rect.x; + } + else { + std::poisson_distribution x_rand(rect.width); + x = x_rand(m_rand_engine) + rect.x; + } - if (rect.height == 0) { - y = rect.y; - } - else { - std::poisson_distribution y_rand(rect.height); - y = y_rand(m_rand_engine) + rect.y; - } + if (rect.height == 0) { + y = rect.y; + } + else { + std::poisson_distribution y_rand(rect.height); + y = y_rand(m_rand_engine) + rect.y; + } - return click({ x, y }); + return click({ x, y }); } Rect WinMacro::getWindowRect() { - RECT rect; - bool ret = ::GetWindowRect(m_handle, &rect); - if (!ret) { - return { 0, 0, 0 ,0 }; - } - double scale = getScreenScale(); - return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top } * scale; + RECT rect; + bool ret = ::GetWindowRect(m_handle, &rect); + if (!ret) { + return { 0, 0, 0 ,0 }; + } + return Rect{ rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top } *getScreenScale(); } -cv::Mat WinMacro::getImage(Rect rect) +cv::Mat WinMacro::getImage(const Rect& rect) { - if (!(static_cast(m_handle_type) & static_cast(HandleType::View))) { - return cv::Mat(); - } + if (!(static_cast(m_handle_type) & static_cast(HandleType::View))) { + return cv::Mat(); + } - HDC pDC;// 源DC - //判断是不是窗口句柄如果是的话不能使用GetDC来获取DC 不然截图会是黑屏 - if (m_handle == ::GetDesktopWindow()) - { - pDC = CreateDCA("DISPLAY", NULL, NULL, NULL); - } - else - { - pDC = ::GetDC(m_handle);//获取屏幕DC(0为全屏,句柄则为窗口) - } - int BitPerPixel = ::GetDeviceCaps(pDC, BITSPIXEL);//获得颜色模式 - if (rect.width == 0 && rect.height == 0)//默认宽度和高度为全屏 - { - rect.width = ::GetDeviceCaps(pDC, HORZRES); //设置图像宽度全屏 - rect.height = ::GetDeviceCaps(pDC, VERTRES); //设置图像高度全屏 - } - HDC memDC;//内存DC - memDC = ::CreateCompatibleDC(pDC); - HBITMAP memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap - memBitmap = ::CreateCompatibleBitmap(pDC, rect.width, rect.height); - oldmemBitmap = (HBITMAP)::SelectObject(memDC, memBitmap);//将memBitmap选入内存DC - if (m_handle == ::GetDesktopWindow()) - { - BitBlt(memDC, 0, 0, rect.width, rect.height, pDC, rect.x, rect.y, SRCCOPY);//图像宽度高度和截取位置 - } - else - { - bool bret = ::PrintWindow(m_handle, memDC, PW_CLIENTONLY); - if (!bret) - { - BitBlt(memDC, 0, 0, rect.width, rect.height, pDC, rect.x, rect.y, SRCCOPY);//图像宽度高度和截取位置 - } - } + HDC pDC;// 源DC + pDC = ::GetDC(m_handle);//获取屏幕DC(0为全屏,句柄则为窗口) + int BitPerPixel = ::GetDeviceCaps(pDC, BITSPIXEL);//获得颜色模式 + HDC memDC;//内存DC + memDC = ::CreateCompatibleDC(pDC); + HBITMAP memBitmap, oldmemBitmap;//建立和屏幕兼容的bitmap + memBitmap = ::CreateCompatibleBitmap(pDC, rect.width, rect.height); + oldmemBitmap = (HBITMAP)::SelectObject(memDC, memBitmap);//将memBitmap选入内存DC + ::PrintWindow(m_handle, memDC, PW_CLIENTONLY); - BITMAP bmp; - GetObject(memBitmap, sizeof(BITMAP), &bmp); - int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8; - cv::Mat dst_mat; - dst_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8U, nChannels)); - GetBitmapBits(memBitmap, bmp.bmHeight * bmp.bmWidth * nChannels, dst_mat.data); + BITMAP bmp; + GetObject(memBitmap, sizeof(BITMAP), &bmp); + int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8; + cv::Mat dst_mat; + dst_mat.create(cv::Size(bmp.bmWidth, bmp.bmHeight), CV_MAKETYPE(CV_8U, nChannels)); + GetBitmapBits(memBitmap, bmp.bmHeight * bmp.bmWidth * nChannels, dst_mat.data); - DeleteObject(memBitmap); - DeleteDC(memDC); - ReleaseDC(m_handle, pDC); + DeleteObject(memBitmap); + DeleteDC(memDC); + ReleaseDC(m_handle, pDC); #ifdef _DEBUG - std::string filename = Configer::getCurDir() + "\\test.bmp"; - cv::imwrite(filename, dst_mat); + std::string filename = Configer::getCurDir() + "\\test.bmp"; + cv::imwrite(filename, dst_mat); #endif - return dst_mat; + return dst_mat; } \ No newline at end of file diff --git a/resource/MissionSucceed.png b/resource/MissionSucceed.png index e66df57373..5049e6df6f 100644 Binary files a/resource/MissionSucceed.png and b/resource/MissionSucceed.png differ diff --git a/resource/PRTS.png b/resource/PRTS.png index 7b52ebfceb..50b8a5897b 100644 Binary files a/resource/PRTS.png and b/resource/PRTS.png differ diff --git a/resource/StartButton1.png b/resource/StartButton1.png index 355930e5de..8248bc57a2 100644 Binary files a/resource/StartButton1.png and b/resource/StartButton1.png differ diff --git a/resource/StartButton2.png b/resource/StartButton2.png index 87d51040ee..1e45c4d6c1 100644 Binary files a/resource/StartButton2.png and b/resource/StartButton2.png differ diff --git a/resource/UseMedicine.png b/resource/UseMedicine.png index 2a357966c8..473057bb35 100644 Binary files a/resource/UseMedicine.png and b/resource/UseMedicine.png differ diff --git a/resource/UseStone.png b/resource/UseStone.png index 532e850e8f..70244b59f4 100644 Binary files a/resource/UseStone.png and b/resource/UseStone.png differ diff --git a/resource/config.json b/resource/config.json index b1d1224c6d..b4099044c4 100644 --- a/resource/config.json +++ b/resource/config.json @@ -29,40 +29,12 @@ ] }, "data": { - "PRTS": { - "viewRect": [ - 1503, - 65, - 280, - 114 - ], - "filename": "PRTS.png", - "similarity": 0.9, - "type": "donothing" - }, - "MissionSucceed": { - "viewRect": [ - 255, - 778, - 71, - 38 - ], - "filename": "MissionSucceed.png", - "similarity": 0.9, - "type": "click", - "ctrlRect": [ - 50, - 596, - 163, - 29 - ] - }, "UseMedicine": { "viewRect": [ - 874, - 157, - 960, - 774 + 571, + 118, + 621, + 504 ], "filename": "UseMedicine.png", "similarity": 0.999, @@ -70,21 +42,38 @@ }, "UseStone": { "viewRect": [ - 874, - 157, - 960, - 774 + 571, + 118, + 621, + 504 ], "filename": "UseStone.png", "similarity": 0.999, "type": "stop" }, + "MissionSucceed": { + "viewRect": [ + 186, + 521, + 47, + 26 + ], + "filename": "MissionSucceed.png", + "similarity": 0.4, + "type": "click", + "ctrlRect": [ + 977, + 596, + 163, + 29 + ] + }, "StartButton1": { "viewRect": [ - 1487, - 940, - 295, - 107 + 968, + 627, + 193, + 70 ], "filename": "StartButton1.png", "similarity": 0.99, @@ -98,10 +87,10 @@ }, "StartButton2": { "viewRect": [ - 1484, - 569, - 190, - 398 + 966, + 386, + 126, + 259 ], "filename": "StartButton2.png", "similarity": 0.99,