feat(master): hook focus changed event
This commit is contained in:
@ -2,27 +2,32 @@
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <psapi.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
#pragma comment(lib, "psapi.lib")
|
||||
|
||||
#pragma warning(disable: 4996)
|
||||
|
||||
// ReSharper disable CppDeprecatedEntity
|
||||
// ReSharper disable CppClangTidyCertErr33C
|
||||
|
||||
std::mutex GLogMutex;
|
||||
std::ofstream GLogFile;
|
||||
|
||||
bool GShouldExit = false;
|
||||
std::atomic<bool> GShouldExit = false;
|
||||
|
||||
void PrintLog(const std::string& Text);
|
||||
|
||||
void CALLBACK FocusEventHookProc(HWINEVENTHOOK, DWORD Event, HWND Window, LONG, LONG, DWORD, DWORD);
|
||||
|
||||
LRESULT CALLBACK MainWindowProc(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam);
|
||||
|
||||
int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
|
||||
@ -47,8 +52,6 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
|
||||
return 0;
|
||||
}
|
||||
|
||||
HWND MainWindow = nullptr;
|
||||
|
||||
WNDCLASS MainWindowClass = { };
|
||||
|
||||
MainWindowClass.lpfnWndProc = MainWindowProc;
|
||||
@ -66,7 +69,7 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
|
||||
return 1;
|
||||
}
|
||||
|
||||
MainWindow = CreateWindow(
|
||||
const HWND MainWindow = CreateWindow(
|
||||
"FocusIME_MainWindow",
|
||||
"FocusIME",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
@ -74,7 +77,7 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
nullptr, nullptr, Instance, nullptr);
|
||||
|
||||
if (!MainWindow)
|
||||
if (MainWindow == nullptr)
|
||||
{
|
||||
MessageBox(nullptr, "Failed to create main window.", "FocusIME", MB_OK | MB_ICONERROR);
|
||||
|
||||
@ -85,6 +88,24 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
|
||||
|
||||
ShowWindow(MainWindow, SW_HIDE);
|
||||
|
||||
const HWINEVENTHOOK FocusEventHook = SetWinEventHook(
|
||||
EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS,
|
||||
nullptr,
|
||||
FocusEventHookProc,
|
||||
0, 0,
|
||||
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||
|
||||
if (FocusEventHook == nullptr)
|
||||
{
|
||||
MessageBox(nullptr, "Failed to set focus event hook.", "FocusIME", MB_OK | MB_ICONWARNING);
|
||||
|
||||
DestroyWindow(MainWindow);
|
||||
|
||||
CloseHandle(Mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
GLogFile.open("Log.txt", std::ios::out | std::ios::app);
|
||||
|
||||
if (!GLogFile.is_open())
|
||||
@ -140,7 +161,13 @@ int WINAPI WinMain(HINSTANCE Instance, HINSTANCE, LPSTR, int)
|
||||
|
||||
PrintLog("FocusIME is shutting down...");
|
||||
|
||||
GLogFile.close();
|
||||
{
|
||||
std::lock_guard Lock(GLogMutex);
|
||||
|
||||
GLogFile.close();
|
||||
}
|
||||
|
||||
UnhookWinEvent(FocusEventHook);
|
||||
|
||||
DestroyWindow(MainWindow);
|
||||
|
||||
@ -237,6 +264,59 @@ LRESULT CALLBACK MainWindowProc(const HWND Window, const UINT Message, const WPA
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CALLBACK FocusEventHookProc(HWINEVENTHOOK, const DWORD Event, const HWND Window, LONG, LONG, DWORD, DWORD)
|
||||
{
|
||||
if (Event == EVENT_OBJECT_FOCUS && Window != nullptr)
|
||||
{
|
||||
std::string ProcessName;
|
||||
|
||||
do
|
||||
{
|
||||
DWORD PID = 0;
|
||||
|
||||
GetWindowThreadProcessId(Window, &PID);
|
||||
|
||||
const HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
|
||||
|
||||
if (ProcessHandle == nullptr)
|
||||
{
|
||||
ProcessName = "Unknown";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
char Buffer[MAX_PATH] = { };
|
||||
|
||||
if (GetModuleBaseName(ProcessHandle, nullptr, Buffer, sizeof(Buffer)) == 0)
|
||||
{
|
||||
CloseHandle(ProcessHandle);
|
||||
|
||||
ProcessName = "Unknown";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
CloseHandle(ProcessHandle);
|
||||
|
||||
ProcessName = Buffer;
|
||||
}
|
||||
while (false);
|
||||
|
||||
char Title[1024] = { };
|
||||
|
||||
GetWindowText(Window, Title, sizeof(Title));
|
||||
|
||||
std::string MessageBuffer = "Focus changed to: " + ProcessName;
|
||||
|
||||
if (strlen(Title) > 0)
|
||||
{
|
||||
MessageBuffer += " (" + std::string(Title) + ")";
|
||||
}
|
||||
|
||||
PrintLog(MessageBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintLog(const std::string& Text)
|
||||
{
|
||||
const auto Now = std::chrono::system_clock::now();
|
||||
@ -244,7 +324,9 @@ void PrintLog(const std::string& Text)
|
||||
|
||||
const long long Milliseconds = (std::chrono::duration_cast<std::chrono::milliseconds>(Now.time_since_epoch()) % 1000).count();
|
||||
|
||||
static std::mutex Mutex; std::lock_guard Lock(Mutex);
|
||||
std::lock_guard Lock(GLogMutex);
|
||||
|
||||
if (!GLogFile.is_open()) return;
|
||||
|
||||
const std::tm* LocalTime = std::localtime(&Time); // NOLINT(concurrency-mt-unsafe)
|
||||
|
||||
@ -261,6 +343,8 @@ void PrintLog(const std::string& Text)
|
||||
Buffer[23] = Digits[Milliseconds / 1 % 10];
|
||||
|
||||
GLogFile << Buffer << Text << std::endl;
|
||||
|
||||
GLogFile.flush();
|
||||
}
|
||||
|
||||
// ReSharper restore CppDeprecatedEntity
|
||||
|
Reference in New Issue
Block a user