[MouseUtils]rename "crosshair"->"crosshairs" (#15761)

* [MouseUtils]rename "crosshair"->"crosshairs"

* Fix crosshairss isnstances in logs
This commit is contained in:
Jaime Bernardo
2022-01-26 14:01:24 +00:00
committed by GitHub
parent a1bb281386
commit 792a04cf48
35 changed files with 765 additions and 765 deletions

View File

@@ -1,452 +0,0 @@
// InclusiveCrosshair.cpp : Defines the entry point for the application.
//
#include "pch.h"
#include "InclusiveCrosshair.h"
#include "trace.h"
#ifdef COMPOSITION
namespace winrt
{
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Composition;
}
namespace ABI
{
using namespace ABI::Windows::System;
using namespace ABI::Windows::UI::Composition::Desktop;
}
#endif
struct InclusiveCrosshair
{
bool MyRegisterClass(HINSTANCE hInstance);
static InclusiveCrosshair* instance;
void Terminate();
void SwitchActivationMode();
void ApplySettings(InclusiveCrosshairSettings& settings, bool applyToRuntimeObjects);
private:
enum class MouseButton
{
Left,
Right
};
void DestroyInclusiveCrosshair();
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept;
void StartDrawing();
void StopDrawing();
bool CreateInclusiveCrosshair();
void UpdateCrosshairPosition();
HHOOK m_mouseHook = NULL;
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept;
static constexpr auto m_className = L"MousePointerCrosshair";
static constexpr auto m_windowTitle = L"PowerToys Mouse Pointer Crosshair";
HWND m_hwndOwner = NULL;
HWND m_hwnd = NULL;
HINSTANCE m_hinstance = NULL;
static constexpr DWORD WM_SWITCH_ACTIVATION_MODE = WM_APP;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
winrt::Compositor m_compositor{ nullptr };
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
winrt::ContainerVisual m_root{ nullptr };
winrt::LayerVisual m_crosshair_border_layer{ nullptr };
winrt::LayerVisual m_crosshair_layer{ nullptr };
winrt::SpriteVisual m_left_crosshair_border{ nullptr };
winrt::SpriteVisual m_left_crosshair{ nullptr };
winrt::SpriteVisual m_right_crosshair_border{ nullptr };
winrt::SpriteVisual m_right_crosshair{ nullptr };
winrt::SpriteVisual m_top_crosshair_border{ nullptr };
winrt::SpriteVisual m_top_crosshair{ nullptr };
winrt::SpriteVisual m_bottom_crosshair_border{ nullptr };
winrt::SpriteVisual m_bottom_crosshair{ nullptr };
bool m_visible = false;
bool m_destroyed = false;
// Configurable Settings
winrt::Windows::UI::Color m_crosshair_border_color = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_BORDER_COLOR;
winrt::Windows::UI::Color m_crosshair_color = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_COLOR;
float m_crosshair_radius = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_RADIUS;
float m_crosshair_thickness = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_THICKNESS;
float m_crosshair_border_size = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_BORDER_SIZE;
float m_crosshair_opacity = max(0.f, min(1.f, (float)INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_OPACITY / 100.0f));
};
InclusiveCrosshair* InclusiveCrosshair::instance = nullptr;
bool InclusiveCrosshair::CreateInclusiveCrosshair()
{
try
{
// We need a dispatcher queue.
DispatcherQueueOptions options = {
sizeof(options),
DQTYPE_THREAD_CURRENT,
DQTAT_COM_ASTA,
};
ABI::IDispatcherQueueController* controller;
winrt::check_hresult(CreateDispatcherQueueController(options, &controller));
*winrt::put_abi(m_dispatcherQueueController) = controller;
// Create the compositor for our window.
m_compositor = winrt::Compositor();
ABI::IDesktopWindowTarget* target;
winrt::check_hresult(m_compositor.as<ABI::ICompositorDesktopInterop>()->CreateDesktopWindowTarget(m_hwnd, false, &target));
*winrt::put_abi(m_target) = target;
// Our composition tree:
//
// [root] ContainerVisual
// \ [crosshair border layer] LayerVisual
// \ [crosshair border sprites]
// [crosshair layer] LayerVisual
// \ [crosshair sprites]
m_root = m_compositor.CreateContainerVisual();
m_root.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_target.Root(m_root);
m_root.Opacity(m_crosshair_opacity);
m_crosshair_border_layer = m_compositor.CreateLayerVisual();
m_crosshair_border_layer.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_root.Children().InsertAtTop(m_crosshair_border_layer);
m_crosshair_border_layer.Opacity(1.0f);
m_crosshair_layer = m_compositor.CreateLayerVisual();
m_crosshair_layer.RelativeSizeAdjustment({ 1.0f, 1.0f });
// Create the crosshair sprites.
m_left_crosshair_border = m_compositor.CreateSpriteVisual();
m_left_crosshair_border.AnchorPoint({ 1.0f, 0.5f });
m_left_crosshair_border.Brush(m_compositor.CreateColorBrush(m_crosshair_border_color));
m_crosshair_border_layer.Children().InsertAtTop(m_left_crosshair_border);
m_left_crosshair = m_compositor.CreateSpriteVisual();
m_left_crosshair.AnchorPoint({ 1.0f, 0.5f });
m_left_crosshair.Brush(m_compositor.CreateColorBrush(m_crosshair_color));
m_crosshair_layer.Children().InsertAtTop(m_left_crosshair);
m_right_crosshair_border = m_compositor.CreateSpriteVisual();
m_right_crosshair_border.AnchorPoint({ 0.0f, 0.5f });
m_right_crosshair_border.Brush(m_compositor.CreateColorBrush(m_crosshair_border_color));
m_crosshair_border_layer.Children().InsertAtTop(m_right_crosshair_border);
m_right_crosshair = m_compositor.CreateSpriteVisual();
m_right_crosshair.AnchorPoint({ 0.0f, 0.5f });
m_right_crosshair.Brush(m_compositor.CreateColorBrush(m_crosshair_color));
m_crosshair_layer.Children().InsertAtTop(m_right_crosshair);
m_top_crosshair_border = m_compositor.CreateSpriteVisual();
m_top_crosshair_border.AnchorPoint({ 0.5f, 1.0f });
m_top_crosshair_border.Brush(m_compositor.CreateColorBrush(m_crosshair_border_color));
m_crosshair_border_layer.Children().InsertAtTop(m_top_crosshair_border);
m_top_crosshair = m_compositor.CreateSpriteVisual();
m_top_crosshair.AnchorPoint({ 0.5f, 1.0f });
m_top_crosshair.Brush(m_compositor.CreateColorBrush(m_crosshair_color));
m_crosshair_layer.Children().InsertAtTop(m_top_crosshair);
m_bottom_crosshair_border = m_compositor.CreateSpriteVisual();
m_bottom_crosshair_border.AnchorPoint({ 0.5f, 0.0f });
m_bottom_crosshair_border.Brush(m_compositor.CreateColorBrush(m_crosshair_border_color));
m_crosshair_border_layer.Children().InsertAtTop(m_bottom_crosshair_border);
m_bottom_crosshair = m_compositor.CreateSpriteVisual();
m_bottom_crosshair.AnchorPoint({ 0.5f, 0.0f });
m_bottom_crosshair.Brush(m_compositor.CreateColorBrush(m_crosshair_color));
m_crosshair_layer.Children().InsertAtTop(m_bottom_crosshair);
m_crosshair_border_layer.Children().InsertAtTop(m_crosshair_layer);
m_crosshair_layer.Opacity(1.0f);
UpdateCrosshairPosition();
return true;
}
catch (...)
{
return false;
}
}
void InclusiveCrosshair::UpdateCrosshairPosition()
{
POINT ptCursor;
GetCursorPos(&ptCursor);
HMONITOR cursorMonitor = MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST);
if (cursorMonitor == NULL)
{
return;
}
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfo(cursorMonitor, &monitorInfo))
{
return;
}
POINT ptMonitorUpperLeft;
ptMonitorUpperLeft.x = monitorInfo.rcMonitor.left;
ptMonitorUpperLeft.y = monitorInfo.rcMonitor.top;
POINT ptMonitorBottomRight;
ptMonitorBottomRight.x = monitorInfo.rcMonitor.right;
ptMonitorBottomRight.y = monitorInfo.rcMonitor.bottom;
// Convert everything to client coordinates.
ScreenToClient(m_hwnd, &ptCursor);
ScreenToClient(m_hwnd, &ptMonitorUpperLeft);
ScreenToClient(m_hwnd, &ptMonitorBottomRight);
// Position crosshair components around the mouse pointer.
m_left_crosshair_border.Offset({ (float)ptCursor.x - m_crosshair_radius + m_crosshair_border_size, (float)ptCursor.y, .0f });
m_left_crosshair_border.Size({ (float)ptCursor.x - (float)ptMonitorUpperLeft.x - m_crosshair_radius + m_crosshair_border_size, m_crosshair_thickness + m_crosshair_border_size * 2 });
m_left_crosshair.Offset({ (float)ptCursor.x - m_crosshair_radius, (float)ptCursor.y, .0f });
m_left_crosshair.Size({ (float)ptCursor.x - (float)ptMonitorUpperLeft.x - m_crosshair_radius, m_crosshair_thickness });
m_right_crosshair_border.Offset({ (float)ptCursor.x + m_crosshair_radius - m_crosshair_border_size, (float)ptCursor.y, .0f });
m_right_crosshair_border.Size({ (float)ptMonitorBottomRight.x - (float)ptCursor.x - m_crosshair_radius + m_crosshair_border_size, m_crosshair_thickness + m_crosshair_border_size * 2 });
m_right_crosshair.Offset({ (float)ptCursor.x + m_crosshair_radius, (float)ptCursor.y, .0f });
m_right_crosshair.Size({ (float)ptMonitorBottomRight.x - (float)ptCursor.x - m_crosshair_radius, m_crosshair_thickness });
m_top_crosshair_border.Offset({ (float)ptCursor.x, (float)ptCursor.y - m_crosshair_radius + m_crosshair_border_size, .0f });
m_top_crosshair_border.Size({ m_crosshair_thickness + m_crosshair_border_size * 2, (float)ptCursor.y - (float)ptMonitorUpperLeft.y - m_crosshair_radius + m_crosshair_border_size });
m_top_crosshair.Offset({ (float)ptCursor.x, (float)ptCursor.y - m_crosshair_radius, .0f });
m_top_crosshair.Size({ m_crosshair_thickness, (float)ptCursor.y - (float)ptMonitorUpperLeft.y - m_crosshair_radius });
m_bottom_crosshair_border.Offset({ (float)ptCursor.x, (float)ptCursor.y + m_crosshair_radius - m_crosshair_border_size, .0f });
m_bottom_crosshair_border.Size({ m_crosshair_thickness + m_crosshair_border_size * 2, (float)ptMonitorBottomRight.y - (float)ptCursor.y - m_crosshair_radius + m_crosshair_border_size });
m_bottom_crosshair.Offset({ (float)ptCursor.x, (float)ptCursor.y + m_crosshair_radius, .0f });
m_bottom_crosshair.Size({ m_crosshair_thickness, (float)ptMonitorBottomRight.y - (float)ptCursor.y - m_crosshair_radius });
}
LRESULT CALLBACK InclusiveCrosshair::MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT* hookData = (MSLLHOOKSTRUCT*)lParam;
if (wParam == WM_MOUSEMOVE) {
instance->UpdateCrosshairPosition();
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
void InclusiveCrosshair::StartDrawing()
{
Logger::info("Start drawing crosshairs.");
Trace::StartDrawingCrosshair();
m_visible = true;
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0);
UpdateCrosshairPosition();
}
void InclusiveCrosshair::StopDrawing()
{
Logger::info("Stop drawing crosshairs.");
m_visible = false;
ShowWindow(m_hwnd, SW_HIDE);
UnhookWindowsHookEx(m_mouseHook);
m_mouseHook = NULL;
}
void InclusiveCrosshair::SwitchActivationMode()
{
PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0);
}
void InclusiveCrosshair::ApplySettings(InclusiveCrosshairSettings& settings, bool applyToRunTimeObjects)
{
m_crosshair_radius = (float)settings.crosshairRadius;
m_crosshair_thickness = (float)settings.crosshairThickness;
m_crosshair_color = settings.crosshairColor;
m_crosshair_opacity = max(0.f, min(1.f, (float)settings.crosshairOpacity / 100.0f));
m_crosshair_border_color = settings.crosshairBorderColor;
m_crosshair_border_size = (float)settings.crosshairBorderSize;
if (applyToRunTimeObjects)
{
// Runtime objects already created. Should update in the owner thread.
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
InclusiveCrosshairSettings localSettings = settings;
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
if (!m_destroyed)
{
// Apply new settings to runtime composition objects.
m_left_crosshair.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_color);
m_right_crosshair.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_color);
m_top_crosshair.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_color);
m_bottom_crosshair.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_color);
m_left_crosshair_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_border_color);
m_right_crosshair_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_border_color);
m_top_crosshair_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_border_color);
m_bottom_crosshair_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshair_border_color);
m_root.Opacity(m_crosshair_opacity);
UpdateCrosshairPosition();
}
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to update the crosshair settings.");
}
}
}
void InclusiveCrosshair::DestroyInclusiveCrosshair()
{
StopDrawing();
PostQuitMessage(0);
}
LRESULT CALLBACK InclusiveCrosshair::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept
{
switch (message)
{
case WM_NCCREATE:
instance->m_hwnd = hWnd;
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_CREATE:
return instance->CreateInclusiveCrosshair() ? 0 : -1;
case WM_NCHITTEST:
return HTTRANSPARENT;
case WM_SWITCH_ACTIVATION_MODE:
if (instance->m_visible)
{
instance->StopDrawing();
}
else
{
instance->StartDrawing();
}
break;
case WM_DESTROY:
instance->DestroyInclusiveCrosshair();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool InclusiveCrosshair::MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wc{};
m_hinstance = hInstance;
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!GetClassInfoW(hInstance, m_className, &wc))
{
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszClassName = m_className;
if (!RegisterClassW(&wc))
{
return false;
}
}
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hInstance, nullptr);
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOREDIRECTIONBITMAP | WS_EX_TOOLWINDOW;
return CreateWindowExW(exStyle, m_className, m_windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hInstance, nullptr) != nullptr;
}
void InclusiveCrosshair::Terminate()
{
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
m_destroyed = true;
DestroyWindow(m_hwndOwner);
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to destroy the window.");
}
}
#pragma region InclusiveCrosshair_API
void InclusiveCrosshairApplySettings(InclusiveCrosshairSettings& settings)
{
if (InclusiveCrosshair::instance != nullptr)
{
Logger::info("Applying settings.");
InclusiveCrosshair::instance->ApplySettings(settings, true);
}
}
void InclusiveCrosshairSwitch()
{
if (InclusiveCrosshair::instance != nullptr)
{
Logger::info("Switching activation mode.");
InclusiveCrosshair::instance->SwitchActivationMode();
}
}
void InclusiveCrosshairDisable()
{
if (InclusiveCrosshair::instance != nullptr)
{
Logger::info("Terminating the crosshair instance.");
InclusiveCrosshair::instance->Terminate();
}
}
bool InclusiveCrosshairIsEnabled()
{
return (InclusiveCrosshair::instance != nullptr);
}
int InclusiveCrosshairMain(HINSTANCE hInstance, InclusiveCrosshairSettings& settings)
{
Logger::info("Starting a crosshair instance.");
if (InclusiveCrosshair::instance != nullptr)
{
Logger::error("A crosshair instance was still working when trying to start a new one.");
return 0;
}
// Perform application initialization:
InclusiveCrosshair crosshair;
InclusiveCrosshair::instance = &crosshair;
crosshair.ApplySettings(settings, false);
if (!crosshair.MyRegisterClass(hInstance))
{
Logger::error("Couldn't initialize a crosshair instance.");
InclusiveCrosshair::instance = nullptr;
return FALSE;
}
Logger::info("Initialized the crosshair instance.");
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Logger::info("Crosshair message loop ended.");
InclusiveCrosshair::instance = nullptr;
return (int)msg.wParam;
}
#pragma endregion InclusiveCrosshair_API

