#include "ScrcpyWindow.h" #include #include #include #include #include #include #ifdef Q_OS_WIN #include #include #endif ScrcpyWindow::ScrcpyWindow(QWidget *parent) : QWidget(parent), m_process(nullptr) { // setWindowFlag(Qt::WindowStaysOnTopHint); startScrcpy(); } ScrcpyWindow::~ScrcpyWindow() { stopScrcpy(); } void ScrcpyWindow::closeEvent(QCloseEvent *event) { qDebug() << "closeEvent triggered"; stopScrcpy(); event->accept(); } void ScrcpyWindow::startScrcpy() { int deviceWidth = 720; int deviceHeight = 1600; QScreen *screen = QGuiApplication::primaryScreen(); int screenHeight = screen->availableGeometry().height(); int screenWidth = screen->availableGeometry().width(); // Вычисляем масштаб так, чтобы устройство влезло в экран (и по ширине, и по высоте) double scaleW = static_cast(screenWidth) / deviceWidth; double scaleH = static_cast(screenHeight) / deviceHeight; double scale = qMin(scaleW, scaleH) * 0.8; // 90% от доступного размера, с отступами int windowWidth = static_cast(deviceWidth * scale); int windowHeight = static_cast(deviceHeight * scale); setFixedSize(windowWidth + 100, windowHeight); // setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint); m_process = new QProcess(this); m_process->start("scrcpy", {"--window-title", "scrcpy", "--always-on-top", "--window-borderless"}); embedPlatformSpecific(); } void ScrcpyWindow::stopScrcpy() { m_process->kill(); // Принудительное завершение процесса delete m_process; m_process = nullptr; #ifdef Q_OS_WIN HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy"); if (hwndScrcpy) { PostMessage(hwndScrcpy, WM_CLOSE, 0, 0); } #endif } #ifdef Q_OS_WIN LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { OutputDebugString(L"WM_CLOSE received\n"); HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy"); if (!hwndScrcpy) return DefWindowProc(hwnd, msg, wParam, lParam); if (msg == WM_CLOSE) { qDebug() << "WM_CLOSE received, closing scrcpy window."; // Возможно, необходимо обработать конкретно это сообщение // или сделать дополнительные проверки. } switch (msg) { case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_MOUSEWHEEL: { // Перевод координат мыши в координаты окна scrcpy POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); qDebug() << "Before ClientToScreen: " << pt.x << ", " << pt.y; ClientToScreen(hwnd, &pt); qDebug() << "After ClientToScreen: " << pt.x << ", " << pt.y; ScreenToClient(hwndScrcpy, &pt); qDebug() << "After ScreenToClient: " << pt.x << ", " << pt.y; LPARAM newLParam = MAKELPARAM(pt.x, pt.y); SendMessage(hwndScrcpy, msg, wParam, newLParam); return 0; } case WM_KEYDOWN: case WM_KEYUP: case WM_CHAR: SendMessage(hwndScrcpy, msg, wParam, lParam); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); } void ScrcpyWindow::embedPlatformSpecific() { HWND hwndScrcpy = FindWindowW(nullptr, L"scrcpy"); int attempts = 0; while (!hwndScrcpy && attempts < 20) { hwndScrcpy = FindWindowW(nullptr, L"scrcpy"); Sleep(100); // Задержка 100 мс attempts++; } if (!hwndScrcpy) { qDebug() << "scrcpy window not found"; return; } Sleep(1000); // Получаем hwnd текущего окна HWND hwndTarget = (HWND)this->winId(); // Устанавливаем окно scrcpy как дочернее SetParent(hwndScrcpy, hwndTarget); // Убираем рамки и заголовок LONG style = GetWindowLong(hwndScrcpy, GWL_STYLE); style &= ~(WS_CAPTION | WS_THICKFRAME | WS_BORDER); SetWindowLong(hwndScrcpy, GWL_STYLE, style); // Получаем размеры клиентской области RECT rect; GetClientRect(hwndTarget, &rect); qDebug() << "Client area size: " << rect.right << ", " << rect.bottom; // int deviceWidth = 720; // int deviceHeight = 1600; // Client area size: 676 , 1502 // Получаем размеры клиентской области // RECT rect; // GetClientRect(hwndTarget, &rect); SetWindowPos(hwndScrcpy, HWND_TOP, 0, 0, rect.right - rect.left - 200, rect.bottom - rect.top, SWP_SHOWWINDOW | SWP_FRAMECHANGED); // rect.right - rect.left, rect.bottom - rect.top, // Сохраняем старую оконную процедуру // LONG_PTR prevWndProc = GetWindowLongPtr(hwndTarget, GWLP_WNDPROC); // SetWindowLongPtr(hwndTarget, GWLP_WNDPROC, (LONG_PTR)wndProc); } #endif