diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index a6987c170a..3ac98ffdad 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -527,6 +527,7 @@ enum EOAC eol epicgames +epo Eqn ERASEBKGND EREOF @@ -574,6 +575,7 @@ fallthrough fancyzones FANCYZONESDRAWLAYOUTTEST FANCYZONESEDITOR +FANCYZONESWINDOWSTYLES Farbraum Faroe FARPROC @@ -695,6 +697,7 @@ helptext Heure HEVC hfile +HFONT hglobal hhk HHmmss @@ -1309,6 +1312,7 @@ NCPAINT NCRBUTTONDBLCLK NCRBUTTONDOWN NCRBUTTONUP +NCRENDERING NDEBUG Ndombe ndp @@ -2254,6 +2258,8 @@ WINDOWSBUILDNUMBER Windowscodecs windowsdesktop windowssearch +WINDOWSTYLES +WINDOWSTYLESICON windowsx windowwalker winerror diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index 576f38511b..e8c370c09e 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -17,6 +17,7 @@ "PowerToys.Interop.dll", "BugReportTool\\PowerToys.BugReportTool.exe", "WebcamReportTool\\PowerToys.WebcamReportTool.exe", + "WindowStylesReportTool\\PowerToys.WindowStylesReportTool.exe", "Telemetry.dll", "PowerToys.ManagedTelemetry.dll", "PowerToys.ManagedCommon.dll", diff --git a/.pipelines/ci/templates/build-powertoys-steps.yml b/.pipelines/ci/templates/build-powertoys-steps.yml index 1204b10401..b54c7a9fd8 100644 --- a/.pipelines/ci/templates/build-powertoys-steps.yml +++ b/.pipelines/ci/templates/build-powertoys-steps.yml @@ -76,6 +76,25 @@ steps: msbuildArgs: ${{ parameters.additionalBuildArguments }} maximumCpuCount: true +- task: NuGetCommand@2 + displayName: Restore NuGet packages for WindowStylesReportTool.sln + inputs: + command: restore + feedsToUse: config + configPath: NuGet.config + restoreSolution: tools\WindowStylesReportTool\WindowStylesReportTool.sln + restoreDirectory: '$(Build.SourcesDirectory)\tools\WindowStylesReportTool\packages' + +- task: VSBuild@1 + displayName: 'Build WindowStylesReportTool.sln' + inputs: + solution: '**\WindowStylesReportTool.sln' + vsVersion: 17.0 + platform: '$(BuildPlatform)' + configuration: '$(BuildConfiguration)' + msbuildArgs: ${{ parameters.additionalBuildArguments }} + maximumCpuCount: true + - task: NuGetCommand@2 displayName: Restore NuGet packages for PowerToysSetup.sln inputs: diff --git a/.pipelines/release.yml b/.pipelines/release.yml index 2112bfd27a..5e7d2d5bc5 100644 --- a/.pipelines/release.yml +++ b/.pipelines/release.yml @@ -155,6 +155,17 @@ jobs: clean: true maximumCpuCount: true + - task: VSBuild@1 + displayName: Build WindowStylesReportTool + inputs: + solution: '**/tools/WindowStylesReportTool/WindowStylesReportTool.sln' + vsVersion: 17.0 + msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + - task: VSBuild@1 displayName: Build PowerToysSetupCustomActions inputs: diff --git a/doc/devdocs/readme.md b/doc/devdocs/readme.md index e06f9b6d65..c2f6459049 100644 --- a/doc/devdocs/readme.md +++ b/doc/devdocs/readme.md @@ -66,6 +66,7 @@ The installer can only be compiled in `Release` mode, step 1 and 2 must be done 1. Compile `PowerToys.sln`. Instructions are listed above. 2. Compile `BugReportTool.sln` tool. Path from root: `tools\BugReportTool\BugReportTool.sln` (details listed below) 3. Compile `WebcamReportTool.sln` tool. Path from root: `tools\WebcamReportTool\WebcamReportTool.sln` (details listed below) +3. Compile `WindowStylesReportTool.sln` tool. Path from root: `tools\WindowStylesReportTool\WindowStylesReportTool.sln` (details listed below) 4. Compile `PowerToysSetup.sln` Path from root: `installer\PowerToysSetup.sln` (details listed below) ### Prerequisites for building the MSI installer @@ -85,6 +86,12 @@ The installer can only be compiled in `Release` mode, step 1 and 2 must be done 2. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` 3. From the `Build` menu, choose `Build Solution`. +### Locally compiling the Window styles reporting tool + +1. Open `tools\WindowStylesReportTool\WindowStylesReportTool.sln` +2. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release` +3. From the `Build` menu, choose `Build Solution`. + ### Locally compiling the installer 1. Open `installer\PowerToysSetup.sln` diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 62fbcb8f3d..f52eb502fc 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -616,6 +616,9 @@ + + + @@ -1049,6 +1052,7 @@ + diff --git a/tools/WindowStylesReportTool/Resource.h b/tools/WindowStylesReportTool/Resource.h new file mode 100644 index 0000000000..3753dba0ce --- /dev/null +++ b/tools/WindowStylesReportTool/Resource.h @@ -0,0 +1,24 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by WindowStylesReportTool.rc + +#define IDR_MAINFRAME 128 +#define IDD_ABOUTBOX 103 +#define IDI_WINDOWSTYLESICON 107 +#define IDI_SMALLICON 108 +#define IDC_WINDOWSTYLES 109 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.cpp b/tools/WindowStylesReportTool/WindowStylesReportTool.cpp new file mode 100644 index 0000000000..3391567cbb --- /dev/null +++ b/tools/WindowStylesReportTool/WindowStylesReportTool.cpp @@ -0,0 +1,424 @@ +#include "pch.h" +#include "WindowStylesReportTool.h" + +#include +#include + +#include +#include +#include + +inline std::optional get_last_error_message(const DWORD dw) +{ + std::optional message; + try + { + const auto msg = std::system_category().message(dw); + message.emplace(begin(msg), end(msg)); + } + catch (...) + { + } + return message; +} + +inline std::wstring get_last_error_or_default(const DWORD dw) +{ + auto message = get_last_error_message(dw); + return message.has_value() ? message.value() : L""; +} + +std::filesystem::path get_desktop_path() +{ + wchar_t* p; + if (S_OK != SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &p)) return ""; + + std::filesystem::path result = p; + CoTaskMemFree(p); + + return result; +} + +// Get the executable path or module name for modern apps +inline std::wstring get_process_path(DWORD pid) noexcept +{ + auto process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, pid); + std::wstring name; + if (process != INVALID_HANDLE_VALUE) + { + name.resize(MAX_PATH); + DWORD name_length = static_cast(name.length()); + if (QueryFullProcessImageNameW(process, 0, (LPWSTR)name.data(), &name_length) == 0) + { + name_length = 0; + } + name.resize(name_length); + CloseHandle(process); + } + return name; +} + +// Get the executable path or module name for modern apps +inline std::wstring get_process_path(HWND window) noexcept +{ + const static std::wstring app_frame_host = L"ApplicationFrameHost.exe"; + + DWORD pid{}; + GetWindowThreadProcessId(window, &pid); + auto name = get_process_path(pid); + + if (name.length() >= app_frame_host.length() && + name.compare(name.length() - app_frame_host.length(), app_frame_host.length(), app_frame_host) == 0) + { + // It is a UWP app. We will enumerate the windows and look for one created + // by something with a different PID + DWORD new_pid = pid; + + EnumChildWindows( + window, [](HWND hwnd, LPARAM param) -> BOOL { + auto new_pid_ptr = reinterpret_cast(param); + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + if (pid != *new_pid_ptr) + { + *new_pid_ptr = pid; + return FALSE; + } + else + { + return TRUE; + } + }, + reinterpret_cast(&new_pid)); + + // If we have a new pid, get the new name. + if (new_pid != pid) + { + return get_process_path(new_pid); + } + } + + return name; +} + +class Logger +{ +private: + inline static std::wofstream logger; + +public: + ~Logger() + { + logger.close(); + } + + static void init(std::string loggerName) + { + std::filesystem::path rootFolder(get_desktop_path()); + + auto logsPath = rootFolder; + logsPath.append(L"window_styles.txt"); + + logger.open(logsPath.string(), std::ios_base::out | std::ios_base::app); + } + + template + static void log(const FormatString& fmt, const Args&... args) + { + logger << std::format(fmt, args...) << std::endl; + } +}; + +std::map dwmAttributesReadable = { + {DWMWINDOWATTRIBUTE::DWMWA_NCRENDERING_ENABLED, L"DWMWA_NCRENDERING_ENABLED"}, + {DWMWINDOWATTRIBUTE::DWMWA_CAPTION_BUTTON_BOUNDS, L"DWMWA_CAPTION_BUTTON_BOUNDS"}, + {DWMWINDOWATTRIBUTE::DWMWA_EXTENDED_FRAME_BOUNDS, L"DWMWA_EXTENDED_FRAME_BOUNDS"}, + {DWMWINDOWATTRIBUTE::DWMWA_CLOAKED, L"DWMWA_CLOAKED"}, +}; + +template +void LogDwmInfo(HWND window, DWMWINDOWATTRIBUTE attr, T& value) +{ + if (DwmGetWindowAttribute(window, attr, &value, sizeof(value)) == S_OK) + { + Logger::log(L"{}: {} ", dwmAttributesReadable[attr], value); + } + else + { + Logger::log(L"Failed to get {}", dwmAttributesReadable[attr]); + } +} + +void LogDwmRect(HWND window, DWMWINDOWATTRIBUTE attr, RECT& value) +{ + if (DwmGetWindowAttribute(window, attr, &value, sizeof(value)) >= 0) + { + Logger::log(L"{}: LT({},{}), RB({},{}), [{} x {}] ", dwmAttributesReadable[attr], value.left, value.top, value.right, value.bottom, value.right - value.left, value.bottom - value.top); + } + else + { + Logger::log(L"Failed to get {}", dwmAttributesReadable[attr]); + } +} + +void LogStyles(HWND window) +{ + auto style = GetWindowLong(window, GWL_STYLE); + + Logger::log(L"------------------ Style --------------------- "); + Logger::log(L""); + + Logger::log(L"WS_BORDER {}", ((style & WS_BORDER) == WS_BORDER)); + Logger::log(L"WS_CAPTION {}", ((style & WS_CAPTION) == WS_CAPTION)); + Logger::log(L"WS_CHILD {}", ((style & WS_CHILD) == WS_CHILD)); + Logger::log(L"WS_CHILDWINDOW {}", ((style & WS_CHILDWINDOW) == WS_CHILDWINDOW)); + Logger::log(L"WS_CLIPCHILDREN {}", ((style & WS_CLIPCHILDREN) == WS_CLIPCHILDREN)); + Logger::log(L"WS_CLIPSIBLINGS {}", ((style & WS_CLIPSIBLINGS) == WS_CLIPSIBLINGS)); + Logger::log(L"WS_DISABLED {}", ((style & WS_DISABLED) == WS_DISABLED)); + Logger::log(L"WS_DLGFRAME {}", ((style & WS_DLGFRAME) == WS_DLGFRAME)); + Logger::log(L"WS_GROUP {}", ((style & WS_GROUP) == WS_GROUP)); + Logger::log(L"WS_HSCROLL {}", ((style & WS_HSCROLL) == WS_HSCROLL)); + Logger::log(L"WS_ICONIC {}", ((style & WS_ICONIC) == WS_ICONIC)); + Logger::log(L"WS_MAXIMIZE {}", ((style & WS_MAXIMIZE) == WS_MAXIMIZE)); + Logger::log(L"WS_MAXIMIZEBOX {}", ((style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX)); + Logger::log(L"WS_MINIMIZE {}", ((style & WS_MINIMIZE) == WS_MINIMIZE)); + Logger::log(L"WS_MINIMIZEBOX {}", ((style & WS_MINIMIZEBOX) == WS_MINIMIZEBOX)); + Logger::log(L"WS_OVERLAPPED {}", ((style & WS_OVERLAPPED) == WS_OVERLAPPED)); + Logger::log(L"WS_OVERLAPPEDWINDOW {}", ((style & WS_OVERLAPPEDWINDOW) == WS_OVERLAPPEDWINDOW)); + Logger::log(L"WS_POPUP {}", ((style & WS_POPUP) == WS_POPUP)); + Logger::log(L"WS_POPUPWINDOW {}", ((style & WS_POPUPWINDOW) == WS_POPUPWINDOW)); + Logger::log(L"WS_SIZEBOX {}", ((style & WS_SIZEBOX) == WS_SIZEBOX)); + Logger::log(L"WS_SYSMENU {}", ((style & WS_SYSMENU) == WS_SYSMENU)); + Logger::log(L"WS_TABSTOP {}", ((style & WS_TABSTOP) == WS_TABSTOP)); + Logger::log(L"WS_THICKFRAME {}", ((style & WS_THICKFRAME) == WS_THICKFRAME)); + Logger::log(L"WS_TILED {}", ((style & WS_TILED) == WS_TILED)); + Logger::log(L"WS_TILEDWINDOW {}", ((style & WS_TILEDWINDOW) == WS_TILEDWINDOW)); + Logger::log(L"WS_VISIBLE {}", ((style & WS_VISIBLE) == WS_VISIBLE)); + Logger::log(L"WS_VSCROLL {}", ((style & WS_VSCROLL) == WS_VSCROLL)); + + Logger::log(L""); +} + +void LogExStyles(HWND window) +{ + auto exStyle = GetWindowLong(window, GWL_EXSTYLE); + Logger::log(L"------------------ Exstyle --------------------- "); + Logger::log(L""); + + Logger::log(L"WS_EX_ACCEPTFILES {}", (exStyle & WS_EX_ACCEPTFILES) == WS_EX_ACCEPTFILES); + Logger::log(L"WS_EX_APPWINDOW {}", (exStyle & WS_EX_APPWINDOW) == WS_EX_APPWINDOW); + Logger::log(L"WS_EX_CLIENTEDGE {}", (exStyle & WS_EX_CLIENTEDGE) == WS_EX_CLIENTEDGE); + Logger::log(L"WS_EX_COMPOSITED {}", (exStyle & WS_EX_COMPOSITED) == WS_EX_COMPOSITED); + Logger::log(L"WS_EX_CONTEXTHELP {}", (exStyle & WS_EX_CONTEXTHELP) == WS_EX_CONTEXTHELP); + Logger::log(L"WS_EX_CONTROLPARENT {}", (exStyle & WS_EX_CONTROLPARENT) == WS_EX_CONTROLPARENT); + Logger::log(L"WS_EX_DLGMODALFRAME {}", (exStyle & WS_EX_DLGMODALFRAME) == WS_EX_DLGMODALFRAME); + Logger::log(L"WS_EX_LAYERED {}", (exStyle & WS_EX_LAYERED) == WS_EX_LAYERED); + Logger::log(L"WS_EX_LAYOUTRTL {}", (exStyle & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL); + Logger::log(L"WS_EX_LEFT {}", (exStyle & WS_EX_LEFT) == WS_EX_LEFT); + Logger::log(L"WS_EX_LEFTSCROLLBAR {}", (exStyle & WS_EX_LEFTSCROLLBAR) == WS_EX_LEFTSCROLLBAR); + Logger::log(L"WS_EX_LTRREADING {}", (exStyle & WS_EX_LTRREADING) == WS_EX_LTRREADING); + Logger::log(L"WS_EX_MDICHILD {}", (exStyle & WS_EX_MDICHILD) == WS_EX_MDICHILD); + Logger::log(L"WS_EX_NOACTIVATE {}", (exStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE); + Logger::log(L"WS_EX_NOINHERITLAYOUT {}", (exStyle & WS_EX_NOINHERITLAYOUT) == WS_EX_NOINHERITLAYOUT); + Logger::log(L"WS_EX_NOPARENTNOTIFY {}", (exStyle & WS_EX_NOPARENTNOTIFY) == WS_EX_NOPARENTNOTIFY); + Logger::log(L"WS_EX_NOREDIRECTIONBITMAP {}", (exStyle & WS_EX_NOREDIRECTIONBITMAP) == WS_EX_NOREDIRECTIONBITMAP); + Logger::log(L"WS_EX_OVERLAPPEDWINDOW {}", (exStyle & WS_EX_OVERLAPPEDWINDOW) == WS_EX_OVERLAPPEDWINDOW); + Logger::log(L"WS_EX_PALETTEWINDOW {}", (exStyle & WS_EX_PALETTEWINDOW) == WS_EX_PALETTEWINDOW); + Logger::log(L"WS_EX_RIGHT {}", (exStyle & WS_EX_RIGHT) == WS_EX_RIGHT); + Logger::log(L"WS_EX_RIGHTSCROLLBAR {}", (exStyle & WS_EX_RIGHTSCROLLBAR) == WS_EX_RIGHTSCROLLBAR); + Logger::log(L"WS_EX_RTLREADING {}", (exStyle & WS_EX_RTLREADING) == WS_EX_RTLREADING); + Logger::log(L"WS_EX_STATICEDGE {}", (exStyle & WS_EX_STATICEDGE) == WS_EX_STATICEDGE); + Logger::log(L"WS_EX_TOOLWINDOW {}", (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW); + Logger::log(L"WS_EX_TOPMOST {}", (exStyle & WS_EX_TOPMOST) == WS_EX_TOPMOST); + Logger::log(L"WS_EX_TRANSPARENT {}", (exStyle & WS_EX_TRANSPARENT) == WS_EX_TRANSPARENT); + Logger::log(L"WS_EX_WINDOWEDGE {}", (exStyle & WS_EX_WINDOWEDGE) == WS_EX_WINDOWEDGE); + + Logger::log(L""); +} + +void LogDwmAttributes(HWND window) +{ + Logger::log(L"------------------ DwmAttributes --------------------- "); + Logger::log(L""); + + int intValue{}; + unsigned int uintValue{}; + + LogDwmInfo(window, DWMWINDOWATTRIBUTE::DWMWA_NCRENDERING_ENABLED, intValue); + LogDwmInfo(window, DWMWINDOWATTRIBUTE::DWMWA_CLOAKED, intValue); + + RECT rectValue{}; + LogDwmRect(window, DWMWINDOWATTRIBUTE::DWMWA_CAPTION_BUTTON_BOUNDS, rectValue); + LogDwmRect(window, DWMWINDOWATTRIBUTE::DWMWA_EXTENDED_FRAME_BOUNDS, rectValue); + + Logger::log(L""); +} + +void LogVirtualDesktopInfo(HWND window) +{ + Logger::log(L"------------------ VirtualDesktop info --------------------- "); + Logger::log(L""); + + IVirtualDesktopManager* vdManager = nullptr; + auto res = CoCreateInstance(CLSID_VirtualDesktopManager, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&vdManager)); + if (FAILED(res)) + { + Logger::log(L"Failed to create VirtualDesktopManager instance"); + Logger::log(L""); + return; + } + + BOOL isWindowOnCurrentDesktop = false; + if (vdManager->IsWindowOnCurrentVirtualDesktop(window, &isWindowOnCurrentDesktop) == S_OK) + { + Logger::log(L"Window is on current virtual desktop: {}", isWindowOnCurrentDesktop); + } + + GUID id{}; + auto vdIdRes = vdManager->GetWindowDesktopId(window, &id); + if (vdIdRes == S_OK) + { + OLECHAR* guidString; + if (StringFromCLSID(id, &guidString) == S_OK) + { + Logger::log(L"Virtual desktop id: {}", guidString); + } + + CoTaskMemFree(guidString); + } + else + { + Logger::log(L"GetWindowDesktopId error: {}", get_last_error_or_default(vdIdRes)); + } + + if (vdManager) + { + vdManager->Release(); + } + + Logger::log(L""); +} + +void LogInfo(HWND window) +{ + auto processPath = get_process_path(window); + auto app = processPath; + auto pos = processPath.find_last_of('\\'); + if (pos != std::string::npos && pos + 1 < processPath.length()) + { + app = processPath.substr(pos + 1); + } + + Logger::log(L"Timestamp: {}", std::chrono::system_clock::now()); + Logger::log(L"Window: {}", app); + + WCHAR className[256]; + auto classNameLength = GetClassName(window, className, sizeof(className)); + if (classNameLength > 0) + { + Logger::log(L"Class: {}", className); + } + else + { + Logger::log(L"GetClassName error: {}", get_last_error_or_default(GetLastError())); + } + + Logger::log(L""); + + LogStyles(window); + LogExStyles(window); + LogDwmAttributes(window); + LogVirtualDesktopInfo(window); + + Logger::log(L"======================================="); + Logger::log(L""); +} + +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); + +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + Logger::init("WindowStylesReportTool"); + + WNDCLASSEXW wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = {}; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSTYLESICON)); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = L""; + wcex.lpszClassName = L"WindowStylesReportTool"; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALLICON)); + + if (!RegisterClassExW(&wcex)) + { + Logger::log(L"Register class error: {}", get_last_error_or_default(GetLastError())); + return FALSE; + } + + HWND hWnd = CreateWindowW(L"WindowStylesReportTool", L"Window Style Report Tool", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 600, 200, nullptr, nullptr, hInstance, nullptr); + if (!hWnd) + { + Logger::log(L"Window creation error: {}", get_last_error_or_default(GetLastError())); + return FALSE; + } + + if (!RegisterHotKey(hWnd, 1, MOD_ALT | MOD_CONTROL | MOD_NOREPEAT, 0x53)) // ctrl + alt + s + { + Logger::log(L"Failed to register hotkey: {}", get_last_error_or_default(GetLastError())); + return FALSE; + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + MSG msg{}; + while (GetMessage(&msg, nullptr, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return (int) msg.wParam; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_HOTKEY: + { + LogInfo(GetForegroundWindow()); + PostQuitMessage(0); + } + break; + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hWnd, &ps); + + LPCWSTR text = L"Please select the target window (using a mouse or Alt+Tab), \r\nand press Ctrl+Alt+S to capture its styles. \r\nYou can find the output file \"window_styles.txt\" on your desktop."; + RECT rc{0,50,600,200}; + DrawText(hdc, text, (int)wcslen(text), &rc, DT_CENTER | DT_WORDBREAK); + + EndPaint(hWnd, &ps); + } + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.h b/tools/WindowStylesReportTool/WindowStylesReportTool.h new file mode 100644 index 0000000000..d00d47e788 --- /dev/null +++ b/tools/WindowStylesReportTool/WindowStylesReportTool.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.ico b/tools/WindowStylesReportTool/WindowStylesReportTool.ico new file mode 100644 index 0000000000..e82442c264 Binary files /dev/null and b/tools/WindowStylesReportTool/WindowStylesReportTool.ico differ diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.rc b/tools/WindowStylesReportTool/WindowStylesReportTool.rc new file mode 100644 index 0000000000..83e42764bd --- /dev/null +++ b/tools/WindowStylesReportTool/WindowStylesReportTool.rc @@ -0,0 +1,103 @@ +ÿþ//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE resource. +// +#ifndef APSTUDIO_INVOKED +#endif +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +IDI_WINDOWSTYLESICON ICON "WindowStylesReportTool.ico" +IDI_SMALL ICON "small.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 163 + TOPMARGIN, 7 + BOTTOMMARGIN, 55 + END +END +#endif // APSTUDIO_INVOKED + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDC_WINDOWSTYLES "WINDOWSTYLES" +END + +#endif +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + \ No newline at end of file diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.sln b/tools/WindowStylesReportTool/WindowStylesReportTool.sln new file mode 100644 index 0000000000..f16f6fe905 --- /dev/null +++ b/tools/WindowStylesReportTool/WindowStylesReportTool.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowStylesReportTool", "WindowStylesReportTool.vcxproj", "{0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Debug|ARM64.ActiveCfg = Debug|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Debug|ARM64.Build.0 = Debug|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Debug|x64.ActiveCfg = Debug|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Debug|x64.Build.0 = Debug|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Release|ARM64.ActiveCfg = Release|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Release|ARM64.Build.0 = Release|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Release|x64.ActiveCfg = Release|x64 + {0FEBAFAF-CB77-41F0-8EF9-8E3AD4B4F842}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D271E9C3-5C4D-45E4-8D23-9F1BB5443513} + EndGlobalSection +EndGlobal diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.vcxproj b/tools/WindowStylesReportTool/WindowStylesReportTool.vcxproj new file mode 100644 index 0000000000..6fb57d152e --- /dev/null +++ b/tools/WindowStylesReportTool/WindowStylesReportTool.vcxproj @@ -0,0 +1,111 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {0febafaf-cb77-41f0-8ef9-8e3ad4b4f842} + WindowStylesReportTool + 10.0.18362.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + true + $(SolutionDir)..\..\$(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)..\..\$(Platform)\$(Configuration)\obj\$(ProjectName)\ + PowerToys.$(ProjectName) + + + false + $(SolutionDir)..\..\$(Platform)\$(Configuration)\$(ProjectName)\ + $(SolutionDir)..\..\$(Platform)\$(Configuration)\obj\$(ProjectName)\ + PowerToys.$(ProjectName) + + + + Level3 + true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + C:\repo\PowerToys\deps\spdlog\include;C:\repo\PowerToys\src\common;C:\repo\PowerToys\src;%(AdditionalIncludeDirectories) + + + Windows + true + dwmapi.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + dwmapi.lib;%(AdditionalDependencies) + + + + + + + + + + + Create + Create + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/WindowStylesReportTool/WindowStylesReportTool.vcxproj.filters b/tools/WindowStylesReportTool/WindowStylesReportTool.vcxproj.filters new file mode 100644 index 0000000000..2aff154c7a --- /dev/null +++ b/tools/WindowStylesReportTool/WindowStylesReportTool.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/tools/WindowStylesReportTool/pch.cpp b/tools/WindowStylesReportTool/pch.cpp new file mode 100644 index 0000000000..17305716aa --- /dev/null +++ b/tools/WindowStylesReportTool/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" \ No newline at end of file diff --git a/tools/WindowStylesReportTool/pch.h b/tools/WindowStylesReportTool/pch.h new file mode 100644 index 0000000000..3166a6ce10 --- /dev/null +++ b/tools/WindowStylesReportTool/pch.h @@ -0,0 +1,3 @@ +#pragma once + +#include \ No newline at end of file diff --git a/tools/WindowStylesReportTool/small.ico b/tools/WindowStylesReportTool/small.ico new file mode 100644 index 0000000000..e82442c264 Binary files /dev/null and b/tools/WindowStylesReportTool/small.ico differ