View File

@@ -1,25 +0,0 @@
#pragma once
#include "pch.h"
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_OPACITY = 75;
const winrt::Windows::UI::Color INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 0, 0);
const winrt::Windows::UI::Color INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_BORDER_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 255, 255);
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_RADIUS = 20;
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_THICKNESS = 5;
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_BORDER_SIZE = 1;
struct InclusiveCrosshairSettings
{
winrt::Windows::UI::Color crosshairColor = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_COLOR;
winrt::Windows::UI::Color crosshairBorderColor = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_BORDER_COLOR;
int crosshairRadius = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_RADIUS;
int crosshairThickness = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_THICKNESS;
int crosshairOpacity = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_OPACITY;
int crosshairBorderSize = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIR_BORDER_SIZE;
};
int InclusiveCrosshairMain(HINSTANCE hinst, InclusiveCrosshairSettings& settings);
void InclusiveCrosshairDisable();
bool InclusiveCrosshairIsEnabled();
void InclusiveCrosshairSwitch();
void InclusiveCrosshairApplySettings(InclusiveCrosshairSettings& settings);

View File

@@ -1,13 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by MousePointerCrosshair.rc
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "PowerToys MousePointerCrosshair"
#define INTERNAL_NAME "MousePointerCrosshair"
#define ORIGINAL_FILENAME "PowerToys.MousePointerCrosshair.dll"
// Non-localizable
//////////////////////////////

