#include "windowfinder.h" #include "QtImprovements/qsettingsplus.h" #include #include #include #ifdef Q_OS_WIN #include #include #include #endif WindowFinder::WindowFinder() {} WindowData WindowFinder::getFrontmostWindowProcess() { #ifdef Q_OS_WIN return WindowFinder::getWin32FrontmostWindowProcess(); #else return WindowData(); #endif } void WindowFinder::sendInputToFrontmostWindow(const QKeySequence &keys, const KeyEventType &type) { #ifdef Q_OS_WIN WindowFinder::sendWin32InputToFrontmostWindow(keys, type); #else return; #endif } void WindowData::importDataFromSetting(const QString &value) { QStringList values = value.split(QSettingsPlus::keyDataSeparator()); this->processName = values[0]; this->processPath = values[1]; values.removeAt(1); values.removeAt(0); this->processWindowTitle = values.join(QSettingsPlus::keyDataSeparator()); } #ifdef Q_OS_WIN WindowData WindowFinder::getWin32FrontmostWindowProcess() { WindowData data; HWND focusWindow = GetForegroundWindow(); DWORD processId; GetWindowThreadProcessId(focusWindow, &processId); HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); TCHAR processPath[MAX_PATH]; DWORD pathLength = GetModuleFileNameExW(processHandle, NULL, processPath, MAX_PATH); assert(pathLength != ERROR_INSUFFICIENT_BUFFER); data.processPath = QString::fromWCharArray(processPath, pathLength); data.processName = QFileInfo(data.processPath).fileName(); /* Extract icon */ // HICON processIcon; // ExtractIconExW(processPath, 0, &processIcon, nullptr, 1); // QByteArray pixelBuffer; // WindowFinder::getWin32IconData(processIcon, 32, pixelBuffer); /* End extract icon */ WCHAR processTitle[512]; DWORD titleLength = GetWindowTextW(focusWindow, &processTitle[0], 512); assert(titleLength != ERROR_INSUFFICIENT_BUFFER); data.processWindowTitle = QString::fromWCharArray(processTitle, titleLength); CloseHandle(processHandle); return data; } // bool WindowFinder::getWin32IconData(HICON hIcon, int nColorBits, QByteArray &buffer) // { // HDC dc = CreateCompatibleDC(NULL); // const char iconHeader[6] = {0, 0, 1, 0, 1, 0}; // buffer.append(iconHeader); // ICONINFO iconInfo; // GetIconInfo(hIcon, &iconInfo); // BITMAPINFO bmInfo = {{0}}; // bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // bmInfo.bmiHeader.biBitCount = 0; // if (!GetDIBits(dc, iconInfo.hbmColor, 0, 0, NULL, &bmInfo, DIB_RGB_COLORS)) // return false; // int nBmInfoSize = sizeof(BITMAPINFOHEADER); // if (nColorBits < 24) // nBmInfoSize += sizeof(RGBQUAD) * (int) (static_cast(1) << nColorBits); // QVector bitmapInfo; // bitmapInfo.resize(nBmInfoSize); // BITMAPINFO *pBmInfo = (BITMAPINFO *) bitmapInfo.data(); // memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER)); // if (!bmInfo.bmiHeader.biSizeImage) // return false; // QVector bits; // bits.resize(bmInfo.bmiHeader.biSizeImage); // pBmInfo->bmiHeader.biBitCount = nColorBits; // pBmInfo->bmiHeader.biCompression = BI_RGB; // if (!GetDIBits(dc, // iconInfo.hbmColor, // 0, // bmInfo.bmiHeader.biHeight, // bits.data(), // pBmInfo, // DIB_RGB_COLORS)) // return false; // BITMAPINFO maskInfo = {{0}}; // maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // maskInfo.bmiHeader.biBitCount = 0; // if (!GetDIBits(dc, iconInfo.hbmMask, 0, 0, NULL, &maskInfo, DIB_RGB_COLORS) // || maskInfo.bmiHeader.biBitCount != 1) // return false; // QVector maskBits; // maskBits.resize(maskInfo.bmiHeader.biSizeImage); // QVector maskInfoBytes; // maskInfoBytes.resize(sizeof(BITMAPINFO) + 2 * sizeof(RGBQUAD)); // BITMAPINFO *pMaskInfo = (BITMAPINFO *) maskInfoBytes.data(); // memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo)); // if (!GetDIBits(dc, // iconInfo.hbmMask, // 0, // maskInfo.bmiHeader.biHeight, // maskBits.data(), // pMaskInfo, // DIB_RGB_COLORS)) { // return false; // } // IconDirEntry dir; // dir.nWidth = (quint8) pBmInfo->bmiHeader.biWidth; // dir.nHeight = (quint8) pBmInfo->bmiHeader.biHeight; // dir.nNumColorsInPalette = (nColorBits == 4 ? 16 : 0); // dir.nReserved = 0; // dir.nNumColorPlanes = 0; // dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount; // dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage // + nBmInfoSize; // dir.nOffset = sizeof(dir) + sizeof(iconHeader); // const char *dirBuffer = reinterpret_cast(&dir); // buffer.append(dirBuffer); // pBmInfo->bmiHeader.biHeight *= 2; // pBmInfo->bmiHeader.biCompression = 0; // pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // const char *bmiHeaderData = reinterpret_cast(&pBmInfo->bmiHeader); // buffer.append(bmiHeaderData); // const char *bitData = reinterpret_cast(bits.data()); // buffer.append(bitData); // const char *maskBitData = reinterpret_cast(maskBits.data()); // buffer.append(maskBitData); // DeleteObject(iconInfo.hbmMask); // DeleteObject(iconInfo.hbmColor); // DeleteDC(dc); // return true; // } void WindowFinder::sendWin32InputToFrontmostWindow(const QKeySequence &keys, const KeyEventType &type) { const QString &keyStrings = keys.toString(); const QStringList &keyStringsList = keyStrings.split(","); for (const QString &keyString : keyStringsList) { const QStringList &keys = keyString.split("+"); for (const QString &key : keys) { INPUT input[1] = {}; ZeroMemory(input, sizeof(input)); input[0].type = INPUT_KEYBOARD; if (key.compare("Shift", Qt::CaseInsensitive) == 0) { input[0].ki.wVk = VK_LSHIFT; } else if (key.compare("X", Qt::CaseInsensitive) == 0) { input[0].ki.wVk = 'X'; } else if (key.compare("Y", Qt::CaseInsensitive) == 0) { input[0].ki.wVk = 'Y'; } else if (key.compare("Z", Qt::CaseInsensitive) == 0) { input[0].ki.wVk = 'Z'; } input[0].ki.dwFlags = type == KeyEventType::RELEASE ? KEYEVENTF_KEYUP : 0; SendInput(ARRAYSIZE(input), input, sizeof(INPUT)); } } } #endif // Q_OS_WIN