Initial commit
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
#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
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef WINDOWFINDER_H
|
||||
#define WINDOWFINDER_H
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
struct IconDirEntry
|
||||
{
|
||||
quint8 nWidth;
|
||||
quint8 nHeight;
|
||||
quint8 nNumColorsInPalette;
|
||||
quint8 nReserved;
|
||||
qint16 nNumColorPlanes;
|
||||
qint16 nBitsPerPixel;
|
||||
quint32 nDataLength;
|
||||
quint32 nOffset;
|
||||
};
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
enum class KeyEventType : qint8 {
|
||||
PRESS,
|
||||
RELEASE,
|
||||
PRESS_AND_RELEASE
|
||||
};
|
||||
Q_DECLARE_METATYPE(KeyEventType)
|
||||
|
||||
|
||||
class WindowData
|
||||
{
|
||||
public:
|
||||
WindowData() = default;
|
||||
~WindowData() = default;
|
||||
WindowData(const WindowData &) = default;
|
||||
WindowData &operator=(const WindowData &) = default;
|
||||
|
||||
void importDataFromSetting(const QString &value);
|
||||
|
||||
QString processName = "";
|
||||
QString processPath = "";
|
||||
QString processWindowTitle = "";
|
||||
};
|
||||
Q_DECLARE_METATYPE(WindowData);
|
||||
|
||||
class WindowFinder
|
||||
{
|
||||
public:
|
||||
WindowFinder();
|
||||
|
||||
static WindowData getFrontmostWindowProcess();
|
||||
static void sendInputToFrontmostWindow(const QKeySequence &keys, const KeyEventType &type);
|
||||
|
||||
private:
|
||||
#ifdef Q_OS_WIN
|
||||
static WindowData getWin32FrontmostWindowProcess();
|
||||
// static bool getWin32IconData(HICON hIcon, int nColorBits, QByteArray &buffer);
|
||||
static void sendWin32InputToFrontmostWindow(const QKeySequence &keys, const KeyEventType &type);
|
||||
#endif // Q_OS_WIN
|
||||
};
|
||||
|
||||
#endif // WINDOWFINDER_H
|
||||
Reference in New Issue
Block a user