View File

@@ -1,14 +0,0 @@
#pragma once
class Trace
{
public:
static void RegisterProvider() noexcept;
static void UnregisterProvider() noexcept;
// Log if the user has MousePointerCrosshair enabled or disabled
static void EnableMousePointerCrosshair(const bool enabled) noexcept;
// Log that the user activated the module by having the crosshair be drawn
static void StartDrawingCrosshair() noexcept;
};

View File

@@ -0,0 +1,452 @@
// InclusiveCrosshairs.cpp : Defines the entry point for the application.
//
#include "pch.h"
#include "InclusiveCrosshairs.h"
#include "trace.h"
#ifdef COMPOSITION
namespace winrt
{
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Composition;
}
namespace ABI
{
using namespace ABI::Windows::System;
using namespace ABI::Windows::UI::Composition::Desktop;
}
#endif
struct InclusiveCrosshairs
{
bool MyRegisterClass(HINSTANCE hInstance);
static InclusiveCrosshairs* instance;
void Terminate();
void SwitchActivationMode();
void ApplySettings(InclusiveCrosshairsSettings& settings, bool applyToRuntimeObjects);
private:
enum class MouseButton
{
Left,
Right
};
void DestroyInclusiveCrosshairs();
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept;
void StartDrawing();
void StopDrawing();
bool CreateInclusiveCrosshairs();
void UpdateCrosshairsPosition();
HHOOK m_mouseHook = NULL;
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept;
static constexpr auto m_className = L"MousePointerCrosshairs";
static constexpr auto m_windowTitle = L"PowerToys Mouse Pointer Crosshairs";
HWND m_hwndOwner = NULL;
HWND m_hwnd = NULL;
HINSTANCE m_hinstance = NULL;
static constexpr DWORD WM_SWITCH_ACTIVATION_MODE = WM_APP;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
winrt::Compositor m_compositor{ nullptr };
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
winrt::ContainerVisual m_root{ nullptr };
winrt::LayerVisual m_crosshairs_border_layer{ nullptr };
winrt::LayerVisual m_crosshairs_layer{ nullptr };
winrt::SpriteVisual m_left_crosshairs_border{ nullptr };
winrt::SpriteVisual m_left_crosshairs{ nullptr };
winrt::SpriteVisual m_right_crosshairs_border{ nullptr };
winrt::SpriteVisual m_right_crosshairs{ nullptr };
winrt::SpriteVisual m_top_crosshairs_border{ nullptr };
winrt::SpriteVisual m_top_crosshairs{ nullptr };
winrt::SpriteVisual m_bottom_crosshairs_border{ nullptr };
winrt::SpriteVisual m_bottom_crosshairs{ nullptr };
bool m_visible = false;
bool m_destroyed = false;
// Configurable Settings
winrt::Windows::UI::Color m_crosshairs_border_color = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_BORDER_COLOR;
winrt::Windows::UI::Color m_crosshairs_color = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_COLOR;
float m_crosshairs_radius = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_RADIUS;
float m_crosshairs_thickness = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_THICKNESS;
float m_crosshairs_border_size = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_BORDER_SIZE;
float m_crosshairs_opacity = max(0.f, min(1.f, (float)INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_OPACITY / 100.0f));
};
InclusiveCrosshairs* InclusiveCrosshairs::instance = nullptr;
bool InclusiveCrosshairs::CreateInclusiveCrosshairs()
{
try
{
// We need a dispatcher queue.
DispatcherQueueOptions options = {
sizeof(options),
DQTYPE_THREAD_CURRENT,
DQTAT_COM_ASTA,
};
ABI::IDispatcherQueueController* controller;
winrt::check_hresult(CreateDispatcherQueueController(options, &controller));
*winrt::put_abi(m_dispatcherQueueController) = controller;
// Create the compositor for our window.
m_compositor = winrt::Compositor();
ABI::IDesktopWindowTarget* target;
winrt::check_hresult(m_compositor.as<ABI::ICompositorDesktopInterop>()->CreateDesktopWindowTarget(m_hwnd, false, &target));
*winrt::put_abi(m_target) = target;
// Our composition tree:
//
// [root] ContainerVisual
// \ [crosshairs border layer] LayerVisual
// \ [crosshairs border sprites]
// [crosshairs layer] LayerVisual
// \ [crosshairs sprites]
m_root = m_compositor.CreateContainerVisual();
m_root.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_target.Root(m_root);
m_root.Opacity(m_crosshairs_opacity);
m_crosshairs_border_layer = m_compositor.CreateLayerVisual();
m_crosshairs_border_layer.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_root.Children().InsertAtTop(m_crosshairs_border_layer);
m_crosshairs_border_layer.Opacity(1.0f);
m_crosshairs_layer = m_compositor.CreateLayerVisual();
m_crosshairs_layer.RelativeSizeAdjustment({ 1.0f, 1.0f });
// Create the crosshairs sprites.
m_left_crosshairs_border = m_compositor.CreateSpriteVisual();
m_left_crosshairs_border.AnchorPoint({ 1.0f, 0.5f });
m_left_crosshairs_border.Brush(m_compositor.CreateColorBrush(m_crosshairs_border_color));
m_crosshairs_border_layer.Children().InsertAtTop(m_left_crosshairs_border);
m_left_crosshairs = m_compositor.CreateSpriteVisual();
m_left_crosshairs.AnchorPoint({ 1.0f, 0.5f });
m_left_crosshairs.Brush(m_compositor.CreateColorBrush(m_crosshairs_color));
m_crosshairs_layer.Children().InsertAtTop(m_left_crosshairs);
m_right_crosshairs_border = m_compositor.CreateSpriteVisual();
m_right_crosshairs_border.AnchorPoint({ 0.0f, 0.5f });
m_right_crosshairs_border.Brush(m_compositor.CreateColorBrush(m_crosshairs_border_color));
m_crosshairs_border_layer.Children().InsertAtTop(m_right_crosshairs_border);
m_right_crosshairs = m_compositor.CreateSpriteVisual();
m_right_crosshairs.AnchorPoint({ 0.0f, 0.5f });
m_right_crosshairs.Brush(m_compositor.CreateColorBrush(m_crosshairs_color));
m_crosshairs_layer.Children().InsertAtTop(m_right_crosshairs);
m_top_crosshairs_border = m_compositor.CreateSpriteVisual();
m_top_crosshairs_border.AnchorPoint({ 0.5f, 1.0f });
m_top_crosshairs_border.Brush(m_compositor.CreateColorBrush(m_crosshairs_border_color));
m_crosshairs_border_layer.Children().InsertAtTop(m_top_crosshairs_border);
m_top_crosshairs = m_compositor.CreateSpriteVisual();
m_top_crosshairs.AnchorPoint({ 0.5f, 1.0f });
m_top_crosshairs.Brush(m_compositor.CreateColorBrush(m_crosshairs_color));
m_crosshairs_layer.Children().InsertAtTop(m_top_crosshairs);
m_bottom_crosshairs_border = m_compositor.CreateSpriteVisual();
m_bottom_crosshairs_border.AnchorPoint({ 0.5f, 0.0f });
m_bottom_crosshairs_border.Brush(m_compositor.CreateColorBrush(m_crosshairs_border_color));
m_crosshairs_border_layer.Children().InsertAtTop(m_bottom_crosshairs_border);
m_bottom_crosshairs = m_compositor.CreateSpriteVisual();
m_bottom_crosshairs.AnchorPoint({ 0.5f, 0.0f });
m_bottom_crosshairs.Brush(m_compositor.CreateColorBrush(m_crosshairs_color));
m_crosshairs_layer.Children().InsertAtTop(m_bottom_crosshairs);
m_crosshairs_border_layer.Children().InsertAtTop(m_crosshairs_layer);
m_crosshairs_layer.Opacity(1.0f);
UpdateCrosshairsPosition();
return true;
}
catch (...)
{
return false;
}
}
void InclusiveCrosshairs::UpdateCrosshairsPosition()
{
POINT ptCursor;
GetCursorPos(&ptCursor);
HMONITOR cursorMonitor = MonitorFromPoint(ptCursor, MONITOR_DEFAULTTONEAREST);
if (cursorMonitor == NULL)
{
return;
}
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(monitorInfo);
if (!GetMonitorInfo(cursorMonitor, &monitorInfo))
{
return;
}
POINT ptMonitorUpperLeft;
ptMonitorUpperLeft.x = monitorInfo.rcMonitor.left;
ptMonitorUpperLeft.y = monitorInfo.rcMonitor.top;
POINT ptMonitorBottomRight;
ptMonitorBottomRight.x = monitorInfo.rcMonitor.right;
ptMonitorBottomRight.y = monitorInfo.rcMonitor.bottom;
// Convert everything to client coordinates.
ScreenToClient(m_hwnd, &ptCursor);
ScreenToClient(m_hwnd, &ptMonitorUpperLeft);
ScreenToClient(m_hwnd, &ptMonitorBottomRight);
// Position crosshairs components around the mouse pointer.
m_left_crosshairs_border.Offset({ (float)ptCursor.x - m_crosshairs_radius + m_crosshairs_border_size, (float)ptCursor.y, .0f });
m_left_crosshairs_border.Size({ (float)ptCursor.x - (float)ptMonitorUpperLeft.x - m_crosshairs_radius + m_crosshairs_border_size, m_crosshairs_thickness + m_crosshairs_border_size * 2 });
m_left_crosshairs.Offset({ (float)ptCursor.x - m_crosshairs_radius, (float)ptCursor.y, .0f });
m_left_crosshairs.Size({ (float)ptCursor.x - (float)ptMonitorUpperLeft.x - m_crosshairs_radius, m_crosshairs_thickness });
m_right_crosshairs_border.Offset({ (float)ptCursor.x + m_crosshairs_radius - m_crosshairs_border_size, (float)ptCursor.y, .0f });
m_right_crosshairs_border.Size({ (float)ptMonitorBottomRight.x - (float)ptCursor.x - m_crosshairs_radius + m_crosshairs_border_size, m_crosshairs_thickness + m_crosshairs_border_size * 2 });
m_right_crosshairs.Offset({ (float)ptCursor.x + m_crosshairs_radius, (float)ptCursor.y, .0f });
m_right_crosshairs.Size({ (float)ptMonitorBottomRight.x - (float)ptCursor.x - m_crosshairs_radius, m_crosshairs_thickness });
m_top_crosshairs_border.Offset({ (float)ptCursor.x, (float)ptCursor.y - m_crosshairs_radius + m_crosshairs_border_size, .0f });
m_top_crosshairs_border.Size({ m_crosshairs_thickness + m_crosshairs_border_size * 2, (float)ptCursor.y - (float)ptMonitorUpperLeft.y - m_crosshairs_radius + m_crosshairs_border_size });
m_top_crosshairs.Offset({ (float)ptCursor.x, (float)ptCursor.y - m_crosshairs_radius, .0f });
m_top_crosshairs.Size({ m_crosshairs_thickness, (float)ptCursor.y - (float)ptMonitorUpperLeft.y - m_crosshairs_radius });
m_bottom_crosshairs_border.Offset({ (float)ptCursor.x, (float)ptCursor.y + m_crosshairs_radius - m_crosshairs_border_size, .0f });
m_bottom_crosshairs_border.Size({ m_crosshairs_thickness + m_crosshairs_border_size * 2, (float)ptMonitorBottomRight.y - (float)ptCursor.y - m_crosshairs_radius + m_crosshairs_border_size });
m_bottom_crosshairs.Offset({ (float)ptCursor.x, (float)ptCursor.y + m_crosshairs_radius, .0f });
m_bottom_crosshairs.Size({ m_crosshairs_thickness, (float)ptMonitorBottomRight.y - (float)ptCursor.y - m_crosshairs_radius });
}
LRESULT CALLBACK InclusiveCrosshairs::MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT* hookData = (MSLLHOOKSTRUCT*)lParam;
if (wParam == WM_MOUSEMOVE) {
instance->UpdateCrosshairsPosition();
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
void InclusiveCrosshairs::StartDrawing()
{
Logger::info("Start drawing crosshairs.");
Trace::StartDrawingCrosshairs();
m_visible = true;
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0);
UpdateCrosshairsPosition();
}
void InclusiveCrosshairs::StopDrawing()
{
Logger::info("Stop drawing crosshairs.");
m_visible = false;
ShowWindow(m_hwnd, SW_HIDE);
UnhookWindowsHookEx(m_mouseHook);
m_mouseHook = NULL;
}
void InclusiveCrosshairs::SwitchActivationMode()
{
PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0);
}
void InclusiveCrosshairs::ApplySettings(InclusiveCrosshairsSettings& settings, bool applyToRunTimeObjects)
{
m_crosshairs_radius = (float)settings.crosshairsRadius;
m_crosshairs_thickness = (float)settings.crosshairsThickness;
m_crosshairs_color = settings.crosshairsColor;
m_crosshairs_opacity = max(0.f, min(1.f, (float)settings.crosshairsOpacity / 100.0f));
m_crosshairs_border_color = settings.crosshairsBorderColor;
m_crosshairs_border_size = (float)settings.crosshairsBorderSize;
if (applyToRunTimeObjects)
{
// Runtime objects already created. Should update in the owner thread.
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
InclusiveCrosshairsSettings localSettings = settings;
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
if (!m_destroyed)
{
// Apply new settings to runtime composition objects.
m_left_crosshairs.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_color);
m_right_crosshairs.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_color);
m_top_crosshairs.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_color);
m_bottom_crosshairs.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_color);
m_left_crosshairs_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_border_color);
m_right_crosshairs_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_border_color);
m_top_crosshairs_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_border_color);
m_bottom_crosshairs_border.Brush().as<winrt::CompositionColorBrush>().Color(m_crosshairs_border_color);
m_root.Opacity(m_crosshairs_opacity);
UpdateCrosshairsPosition();
}
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to update the crosshairs settings.");
}
}
}
void InclusiveCrosshairs::DestroyInclusiveCrosshairs()
{
StopDrawing();
PostQuitMessage(0);
}
LRESULT CALLBACK InclusiveCrosshairs::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept
{
switch (message)
{
case WM_NCCREATE:
instance->m_hwnd = hWnd;
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_CREATE:
return instance->CreateInclusiveCrosshairs() ? 0 : -1;
case WM_NCHITTEST:
return HTTRANSPARENT;
case WM_SWITCH_ACTIVATION_MODE:
if (instance->m_visible)
{
instance->StopDrawing();
}
else
{
instance->StartDrawing();
}
break;
case WM_DESTROY:
instance->DestroyInclusiveCrosshairs();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool InclusiveCrosshairs::MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wc{};
m_hinstance = hInstance;
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!GetClassInfoW(hInstance, m_className, &wc))
{
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszClassName = m_className;
if (!RegisterClassW(&wc))
{
return false;
}
}
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hInstance, nullptr);
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOREDIRECTIONBITMAP | WS_EX_TOOLWINDOW;
return CreateWindowExW(exStyle, m_className, m_windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hInstance, nullptr) != nullptr;
}
void InclusiveCrosshairs::Terminate()
{
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
m_destroyed = true;
DestroyWindow(m_hwndOwner);
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to destroy the window.");
}
}
#pragma region InclusiveCrosshairs_API
void InclusiveCrosshairsApplySettings(InclusiveCrosshairsSettings& settings)
{
if (InclusiveCrosshairs::instance != nullptr)
{
Logger::info("Applying settings.");
InclusiveCrosshairs::instance->ApplySettings(settings, true);
}
}
void InclusiveCrosshairsSwitch()
{
if (InclusiveCrosshairs::instance != nullptr)
{
Logger::info("Switching activation mode.");
InclusiveCrosshairs::instance->SwitchActivationMode();
}
}
void InclusiveCrosshairsDisable()
{
if (InclusiveCrosshairs::instance != nullptr)
{
Logger::info("Terminating the crosshairs instance.");
InclusiveCrosshairs::instance->Terminate();
}
}
bool InclusiveCrosshairsIsEnabled()
{
return (InclusiveCrosshairs::instance != nullptr);
}
int InclusiveCrosshairsMain(HINSTANCE hInstance, InclusiveCrosshairsSettings& settings)
{
Logger::info("Starting a crosshairs instance.");
if (InclusiveCrosshairs::instance != nullptr)
{
Logger::error("A crosshairs instance was still working when trying to start a new one.");
return 0;
}
// Perform application initialization:
InclusiveCrosshairs crosshairs;
InclusiveCrosshairs::instance = &crosshairs;
crosshairs.ApplySettings(settings, false);
if (!crosshairs.MyRegisterClass(hInstance))
{
Logger::error("Couldn't initialize a crosshairs instance.");
InclusiveCrosshairs::instance = nullptr;
return FALSE;
}
Logger::info("Initialized the crosshairs instance.");
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Logger::info("Crosshairs message loop ended.");
InclusiveCrosshairs::instance = nullptr;
return (int)msg.wParam;
}
#pragma endregion InclusiveCrosshairs_API

