201 lines
6.1 KiB
C++
201 lines
6.1 KiB
C++
#include "windowfinder.h"
|
|
|
|
#include "QtImprovements/qsettingsplus.h"
|
|
|
|
#include <QFileInfo>
|
|
#include <QImage>
|
|
#include <QKeySequence>
|
|
|
|
#ifdef Q_OS_WIN
|
|
#include <Windows.h>
|
|
#include <processthreadsapi.h>
|
|
#include <Psapi.h>
|
|
#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<unsigned long long>(1) << nColorBits);
|
|
|
|
// QVector<quint8> bitmapInfo;
|
|
// bitmapInfo.resize(nBmInfoSize);
|
|
// BITMAPINFO *pBmInfo = (BITMAPINFO *) bitmapInfo.data();
|
|
// memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER));
|
|
|
|
// if (!bmInfo.bmiHeader.biSizeImage)
|
|
// return false;
|
|
// QVector<quint8> 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<quint8> maskBits;
|
|
// maskBits.resize(maskInfo.bmiHeader.biSizeImage);
|
|
// QVector<quint8> 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<const char *>(&dir);
|
|
// buffer.append(dirBuffer);
|
|
|
|
// pBmInfo->bmiHeader.biHeight *= 2;
|
|
// pBmInfo->bmiHeader.biCompression = 0;
|
|
// pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage;
|
|
// const char *bmiHeaderData = reinterpret_cast<const char *>(&pBmInfo->bmiHeader);
|
|
// buffer.append(bmiHeaderData);
|
|
|
|
// const char *bitData = reinterpret_cast<const char *>(bits.data());
|
|
// buffer.append(bitData);
|
|
|
|
// const char *maskBitData = reinterpret_cast<const char *>(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
|