Mercurial > minori
view dep/animone/src/win/win32.cc @ 327:b5d6c27c308f
anime: refactor Anime::SeriesSeason to Season class
ToLocalString has also been altered to take in both season
and year because lots of locales actually treat formatting
seasons differently! most notably is Russian which adds a
suffix at the end to notate seasons(??)
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Thu, 13 Jun 2024 01:49:18 -0400 |
parents | b1f625b0227c |
children | a7d4e5107531 |
line wrap: on
line source
/* * win/win32.cc: support for Windows * * Surprisingly, this is the one time where Microsoft actually * does it fairly OK. Everything has a pretty simple API, despite * the stupid wide string stuff. */ #include "animone/win/win32.h" #include "animone.h" #include "animone/util/win32.h" #include "animone/win.h" #include "animone/fd.h" #include <set> #include <string> #include <windows.h> namespace animone::internal::win32 { static std::wstring GetWindowClassName(HWND hwnd) { static constexpr int kMaxSize = 256; std::wstring buffer(kMaxSize, L'\0'); const auto size = ::GetClassNameW(hwnd, &buffer.front(), buffer.length()); buffer.resize(size); return buffer; } static std::wstring GetWindowText(HWND hwnd) { const auto estimated_size = ::GetWindowTextLengthW(hwnd); std::wstring buffer(estimated_size + 1, L'\0'); const auto size = ::GetWindowTextW(hwnd, &buffer.front(), buffer.length()); /* GetWindowTextLength docs: * "Under certain conditions, the GetWindowTextLength function may return a value * that is larger than the actual length of the text." */ buffer.resize(size); return buffer; } static DWORD GetWindowProcessId(HWND hwnd) { DWORD process_id = 0; ::GetWindowThreadProcessId(hwnd, &process_id); return process_id; } //////////////////////////////////////////////////////////////////////////////// static bool VerifyWindowStyle(HWND hwnd) { const auto window_style = ::GetWindowLong(hwnd, GWL_STYLE); const auto window_ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); auto has_style = [&window_style](DWORD style) { return (window_style & style) != 0; }; auto has_ex_style = [&window_ex_style](DWORD ex_style) { return (window_ex_style & ex_style) != 0; }; // Toolbars, tooltips and similar topmost windows if (has_style(WS_POPUP) && has_ex_style(WS_EX_TOOLWINDOW)) return false; if (has_ex_style(WS_EX_TOPMOST) && has_ex_style(WS_EX_TOOLWINDOW)) return false; return true; } static bool VerifyClassName(const std::wstring& name) { static const std::set<std::wstring> invalid_names = { // System classes L"#32770", // Dialog box L"CabinetWClass", // Windows Explorer L"ComboLBox", L"DDEMLEvent", L"DDEMLMom", L"DirectUIHWND", L"GDI+ Hook Window Class", L"IME", L"Internet Explorer_Hidden", L"MSCTFIME UI", L"tooltips_class32", }; return !name.empty() && !invalid_names.count(name); } static bool VerifyProcessPath(const std::wstring& path) { return !path.empty() && !IsSystemDirectory(path); } static bool VerifyProcessFileName(const std::wstring& name) { static const std::set<std::wstring> invalid_names = { // System files L"explorer", // Windows Explorer L"taskeng", // Task Scheduler Engine L"taskhost", // Host Process for Windows Tasks L"taskhostex", // Host Process for Windows Tasks L"Taskmgr", // Task Manager }; return !name.empty() && !invalid_names.count(name); } //////////////////////////////////////////////////////////////////////////////// static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM param) { if (!::IsWindowVisible(hwnd)) return TRUE; if (!VerifyWindowStyle(hwnd)) return TRUE; Window window; window.id = static_cast<unsigned int>(reinterpret_cast<ULONG_PTR>(hwnd)); window.text = ToUtf8String(GetWindowText(hwnd)); { std::wstring class_name = GetWindowClassName(hwnd); window.class_name = ToUtf8String(class_name); if (!VerifyClassName(class_name)) return TRUE; } Process process; process.pid = GetWindowProcessId(hwnd); GetProcessName(process.pid, process.name); auto& window_proc = *reinterpret_cast<window_proc_t*>(param); if (!window_proc(process, window)) return FALSE; return TRUE; } bool EnumerateWindows(window_proc_t window_proc) { if (!window_proc) return false; const auto param = reinterpret_cast<LPARAM>(&window_proc); // Note that EnumWindows enumerates only top-level windows of desktop apps // (as opposed to UWP apps) on Windows 8 and above. return ::EnumWindows(EnumWindowsProc, param) != FALSE; } } // namespace animone::internal::win32