View File

@@ -0,0 +1,25 @@
#pragma once
#include "pch.h"
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_OPACITY = 75;
const winrt::Windows::UI::Color INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 0, 0);
const winrt::Windows::UI::Color INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_BORDER_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 255, 255);
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_RADIUS = 20;
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_THICKNESS = 5;
constexpr int INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_BORDER_SIZE = 1;
struct InclusiveCrosshairsSettings
{
winrt::Windows::UI::Color crosshairsColor = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_COLOR;
winrt::Windows::UI::Color crosshairsBorderColor = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_BORDER_COLOR;
int crosshairsRadius = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_RADIUS;
int crosshairsThickness = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_THICKNESS;
int crosshairsOpacity = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_OPACITY;
int crosshairsBorderSize = INCLUSIVE_MOUSE_DEFAULT_CROSSHAIRS_BORDER_SIZE;
};
int InclusiveCrosshairsMain(HINSTANCE hinst, InclusiveCrosshairsSettings& settings);
void InclusiveCrosshairsDisable();
bool InclusiveCrosshairsIsEnabled();
void InclusiveCrosshairsSwitch();
void InclusiveCrosshairsApplySettings(InclusiveCrosshairsSettings& settings);

View File

@@ -15,9 +15,9 @@
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{eae14c0e-7a6b-45da-9080-a7d8c077ba6e}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>MousePointerCrosshair</RootNamespace>
<RootNamespace>MousePointerCrosshairs</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<ProjectName>MousePointerCrosshair</ProjectName>
<ProjectName>MousePointerCrosshairs</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="..\..\..\..\deps\spdlog.props" />
@@ -49,12 +49,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
<TargetName>PowerToys.MousePointerCrosshair</TargetName>
<TargetName>PowerToys.MousePointerCrosshairs</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
<TargetName>PowerToys.MousePointerCrosshair</TargetName>
<TargetName>PowerToys.MousePointerCrosshairs</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
@@ -104,14 +104,14 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="InclusiveCrosshair.h" />
<ClInclude Include="InclusiveCrosshairs.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="trace.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="InclusiveCrosshair.cpp" />
<ClCompile Include="InclusiveCrosshairs.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
</ClCompile>
@@ -121,7 +121,7 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="MousePointerCrosshair.rc" />
<ResourceCompile Include="MousePointerCrosshairs.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">

View File

@@ -10,7 +10,7 @@
<ClCompile Include="trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="InclusiveCrosshair.cpp">
<ClCompile Include="InclusiveCrosshairs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -24,7 +24,7 @@
<ClInclude Include="resource.h">
<Filter>Resource Files</Filter>
</ClInclude>
<ClInclude Include="InclusiveCrosshair.h">
<ClInclude Include="InclusiveCrosshairs.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@@ -49,7 +49,7 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="MousePointerCrosshair.rc">
<ResourceCompile Include="MousePointerCrosshairs.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>

View File

@@ -2,7 +2,7 @@
#include <interface/powertoy_module_interface.h>
#include <common/SettingsAPI/settings_objects.h>
#include "trace.h"
#include "InclusiveCrosshair.h"
#include "InclusiveCrosshairs.h"
#include "common/utils/color.h"
// Non-Localizable strings
@@ -11,12 +11,12 @@ namespace
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_VALUE[] = L"value";
const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut";
const wchar_t JSON_KEY_CROSSHAIR_COLOR[] = L"crosshair_color";
const wchar_t JSON_KEY_CROSSHAIR_OPACITY[] = L"crosshair_opacity";
const wchar_t JSON_KEY_CROSSHAIR_RADIUS[] = L"crosshair_radius";
const wchar_t JSON_KEY_CROSSHAIR_THICKNESS[] = L"crosshair_thickness";
const wchar_t JSON_KEY_CROSSHAIR_BORDER_COLOR[] = L"crosshair_border_color";
const wchar_t JSON_KEY_CROSSHAIR_BORDER_SIZE[] = L"crosshair_border_size";
const wchar_t JSON_KEY_CROSSHAIRS_COLOR[] = L"crosshairs_color";
const wchar_t JSON_KEY_CROSSHAIRS_OPACITY[] = L"crosshairs_opacity";
const wchar_t JSON_KEY_CROSSHAIRS_RADIUS[] = L"crosshairs_radius";
const wchar_t JSON_KEY_CROSSHAIRS_THICKNESS[] = L"crosshairs_thickness";
const wchar_t JSON_KEY_CROSSHAIRS_BORDER_COLOR[] = L"crosshairs_border_color";
const wchar_t JSON_KEY_CROSSHAIRS_BORDER_SIZE[] = L"crosshairs_border_size";
}
extern "C" IMAGE_DOS_HEADER __ImageBase;
@@ -42,12 +42,12 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
}
// The PowerToy name that will be shown in the settings.
const static wchar_t* MODULE_NAME = L"MousePointerCrosshair";
const static wchar_t* MODULE_NAME = L"MousePointerCrosshairs";
// Add a description that will we shown in the module settings page.
const static wchar_t* MODULE_DESC = L"<no description>";
// Implement the PowerToy Module Interface and all the required methods.
class MousePointerCrosshair : public PowertoyModuleIface
class MousePointerCrosshairs : public PowertoyModuleIface
{
private:
// The PowerToy state.
@@ -56,14 +56,14 @@ private:
// Hotkey to invoke the module
HotkeyEx m_hotkey;
// Mouse Pointer Crosshair specific settings
InclusiveCrosshairSettings m_inclusiveCrosshairSettings;
// Mouse Pointer Crosshairs specific settings
InclusiveCrosshairsSettings m_inclusiveCrosshairsSettings;
public:
// Constructor
MousePointerCrosshair()
MousePointerCrosshairs()
{
LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mousePointerCrosshairLoggerName);
LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mousePointerCrosshairsLoggerName);
init_settings();
};
@@ -112,11 +112,11 @@ public:
parse_settings(values);
InclusiveCrosshairApplySettings(m_inclusiveCrosshairSettings);
InclusiveCrosshairsApplySettings(m_inclusiveCrosshairsSettings);
}
catch (std::exception&)
{
Logger::error("Invalid json when trying to parse Mouse Pointer Crosshair settings json.");
Logger::error("Invalid json when trying to parse Mouse Pointer Crosshairs settings json.");
}
}
@@ -124,16 +124,16 @@ public:
virtual void enable()
{
m_enabled = true;
Trace::EnableMousePointerCrosshair(true);
std::thread([=]() { InclusiveCrosshairMain(m_hModule, m_inclusiveCrosshairSettings); }).detach();
Trace::EnableMousePointerCrosshairs(true);
std::thread([=]() { InclusiveCrosshairsMain(m_hModule, m_inclusiveCrosshairsSettings); }).detach();
}
// Disable the powertoy
virtual void disable()
{
m_enabled = false;
Trace::EnableMousePointerCrosshair(false);
InclusiveCrosshairDisable();
Trace::EnableMousePointerCrosshairs(false);
InclusiveCrosshairsDisable();
}
// Returns if the powertoys is enabled
@@ -155,7 +155,7 @@ public:
virtual void OnHotkeyEx() override
{
InclusiveCrosshairSwitch();
InclusiveCrosshairsSwitch();
}
// Load the settings file.
void init_settings()
@@ -164,12 +164,12 @@ public:
{
// Load and parse the settings file for this PowerToy.
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(MousePointerCrosshair::get_key());
PowerToysSettings::PowerToyValues::load_from_settings_file(MousePointerCrosshairs::get_key());
parse_settings(settings);
}
catch (std::exception&)
{
Logger::error("Invalid json when trying to load the Mouse Pointer Crosshair settings json from file.");
Logger::error("Invalid json when trying to load the Mouse Pointer Crosshairs settings json from file.");
}
}
@@ -177,7 +177,7 @@ public:
{
// TODO: refactor to use common/utils/json.h instead
auto settingsObject = settings.get_raw_json();
InclusiveCrosshairSettings inclusiveCrosshairSettings;
InclusiveCrosshairsSettings inclusiveCrosshairsSettings;
if (settingsObject.GetView().Size())
{
try
@@ -210,13 +210,13 @@ public:
}
catch (...)
{
Logger::warn("Failed to initialize Mouse Pointer Crosshair activation shortcut");
Logger::warn("Failed to initialize Mouse Pointer Crosshairs activation shortcut");
}
try
{
// Parse Opacity
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIR_OPACITY);
inclusiveCrosshairSettings.crosshairOpacity = (uint8_t)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIRS_OPACITY);
inclusiveCrosshairsSettings.crosshairsOpacity = (uint8_t)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
@@ -224,28 +224,28 @@ public:
}
try
{
// Parse crosshair color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIR_COLOR);
auto crosshairColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
// Parse crosshairs color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIRS_COLOR);
auto crosshairsColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(crosshairColor, &r, &g, &b))
if (!checkValidRGB(crosshairsColor, &r, &g, &b))
{
Logger::error("Crosshair color RGB value is invalid. Will use default value");
Logger::error("Crosshairs color RGB value is invalid. Will use default value");
}
else
{
inclusiveCrosshairSettings.crosshairColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
inclusiveCrosshairsSettings.crosshairsColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize crosshair color from settings. Will use default value");
Logger::warn("Failed to initialize crosshairs color from settings. Will use default value");
}
try
{
// Parse Radius
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIR_RADIUS);
inclusiveCrosshairSettings.crosshairRadius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIRS_RADIUS);
inclusiveCrosshairsSettings.crosshairsRadius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
@@ -254,8 +254,8 @@ public:
try
{
// Parse Thickness
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIR_THICKNESS);
inclusiveCrosshairSettings.crosshairThickness = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIRS_THICKNESS);
inclusiveCrosshairsSettings.crosshairsThickness = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
@@ -263,28 +263,28 @@ public:
}
try
{
// Parse crosshair border color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIR_BORDER_COLOR);
auto crosshairBorderColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
// Parse crosshairs border color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIRS_BORDER_COLOR);
auto crosshairsBorderColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(crosshairBorderColor, &r, &g, &b))
if (!checkValidRGB(crosshairsBorderColor, &r, &g, &b))
{
Logger::error("Crosshair border color RGB value is invalid. Will use default value");
Logger::error("Crosshairs border color RGB value is invalid. Will use default value");
}
else
{
inclusiveCrosshairSettings.crosshairBorderColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
inclusiveCrosshairsSettings.crosshairsBorderColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize crosshair border color from settings. Will use default value");
Logger::warn("Failed to initialize crosshairs border color from settings. Will use default value");
}
try
{
// Parse border size
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIR_BORDER_SIZE);
inclusiveCrosshairSettings.crosshairBorderSize = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_CROSSHAIRS_BORDER_SIZE);
inclusiveCrosshairsSettings.crosshairsBorderSize = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
@@ -293,20 +293,20 @@ public:
}
else
{
Logger::info("Mouse Pointer Crosshair settings are empty");
Logger::info("Mouse Pointer Crosshairs settings are empty");
}
if (!m_hotkey.modifiersMask)
{
Logger::info("Mouse Pointer Crosshair is going to use default shortcut");
Logger::info("Mouse Pointer Crosshairs is going to use default shortcut");
m_hotkey.modifiersMask = MOD_CONTROL | MOD_ALT;
m_hotkey.vkCode = 0x50; // P key
}
m_inclusiveCrosshairSettings = inclusiveCrosshairSettings;
m_inclusiveCrosshairsSettings = inclusiveCrosshairsSettings;
}
};
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
{
return new MousePointerCrosshair();
return new MousePointerCrosshairs();
}

