Mouse Utils - Mouse Highlighter (#14496)
* New PowerToys template * Add CppWinRt to empty PowerToy * Add Settings reference to empty PowerToy * Use proper output dir * Proper WindowsTargetPlatformVersion * Add filters to vcxproj * Proper resource file generation * Add MouseHighlighter proof of concept code * Abstract implementation into a struct * Enable module * Disable module * Add enable module to settings page * Can change the hotkey in settings * Remove remaining boilerplate code * Add logging * Add telemetry * Add Oobe entry * Add installer instructions * Add dll to pipelines * fix spellchecker * Add more configurability * Make settings a bit prettier * Fix spellchecker * Fix wrong default fade timers * Fix user facing strings * Tweak default duration values * Fix to appear in every virtual desktop * [Mouse Highlighter] Show highlight on mouse drag (#14529) * [Mouse Highlighter]show pointer on mouse drag * fix spellchecker * [MU] UI tweaks (#14544) * UI tweaks * Update Resources.resw * Updated text strings * fix spellcheck Co-authored-by: Laute <Niels.Laute@philips.com> * tweak default values * PR feedback: use wstring_view * PR feedback: Log error on json error * PR feedback: don't throw 1 * PR feedback: fix copy-pasta leftColor->rightColor * PR feedback:Add another error message on exception * PR feedback: add todo to use commons/utils/json.h Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Laute <Niels.Laute@philips.com>
This commit is contained in:
parent
0dae5d0402
commit
2d5276f742
3
.github/actions/spell-check/expect.txt
vendored
3
.github/actions/spell-check/expect.txt
vendored
|
@ -763,8 +763,10 @@ hglobal
|
||||||
hhk
|
hhk
|
||||||
HHmmss
|
HHmmss
|
||||||
HHOOK
|
HHOOK
|
||||||
|
hhx
|
||||||
HICON
|
HICON
|
||||||
HIDEWINDOW
|
HIDEWINDOW
|
||||||
|
highlighter
|
||||||
HIMAGELIST
|
HIMAGELIST
|
||||||
himl
|
himl
|
||||||
hinst
|
hinst
|
||||||
|
@ -2084,6 +2086,7 @@ Switchbetweenvirtualdesktops
|
||||||
SWP
|
SWP
|
||||||
swprintf
|
swprintf
|
||||||
SWRESTORE
|
SWRESTORE
|
||||||
|
swscanf
|
||||||
SYMED
|
SYMED
|
||||||
SYMOPT
|
SYMOPT
|
||||||
SYNCMFT
|
SYNCMFT
|
||||||
|
|
|
@ -171,6 +171,7 @@ build:
|
||||||
- 'modules\launcher\Wox.Infrastructure.dll'
|
- 'modules\launcher\Wox.Infrastructure.dll'
|
||||||
- 'modules\launcher\Wox.Plugin.dll'
|
- 'modules\launcher\Wox.Plugin.dll'
|
||||||
- 'modules\MouseUtils\FindMyMouse.dll'
|
- 'modules\MouseUtils\FindMyMouse.dll'
|
||||||
|
- 'modules\MouseUtils\MouseHighlighter.dll'
|
||||||
- 'modules\PowerRename\PowerRenameExt.dll'
|
- 'modules\PowerRename\PowerRenameExt.dll'
|
||||||
- 'modules\PowerRename\PowerRenameUILib.dll'
|
- 'modules\PowerRename\PowerRenameUILib.dll'
|
||||||
- 'modules\PowerRename\PowerRename.exe'
|
- 'modules\PowerRename\PowerRename.exe'
|
||||||
|
|
|
@ -371,6 +371,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseUtils", "MouseUtils",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseHighlighter", "src\modules\MouseUtils\MouseHighlighter\MouseHighlighter.vcxproj", "{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
@ -986,6 +988,12 @@ Global
|
||||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.ActiveCfg = Release|x64
|
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.ActiveCfg = Release|x64
|
||||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.Build.0 = Release|x64
|
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.Build.0 = Release|x64
|
||||||
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x86.ActiveCfg = Release|x64
|
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x86.ActiveCfg = Release|x64
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x64.Build.0 = Release|x64
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x86.ActiveCfg = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -1105,6 +1113,7 @@ Global
|
||||||
{4642D596-723F-4BFC-894C-46811219AC4A} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
{4642D596-723F-4BFC-894C-46811219AC4A} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
|
||||||
{322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
{322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||||
{E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
{E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||||
|
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88} = {322566EF-20DC-43A6-B9F8-616AF942579A}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||||
|
|
BIN
doc/images/icons/Find My Mouse.png
Normal file
BIN
doc/images/icons/Find My Mouse.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
doc/images/icons/Mouse Highlighter.png
Normal file
BIN
doc/images/icons/Mouse Highlighter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -657,6 +657,9 @@
|
||||||
<Component Id="Module_FindMyMouse" Guid="60D0E4AE-188F-4403-BF06-1465AACC1BC5" Win64="yes">
|
<Component Id="Module_FindMyMouse" Guid="60D0E4AE-188F-4403-BF06-1465AACC1BC5" Win64="yes">
|
||||||
<File Source="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)\FindMyMouse.dll" KeyPath="yes" />
|
<File Source="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)\FindMyMouse.dll" KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component Id="Module_MouseHighlighter" Guid="3BAEA39F-A73D-48D2-9616-BBED5B8C86D3" Win64="yes">
|
||||||
|
<File Source="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)\MouseHighlighter.dll" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
|
|
||||||
<!-- Shortcut guide -->
|
<!-- Shortcut guide -->
|
||||||
|
@ -971,6 +974,7 @@
|
||||||
<ComponentRef Id="Module_Awake_runtime_netcoreapp30"/>
|
<ComponentRef Id="Module_Awake_runtime_netcoreapp30"/>
|
||||||
<ComponentRef Id="Module_Awake_runtime_netcoreapp21"/>
|
<ComponentRef Id="Module_Awake_runtime_netcoreapp21"/>
|
||||||
<ComponentRef Id="Module_FindMyMouse"/>
|
<ComponentRef Id="Module_FindMyMouse"/>
|
||||||
|
<ComponentRef Id="Module_MouseHighlighter"/>
|
||||||
<ComponentRef Id="SettingsV2" />
|
<ComponentRef Id="SettingsV2" />
|
||||||
<ComponentRef Id="SettingsV2Assets" />
|
<ComponentRef Id="SettingsV2Assets" />
|
||||||
<ComponentRef Id="SettingsV2AssetsModules" />
|
<ComponentRef Id="SettingsV2AssetsModules" />
|
||||||
|
|
|
@ -26,6 +26,7 @@ struct LogSettings
|
||||||
inline const static std::string keyboardManagerLoggerName = "keyboard-manager";
|
inline const static std::string keyboardManagerLoggerName = "keyboard-manager";
|
||||||
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
|
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
|
||||||
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
|
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
|
||||||
|
inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter";
|
||||||
inline const static std::string powerRenameLoggerName = "powerrename";
|
inline const static std::string powerRenameLoggerName = "powerrename";
|
||||||
inline const static int retention = 30;
|
inline const static int retention = 30;
|
||||||
std::wstring logLevel;
|
std::wstring logLevel;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||||
|
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 .\ resource.base.h resource.h MouseHighlighter.base.rc MouseHighlighter.rc" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <windows.h>
|
||||||
|
#include "resource.h"
|
||||||
|
#include "../../../../common/version/version.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#include "winres.h"
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
1 VERSIONINFO
|
||||||
|
FILEVERSION FILE_VERSION
|
||||||
|
PRODUCTVERSION PRODUCT_VERSION
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT_WINDOWS32
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE VFT2_UNKNOWN
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", COMPANY_NAME
|
||||||
|
VALUE "FileDescription", FILE_DESCRIPTION
|
||||||
|
VALUE "FileVersion", FILE_VERSION_STRING
|
||||||
|
VALUE "InternalName", INTERNAL_NAME
|
||||||
|
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||||
|
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||||
|
VALUE "ProductName", PRODUCT_NAME
|
||||||
|
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||||
|
END
|
||||||
|
END
|
443
src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp
Normal file
443
src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.cpp
Normal file
|
@ -0,0 +1,443 @@
|
||||||
|
// MouseHighlighter.cpp : Defines the entry point for the application.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
#include "MouseHighlighter.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 Highlighter
|
||||||
|
{
|
||||||
|
bool MyRegisterClass(HINSTANCE hInstance);
|
||||||
|
static Highlighter* instance;
|
||||||
|
void Terminate();
|
||||||
|
void SwitchActivationMode();
|
||||||
|
void ApplySettings(MouseHighlighterSettings settings);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class MouseButton
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
};
|
||||||
|
|
||||||
|
void DestroyHighlighter();
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept;
|
||||||
|
void StartDrawing();
|
||||||
|
void StopDrawing();
|
||||||
|
bool CreateHighlighter();
|
||||||
|
void AddDrawingPoint(MouseButton button);
|
||||||
|
void UpdateDrawingPointPosition(MouseButton button);
|
||||||
|
void StartDrawingPointFading(MouseButton button);
|
||||||
|
void ClearDrawing();
|
||||||
|
HHOOK m_mouseHook = NULL;
|
||||||
|
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept;
|
||||||
|
|
||||||
|
static constexpr auto m_className = L"MouseHighlighter";
|
||||||
|
static constexpr auto m_windowTitle = L"MouseHighlighter";
|
||||||
|
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_layer{ nullptr };
|
||||||
|
winrt::ShapeVisual m_shape{ nullptr };
|
||||||
|
|
||||||
|
winrt::CompositionSpriteShape m_leftPointer{ nullptr };
|
||||||
|
winrt::CompositionSpriteShape m_rightPointer{ nullptr };
|
||||||
|
bool m_leftButtonPressed = false;
|
||||||
|
bool m_rightButtonPressed = false;
|
||||||
|
|
||||||
|
bool m_visible = false;
|
||||||
|
|
||||||
|
// Possible configurable settings
|
||||||
|
float m_radius = MOUSE_HIGHLIGHTER_DEFAULT_RADIUS;
|
||||||
|
|
||||||
|
int m_fadeDelay_ms = MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS;
|
||||||
|
int m_fadeDuration_ms = MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS;
|
||||||
|
|
||||||
|
winrt::Windows::UI::Color m_leftClickColor = MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR;
|
||||||
|
winrt::Windows::UI::Color m_rightClickColor = MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR;
|
||||||
|
};
|
||||||
|
|
||||||
|
Highlighter* Highlighter::instance = nullptr;
|
||||||
|
|
||||||
|
bool Highlighter::CreateHighlighter()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Create visual root
|
||||||
|
m_root = m_compositor.CreateContainerVisual();
|
||||||
|
m_root.RelativeSizeAdjustment({ 1.0f, 1.0f });
|
||||||
|
m_target.Root(m_root);
|
||||||
|
|
||||||
|
// Create the shapes container visual and add it to root.
|
||||||
|
m_shape = m_compositor.CreateShapeVisual();
|
||||||
|
m_shape.RelativeSizeAdjustment({ 1.0f, 1.0f });
|
||||||
|
m_root.Children().InsertAtTop(m_shape);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Highlighter::AddDrawingPoint(MouseButton button)
|
||||||
|
{
|
||||||
|
POINT pt;
|
||||||
|
|
||||||
|
// Applies DPIs.
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
|
||||||
|
// Converts to client area of the Windows.
|
||||||
|
ScreenToClient(m_hwnd, &pt);
|
||||||
|
|
||||||
|
// Create circle and add it.
|
||||||
|
auto circleGeometry = m_compositor.CreateEllipseGeometry();
|
||||||
|
circleGeometry.Radius({ m_radius, m_radius });
|
||||||
|
auto circleShape = m_compositor.CreateSpriteShape(circleGeometry);
|
||||||
|
circleShape.Offset({ (float)pt.x, (float)pt.y });
|
||||||
|
if (button == MouseButton::Left)
|
||||||
|
{
|
||||||
|
circleShape.FillBrush(m_compositor.CreateColorBrush(m_leftClickColor));
|
||||||
|
m_leftPointer = circleShape;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//right
|
||||||
|
circleShape.FillBrush(m_compositor.CreateColorBrush(m_rightClickColor));
|
||||||
|
m_rightPointer = circleShape;
|
||||||
|
}
|
||||||
|
m_shape.Shapes().Append(circleShape);
|
||||||
|
|
||||||
|
// TODO: We're leaking shapes for long drawing sessions.
|
||||||
|
// Perhaps add a task to the Dispatcher every X circles to clean up.
|
||||||
|
|
||||||
|
// Get back on top in case other Window is now the topmost.
|
||||||
|
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
|
||||||
|
GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Highlighter::UpdateDrawingPointPosition(MouseButton button)
|
||||||
|
{
|
||||||
|
POINT pt;
|
||||||
|
|
||||||
|
// Applies DPIs.
|
||||||
|
GetCursorPos(&pt);
|
||||||
|
|
||||||
|
// Converts to client area of the Windows.
|
||||||
|
ScreenToClient(m_hwnd, &pt);
|
||||||
|
|
||||||
|
if (button == MouseButton::Left)
|
||||||
|
{
|
||||||
|
m_leftPointer.Offset({ (float)pt.x, (float)pt.y });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//right
|
||||||
|
m_rightPointer.Offset({ (float)pt.x, (float)pt.y });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Highlighter::StartDrawingPointFading(MouseButton button)
|
||||||
|
{
|
||||||
|
winrt::Windows::UI::Composition::CompositionSpriteShape circleShape{ nullptr };
|
||||||
|
if (button == MouseButton::Left)
|
||||||
|
{
|
||||||
|
circleShape = m_leftPointer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//right
|
||||||
|
circleShape = m_rightPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto brushColor = circleShape.FillBrush().as<winrt::Windows::UI::Composition::CompositionColorBrush>().Color();
|
||||||
|
|
||||||
|
// Animate opacity to simulate a fade away effect.
|
||||||
|
auto animation = m_compositor.CreateColorKeyFrameAnimation();
|
||||||
|
animation.InsertKeyFrame(1, winrt::Windows::UI::ColorHelper::FromArgb(0, brushColor.R, brushColor.G, brushColor.B));
|
||||||
|
using timeSpan = std::chrono::duration<int, std::ratio<1, 1000>>;
|
||||||
|
std::chrono::milliseconds duration(m_fadeDuration_ms);
|
||||||
|
std::chrono::milliseconds delay(m_fadeDelay_ms);
|
||||||
|
animation.Duration(timeSpan(duration));
|
||||||
|
animation.DelayTime(timeSpan(delay));
|
||||||
|
|
||||||
|
circleShape.FillBrush().StartAnimation(L"Color", animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Highlighter::ClearDrawing()
|
||||||
|
{
|
||||||
|
m_shape.Shapes().Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept
|
||||||
|
{
|
||||||
|
if (nCode >= 0)
|
||||||
|
{
|
||||||
|
MSLLHOOKSTRUCT* hookData = (MSLLHOOKSTRUCT*)lParam;
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
instance->AddDrawingPoint(MouseButton::Left);
|
||||||
|
instance->m_leftButtonPressed = true;
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
instance->AddDrawingPoint(MouseButton::Right);
|
||||||
|
instance->m_rightButtonPressed = true;
|
||||||
|
break;
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
if (instance->m_leftButtonPressed)
|
||||||
|
{
|
||||||
|
instance->UpdateDrawingPointPosition(MouseButton::Left);
|
||||||
|
}
|
||||||
|
if (instance->m_rightButtonPressed)
|
||||||
|
{
|
||||||
|
instance->UpdateDrawingPointPosition(MouseButton::Right);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
if (instance->m_leftButtonPressed)
|
||||||
|
{
|
||||||
|
instance->StartDrawingPointFading(MouseButton::Left);
|
||||||
|
instance->m_leftButtonPressed = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
if (instance->m_rightButtonPressed)
|
||||||
|
{
|
||||||
|
instance->StartDrawingPointFading(MouseButton::Right);
|
||||||
|
instance->m_rightButtonPressed = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CallNextHookEx(0, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Highlighter::StartDrawing()
|
||||||
|
{
|
||||||
|
Logger::info("Starting draw mode.");
|
||||||
|
Trace::StartHighlightingSession();
|
||||||
|
m_visible = true;
|
||||||
|
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
|
||||||
|
GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
|
||||||
|
ClearDrawing();
|
||||||
|
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
||||||
|
m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Highlighter::StopDrawing()
|
||||||
|
{
|
||||||
|
Logger::info("Stopping draw mode.");
|
||||||
|
m_visible = false;
|
||||||
|
m_leftButtonPressed = false;
|
||||||
|
m_rightButtonPressed = false;
|
||||||
|
m_leftPointer = nullptr;
|
||||||
|
m_rightPointer = nullptr;
|
||||||
|
ShowWindow(m_hwnd, SW_HIDE);
|
||||||
|
UnhookWindowsHookEx(m_mouseHook);
|
||||||
|
ClearDrawing();
|
||||||
|
m_mouseHook = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Highlighter::SwitchActivationMode()
|
||||||
|
{
|
||||||
|
PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Highlighter::ApplySettings(MouseHighlighterSettings settings) {
|
||||||
|
m_radius = (float)settings.radius;
|
||||||
|
m_fadeDelay_ms = settings.fadeDelayMs;
|
||||||
|
m_fadeDuration_ms = settings.fadeDurationMs;
|
||||||
|
m_leftClickColor = settings.leftButtonColor;
|
||||||
|
m_rightClickColor = settings.rightButtonColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Highlighter::DestroyHighlighter()
|
||||||
|
{
|
||||||
|
StopDrawing();
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK Highlighter::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->CreateHighlighter() ? 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->DestroyHighlighter();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Highlighter::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 Highlighter::Terminate()
|
||||||
|
{
|
||||||
|
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
|
||||||
|
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
|
||||||
|
DestroyWindow(m_hwndOwner);
|
||||||
|
});
|
||||||
|
if (!enqueueSucceeded)
|
||||||
|
{
|
||||||
|
Logger::error("Couldn't enqueue message to destroy the window.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma region MouseHighlighter_API
|
||||||
|
|
||||||
|
void MouseHighlighterApplySettings(MouseHighlighterSettings settings)
|
||||||
|
{
|
||||||
|
if (Highlighter::instance != nullptr)
|
||||||
|
{
|
||||||
|
Logger::info("Applying settings.");
|
||||||
|
Highlighter::instance->ApplySettings(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseHighlighterSwitch()
|
||||||
|
{
|
||||||
|
if (Highlighter::instance != nullptr)
|
||||||
|
{
|
||||||
|
Logger::info("Switching activation mode.");
|
||||||
|
Highlighter::instance->SwitchActivationMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseHighlighterDisable()
|
||||||
|
{
|
||||||
|
if (Highlighter::instance != nullptr)
|
||||||
|
{
|
||||||
|
Logger::info("Terminating the highlighter instance.");
|
||||||
|
Highlighter::instance->Terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MouseHighlighterIsEnabled()
|
||||||
|
{
|
||||||
|
return (Highlighter::instance != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MouseHighlighterMain(HINSTANCE hInstance, MouseHighlighterSettings settings)
|
||||||
|
{
|
||||||
|
Logger::info("Starting a highlighter instance.");
|
||||||
|
if (Highlighter::instance != nullptr)
|
||||||
|
{
|
||||||
|
Logger::error("A highlighter instance was still working when trying to start a new one.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform application initialization:
|
||||||
|
Highlighter highlighter;
|
||||||
|
Highlighter::instance = &highlighter;
|
||||||
|
highlighter.ApplySettings(settings);
|
||||||
|
if (!highlighter.MyRegisterClass(hInstance))
|
||||||
|
{
|
||||||
|
Logger::error("Couldn't initialize a highlighter instance.");
|
||||||
|
Highlighter::instance = nullptr;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
Logger::info("Initialized the highlighter instance.");
|
||||||
|
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
// Main message loop:
|
||||||
|
while (GetMessage(&msg, nullptr, 0, 0))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::info("Mouse highlighter message loop ended.");
|
||||||
|
Highlighter::instance = nullptr;
|
||||||
|
|
||||||
|
return (int)msg.wParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion MouseHighlighter_API
|
24
src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.h
Normal file
24
src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_OPACITY = 160;
|
||||||
|
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(MOUSE_HIGHLIGHTER_DEFAULT_OPACITY, 255, 255, 0);
|
||||||
|
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(MOUSE_HIGHLIGHTER_DEFAULT_OPACITY, 0, 0, 255);
|
||||||
|
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_RADIUS = 20;
|
||||||
|
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS = 500;
|
||||||
|
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS = 250;
|
||||||
|
|
||||||
|
struct MouseHighlighterSettings
|
||||||
|
{
|
||||||
|
winrt::Windows::UI::Color leftButtonColor = MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR;
|
||||||
|
winrt::Windows::UI::Color rightButtonColor = MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR;
|
||||||
|
int radius = MOUSE_HIGHLIGHTER_DEFAULT_RADIUS;
|
||||||
|
int fadeDelayMs = MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS;
|
||||||
|
int fadeDurationMs = MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS;
|
||||||
|
};
|
||||||
|
|
||||||
|
int MouseHighlighterMain(HINSTANCE hinst, MouseHighlighterSettings settings);
|
||||||
|
void MouseHighlighterDisable();
|
||||||
|
bool MouseHighlighterIsEnabled();
|
||||||
|
void MouseHighlighterSwitch();
|
||||||
|
void MouseHighlighterApplySettings(MouseHighlighterSettings settings);
|
145
src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.vcxproj
Normal file
145
src/modules/MouseUtils/MouseHighlighter/MouseHighlighter.vcxproj
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{782a61be-9d85-4081-b35c-1ccc9dcc1e88}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>MouseHighlighter</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>MouseHighlighter</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="MouseHighlighter.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="trace.h" />
|
||||||
|
<ClInclude Include="Generated Files\resource.h" />
|
||||||
|
<None Include="resource.base.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="MouseHighlighter.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="trace.cpp" />
|
||||||
|
<None Include="MouseHighlighter.base.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="Generated Files\MouseHighlighter.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||||
|
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
|
||||||
|
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||||
|
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="trace.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="dllmain.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="MouseHighlighter.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="trace.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Generated Files\resource.h">
|
||||||
|
<Filter>Generated Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="MouseHighlighter.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="MouseHighlighter.base.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="resource.base.h">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{b012a2c8-5ccb-47fc-9429-4ebf877928e2}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{c8345550-9836-40a0-b473-0f4bf6129568}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{7934ee5b-8427-486d-9324-73b6bcf60eed}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Generated Files">
|
||||||
|
<UniqueIdentifier>{e1083d6b-b856-42a6-bd1f-1710e96170ba}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="Generated Files\MouseHighlighter.rc">
|
||||||
|
<Filter>Generated Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
323
src/modules/MouseUtils/MouseHighlighter/dllmain.cpp
Normal file
323
src/modules/MouseUtils/MouseHighlighter/dllmain.cpp
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
#include "pch.h"
|
||||||
|
#include <interface/powertoy_module_interface.h>
|
||||||
|
#include <common/SettingsAPI/settings_objects.h>
|
||||||
|
#include "trace.h"
|
||||||
|
#include "MouseHighlighter.h"
|
||||||
|
|
||||||
|
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_LEFT_BUTTON_CLICK_COLOR[] = L"left_button_click_color";
|
||||||
|
const wchar_t JSON_KEY_RIGHT_BUTTON_CLICK_COLOR[] = L"right_button_click_color";
|
||||||
|
const wchar_t JSON_KEY_HIGHLIGHT_OPACITY[] = L"highlight_opacity";
|
||||||
|
const wchar_t JSON_KEY_HIGHLIGHT_RADIUS[] = L"highlight_radius";
|
||||||
|
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DELAY_MS[] = L"highlight_fade_delay_ms";
|
||||||
|
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DURATION_MS[] = L"highlight_fade_duration_ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
|
HMODULE m_hModule;
|
||||||
|
|
||||||
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||||
|
{
|
||||||
|
m_hModule = hModule;
|
||||||
|
switch (ul_reason_for_call)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
Trace::RegisterProvider();
|
||||||
|
break;
|
||||||
|
case DLL_THREAD_ATTACH:
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
Trace::UnregisterProvider();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The PowerToy name that will be shown in the settings.
|
||||||
|
const static wchar_t* MODULE_NAME = L"MouseHighlighter";
|
||||||
|
// 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 MouseHighlighter : public PowertoyModuleIface
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// The PowerToy state.
|
||||||
|
bool m_enabled = false;
|
||||||
|
|
||||||
|
// Hotkey to invoke the module
|
||||||
|
HotkeyEx m_hotkey;
|
||||||
|
|
||||||
|
// Mouse Highlighter specific settings
|
||||||
|
MouseHighlighterSettings m_highlightSettings;
|
||||||
|
|
||||||
|
// helper function to get the RGB from a #FFFFFF string.
|
||||||
|
bool checkValidRGB(std::wstring_view hex, uint8_t* R, uint8_t* G, uint8_t* B)
|
||||||
|
{
|
||||||
|
if (hex.length() != 7)
|
||||||
|
return false;
|
||||||
|
hex = hex.substr(1, 6); // remove #
|
||||||
|
for (auto& c : hex)
|
||||||
|
{
|
||||||
|
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (swscanf_s(hex.data(), L"%2hhx%2hhx%2hhx", R, G, B) != 3)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
MouseHighlighter()
|
||||||
|
{
|
||||||
|
LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mouseHighlighterLoggerName);
|
||||||
|
init_settings();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Destroy the powertoy and free memory
|
||||||
|
virtual void destroy() override
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the localized display name of the powertoy
|
||||||
|
virtual const wchar_t* get_name() override
|
||||||
|
{
|
||||||
|
return MODULE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the non localized key of the powertoy, this will be cached by the runner
|
||||||
|
virtual const wchar_t* get_key() override
|
||||||
|
{
|
||||||
|
return MODULE_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return JSON with the configuration options.
|
||||||
|
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||||
|
{
|
||||||
|
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||||
|
PowerToysSettings::Settings settings(hinstance, get_name());
|
||||||
|
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signal from the Settings editor to call a custom action.
|
||||||
|
// This can be used to spawn more complex editors.
|
||||||
|
virtual void call_custom_action(const wchar_t* action) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the runner to pass the updated settings values as a serialized JSON.
|
||||||
|
virtual void set_config(const wchar_t* config) override
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse the input JSON string.
|
||||||
|
PowerToysSettings::PowerToyValues values =
|
||||||
|
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||||
|
|
||||||
|
parse_settings(values);
|
||||||
|
|
||||||
|
MouseHighlighterApplySettings(m_highlightSettings);
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
Logger::error("Invalid json when trying to parse Mouse Highlighter settings json.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the powertoy
|
||||||
|
virtual void enable()
|
||||||
|
{
|
||||||
|
m_enabled = true;
|
||||||
|
Trace::EnableMouseHighlighter(true);
|
||||||
|
std::thread([=]() { MouseHighlighterMain(m_hModule, m_highlightSettings); }).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable the powertoy
|
||||||
|
virtual void disable()
|
||||||
|
{
|
||||||
|
m_enabled = false;
|
||||||
|
Trace::EnableMouseHighlighter(false);
|
||||||
|
MouseHighlighterDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns if the powertoys is enabled
|
||||||
|
virtual bool is_enabled() override
|
||||||
|
{
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::optional<HotkeyEx> GetHotkeyEx() override
|
||||||
|
{
|
||||||
|
return m_hotkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnHotkeyEx() override
|
||||||
|
{
|
||||||
|
MouseHighlighterSwitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the settings file.
|
||||||
|
void init_settings()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Load and parse the settings file for this PowerToy.
|
||||||
|
PowerToysSettings::PowerToyValues settings =
|
||||||
|
PowerToysSettings::PowerToyValues::load_from_settings_file(MouseHighlighter::get_key());
|
||||||
|
parse_settings(settings);
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
Logger::error("Invalid json when trying to load the Mouse Highlighter settings json from file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_settings(PowerToysSettings::PowerToyValues& settings)
|
||||||
|
{
|
||||||
|
// TODO: refactor to use common/utils/json.h instead
|
||||||
|
auto settingsObject = settings.get_raw_json();
|
||||||
|
MouseHighlighterSettings highlightSettings;
|
||||||
|
if (settingsObject.GetView().Size())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse HotKey
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
|
||||||
|
auto hotkey = PowerToysSettings::HotkeyObject::from_json(jsonPropertiesObject);
|
||||||
|
m_hotkey = HotkeyEx();
|
||||||
|
if (hotkey.win_pressed())
|
||||||
|
{
|
||||||
|
m_hotkey.modifiersMask |= MOD_WIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hotkey.ctrl_pressed())
|
||||||
|
{
|
||||||
|
m_hotkey.modifiersMask |= MOD_CONTROL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hotkey.shift_pressed())
|
||||||
|
{
|
||||||
|
m_hotkey.modifiersMask |= MOD_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hotkey.alt_pressed())
|
||||||
|
{
|
||||||
|
m_hotkey.modifiersMask |= MOD_ALT;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hotkey.vkCode = hotkey.get_code();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize Mouse Highlighter activation shortcut");
|
||||||
|
}
|
||||||
|
uint8_t opacity = MOUSE_HIGHLIGHTER_DEFAULT_OPACITY;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse Opacity
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_OPACITY);
|
||||||
|
opacity = (uint8_t)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize Opacity from settings. Will use default value");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse left button click color
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_LEFT_BUTTON_CLICK_COLOR);
|
||||||
|
auto leftColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
|
||||||
|
uint8_t r, g, b;
|
||||||
|
if (!checkValidRGB(leftColor,&r,&g,&b))
|
||||||
|
{
|
||||||
|
Logger::error("Left click color RGB value is invalid. Will use default value");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
highlightSettings.leftButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(opacity, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize left click color from settings. Will use default value");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse right button click color
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_RIGHT_BUTTON_CLICK_COLOR);
|
||||||
|
auto rightColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
|
||||||
|
uint8_t r, g, b;
|
||||||
|
if (!checkValidRGB(rightColor, &r, &g, &b))
|
||||||
|
{
|
||||||
|
Logger::error("Right click color RGB value is invalid. Will use default value");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
highlightSettings.rightButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(opacity, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize right click color from settings. Will use default value");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse Radius
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_RADIUS);
|
||||||
|
highlightSettings.radius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize Radius from settings. Will use default value");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse Fade Delay
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_FADE_DELAY_MS);
|
||||||
|
highlightSettings.fadeDelayMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize Fade Delay from settings. Will use default value");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Parse Fade Duration
|
||||||
|
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_FADE_DURATION_MS);
|
||||||
|
highlightSettings.fadeDurationMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Logger::warn("Failed to initialize Fade Duration from settings. Will use default value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::info("Mouse Highlighter settings are empty");
|
||||||
|
}
|
||||||
|
if (!m_hotkey.modifiersMask)
|
||||||
|
{
|
||||||
|
Logger::info("Mouse Highlighter is going to use default shortcut");
|
||||||
|
m_hotkey.modifiersMask = MOD_SHIFT | MOD_WIN;
|
||||||
|
m_hotkey.vkCode = 0x48; // H key
|
||||||
|
}
|
||||||
|
m_highlightSettings = highlightSettings;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||||
|
{
|
||||||
|
return new MouseHighlighter();
|
||||||
|
}
|
4
src/modules/MouseUtils/MouseHighlighter/packages.config
Normal file
4
src/modules/MouseUtils/MouseHighlighter/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||||
|
</packages>
|
1
src/modules/MouseUtils/MouseHighlighter/pch.cpp
Normal file
1
src/modules/MouseUtils/MouseHighlighter/pch.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "pch.h"
|
22
src/modules/MouseUtils/MouseHighlighter/pch.h
Normal file
22
src/modules/MouseUtils/MouseHighlighter/pch.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define COMPOSITION
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#include <hIdUsage.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#ifdef COMPOSITION
|
||||||
|
#include <windows.ui.composition.interop.h>
|
||||||
|
#include <DispatcherQueue.h>
|
||||||
|
#include <winrt/Windows.System.h>
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
#include <winrt/Windows.UI.Composition.Desktop.h>
|
||||||
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ProjectTelemetry.h>
|
||||||
|
#include <common/SettingsAPI/settings_helpers.h>
|
||||||
|
#include <common/logger/logger.h>
|
||||||
|
#include <common/utils/logger_helper.h>
|
14
src/modules/MouseUtils/MouseHighlighter/resource.base.h
Normal file
14
src/modules/MouseUtils/MouseHighlighter/resource.base.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by MouseHighlighter.rc
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Non-localizable
|
||||||
|
|
||||||
|
#define FILE_DESCRIPTION "PowerToys MouseHighlighter"
|
||||||
|
#define INTERNAL_NAME "MouseHighlighter"
|
||||||
|
#define ORIGINAL_FILENAME "MouseHighlighter.dll"
|
||||||
|
#define IDS_KEYBOARDMANAGER_ICON 1001
|
||||||
|
|
||||||
|
// Non-localizable
|
||||||
|
//////////////////////////////
|
40
src/modules/MouseUtils/MouseHighlighter/trace.cpp
Normal file
40
src/modules/MouseUtils/MouseHighlighter/trace.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include "pch.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
TRACELOGGING_DEFINE_PROVIDER(
|
||||||
|
g_hProvider,
|
||||||
|
"Microsoft.PowerToys",
|
||||||
|
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||||
|
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||||
|
TraceLoggingOptionProjectTelemetry());
|
||||||
|
|
||||||
|
void Trace::RegisterProvider() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingRegister(g_hProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Trace::UnregisterProvider() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingUnregister(g_hProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log if the user has MouseHighlighter enabled or disabled
|
||||||
|
void Trace::EnableMouseHighlighter(const bool enabled) noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hProvider,
|
||||||
|
"MouseHighlighter_EnableMouseHighlighter",
|
||||||
|
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||||
|
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||||
|
TraceLoggingBoolean(enabled, "Enabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log that the user activated the module by starting a highlighting session
|
||||||
|
void Trace::StartHighlightingSession() noexcept
|
||||||
|
{
|
||||||
|
TraceLoggingWrite(
|
||||||
|
g_hProvider,
|
||||||
|
"MouseHighlighter_StartHighlightingSession",
|
||||||
|
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||||
|
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||||
|
}
|
14
src/modules/MouseUtils/MouseHighlighter/trace.h
Normal file
14
src/modules/MouseUtils/MouseHighlighter/trace.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Trace
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void RegisterProvider() noexcept;
|
||||||
|
static void UnregisterProvider() noexcept;
|
||||||
|
|
||||||
|
// Log if the user has MouseHighlighter enabled or disabled
|
||||||
|
static void EnableMouseHighlighter(const bool enabled) noexcept;
|
||||||
|
|
||||||
|
// Log that the user activated the module by starting a highlighting session
|
||||||
|
static void StartHighlightingSession() noexcept;
|
||||||
|
};
|
|
@ -148,7 +148,8 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||||
L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll",
|
L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll",
|
||||||
L"modules/ColorPicker/ColorPicker.dll",
|
L"modules/ColorPicker/ColorPicker.dll",
|
||||||
L"modules/Awake/AwakeModuleInterface.dll",
|
L"modules/Awake/AwakeModuleInterface.dll",
|
||||||
L"modules/MouseUtils/FindMyMouse.dll"
|
L"modules/MouseUtils/FindMyMouse.dll" ,
|
||||||
|
L"modules/MouseUtils/MouseHighlighter.dll"
|
||||||
|
|
||||||
};
|
};
|
||||||
const auto VCM_PATH = L"modules/VideoConference/VideoConferenceModule.dll";
|
const auto VCM_PATH = L"modules/VideoConference/VideoConferenceModule.dll";
|
||||||
|
|
|
@ -191,6 +191,22 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool mouseHighlighter = true;
|
||||||
|
|
||||||
|
[JsonPropertyName("MouseHighlighter")]
|
||||||
|
public bool MouseHighlighter
|
||||||
|
{
|
||||||
|
get => mouseHighlighter;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (mouseHighlighter != value)
|
||||||
|
{
|
||||||
|
LogTelemetryEvent(value);
|
||||||
|
mouseHighlighter = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string ToJsonString()
|
public string ToJsonString()
|
||||||
{
|
{
|
||||||
return JsonSerializer.Serialize(this);
|
return JsonSerializer.Serialize(this);
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
|
||||||
|
{
|
||||||
|
public static class SettingsUtilities
|
||||||
|
{
|
||||||
|
public static string ToRGBHex(string color)
|
||||||
|
{
|
||||||
|
if (color == null)
|
||||||
|
{
|
||||||
|
return "#FFFFFF";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using InvariantCulture as these are expected to be hex codes.
|
||||||
|
bool success = int.TryParse(
|
||||||
|
color.Replace("#", string.Empty),
|
||||||
|
System.Globalization.NumberStyles.HexNumber,
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
out int argb);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Color clr = Color.FromArgb(argb);
|
||||||
|
return "#" + clr.R.ToString("X2", CultureInfo.InvariantCulture) +
|
||||||
|
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
|
||||||
|
clr.B.ToString("X2", CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "#FFFFFF";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
{
|
||||||
|
public class MouseHighlighterProperties
|
||||||
|
{
|
||||||
|
[JsonPropertyName("activation_shortcut")]
|
||||||
|
public HotkeySettings ActivationShortcut { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("left_button_click_color")]
|
||||||
|
public StringProperty LeftButtonClickColor { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("right_button_click_color")]
|
||||||
|
public StringProperty RightButtonClickColor { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("highlight_opacity")]
|
||||||
|
public IntProperty HighlightOpacity { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("highlight_radius")]
|
||||||
|
public IntProperty HighlightRadius { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("highlight_fade_delay_ms")]
|
||||||
|
public IntProperty HighlightFadeDelayMs { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("highlight_fade_duration_ms")]
|
||||||
|
public IntProperty HighlightFadeDurationMs { get; set; }
|
||||||
|
|
||||||
|
public MouseHighlighterProperties()
|
||||||
|
{
|
||||||
|
ActivationShortcut = new HotkeySettings(true, false, false, true, 0x48);
|
||||||
|
LeftButtonClickColor = new StringProperty("#FFFF00");
|
||||||
|
RightButtonClickColor = new StringProperty("#0000FF");
|
||||||
|
HighlightOpacity = new IntProperty(160);
|
||||||
|
HighlightRadius = new IntProperty(20);
|
||||||
|
HighlightFadeDelayMs = new IntProperty(500);
|
||||||
|
HighlightFadeDurationMs = new IntProperty(250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
{
|
||||||
|
public class MouseHighlighterSettings : BasePTModuleSettings, ISettingsConfig
|
||||||
|
{
|
||||||
|
public const string ModuleName = "MouseHighlighter";
|
||||||
|
|
||||||
|
[JsonPropertyName("properties")]
|
||||||
|
public MouseHighlighterProperties Properties { get; set; }
|
||||||
|
|
||||||
|
public MouseHighlighterSettings()
|
||||||
|
{
|
||||||
|
Name = ModuleName;
|
||||||
|
Properties = new MouseHighlighterProperties();
|
||||||
|
Version = "1.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetModuleName()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This can be utilized in the future if the settings.json file is to be modified/deleted.
|
||||||
|
public bool UpgradeSettingsConfiguration()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
{
|
||||||
|
public class MouseHighlighterSettingsIPCMessage
|
||||||
|
{
|
||||||
|
[JsonPropertyName("powertoys")]
|
||||||
|
public SndMouseHighlighterSettings Powertoys { get; set; }
|
||||||
|
|
||||||
|
public MouseHighlighterSettingsIPCMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MouseHighlighterSettingsIPCMessage(SndMouseHighlighterSettings settings)
|
||||||
|
{
|
||||||
|
this.Powertoys = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToJsonString()
|
||||||
|
{
|
||||||
|
return JsonSerializer.Serialize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
{
|
||||||
|
public class SndMouseHighlighterSettings
|
||||||
|
{
|
||||||
|
[JsonPropertyName("MouseHighlighter")]
|
||||||
|
public MouseHighlighterSettings MouseHighlighter { get; set; }
|
||||||
|
|
||||||
|
public SndMouseHighlighterSettings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SndMouseHighlighterSettings(MouseHighlighterSettings settings)
|
||||||
|
{
|
||||||
|
MouseHighlighter = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToJsonString()
|
||||||
|
{
|
||||||
|
return JsonSerializer.Serialize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -554,7 +554,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
// The fallback value is based on ToRGBHex's behavior, which returns
|
// The fallback value is based on ToRGBHex's behavior, which returns
|
||||||
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
||||||
// This extra handling is added here to deal with FxCop warnings.
|
// This extra handling is added here to deal with FxCop warnings.
|
||||||
value = (value != null) ? ToRGBHex(value) : "#FFFFFF";
|
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
|
||||||
if (!value.Equals(_zoneHighlightColor, StringComparison.OrdinalIgnoreCase))
|
if (!value.Equals(_zoneHighlightColor, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_zoneHighlightColor = value;
|
_zoneHighlightColor = value;
|
||||||
|
@ -576,7 +576,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
// The fallback value is based on ToRGBHex's behavior, which returns
|
// The fallback value is based on ToRGBHex's behavior, which returns
|
||||||
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
||||||
// This extra handling is added here to deal with FxCop warnings.
|
// This extra handling is added here to deal with FxCop warnings.
|
||||||
value = (value != null) ? ToRGBHex(value) : "#FFFFFF";
|
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
|
||||||
if (!value.Equals(_zoneBorderColor, StringComparison.OrdinalIgnoreCase))
|
if (!value.Equals(_zoneBorderColor, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_zoneBorderColor = value;
|
_zoneBorderColor = value;
|
||||||
|
@ -598,7 +598,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
// The fallback value is based on ToRGBHex's behavior, which returns
|
// The fallback value is based on ToRGBHex's behavior, which returns
|
||||||
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
||||||
// This extra handling is added here to deal with FxCop warnings.
|
// This extra handling is added here to deal with FxCop warnings.
|
||||||
value = (value != null) ? ToRGBHex(value) : "#FFFFFF";
|
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
|
||||||
if (!value.Equals(_zoneInActiveColor, StringComparison.OrdinalIgnoreCase))
|
if (!value.Equals(_zoneInActiveColor, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_zoneInActiveColor = value;
|
_zoneInActiveColor = value;
|
||||||
|
@ -753,27 +753,5 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
OnPropertyChanged(propertyName);
|
OnPropertyChanged(propertyName);
|
||||||
SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath());
|
SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ToRGBHex(string color)
|
|
||||||
{
|
|
||||||
// Using InvariantCulture as these are expected to be hex codes.
|
|
||||||
bool success = int.TryParse(
|
|
||||||
color.Replace("#", string.Empty),
|
|
||||||
System.Globalization.NumberStyles.HexNumber,
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
out int argb);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
Color clr = Color.FromArgb(argb);
|
|
||||||
return "#" + clr.R.ToString("X2", CultureInfo.InvariantCulture) +
|
|
||||||
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
|
|
||||||
clr.B.ToString("X2", CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "#FFFFFF";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
|
|
||||||
private FindMyMouseSettings FindMyMouseSettingsConfig { get; set; }
|
private FindMyMouseSettings FindMyMouseSettingsConfig { get; set; }
|
||||||
|
|
||||||
public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
|
private MouseHighlighterSettings MouseHighlighterSettingsConfig { get; set; }
|
||||||
|
|
||||||
|
public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, ISettingsRepository<MouseHighlighterSettings> mouseHighlighterSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
|
||||||
{
|
{
|
||||||
SettingsUtils = settingsUtils;
|
SettingsUtils = settingsUtils;
|
||||||
|
|
||||||
|
@ -31,6 +33,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
|
|
||||||
_isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse;
|
_isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse;
|
||||||
|
|
||||||
|
_isMouseHighlighterEnabled = GeneralSettingsConfig.Enabled.MouseHighlighter;
|
||||||
|
|
||||||
// To obtain the find my mouse settings, if the file exists.
|
// To obtain the find my mouse settings, if the file exists.
|
||||||
// If not, to create a file with the default settings and to return the default configurations.
|
// If not, to create a file with the default settings and to return the default configurations.
|
||||||
if (findMyMouseSettingsRepository == null)
|
if (findMyMouseSettingsRepository == null)
|
||||||
|
@ -41,6 +45,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
|
FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
|
||||||
_findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value;
|
_findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value;
|
||||||
|
|
||||||
|
if (mouseHighlighterSettingsRepository == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(mouseHighlighterSettingsRepository));
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseHighlighterSettingsConfig = mouseHighlighterSettingsRepository.SettingsConfig;
|
||||||
|
string leftClickColor = MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value;
|
||||||
|
_highlighterLeftButtonClickColor = !string.IsNullOrEmpty(leftClickColor) ? leftClickColor : "#FFFF00";
|
||||||
|
|
||||||
|
string rightClickColor = MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value;
|
||||||
|
_highlighterRightButtonClickColor = !string.IsNullOrEmpty(rightClickColor) ? rightClickColor : "#0000FF";
|
||||||
|
|
||||||
|
_highlighterOpacity = MouseHighlighterSettingsConfig.Properties.HighlightOpacity.Value;
|
||||||
|
_highlighterRadius = MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value;
|
||||||
|
_highlightFadeDelayMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value;
|
||||||
|
_highlightFadeDurationMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value;
|
||||||
|
|
||||||
// set the callback functions value to handle outgoing IPC message.
|
// set the callback functions value to handle outgoing IPC message.
|
||||||
SendConfigMSG = ipcMSGCallBackFunc;
|
SendConfigMSG = ipcMSGCallBackFunc;
|
||||||
}
|
}
|
||||||
|
@ -93,9 +114,180 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||||
SettingsUtils.SaveSettings(FindMyMouseSettingsConfig.ToJsonString(), FindMyMouseSettings.ModuleName);
|
SettingsUtils.SaveSettings(FindMyMouseSettingsConfig.ToJsonString(), FindMyMouseSettings.ModuleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsMouseHighlighterEnabled
|
||||||
|
{
|
||||||
|
get => _isMouseHighlighterEnabled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_isMouseHighlighterEnabled != value)
|
||||||
|
{
|
||||||
|
_isMouseHighlighterEnabled = value;
|
||||||
|
|
||||||
|
GeneralSettingsConfig.Enabled.MouseHighlighter = value;
|
||||||
|
OnPropertyChanged(nameof(_isMouseHighlighterEnabled));
|
||||||
|
|
||||||
|
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||||
|
SendConfigMSG(outgoing.ToString());
|
||||||
|
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HotkeySettings MouseHighlighterActivationShortcut
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return MouseHighlighterSettingsConfig.Properties.ActivationShortcut;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (MouseHighlighterSettingsConfig.Properties.ActivationShortcut != value)
|
||||||
|
{
|
||||||
|
MouseHighlighterSettingsConfig.Properties.ActivationShortcut = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MouseHighlighterLeftButtonClickColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _highlighterLeftButtonClickColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// The fallback value is based on ToRGBHex's behavior, which returns
|
||||||
|
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
||||||
|
// This extra handling is added here to deal with FxCop warnings.
|
||||||
|
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
|
||||||
|
if (!value.Equals(_highlighterLeftButtonClickColor, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_highlighterLeftButtonClickColor = value;
|
||||||
|
MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MouseHighlighterRightButtonClickColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _highlighterRightButtonClickColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// The fallback value is based on ToRGBHex's behavior, which returns
|
||||||
|
// #FFFFFF if any exceptions are encountered, e.g. from passing in a null value.
|
||||||
|
// This extra handling is added here to deal with FxCop warnings.
|
||||||
|
value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
|
||||||
|
if (!value.Equals(_highlighterRightButtonClickColor, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
_highlighterRightButtonClickColor = value;
|
||||||
|
MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MouseHighlighterOpacity
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _highlighterOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _highlighterOpacity)
|
||||||
|
{
|
||||||
|
_highlighterOpacity = value;
|
||||||
|
MouseHighlighterSettingsConfig.Properties.HighlightOpacity.Value = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MouseHighlighterRadius
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _highlighterRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _highlighterRadius)
|
||||||
|
{
|
||||||
|
_highlighterRadius = value;
|
||||||
|
MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MouseHighlighterFadeDelayMs
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _highlightFadeDelayMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _highlightFadeDelayMs)
|
||||||
|
{
|
||||||
|
_highlightFadeDelayMs = value;
|
||||||
|
MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MouseHighlighterFadeDurationMs
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _highlightFadeDurationMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _highlightFadeDurationMs)
|
||||||
|
{
|
||||||
|
_highlightFadeDurationMs = value;
|
||||||
|
MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value = value;
|
||||||
|
NotifyMouseHighlighterPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NotifyMouseHighlighterPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
|
||||||
|
SndMouseHighlighterSettings outsettings = new SndMouseHighlighterSettings(MouseHighlighterSettingsConfig);
|
||||||
|
SndModuleSettings<SndMouseHighlighterSettings> ipcMessage = new SndModuleSettings<SndMouseHighlighterSettings>(outsettings);
|
||||||
|
SendConfigMSG(ipcMessage.ToJsonString());
|
||||||
|
SettingsUtils.SaveSettings(MouseHighlighterSettingsConfig.ToJsonString(), MouseHighlighterSettings.ModuleName);
|
||||||
|
}
|
||||||
|
|
||||||
private Func<string, int> SendConfigMSG { get; }
|
private Func<string, int> SendConfigMSG { get; }
|
||||||
|
|
||||||
private bool _isFindMyMouseEnabled;
|
private bool _isFindMyMouseEnabled;
|
||||||
private bool _findMyMouseDoNotActivateOnGameMode;
|
private bool _findMyMouseDoNotActivateOnGameMode;
|
||||||
|
|
||||||
|
private bool _isMouseHighlighterEnabled;
|
||||||
|
private string _highlighterLeftButtonClickColor;
|
||||||
|
private string _highlighterRightButtonClickColor;
|
||||||
|
private int _highlighterOpacity;
|
||||||
|
private int _highlighterRadius;
|
||||||
|
private int _highlightFadeDelayMs;
|
||||||
|
private int _highlightFadeDurationMs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
|
@ -237,8 +237,11 @@
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsAwake.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsAwake.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsFancyZones.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsFancyZones.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsFileExplorerPreview.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsFileExplorerPreview.png" />
|
||||||
|
<Content Include="Assets\FluentIcons\FluentIconsFindMyMouse.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsImageResizer.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsImageResizer.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsKeyboardManager.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsKeyboardManager.png" />
|
||||||
|
<Content Include="Assets\FluentIcons\FluentIconsMouseHighlighter.png" />
|
||||||
|
<Content Include="Assets\FluentIcons\FluentIconsMouseHighlighter.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsMouseUtils.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsMouseUtils.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsPowerRename.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsPowerRename.png" />
|
||||||
<Content Include="Assets\FluentIcons\FluentIconsPowerToys.png" />
|
<Content Include="Assets\FluentIcons\FluentIconsPowerToys.png" />
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
Style="{ThemeResource OobeSubtitleStyle}" />
|
Style="{ThemeResource OobeSubtitleStyle}" />
|
||||||
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_MouseUtils_FindMyMouse_Description" />
|
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_MouseUtils_FindMyMouse_Description" />
|
||||||
|
|
||||||
|
<TextBlock x:Uid="Oobe_MouseUtils_MouseHighlighter"
|
||||||
|
Style="{ThemeResource OobeSubtitleStyle}" />
|
||||||
|
<toolkitcontrols:MarkdownTextBlock Background="Transparent" x:Uid="Oobe_MouseUtils_MouseHighlighter_Description" />
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
|
<StackPanel Orientation="Horizontal" Spacing="12" Margin="0,24,0,0">
|
||||||
<Button x:Uid="OOBE_Settings"
|
<Button x:Uid="OOBE_Settings"
|
||||||
Click="SettingsLaunchButton_Click"/>
|
Click="SettingsLaunchButton_Click"/>
|
||||||
|
|
|
@ -655,11 +655,11 @@
|
||||||
<value>Shows a help overlay with Windows shortcuts.</value>
|
<value>Shows a help overlay with Windows shortcuts.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShortcutGuide_PressTime.Header" xml:space="preserve">
|
<data name="ShortcutGuide_PressTime.Header" xml:space="preserve">
|
||||||
<value>Press duration before showing (ms)</value>
|
<value>Press duration before showing</value>
|
||||||
<comment>pressing a key in milliseconds</comment>
|
<comment>pressing a key in milliseconds</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShortcutGuide_PressTime.Description" xml:space="preserve">
|
<data name="ShortcutGuide_PressTime.Description" xml:space="preserve">
|
||||||
<value>How long to press the Windows key to activate the module</value>
|
<value>How long to press the Windows key to activate the module (in ms)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShortcutGuide_ActivationMethod.Header" xml:space="preserve">
|
<data name="ShortcutGuide_ActivationMethod.Header" xml:space="preserve">
|
||||||
<value>Activation method</value>
|
<value>Activation method</value>
|
||||||
|
@ -1247,7 +1247,7 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||||
<value>Activation shortcut</value>
|
<value>Activation shortcut</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Activation_Shortcut.Description" xml:space="preserve">
|
<data name="Activation_Shortcut.Description" xml:space="preserve">
|
||||||
<value>Customize the keyboard shortcut to activate this module</value>
|
<value>Customize the shortcut to activate this module</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Oobe_GetStarted.Text" xml:space="preserve">
|
<data name="Oobe_GetStarted.Text" xml:space="preserve">
|
||||||
<value>Let's get started!</value>
|
<value>Let's get started!</value>
|
||||||
|
@ -1627,9 +1627,17 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex
|
||||||
<comment>Mouse as in the hardware peripheral</comment>
|
<comment>Mouse as in the hardware peripheral</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Oobe_MouseUtils_FindMyMouse_Description.Text" xml:space="preserve">
|
<data name="Oobe_MouseUtils_FindMyMouse_Description.Text" xml:space="preserve">
|
||||||
<value>Click twice on the Left Control key to focus on your mouse.</value>
|
<value>Press the left Ctrl key twice to focus the mouse pointer.</value>
|
||||||
<comment>Mouse as in the hardware peripheral. Key as in a keyboard key</comment>
|
<comment>Mouse as in the hardware peripheral. Key as in a keyboard key</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Oobe_MouseUtils_MouseHighlighter.Text" xml:space="preserve">
|
||||||
|
<value>Mouse Highlighter</value>
|
||||||
|
<comment>Mouse as in the hardware peripheral.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Oobe_MouseUtils_MouseHighlighter_Description.Text" xml:space="preserve">
|
||||||
|
<value>Use a keyboard shortcut highlight left and right mouse clicks.</value>
|
||||||
|
<comment>Mouse as in the hardware peripheral.</comment>
|
||||||
|
</data>
|
||||||
<data name="Launch_Run.Content" xml:space="preserve">
|
<data name="Launch_Run.Content" xml:space="preserve">
|
||||||
<value>Launch PowerToys Run</value>
|
<value>Launch PowerToys Run</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -1709,18 +1717,67 @@ From there, simply click on a Markdown file, PDF file or SVG icon in the File Ex
|
||||||
<data name="MouseUtils.ModuleDescription" xml:space="preserve">
|
<data name="MouseUtils.ModuleDescription" xml:space="preserve">
|
||||||
<value>A collection of mouse utilities.</value>
|
<value>A collection of mouse utilities.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MouseUtils_FindMyMouse.Header" xml:space="preserve">
|
||||||
|
<value>Find My Mouse</value>
|
||||||
|
<comment>Refers to the utility name</comment>
|
||||||
|
</data>
|
||||||
<data name="MouseUtils_Enable_FindMyMouse.Header" xml:space="preserve">
|
<data name="MouseUtils_Enable_FindMyMouse.Header" xml:space="preserve">
|
||||||
<value>Enable Find My Mouse</value>
|
<value>Enable Find My Mouse</value>
|
||||||
<comment>"Find My Mouse" is the name of the utility.</comment>
|
<comment>"Find My Mouse" is the name of the utility.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MouseUtils_Enable_FindMyMouse.Description" xml:space="preserve">
|
<data name="MouseUtils_FindMyMouse_Description.Text" xml:space="preserve">
|
||||||
<value>Press the Left Control key twice to focus the mouse pointer.</value>
|
<value>Find My Mouse highlights the position of the cursor when pressing the left Ctrl key twice.</value>
|
||||||
<comment>"Left Control" is a keyboard key.</comment>
|
<comment>"Ctrl" is a keyboard key. "Find My Mouse" is the name of the utility</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="MouseUtils_Prevent_Activation_On_Game_Mode.Content" xml:space="preserve">
|
<data name="MouseUtils_Prevent_Activation_On_Game_Mode.Content" xml:space="preserve">
|
||||||
<value>Do not activate when Game Mode is on</value>
|
<value>Do not activate when Game Mode is on</value>
|
||||||
<comment>"Game mode" is the Windows feature to prevent notification when playing a game.</comment>
|
<comment>"Game mode" is the Windows feature to prevent notification when playing a game.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter.Header" xml:space="preserve">
|
||||||
|
<value>Mouse Highlighter</value>
|
||||||
|
<comment>Refers to the utility name</comment>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_Enable_MouseHighlighter.Header" xml:space="preserve">
|
||||||
|
<value>Enable Mouse Highlighter</value>
|
||||||
|
<comment>"Find My Mouse" is the name of the utility.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_Description.Text" xml:space="preserve">
|
||||||
|
<value>Mouse Highlighter mode will highlight mouse clicks.</value>
|
||||||
|
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<data name="MouseUtils_MouseHighlighter_ActivationShortcut.Header" xml:space="preserve">
|
||||||
|
<value>Activation shortcut</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_ActivationShortcut.Description" xml:space="preserve">
|
||||||
|
<value>Customize the shortcut to turn on or off this mode</value>
|
||||||
|
<comment>"Mouse Highlighter" is the name of the utility. Mouse is the hardware mouse.</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<data name="MouseUtils_MouseHighlighter_LeftButtonClickColor.Header" xml:space="preserve">
|
||||||
|
<value>Left button highlight color</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_RightButtonClickColor.Header" xml:space="preserve">
|
||||||
|
<value>Right button highlight color</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_HighlightOpacity.Header" xml:space="preserve">
|
||||||
|
<value>Opacity</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_HighlightRadius.Header" xml:space="preserve">
|
||||||
|
<value>Radius</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_FadeDelayMs.Header" xml:space="preserve">
|
||||||
|
<value>Fade delay</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_FadeDelayMs.Description" xml:space="preserve">
|
||||||
|
<value>How long it takes before a highlight starts to disappear (in ms)</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_FadeDurationMs.Header" xml:space="preserve">
|
||||||
|
<value>Fade duration</value>
|
||||||
|
</data>
|
||||||
|
<data name="MouseUtils_MouseHighlighter_FadeDurationMs.Description" xml:space="preserve">
|
||||||
|
<value>Duration of the disappear animation (in ms)</value>
|
||||||
|
</data>
|
||||||
<data name="FancyZones_Radio_Custom_Colors.Content" xml:space="preserve">
|
<data name="FancyZones_Radio_Custom_Colors.Content" xml:space="preserve">
|
||||||
<value>Custom colors</value>
|
<value>Custom colors</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -13,22 +13,117 @@
|
||||||
ModuleImageSource="ms-appx:///Assets/Modules/MouseUtils.png">
|
ModuleImageSource="ms-appx:///Assets/Modules/MouseUtils.png">
|
||||||
<controls:SettingsPageControl.ModuleContent>
|
<controls:SettingsPageControl.ModuleContent>
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
|
<controls:SettingsGroup x:Uid="MouseUtils_FindMyMouse">
|
||||||
|
<TextBlock x:Uid="MouseUtils_FindMyMouse_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||||
|
<controls:SettingExpander IsExpanded="True">
|
||||||
|
<controls:SettingExpander.Header>
|
||||||
|
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse">
|
||||||
|
<controls:Setting.Icon>
|
||||||
|
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsFindMyMouse.png" ShowAsMonochrome="False" />
|
||||||
|
</controls:Setting.Icon>
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
</controls:SettingExpander.Header>
|
||||||
|
<controls:SettingExpander.Content>
|
||||||
|
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
|
||||||
|
IsChecked="{x:Bind ViewModel.FindMyMouseDoNotActivateOnGameMode, Mode=TwoWay}"
|
||||||
|
Margin="{StaticResource ExpanderSettingMargin}"
|
||||||
|
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" />
|
||||||
|
</controls:SettingExpander.Content>
|
||||||
|
</controls:SettingExpander>
|
||||||
|
</controls:SettingsGroup>
|
||||||
|
<controls:SettingsGroup x:Uid="MouseUtils_MouseHighlighter">
|
||||||
|
<TextBlock x:Uid="MouseUtils_MouseHighlighter_Description" Margin="0,0,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
|
||||||
|
<controls:Setting x:Uid="MouseUtils_Enable_MouseHighlighter">
|
||||||
|
<controls:Setting.Icon>
|
||||||
|
<BitmapIcon UriSource="ms-appx:///Assets/FluentIcons/FluentIconsMouseHighlighter.png" ShowAsMonochrome="False" />
|
||||||
|
</controls:Setting.Icon>
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<ToggleSwitch IsOn="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
|
||||||
<controls:SettingExpander IsExpanded="True">
|
|
||||||
<controls:SettingExpander.Header>
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_ActivationShortcut" Icon="" IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}">
|
||||||
<controls:Setting x:Uid="MouseUtils_Enable_FindMyMouse" Icon="">
|
<controls:Setting.ActionContent>
|
||||||
<controls:Setting.ActionContent>
|
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.MouseHighlighterActivationShortcut, Mode=TwoWay}"
|
||||||
<ToggleSwitch IsOn="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=TwoWay}" HorizontalAlignment="Right"/>
|
MinWidth="{StaticResource SettingActionControlMinWidth}"/>
|
||||||
</controls:Setting.ActionContent>
|
</controls:Setting.ActionContent>
|
||||||
</controls:Setting>
|
</controls:Setting>
|
||||||
</controls:SettingExpander.Header>
|
|
||||||
<controls:SettingExpander.Content>
|
<controls:SettingExpander IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}" IsExpanded="True" >
|
||||||
<CheckBox x:Uid="MouseUtils_Prevent_Activation_On_Game_Mode"
|
<controls:SettingExpander.Header>
|
||||||
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.FindMyMouseDoNotActivateOnGameMode}"
|
<controls:Setting x:Uid="ShortcutGuide_Appearance_Behavior" Icon="" />
|
||||||
Margin="{StaticResource ExpanderSettingMargin}"
|
</controls:SettingExpander.Header>
|
||||||
IsEnabled="{x:Bind ViewModel.IsFindMyMouseEnabled, Mode=OneWay}" />
|
|
||||||
</controls:SettingExpander.Content>
|
|
||||||
</controls:SettingExpander>
|
<controls:SettingExpander.Content>
|
||||||
|
|
||||||
|
<StackPanel>
|
||||||
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_LeftButtonClickColor" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsMouseHighlighterEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterLeftButtonClickColor, Mode=TwoWay}" />
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
|
||||||
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_RightButtonClickColor" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsMouseHighlighterEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterRightButtonClickColor, Mode=TwoWay}" />
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
|
||||||
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_HighlightOpacity" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsMouseHighlighterEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<Slider Minimum="0"
|
||||||
|
Maximum="255"
|
||||||
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
|
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MouseHighlighterOpacity}"
|
||||||
|
HorizontalAlignment="Right"/>
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
|
||||||
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_HighlightRadius" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsMouseHighlighterEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<muxc:NumberBox Minimum="5"
|
||||||
|
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MouseHighlighterRadius}"
|
||||||
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
|
SpinButtonPlacementMode="Compact"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
SmallChange="1"
|
||||||
|
LargeChange="10"/>
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
|
||||||
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_FadeDelayMs" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsMouseHighlighterEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<muxc:NumberBox Minimum="100"
|
||||||
|
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MouseHighlighterFadeDelayMs}"
|
||||||
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
|
SpinButtonPlacementMode="Compact"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
SmallChange="10"
|
||||||
|
LargeChange="100"/>
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
|
||||||
|
<controls:Setting x:Uid="MouseUtils_MouseHighlighter_FadeDurationMs" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsMouseHighlighterEnabled}" Style="{StaticResource ExpanderContentSettingStyle}">
|
||||||
|
<controls:Setting.ActionContent>
|
||||||
|
<muxc:NumberBox Minimum="100"
|
||||||
|
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MouseHighlighterFadeDurationMs}"
|
||||||
|
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||||
|
SpinButtonPlacementMode="Compact"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
SmallChange="10"
|
||||||
|
LargeChange="100"/>
|
||||||
|
</controls:Setting.ActionContent>
|
||||||
|
</controls:Setting>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:SettingExpander.Content>
|
||||||
|
</controls:SettingExpander>
|
||||||
|
</controls:SettingsGroup>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</controls:SettingsPageControl.ModuleContent>
|
</controls:SettingsPageControl.ModuleContent>
|
||||||
<controls:SettingsPageControl.PrimaryLinks>
|
<controls:SettingsPageControl.PrimaryLinks>
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||||
public MouseUtilsPage()
|
public MouseUtilsPage()
|
||||||
{
|
{
|
||||||
var settingsUtils = new SettingsUtils();
|
var settingsUtils = new SettingsUtils();
|
||||||
ViewModel = new MouseUtilsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<FindMyMouseSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
|
ViewModel = new MouseUtilsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<FindMyMouseSettings>.GetInstance(settingsUtils), SettingsRepository<MouseHighlighterSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
|
||||||
DataContext = ViewModel;
|
DataContext = ViewModel;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue