2024-12-26 01:10:17 +08:00
|
|
|
|
#ifndef WINXP
|
2024-12-25 22:59:54 +08:00
|
|
|
|
#include <wil/com.h>
|
|
|
|
|
#include <uiautomation.h>
|
2024-12-26 01:10:17 +08:00
|
|
|
|
#endif
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API void showintab(HWND hwnd, bool show, bool tool)
|
2024-04-14 20:55:06 +08:00
|
|
|
|
{
|
2024-05-29 10:16:49 +08:00
|
|
|
|
// WS_EX_TOOLWINDOW可以立即生效,WS_EX_APPWINDOW必须切换焦点才生效。但是WS_EX_TOOLWINDOW会改变窗口样式,因此只对无边框窗口使用。
|
|
|
|
|
LONG style = GetWindowLong(hwnd, GWL_STYLE);
|
2024-04-14 20:55:06 +08:00
|
|
|
|
auto style_ex = GetWindowLong(hwnd, GWL_EXSTYLE);
|
|
|
|
|
if (show)
|
|
|
|
|
{
|
|
|
|
|
style_ex |= WS_EX_APPWINDOW;
|
2024-07-30 13:51:29 +08:00
|
|
|
|
// if ((style & WS_OVERLAPPEDWINDOW) != WS_OVERLAPPEDWINDOW)
|
2024-08-02 19:26:29 +08:00
|
|
|
|
if (tool)
|
|
|
|
|
style_ex &= ~WS_EX_TOOLWINDOW;
|
2024-04-14 20:55:06 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
style_ex &= ~WS_EX_APPWINDOW;
|
2024-07-30 13:51:29 +08:00
|
|
|
|
// if ((style & WS_OVERLAPPEDWINDOW) != WS_OVERLAPPEDWINDOW)
|
2024-08-02 19:26:29 +08:00
|
|
|
|
if (tool)
|
|
|
|
|
style_ex |= WS_EX_TOOLWINDOW;
|
2024-08-02 18:17:49 +08:00
|
|
|
|
}
|
|
|
|
|
SetWindowLong(hwnd, GWL_EXSTYLE, style_ex);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API bool pid_running(DWORD pid)
|
2024-04-14 20:55:06 +08:00
|
|
|
|
{
|
|
|
|
|
DWORD code;
|
2024-11-15 08:38:25 +08:00
|
|
|
|
#ifndef WINXP
|
2024-06-30 20:08:02 +08:00
|
|
|
|
GetExitCodeProcess(AutoHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid)), &code);
|
2024-11-15 08:38:25 +08:00
|
|
|
|
#else
|
|
|
|
|
GetExitCodeProcess(AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)), &code);
|
|
|
|
|
#endif
|
2024-06-30 20:08:02 +08:00
|
|
|
|
// 句柄必須具有 PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 訪問許可權。 如需詳細資訊,請參閱 處理安全性和訪問許可權。
|
|
|
|
|
// Windows Server 2003 和 Windows XP: 句柄必須具有 PROCESS_QUERY_INFORMATION 訪問許可權。
|
2024-04-14 20:55:06 +08:00
|
|
|
|
return code == STILL_ACTIVE;
|
|
|
|
|
// auto process = AutoHandle(OpenProcess(SYNCHRONIZE, FALSE, pid));
|
|
|
|
|
// DWORD ret = WaitForSingleObject(process, 0);
|
|
|
|
|
// return ret == WAIT_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct __EnumWindowsProc
|
|
|
|
|
{
|
|
|
|
|
DWORD pid;
|
|
|
|
|
HWND hwnd;
|
|
|
|
|
};
|
|
|
|
|
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
|
if (IsWindow(hwnd) && IsWindowEnabled(hwnd) & IsWindowVisible(hwnd))
|
|
|
|
|
{
|
|
|
|
|
auto info = (__EnumWindowsProc *)lParam;
|
|
|
|
|
|
|
|
|
|
DWORD processId;
|
|
|
|
|
GetWindowThreadProcessId(hwnd, &processId);
|
|
|
|
|
if (info->pid == processId && info->hwnd == 0)
|
|
|
|
|
{
|
|
|
|
|
info->hwnd = hwnd;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API HWND getpidhwndfirst(DWORD pid)
|
2024-04-14 20:55:06 +08:00
|
|
|
|
{
|
|
|
|
|
__EnumWindowsProc info = {pid, 0};
|
|
|
|
|
EnumWindows(EnumWindowsProc, (LPARAM)&info);
|
|
|
|
|
return info.hwnd;
|
|
|
|
|
}
|
2025-01-01 20:26:47 +08:00
|
|
|
|
namespace
|
2024-04-14 20:55:06 +08:00
|
|
|
|
{
|
2025-01-01 20:26:47 +08:00
|
|
|
|
BOOL Is64BitOS()
|
2024-04-14 20:55:06 +08:00
|
|
|
|
{
|
2025-01-01 20:26:47 +08:00
|
|
|
|
SYSTEM_INFO systemInfo = {0};
|
|
|
|
|
GetNativeSystemInfo(&systemInfo);
|
|
|
|
|
return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64;
|
2024-04-14 20:55:06 +08:00
|
|
|
|
}
|
2025-01-01 20:26:47 +08:00
|
|
|
|
}
|
|
|
|
|
DECLARE_API bool Is64bit(DWORD pid)
|
|
|
|
|
{
|
|
|
|
|
if (!Is64BitOS())
|
2024-04-14 20:55:06 +08:00
|
|
|
|
return false;
|
2025-01-01 20:26:47 +08:00
|
|
|
|
#ifndef WINXP
|
|
|
|
|
auto hprocess = AutoHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid));
|
|
|
|
|
#else
|
|
|
|
|
auto hprocess = AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid));
|
|
|
|
|
#endif
|
|
|
|
|
// 進程的控制碼。 控制碼必須具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION存取權限。 如需詳細資訊,請參閱 處理安全性和存取權限。
|
|
|
|
|
// Windows Server 2003 和 Windows XP: 控制碼必須具有PROCESS_QUERY_INFORMATION存取權限。
|
|
|
|
|
BOOL f64bitProc = false;
|
|
|
|
|
f64bitProc = !(IsWow64Process(hprocess, &f64bitProc) && f64bitProc);
|
|
|
|
|
return f64bitProc;
|
2024-08-02 19:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-11-04 23:10:41 +08:00
|
|
|
|
DECLARE_API void getprocesses(void (*cb)(DWORD, const wchar_t *))
|
2024-08-02 19:26:29 +08:00
|
|
|
|
{
|
|
|
|
|
std::unordered_map<std::wstring, std::vector<int>> exe_pid;
|
|
|
|
|
AutoHandle hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
|
|
if (hSnapshot == INVALID_HANDLE_VALUE)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
PROCESSENTRY32 pe32;
|
|
|
|
|
pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
|
auto currpid = GetCurrentProcessId();
|
|
|
|
|
if (Process32First(hSnapshot, &pe32))
|
|
|
|
|
{
|
|
|
|
|
do
|
|
|
|
|
{
|
2024-08-03 17:46:50 +08:00
|
|
|
|
cb(pe32.th32ProcessID, pe32.szExeFile);
|
2024-08-02 19:26:29 +08:00
|
|
|
|
} while (Process32Next(hSnapshot, &pe32));
|
|
|
|
|
}
|
2024-10-16 15:24:38 +08:00
|
|
|
|
}
|
2024-11-15 03:21:30 +08:00
|
|
|
|
|
2024-11-30 04:03:13 +08:00
|
|
|
|
DECLARE_API bool check_window_viewable(HWND hwnd)
|
|
|
|
|
{
|
|
|
|
|
RECT windowRect;
|
|
|
|
|
if (!GetWindowRect(hwnd, &windowRect))
|
|
|
|
|
return false;
|
|
|
|
|
HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
|
|
|
if (!hMonitor)
|
|
|
|
|
return false;
|
|
|
|
|
MONITORINFO monitorInfo;
|
|
|
|
|
monitorInfo.cbSize = sizeof(MONITORINFO);
|
|
|
|
|
if (!GetMonitorInfo(hMonitor, &monitorInfo))
|
|
|
|
|
return false;
|
|
|
|
|
RECT _;
|
|
|
|
|
return IntersectRect(&_, &windowRect, &monitorInfo.rcWork);
|
2024-12-25 22:59:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DECLARE_API void GetSelectedText(void (*cb)(const wchar_t *))
|
|
|
|
|
{
|
2024-12-26 01:10:17 +08:00
|
|
|
|
#ifndef WINXP
|
2024-12-29 18:09:35 +08:00
|
|
|
|
CO_INIT co;
|
|
|
|
|
CHECK_FAILURE_NORET(co);
|
2024-12-25 22:59:54 +08:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// 初始化 COM
|
|
|
|
|
wil::com_ptr<IUIAutomation> automation;
|
|
|
|
|
if (FAILED(CoCreateInstance(CLSID_CUIAutomation, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&automation))) || !automation)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("无法初始化 UI Automation.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取焦点元素
|
|
|
|
|
wil::com_ptr<IUIAutomationElement> focusedElement;
|
|
|
|
|
if (FAILED(automation->GetFocusedElement(&focusedElement)) || !focusedElement)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("无法获取当前焦点元素.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否支持 TextPattern
|
|
|
|
|
wil::com_ptr<IUIAutomationTextPattern> textPattern;
|
|
|
|
|
if (FAILED(focusedElement->GetCurrentPatternAs(UIA_TextPatternId, IID_PPV_ARGS(&textPattern))) || !textPattern)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("当前元素不支持 TextPattern.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取选定的文本范围
|
|
|
|
|
wil::com_ptr<IUIAutomationTextRangeArray> selection;
|
|
|
|
|
if (FAILED(textPattern->GetSelection(&selection)) || !selection)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("无法获取选定的文本范围.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取第一个选定范围
|
|
|
|
|
wil::com_ptr<IUIAutomationTextRange> range;
|
|
|
|
|
if (FAILED(selection->GetElement(0, &range)) || !range)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("没有选定文本.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 提取文本
|
2024-12-29 15:35:27 +08:00
|
|
|
|
wil::unique_bstr text;
|
2024-12-25 22:59:54 +08:00
|
|
|
|
if (FAILED(range->GetText(-1, &text)) || !text)
|
|
|
|
|
{
|
|
|
|
|
throw std::runtime_error("无法提取选定的文本.");
|
|
|
|
|
}
|
2024-12-29 15:35:27 +08:00
|
|
|
|
cb(text.get());
|
2024-12-25 22:59:54 +08:00
|
|
|
|
}
|
|
|
|
|
catch (std::exception &e)
|
|
|
|
|
{
|
|
|
|
|
printf(e.what());
|
|
|
|
|
}
|
2024-12-26 01:10:17 +08:00
|
|
|
|
#endif
|
2024-12-25 22:59:54 +08:00
|
|
|
|
}
|
2025-01-01 21:02:35 +08:00
|
|
|
|
|
|
|
|
|
DECLARE_API void *get_allAccess_ptr()
|
|
|
|
|
{
|
|
|
|
|
return &allAccess;
|
|
|
|
|
}
|