View File

@@ -0,0 +1,13 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by MousePointerCrosshairs.rc
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "PowerToys MousePointerCrosshairs"
#define INTERNAL_NAME "MousePointerCrosshairs"
#define ORIGINAL_FILENAME "PowerToys.MousePointerCrosshairs.dll"
// Non-localizable
//////////////////////////////

View File

@@ -18,23 +18,23 @@ void Trace::UnregisterProvider() noexcept
TraceLoggingUnregister(g_hProvider);
}
// Log if the user has MousePointerCrosshair enabled or disabled
void Trace::EnableMousePointerCrosshair(const bool enabled) noexcept
// Log if the user has MousePointerCrosshairs enabled or disabled
void Trace::EnableMousePointerCrosshairs(const bool enabled) noexcept
{
TraceLoggingWrite(
g_hProvider,
"MousePointerCrosshair_EnableMousePointerCrosshair",
"MousePointerCrosshairs_EnableMousePointerCrosshairs",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(enabled, "Enabled"));
}
// Log that the user activated the module by having the crosshair be drawn
void Trace::StartDrawingCrosshair() noexcept
// Log that the user activated the module by having the crosshairs be drawn
void Trace::StartDrawingCrosshairs() noexcept
{
TraceLoggingWrite(
g_hProvider,
"MousePointerCrosshair_StartDrawingCrosshair",
"MousePointerCrosshairs_StartDrawingCrosshairs",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}

View File

@@ -0,0 +1,14 @@
#pragma once
class Trace
{
public:
static void RegisterProvider() noexcept;
static void UnregisterProvider() noexcept;
// Log if the user has MousePointerCrosshairs enabled or disabled
static void EnableMousePointerCrosshairs(const bool enabled) noexcept;
// Log that the user activated the module by having the crosshairs be drawn
static void StartDrawingCrosshairs() noexcept;
};