[FancyZones] Clasify strings in FancyZones to localizable and non-localizable (#5315)

* Clasify strings in FancyZones to localizable and non-localizable

* Address PR comments

* Better handling of FirePropertyChanged event

* Address PR comments

* Update properties
This commit is contained in:
vldmr11080 2020-08-11 13:51:06 +02:00 committed by GitHub
parent b8b6dbe791
commit 145347f7ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 362 additions and 190 deletions

View File

@ -82,7 +82,10 @@ public:
s_llKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), NULL);
if (!s_llKeyboardHook)
{
MessageBoxW(NULL, L"Cannot install keyboard listener.", L"PowerToys - FancyZones", MB_OK | MB_ICONERROR);
MessageBoxW(NULL,
GET_RESOURCE_STRING(IDS_KEYBOARD_LISTENER_ERROR).c_str(),
GET_RESOURCE_STRING(IDS_POWERTOYS_FANCYZONES).c_str(),
MB_OK | MB_ICONERROR);
}
}
@ -103,7 +106,10 @@ public:
}
else
{
MessageBoxW(NULL, L"Cannot install Windows event listener.", L"PowerToys - FancyZones", MB_OK | MB_ICONERROR);
MessageBoxW(NULL,
GET_RESOURCE_STRING(IDS_WINDOW_EVENT_LISTENER_ERROR).c_str(),
GET_RESOURCE_STRING(IDS_POWERTOYS_FANCYZONES).c_str(),
MB_OK | MB_ICONERROR);
}
}

View File

@ -13,6 +13,9 @@ namespace FancyZonesEditor
/// </summary>
public partial class CanvasEditor : UserControl
{
// Non-localizable strings
private const string PropertyUpdateLayoutID = "UpdateLayout";
private CanvasLayoutModel _model;
public CanvasEditor()
@ -35,7 +38,7 @@ namespace FancyZonesEditor
private void OnModelChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Zones")
if (e.PropertyName == PropertyUpdateLayoutID)
{
UpdateZoneRects();
}

View File

@ -16,7 +16,12 @@ namespace FancyZonesEditor
/// </summary>
public partial class GridEditor : UserControl
{
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register("Model", typeof(GridLayoutModel), typeof(GridEditor), new PropertyMetadata(null, OnGridDimensionsChanged));
// Non-localizable strings
private const string PropertyRowsChangedID = "Rows";
private const string PropertyColumnsChangedID = "Columns";
private const string ObjectDependencyID = "Model";
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register(ObjectDependencyID, typeof(GridLayoutModel), typeof(GridEditor), new PropertyMetadata(null, OnGridDimensionsChanged));
private static int gridEditorUniqueIdCounter = 0;
@ -336,7 +341,7 @@ namespace FancyZonesEditor
private void OnGridDimensionsChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
// Only enter if this is the newest instance
if (((e.PropertyName == "Rows") || (e.PropertyName == "Columns")) && gridEditorUniqueId == gridEditorUniqueIdCounter)
if (((e.PropertyName == PropertyRowsChangedID) || (e.PropertyName == PropertyColumnsChangedID)) && gridEditorUniqueId == gridEditorUniqueIdCounter)
{
OnGridDimensionsChanged();
}

View File

@ -17,7 +17,12 @@ namespace FancyZonesEditor
/// </summary>
public partial class GridZone : UserControl
{
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(GridZone), new PropertyMetadata(false, OnSelectionChanged));
// Non-localizable strings
private const string ObjectDependencyID = "IsSelected";
private const string GridZoneBackgroundBrushID = "GridZoneBackgroundBrush";
private const string PropertyIsShiftKeyPressedID = "IsShiftKeyPressed";
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(ObjectDependencyID, typeof(bool), typeof(GridZone), new PropertyMetadata(false, OnSelectionChanged));
public event SplitEventHandler Split;
@ -45,7 +50,7 @@ namespace FancyZonesEditor
private void OnSelectionChanged()
{
Background = IsSelected ? SystemParameters.WindowGlassBrush : App.Current.Resources["GridZoneBackgroundBrush"] as SolidColorBrush;
Background = IsSelected ? SystemParameters.WindowGlassBrush : App.Current.Resources[GridZoneBackgroundBrushID] as SolidColorBrush;
}
public bool IsSelected
@ -69,7 +74,7 @@ namespace FancyZonesEditor
private void ZoneSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsShiftKeyPressed")
if (e.PropertyName == PropertyIsShiftKeyPressedID)
{
_switchOrientation = ((App)Application.Current).ZoneSettings.IsShiftKeyPressed;
if (_lastPos.X != -1)

View File

@ -17,7 +17,13 @@ namespace FancyZonesEditor
/// </summary>
public partial class LayoutPreview : UserControl
{
public static readonly DependencyProperty IsActualSizeProperty = DependencyProperty.Register("IsActualSize", typeof(bool), typeof(LayoutPreview), new PropertyMetadata(false));
// Non-localizable strings
private const string PropertyZoneCountID = "ZoneCount";
private const string PropertyShowSpacingID = "ShowSpacing";
private const string PropertySpacingID = "Spacing";
private const string ObjectDependencyID = "IsActualSize";
public static readonly DependencyProperty IsActualSizeProperty = DependencyProperty.Register(ObjectDependencyID, typeof(bool), typeof(LayoutPreview), new PropertyMetadata(false));
private LayoutModel _model;
private List<Int32Rect> _zones = new List<Int32Rect>();
@ -43,11 +49,11 @@ namespace FancyZonesEditor
private void ZoneSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "ZoneCount")
if (e.PropertyName == PropertyZoneCountID)
{
RenderPreview();
}
else if ((e.PropertyName == "ShowSpacing") || (e.PropertyName == "Spacing"))
else if ((e.PropertyName == PropertyShowSpacingID) || (e.PropertyName == PropertySpacingID))
{
if (_model is GridLayoutModel)
{

View File

@ -20,6 +20,8 @@ namespace FancyZonesEditor
// TODO: share the constants b/w C# Editor and FancyZoneLib
public const int MaxZones = 40;
private readonly Settings _settings = ((App)Application.Current).ZoneSettings;
// Localizable string
private static readonly string _defaultNamePrefix = "Custom Layout ";
public int WrapPanelItemSize { get; set; } = 262;

View File

@ -14,6 +14,12 @@ namespace FancyZonesEditor.Models
// Free form Layout Model, which specifies independent zone rects
public class CanvasLayoutModel : LayoutModel
{
// Localizable strings
private const string ErrorPersistingCanvasLayout = "Error persisting canvas layout";
// Non-localizable strings
private const string ModelTypeID = "canvas";
public CanvasLayoutModel(string uuid, string name, LayoutType type, IList<Int32Rect> zones, int workAreaWidth, int workAreaHeight)
: base(uuid, name, type)
{
@ -56,7 +62,7 @@ namespace FancyZonesEditor.Models
public void RemoveZoneAt(int index)
{
Zones.RemoveAt(index);
FirePropertyChanged("Zones");
UpdateLayout();
}
// AddZone
@ -64,7 +70,12 @@ namespace FancyZonesEditor.Models
public void AddZone(Int32Rect zone)
{
Zones.Add(zone);
FirePropertyChanged("Zones");
UpdateLayout();
}
private void UpdateLayout()
{
FirePropertyChanged();
}
// Clone
@ -178,7 +189,7 @@ namespace FancyZonesEditor.Models
{
Uuid = "{" + Guid.ToString().ToUpper() + "}",
Name = Name,
Type = "canvas",
Type = ModelTypeID,
Info = layoutInfo,
};
@ -194,7 +205,7 @@ namespace FancyZonesEditor.Models
}
catch (Exception ex)
{
ShowExceptionMessageBox("Error persisting canvas layout", ex);
ShowExceptionMessageBox(ErrorPersistingCanvasLayout, ex);
}
}
}

View File

@ -14,6 +14,12 @@ namespace FancyZonesEditor.Models
// Grid-styled Layout Model, which specifies rows, columns, percentage sizes, and row/column spans
public class GridLayoutModel : LayoutModel
{
// Localizable strings
private const string ErrorPersistingGridLayout = "Error persisting grid layout";
// Non-localizable strings
private const string ModelTypeID = "grid";
// Rows - number of rows in the Grid
public int Rows
{
@ -220,7 +226,7 @@ namespace FancyZonesEditor.Models
{
Uuid = "{" + Guid.ToString().ToUpper() + "}",
Name = Name,
Type = "grid",
Type = ModelTypeID,
Info = layoutInfo,
};
JsonSerializerOptions options = new JsonSerializerOptions
@ -235,7 +241,7 @@ namespace FancyZonesEditor.Models
}
catch (Exception ex)
{
ShowExceptionMessageBox("Error persisting grid layout", ex);
ShowExceptionMessageBox(ErrorPersistingGridLayout, ex);
}
}
}

View File

@ -61,9 +61,11 @@ namespace FancyZonesEditor.Models
private const string PriorityGridJsonTag = "priority-grid";
private const string CustomJsonTag = "custom";
private const string PowerToysIssuesLink = "https://aka.ms/powerToysReportBug";
public static void ShowExceptionMessageBox(string message, Exception exception = null)
{
string fullMessage = ErrorMessageBoxMessage + "https://aka.ms/powerToysReportBug \n" + message;
string fullMessage = ErrorMessageBoxMessage + PowerToysIssuesLink + " \n" + message;
if (exception != null)
{
fullMessage += ": " + exception.Message;

View File

@ -60,9 +60,19 @@ namespace FancyZonesEditor
private const string ErrorInvalidArgs = "FancyZones Editor arguments are invalid.";
private const string ErrorNonStandaloneApp = "FancyZones Editor should not be run as standalone application.";
// Non-localizable strings
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
// Displayed layout names are localizable strings, but their underlying json tags are not.
private const string FocusLayoutID = "Focus";
private const string ColumnsLayoutID = "Columns";
private const string RowsLayoutID = "Rows";
private const string GridLayoutID = "Grid";
private const string PriorityGridLayoutID = "Priority Grid";
private const string CreateNewCustomLabel = "Create new custom";
// Non-localizable strings
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
private const string ActiveZoneSetsTmpFileName = "FancyZonesActiveZoneSets.json";
private const string AppliedZoneSetsTmpFileName = "FancyZonesAppliedZoneSets.json";
private const string DeletedCustomZoneSetsTmpFileName = "FancyZonesDeletedCustomZoneSets.json";
@ -79,6 +89,15 @@ namespace FancyZonesEditor
private const string EditorSpacingJsonTag = "editor-spacing";
private const string EditorZoneCountJsonTag = "editor-zone-count";
private const string FocusJsonTag = "focus";
private const string ColumnsJsonTag = "columns";
private const string RowsJsonTag = "rows";
private const string GridJsonTag = "grid";
private const string PriorityGridJsonTag = "priority-grid";
private const string CustomJsonTag = "custom";
private const string DebugMode = "Debug";
// hard coded data for all the "Priority Grid" configurations that are unique to "Grid"
private static readonly byte[][] _priorityData = new byte[][]
{
@ -128,30 +147,30 @@ namespace FancyZonesEditor
// Initialize the five default layout models: Focus, Columns, Rows, Grid, and PriorityGrid
DefaultModels = new List<LayoutModel>(5);
_focusModel = new CanvasLayoutModel("Focus", LayoutType.Focus);
_focusModel = new CanvasLayoutModel(FocusLayoutID, LayoutType.Focus);
DefaultModels.Add(_focusModel);
_columnsModel = new GridLayoutModel("Columns", LayoutType.Columns)
_columnsModel = new GridLayoutModel(ColumnsLayoutID, LayoutType.Columns)
{
Rows = 1,
RowPercents = new List<int>(1) { _multiplier },
};
DefaultModels.Add(_columnsModel);
_rowsModel = new GridLayoutModel("Rows", LayoutType.Rows)
_rowsModel = new GridLayoutModel(RowsLayoutID, LayoutType.Rows)
{
Columns = 1,
ColumnPercents = new List<int>(1) { _multiplier },
};
DefaultModels.Add(_rowsModel);
_gridModel = new GridLayoutModel("Grid", LayoutType.Grid);
_gridModel = new GridLayoutModel(GridLayoutID, LayoutType.Grid);
DefaultModels.Add(_gridModel);
_priorityGridModel = new GridLayoutModel("Priority Grid", LayoutType.PriorityGrid);
_priorityGridModel = new GridLayoutModel(PriorityGridLayoutID, LayoutType.PriorityGrid);
DefaultModels.Add(_priorityGridModel);
_blankCustomModel = new CanvasLayoutModel("Create new custom", LayoutType.Blank);
_blankCustomModel = new CanvasLayoutModel(CreateNewCustomLabel, LayoutType.Blank);
UpdateLayoutModels();
}
@ -421,22 +440,22 @@ namespace FancyZonesEditor
{
switch (layoutType)
{
case "focus":
case FocusJsonTag:
ActiveZoneSetLayoutType = LayoutType.Focus;
break;
case "columns":
case ColumnsJsonTag:
ActiveZoneSetLayoutType = LayoutType.Columns;
break;
case "rows":
case RowsJsonTag:
ActiveZoneSetLayoutType = LayoutType.Rows;
break;
case "grid":
case GridJsonTag:
ActiveZoneSetLayoutType = LayoutType.Grid;
break;
case "priority-grid":
case PriorityGridJsonTag:
ActiveZoneSetLayoutType = LayoutType.PriorityGrid;
break;
case "custom":
case CustomJsonTag:
ActiveZoneSetLayoutType = LayoutType.Custom;
break;
}
@ -461,7 +480,7 @@ namespace FancyZonesEditor
if (args.Length == 2)
{
if (args[1].Equals("Debug"))
if (args[1].Equals(DebugMode))
{
ParseDeviceInfoData(ParseDeviceMode.Debug);
}
@ -529,9 +548,6 @@ namespace FancyZonesEditor
private static ObservableCollection<LayoutModel> _customModels;
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
public static bool IsPredefinedLayout(LayoutModel model)
{
return model.Type != LayoutType.Custom;

View File

@ -32,6 +32,14 @@ namespace
constexpr int CUSTOM_POSITIONING_LEFT_TOP_PADDING = 16;
}
// Non-localizable strings
namespace NonLocalizable
{
const wchar_t ToolWindowClassName[] = L"SuperFancyZones";
const wchar_t FZEditorExecutablePath[] = L"modules\\FancyZones\\FancyZonesEditor.exe";
const wchar_t SplashClassName[] = L"MsoSplash";
}
struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZonesCallback, IZoneWindowHost>
{
public:
@ -301,14 +309,16 @@ FancyZones::Run() noexcept
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = s_WndProc;
wcex.hInstance = m_hinstance;
wcex.lpszClassName = L"SuperFancyZones";
wcex.lpszClassName = NonLocalizable::ToolWindowClassName;
RegisterClassExW(&wcex);
BufferedPaintInit();
m_window = CreateWindowExW(WS_EX_TOOLWINDOW, L"SuperFancyZones", L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, m_hinstance, this);
m_window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, m_hinstance, this);
if (!m_window)
{
return;
}
RegisterHotKey(m_window, 1, m_settings->GetSettings()->editorHotkey.get_modifiers(), m_settings->GetSettings()->editorHotkey.get_code());
@ -363,7 +373,7 @@ bool FancyZones::ShouldProcessNewWindow(HWND window) noexcept
// Avoid processing splash screens, already stamped (zoned) windows, or those windows
// that belong to excluded applications list.
if (IsSplashScreen(window) ||
(reinterpret_cast<size_t>(::GetProp(window, MULTI_ZONE_STAMP)) != 0) ||
(reinterpret_cast<size_t>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID)) != 0) ||
!IsInterestingWindow(window, m_settings->GetSettings()->excludedAppsArray))
{
return false;
@ -715,7 +725,7 @@ void FancyZones::ToggleEditor() noexcept
SHELLEXECUTEINFO sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
sei.lpFile = L"modules\\FancyZones\\FancyZonesEditor.exe";
sei.lpFile = NonLocalizable::FZEditorExecutablePath;
sei.lpParameters = params.c_str();
sei.nShow = SW_SHOWNORMAL;
ShellExecuteEx(&sei);
@ -1016,7 +1026,7 @@ void FancyZones::UpdateZoneWindows() noexcept
void FancyZones::UpdateWindowsPositions() noexcept
{
auto callback = [](HWND window, LPARAM data) -> BOOL {
size_t bitmask = reinterpret_cast<size_t>(::GetProp(window, MULTI_ZONE_STAMP));
size_t bitmask = reinterpret_cast<size_t>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID));
if (bitmask != 0)
{
@ -1145,14 +1155,13 @@ void FancyZones::RegisterVirtualDesktopUpdates(std::vector<GUID>& ids) noexcept
bool FancyZones::IsSplashScreen(HWND window)
{
wchar_t splashClassName[] = L"MsoSplash"; // shouldn't be localized
wchar_t className[MAX_PATH];
if (GetClassName(window, className, MAX_PATH) == 0)
{
return false;
}
return wcscmp(splashClassName, className) == 0;
return wcscmp(NonLocalizable::SplashClassName, className) == 0;
}
void FancyZones::OnEditorExitEvent() noexcept

View File

@ -22,19 +22,19 @@ namespace NonLocalizable
const wchar_t FancyZonesStr[] = L"FancyZones";
const wchar_t LayoutsStr[] = L"Layouts";
const wchar_t NullStr[] = L"null";
}
namespace
{
const wchar_t* FANCY_ZONES_DATA_FILE = L"zones-settings.json";
const wchar_t* FANCY_ZONES_APP_ZONE_HISTORY_FILE = L"app-zone-history.json";
const wchar_t* DEFAULT_GUID = L"{00000000-0000-0000-0000-000000000000}";
const wchar_t* REG_SETTINGS = L"Software\\SuperFancyZones";
const wchar_t FancyZonesDataFile[] = L"zones-settings.json";
const wchar_t FancyZonesAppZoneHistoryFile[] = L"app-zone-history.json";
const wchar_t DefaultGuid[] = L"{00000000-0000-0000-0000-000000000000}";
const wchar_t RegistryPath[] = L"Software\\SuperFancyZones";
const wchar_t ActiveZoneSetsTmpFileName[] = L"FancyZonesActiveZoneSets.json";
const wchar_t AppliedZoneSetsTmpFileName[] = L"FancyZonesAppliedZoneSets.json";
const wchar_t DeletedCustomZoneSetsTmpFileName[] = L"FancyZonesDeletedCustomZoneSets.json";
}
namespace
{
std::wstring ExtractVirtualDesktopId(const std::wstring& deviceId)
{
// Format: <device-id>_<resolution>_<virtual-desktop-id>
@ -71,12 +71,12 @@ FancyZonesData& FancyZonesDataInstance()
FancyZonesData::FancyZonesData()
{
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::FancyZonesStr);
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(FANCY_ZONES_DATA_FILE);
appZoneHistoryFileName = saveFolderPath + L"\\" + std::wstring(FANCY_ZONES_APP_ZONE_HISTORY_FILE);
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile);
appZoneHistoryFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesAppZoneHistoryFile);
activeZoneSetTmpFileName = GetTempDirPath() + ActiveZoneSetsTmpFileName;
appliedZoneSetTmpFileName = GetTempDirPath() + AppliedZoneSetsTmpFileName;
deletedCustomZoneSetsTmpFileName = GetTempDirPath() + DeletedCustomZoneSetsTmpFileName;
activeZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::ActiveZoneSetsTmpFileName;
appliedZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::AppliedZoneSetsTmpFileName;
deletedCustomZoneSetsTmpFileName = GetTempDirPath() + NonLocalizable::DeletedCustomZoneSetsTmpFileName;
}
std::optional<FancyZonesDataTypes::DeviceInfoData> FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const
@ -141,7 +141,7 @@ void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId)
{
for (auto& data : perDesktopData)
{
if (ExtractVirtualDesktopId(data.deviceId) == DEFAULT_GUID)
if (ExtractVirtualDesktopId(data.deviceId) == NonLocalizable::DefaultGuid)
{
data.deviceId = replaceDesktopId(data.deviceId);
}
@ -150,7 +150,7 @@ void FancyZonesData::UpdatePrimaryDesktopData(const std::wstring& desktopId)
std::vector<std::wstring> toReplace{};
for (const auto& [id, data] : deviceInfoMap)
{
if (ExtractVirtualDesktopId(id) == DEFAULT_GUID)
if (ExtractVirtualDesktopId(id) == NonLocalizable::DefaultGuid)
{
toReplace.push_back(id);
}
@ -290,10 +290,10 @@ bool FancyZonesData::RemoveAppLastZone(HWND window, const std::wstring_view& dev
}
// if there is another instance of same application placed in the same zone don't erase history
size_t windowZoneStamp = reinterpret_cast<size_t>(::GetProp(window, MULTI_ZONE_STAMP));
size_t windowZoneStamp = reinterpret_cast<size_t>(::GetProp(window, ZonedWindowProperties::PropertyMultipleZoneID));
for (auto placedWindow : data->processIdToHandleMap)
{
size_t placedWindowZoneStamp = reinterpret_cast<size_t>(::GetProp(placedWindow.second, MULTI_ZONE_STAMP));
size_t placedWindowZoneStamp = reinterpret_cast<size_t>(::GetProp(placedWindow.second, ZonedWindowProperties::PropertyMultipleZoneID));
if (IsWindow(placedWindow.second) && (windowZoneStamp == placedWindowZoneStamp))
{
return false;
@ -477,7 +477,7 @@ void FancyZonesData::MigrateCustomZoneSetsFromRegistry()
{
std::scoped_lock lock{ dataLock };
wchar_t key[256];
StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", REG_SETTINGS, NonLocalizable::LayoutsStr);
StringCchPrintf(key, ARRAYSIZE(key), L"%s\\%s", NonLocalizable::RegistryPath, NonLocalizable::LayoutsStr);
HKEY hkey;
if (RegOpenKeyExW(HKEY_CURRENT_USER, key, 0, KEY_ALL_ACCESS, &hkey) == ERROR_SUCCESS)
{

View File

@ -4,6 +4,37 @@
#include "lib/FancyZones.h"
#include "trace.h"
// Non-Localizable strings
namespace NonLocalizable
{
// FancyZones settings descriptions are localized, but underlying toggle (spinner, color picker) names are not.
const wchar_t ShiftDragID[] = L"fancyzones_shiftDrag";
const wchar_t MouseSwitchID[] = L"fancyzones_mouseSwitch";
const wchar_t OverrideSnapHotKeysID[] = L"fancyzones_overrideSnapHotkeys";
const wchar_t MoveWindowAcrossMonitorsID[] = L"fancyzones_moveWindowAcrossMonitors";
const wchar_t DisplayChangeMoveWindowsID[] = L"fancyzones_displayChange_moveWindows";
const wchar_t ZoneSetChangeMoveWindowsID[] = L"fancyzones_zoneSetChange_moveWindows";
const wchar_t AppLastZoneMoveWindowsID[] = L"fancyzones_appLastZone_moveWindows";
const wchar_t OpenWindowOnActiveMonitorID[] = L"fancyzones_openWindowOnActiveMonitor";
const wchar_t RestoreSizeID[] = L"fancyzones_restoreSize";
const wchar_t UseCursorPosEditorStartupScreenID[] = L"use_cursorpos_editor_startupscreen";
const wchar_t ShowOnAllMonitorsID[] = L"fancyzones_show_on_all_monitors";
const wchar_t SpanZonesAcrossMonitorsID[] = L"fancyzones_span_zones_across_monitors";
const wchar_t MakeDraggedWindowTransparentID[] = L"fancyzones_makeDraggedWindowTransparent";
const wchar_t ZoneColorID[] = L"fancyzones_zoneColor";
const wchar_t ZoneBorderColorID[] = L"fancyzones_zoneBorderColor";
const wchar_t ZoneHighlightColorID[] = L"fancyzones_zoneHighlightColor";
const wchar_t EditorHotkeyID[] = L"fancyzones_editor_hotkey";
const wchar_t ExcludedAppsID[] = L"fancyzones_excluded_apps";
const wchar_t ZoneHighlightOpacityID[] = L"fancyzones_highlight_opacity";
const wchar_t ToggleEditorActionID[] = L"ToggledFZEditor";
const wchar_t IconKeyID[] = L"pt-fancy-zones";
const wchar_t OverviewURL[] = L"https://aka.ms/PowerToysOverview_FancyZones";
const wchar_t VideoURL[] = L"https://youtu.be/rTtGzZYAXgY";
}
struct FancyZonesSettings : winrt::implements<FancyZonesSettings, IFancyZonesSettings>
{
public:
@ -37,29 +68,23 @@ private:
bool* value;
int resourceId;
} m_configBools[13 /* 14 */] = { // "Turning FLASHING_ZONE option off"
{ L"fancyzones_shiftDrag", &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG },
{ L"fancyzones_mouseSwitch", &m_settings.mouseSwitch, IDS_SETTING_DESCRIPTION_MOUSESWITCH },
{ L"fancyzones_overrideSnapHotkeys", &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS },
{ L"fancyzones_moveWindowAcrossMonitors", &m_settings.moveWindowAcrossMonitors, IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS },
{ NonLocalizable::ShiftDragID, &m_settings.shiftDrag, IDS_SETTING_DESCRIPTION_SHIFTDRAG },
{ NonLocalizable::MouseSwitchID, &m_settings.mouseSwitch, IDS_SETTING_DESCRIPTION_MOUSESWITCH },
{ NonLocalizable::OverrideSnapHotKeysID, &m_settings.overrideSnapHotkeys, IDS_SETTING_DESCRIPTION_OVERRIDE_SNAP_HOTKEYS },
{ NonLocalizable::MoveWindowAcrossMonitorsID, &m_settings.moveWindowAcrossMonitors, IDS_SETTING_DESCRIPTION_MOVE_WINDOW_ACROSS_MONITORS },
// "Turning FLASHING_ZONE option off"
//{ L"fancyzones_zoneSetChange_flashZones", &m_settings.zoneSetChange_flashZones, IDS_SETTING_DESCRIPTION_ZONESETCHANGE_FLASHZONES },
{ L"fancyzones_displayChange_moveWindows", &m_settings.displayChange_moveWindows, IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS },
{ L"fancyzones_zoneSetChange_moveWindows", &m_settings.zoneSetChange_moveWindows, IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS },
{ L"fancyzones_appLastZone_moveWindows", &m_settings.appLastZone_moveWindows, IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS },
{ L"fancyzones_openWindowOnActiveMonitor", &m_settings.openWindowOnActiveMonitor, IDS_SETTING_DESCRIPTION_OPEN_WINDOW_ON_ACTIVE_MONITOR },
{ L"fancyzones_restoreSize", &m_settings.restoreSize, IDS_SETTING_DESCRIPTION_RESTORESIZE },
{ L"use_cursorpos_editor_startupscreen", &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN },
{ L"fancyzones_show_on_all_monitors", &m_settings.showZonesOnAllMonitors, IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS },
{ L"fancyzones_span_zones_across_monitors", &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
{ L"fancyzones_makeDraggedWindowTransparent", &m_settings.makeDraggedWindowTransparent, IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT },
{ NonLocalizable::DisplayChangeMoveWindowsID, &m_settings.displayChange_moveWindows, IDS_SETTING_DESCRIPTION_DISPLAYCHANGE_MOVEWINDOWS },
{ NonLocalizable::ZoneSetChangeMoveWindowsID, &m_settings.zoneSetChange_moveWindows, IDS_SETTING_DESCRIPTION_ZONESETCHANGE_MOVEWINDOWS },
{ NonLocalizable::AppLastZoneMoveWindowsID, &m_settings.appLastZone_moveWindows, IDS_SETTING_DESCRIPTION_APPLASTZONE_MOVEWINDOWS },
{ NonLocalizable::OpenWindowOnActiveMonitorID, &m_settings.openWindowOnActiveMonitor, IDS_SETTING_DESCRIPTION_OPEN_WINDOW_ON_ACTIVE_MONITOR },
{ NonLocalizable::RestoreSizeID, &m_settings.restoreSize, IDS_SETTING_DESCRIPTION_RESTORESIZE },
{ NonLocalizable::UseCursorPosEditorStartupScreenID, &m_settings.use_cursorpos_editor_startupscreen, IDS_SETTING_DESCRIPTION_USE_CURSORPOS_EDITOR_STARTUPSCREEN },
{ NonLocalizable::ShowOnAllMonitorsID, &m_settings.showZonesOnAllMonitors, IDS_SETTING_DESCRIPTION_SHOW_FANCY_ZONES_ON_ALL_MONITORS},
{ NonLocalizable::SpanZonesAcrossMonitorsID, &m_settings.spanZonesAcrossMonitors, IDS_SETTING_DESCRIPTION_SPAN_ZONES_ACROSS_MONITORS },
{ NonLocalizable::MakeDraggedWindowTransparentID, &m_settings.makeDraggedWindowTransparent, IDS_SETTING_DESCRIPTION_MAKE_DRAGGED_WINDOW_TRANSPARENT},
};
const std::wstring m_zoneColorName = L"fancyzones_zoneColor";
const std::wstring m_zoneBorderColorName = L"fancyzones_zoneBorderColor";
const std::wstring m_zoneHighlightName = L"fancyzones_zoneHighlightColor";
const std::wstring m_editorHotkeyName = L"fancyzones_editor_hotkey";
const std::wstring m_excludedAppsName = L"fancyzones_excluded_apps";
const std::wstring m_zoneHighlightOpacity = L"fancyzones_highlight_opacity";
};
IFACEMETHODIMP_(bool) FancyZonesSettings::GetConfig(_Out_ PWSTR buffer, _Out_ int *buffer_size) noexcept
@ -68,32 +93,32 @@ IFACEMETHODIMP_(bool) FancyZonesSettings::GetConfig(_Out_ PWSTR buffer, _Out_ in
// Pass a string literal or a resource id to Settings::set_description().
settings.set_description(IDS_SETTING_DESCRIPTION);
settings.set_icon_key(L"pt-fancy-zones");
settings.set_overview_link(L"https://aka.ms/PowerToysOverview_FancyZones");
settings.set_video_link(L"https://youtu.be/rTtGzZYAXgY");
settings.set_icon_key(NonLocalizable::IconKeyID);
settings.set_overview_link(NonLocalizable::OverviewURL);
settings.set_video_link(NonLocalizable::VideoURL);
// Add a custom action property. When using this settings type, the "PowertoyModuleIface::call_custom_action()"
// method should be overridden as well.
settings.add_custom_action(
L"ToggledFZEditor", // action name.
NonLocalizable::ToggleEditorActionID, // action name.
IDS_SETTING_LAUNCH_EDITOR_LABEL,
IDS_SETTING_LAUNCH_EDITOR_BUTTON,
IDS_SETTING_LAUNCH_EDITOR_DESCRIPTION
);
settings.add_hotkey(m_editorHotkeyName, IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, m_settings.editorHotkey);
settings.add_hotkey(NonLocalizable::EditorHotkeyID, IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL, m_settings.editorHotkey);
for (auto const& setting : m_configBools)
{
settings.add_bool_toggle(setting.name, setting.resourceId, *setting.value);
}
settings.add_color_picker(m_zoneHighlightName, IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR, m_settings.zoneHighlightColor);
settings.add_color_picker(m_zoneColorName, IDS_SETTING_DESCRIPTION_ZONECOLOR, m_settings.zoneColor);
settings.add_color_picker(m_zoneBorderColorName, IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR, m_settings.zoneBorderColor);
settings.add_color_picker(NonLocalizable::ZoneHighlightColorID, IDS_SETTING_DESCRIPTION_ZONEHIGHLIGHTCOLOR, m_settings.zoneHighlightColor);
settings.add_color_picker(NonLocalizable::ZoneColorID, IDS_SETTING_DESCRIPTION_ZONECOLOR, m_settings.zoneColor);
settings.add_color_picker(NonLocalizable::ZoneBorderColorID, IDS_SETTING_DESCRIPTION_ZONE_BORDER_COLOR, m_settings.zoneBorderColor);
settings.add_int_spinner(m_zoneHighlightOpacity, IDS_SETTINGS_HIGHLIGHT_OPACITY, m_settings.zoneHighlightOpacity, 0, 100, 1);
settings.add_int_spinner(NonLocalizable::ZoneHighlightOpacityID, IDS_SETTINGS_HIGHLIGHT_OPACITY, m_settings.zoneHighlightOpacity, 0, 100, 1);
settings.add_multiline_string(m_excludedAppsName, IDS_SETTING_EXCLUDED_APPS_DESCRIPTION, m_settings.excludedApps);
settings.add_multiline_string(NonLocalizable::ExcludedAppsID, IDS_SETTING_EXCLUDED_APPS_DESCRIPTION, m_settings.excludedApps);
return settings.serialize_to_buffer(buffer, buffer_size);
}
@ -116,7 +141,7 @@ IFACEMETHODIMP_(void) FancyZonesSettings::CallCustomAction(PCWSTR action) noexce
PowerToysSettings::CustomActionObject action_object =
PowerToysSettings::CustomActionObject::from_json_string(action);
if (m_callback && action_object.get_name() == L"ToggledFZEditor")
if (m_callback && action_object.get_name() == NonLocalizable::ToggleEditorActionID)
{
m_callback->ToggleEditor();
}
@ -137,27 +162,27 @@ void FancyZonesSettings::LoadSettings(PCWSTR config, bool fromFile) noexcept try
}
}
if (auto val = values.get_string_value(m_zoneColorName))
if (auto val = values.get_string_value(NonLocalizable::ZoneColorID))
{
m_settings.zoneColor = std::move(*val);
}
if (auto val = values.get_string_value(m_zoneBorderColorName))
if (auto val = values.get_string_value(NonLocalizable::ZoneBorderColorID))
{
m_settings.zoneBorderColor = std::move(*val);
}
if (auto val = values.get_string_value(m_zoneHighlightName))
if (auto val = values.get_string_value(NonLocalizable::ZoneHighlightColorID))
{
m_settings.zoneHighlightColor = std::move(*val);
}
if (const auto val = values.get_json(m_editorHotkeyName))
if (const auto val = values.get_json(NonLocalizable::EditorHotkeyID))
{
m_settings.editorHotkey = PowerToysSettings::HotkeyObject::from_json(*val);
}
if (auto val = values.get_string_value(m_excludedAppsName))
if (auto val = values.get_string_value(NonLocalizable::ExcludedAppsID))
{
m_settings.excludedApps = std::move(*val);
m_settings.excludedAppsArray.clear();
@ -180,7 +205,7 @@ void FancyZonesSettings::LoadSettings(PCWSTR config, bool fromFile) noexcept try
}
}
if (auto val = values.get_int_value(m_zoneHighlightOpacity))
if (auto val = values.get_int_value(NonLocalizable::ZoneHighlightOpacityID))
{
m_settings.zoneHighlightOpacity = *val;
}
@ -196,12 +221,12 @@ void FancyZonesSettings::SaveSettings() noexcept try
values.add_property(setting.name, *setting.value);
}
values.add_property(m_zoneColorName, m_settings.zoneColor);
values.add_property(m_zoneBorderColorName, m_settings.zoneBorderColor);
values.add_property(m_zoneHighlightName, m_settings.zoneHighlightColor);
values.add_property(m_zoneHighlightOpacity, m_settings.zoneHighlightOpacity);
values.add_property(m_editorHotkeyName, m_settings.editorHotkey.get_json());
values.add_property(m_excludedAppsName, m_settings.excludedApps);
values.add_property(NonLocalizable::ZoneColorID, m_settings.zoneColor);
values.add_property(NonLocalizable::ZoneBorderColorID, m_settings.zoneBorderColor);
values.add_property(NonLocalizable::ZoneHighlightColorID, m_settings.zoneHighlightColor);
values.add_property(NonLocalizable::ZoneHighlightOpacityID, m_settings.zoneHighlightOpacity);
values.add_property(NonLocalizable::EditorHotkeyID, m_settings.editorHotkey.get_json());
values.add_property(NonLocalizable::ExcludedAppsID, m_settings.excludedApps);
values.save_to_settings_file();
}

View File

@ -1,11 +1,17 @@
#pragma once
#define MULTI_ZONE_STAMP L"FancyZones_zones"
#define RESTORE_SIZE_STAMP L"FancyZones_RestoreSize"
#define RESTORE_ORIGIN_STAMP L"FancyZones_RestoreOrigin"
#define MULTI_MONITOR_MODE_DEVICE L"FancyZonesMultiMonitorDevice"
#include <common/settings_objects.h>
// Zoned window properties are not localized.
namespace ZonedWindowProperties
{
const wchar_t PropertyMultipleZoneID[] = L"FancyZones_zones";
const wchar_t PropertyRestoreSizeID[] = L"FancyZones_RestoreSize";
const wchar_t PropertyRestoreOriginID[] = L"FancyZones_RestoreOrigin";
const wchar_t MultiMonitorDeviceID[] = L"FancyZones_MultiMonitorDevice";
}
struct Settings
{
// The values specified here are the defaults.

View File

@ -2,13 +2,17 @@
#include "VirtualDesktopUtils.h"
namespace VirtualDesktopUtils
// Non-Localizable strings
namespace NonLocalizable
{
const CLSID CLSID_ImmersiveShell = { 0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39 };
const wchar_t RegCurrentVirtualDesktop[] = L"CurrentVirtualDesktop";
const wchar_t RegVirtualDesktopIds[] = L"VirtualDesktopIDs";
const wchar_t RegKeyVirtualDesktops[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VirtualDesktops";
}
namespace VirtualDesktopUtils
{
const CLSID CLSID_ImmersiveShell = { 0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39 };
IServiceProvider* GetServiceProvider()
{
@ -64,7 +68,7 @@ namespace VirtualDesktopUtils
if (RegOpenKeyExW(HKEY_CURRENT_USER, sessionKeyPath, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
{
DWORD size = sizeof(GUID);
if (RegQueryValueExW(key.get(), RegCurrentVirtualDesktop, 0, nullptr, reinterpret_cast<BYTE*>(&value), &size) == ERROR_SUCCESS)
if (RegQueryValueExW(key.get(), NonLocalizable::RegCurrentVirtualDesktop, 0, nullptr, reinterpret_cast<BYTE*>(&value), &size) == ERROR_SUCCESS)
{
*desktopId = value;
return true;
@ -99,13 +103,13 @@ namespace VirtualDesktopUtils
}
DWORD bufferCapacity;
// request regkey binary buffer capacity only
if (RegQueryValueExW(hKey, RegVirtualDesktopIds, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS)
if (RegQueryValueExW(hKey, NonLocalizable::RegVirtualDesktopIds, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS)
{
return false;
}
std::unique_ptr<BYTE[]> buffer = std::make_unique<BYTE[]>(bufferCapacity);
// request regkey binary content
if (RegQueryValueExW(hKey, RegVirtualDesktopIds, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS)
if (RegQueryValueExW(hKey, NonLocalizable::RegVirtualDesktopIds, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS)
{
return false;
}
@ -147,7 +151,7 @@ namespace VirtualDesktopUtils
HKEY OpenVirtualDesktopsRegKey()
{
HKEY hKey{ nullptr };
if (RegOpenKeyEx(HKEY_CURRENT_USER, RegKeyVirtualDesktops, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
if (RegOpenKeyEx(HKEY_CURRENT_USER, NonLocalizable::RegKeyVirtualDesktops, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
{
return hKey;
}

View File

@ -16,9 +16,11 @@
extern "C" IMAGE_DOS_HEADER __ImageBase;
namespace
// Non-Localizable strings
namespace NonLocalizable
{
const wchar_t TOAST_TITLE[] = L"FancyZones";
const wchar_t FancyZonesRunAsAdminInfoPage[] = L"https://aka.ms/powertoysDetectedElevatedHelp";
const wchar_t ToastNotificationButtonUrl[] = L"powertoys://cant_drag_elevated_disable/";
}
namespace WindowMoveHandlerUtils
@ -335,7 +337,7 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c
{
if (WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent())
{
::RemoveProp(window, RESTORE_SIZE_STAMP);
::RemoveProp(window, ZonedWindowProperties::PropertyRestoreSizeID);
}
else if (!IsWindowMaximized(window))
{
@ -361,7 +363,7 @@ void WindowMoveHandlerPrivate::MoveSizeEnd(HWND window, POINT const& ptScreen, c
}
}
}
::RemoveProp(window, MULTI_ZONE_STAMP);
::RemoveProp(window, ZonedWindowProperties::PropertyMultipleZoneID);
}
m_inMoveSize = false;
@ -401,11 +403,11 @@ void WindowMoveHandlerPrivate::WarnIfElevationIsRequired(HWND window) noexcept
if (!warning_shown && !is_cant_drag_elevated_warning_disabled())
{
std::vector<notifications::action_t> actions = {
notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), L"https://aka.ms/powertoysDetectedElevatedHelp" },
notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN), L"powertoys://cant_drag_elevated_disable/" }
notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), NonLocalizable::FancyZonesRunAsAdminInfoPage },
notifications::link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN), NonLocalizable::ToastNotificationButtonUrl }
};
notifications::show_toast_with_activations(GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED),
TOAST_TITLE,
GET_RESOURCE_STRING(IDS_FANCYZONES),
{},
std::move(actions));
warning_shown = true;

View File

@ -699,7 +699,7 @@ bool ZoneSet::CalculateGridZones(Rect workArea, FancyZonesDataTypes::GridLayoutI
void ZoneSet::StampWindow(HWND window, size_t bitmask) noexcept
{
SetProp(window, MULTI_ZONE_STAMP, reinterpret_cast<HANDLE>(bitmask));
SetProp(window, ZonedWindowProperties::PropertyMultipleZoneID, reinterpret_cast<HANDLE>(bitmask));
}
winrt::com_ptr<IZoneSet> MakeZoneSet(ZoneSetConfig const& config) noexcept

View File

@ -15,6 +15,13 @@
#include <gdiplus.h>
// Non-Localizable strings
namespace NonLocalizable
{
const wchar_t SegoeUiFont[] = L"Segoe ui";
const wchar_t ToolWindowClassName[] = L"SuperFancyZones_ZoneWindow";
}
namespace ZoneWindowUtils
{
std::wstring GenerateUniqueId(HMONITOR monitor, PCWSTR deviceId, PCWSTR virtualDesktopId)
@ -36,7 +43,7 @@ namespace ZoneWindowUtils
std::wstring GenerateUniqueIdAllMonitorsArea(PCWSTR virtualDesktopId)
{
std::wstring result{ MULTI_MONITOR_MODE_DEVICE };
std::wstring result{ ZonedWindowProperties::MultiMonitorDeviceID };
RECT combinedResolution = GetAllMonitorsCombinedRect<&MONITORINFO::rcMonitor>();
@ -71,7 +78,7 @@ namespace ZoneWindowDrawUtils
{
Gdiplus::Graphics g(hdc.get());
Gdiplus::FontFamily fontFamily(L"Segoe ui");
Gdiplus::FontFamily fontFamily(NonLocalizable::SegoeUiFont);
Gdiplus::Font font(&fontFamily, 80, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel);
Gdiplus::SolidBrush solidBrush(Gdiplus::Color(255, 0, 0, 0));
@ -253,7 +260,7 @@ ZoneWindow::ZoneWindow(HINSTANCE hinstance)
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = s_WndProc;
wcex.hInstance = hinstance;
wcex.lpszClassName = L"SuperFancyZones_ZoneWindow";
wcex.lpszClassName = NonLocalizable::ToolWindowClassName;
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
RegisterClassExW(&wcex);
@ -292,7 +299,7 @@ bool ZoneWindow::Init(IZoneWindowHost* host, HINSTANCE hinstance, HMONITOR monit
InitializeZoneSets(parentUniqueId);
m_window = wil::unique_hwnd{
CreateWindowExW(WS_EX_TOOLWINDOW, L"SuperFancyZones_ZoneWindow", L"", WS_POPUP, workAreaRect.left(), workAreaRect.top(), workAreaRect.width(), workAreaRect.height(), nullptr, nullptr, hinstance, this)
CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, workAreaRect.left(), workAreaRect.top(), workAreaRect.width(), workAreaRect.height(), nullptr, nullptr, hinstance, this)
};
if (!m_window)

View File

@ -28,10 +28,13 @@ BEGIN
IDS_SETTING_LAUNCH_EDITOR_HOTKEY_LABEL "Configure the zone editor hotkey"
IDS_SETTING_EXCLUDED_APPS_DESCRIPTION "To exclude an application from snapping to zones add its name here (one per line). Excluded apps will react to the Windows Snap regardless of all other settings."
IDS_SETTINGS_HIGHLIGHT_OPACITY "Zone opacity (%)"
IDS_FANCYZONES L"FancyZones"
IDS_CANT_DRAG_ELEVATED L"We've detected an application running with administrator privileges. This blocks some functionality in PowerToys. Visit our wiki page to learn more."
IDS_CANT_DRAG_ELEVATED_LEARN_MORE L"Learn more"
IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN L"Don't show again"
IDS_FANCYZONES "FancyZones"
IDS_CANT_DRAG_ELEVATED "We've detected an application running with administrator privileges. This blocks some functionality in PowerToys. Visit our wiki page to learn more."
IDS_CANT_DRAG_ELEVATED_LEARN_MORE "Learn more"
IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN "Don't show again"
IDS_KEYBOARD_LISTENER_ERROR "Cannot install keyboard listener."
IDS_WINDOW_EVENT_LISTENER_ERROR "Cannot install Windows event listener."
IDS_POWERTOYS_FANCYZONES "PowerToys - FancyZones"
END
1 VERSIONINFO

View File

@ -40,3 +40,6 @@
#define IDS_CANT_DRAG_ELEVATED 126
#define IDS_CANT_DRAG_ELEVATED_LEARN_MORE 127
#define IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN 128
#define IDS_KEYBOARD_LISTENER_ERROR 129
#define IDS_WINDOW_EVENT_LISTENER_ERROR 130
#define IDS_POWERTOYS_FANCYZONES 131

View File

@ -5,9 +5,59 @@
#include "lib/FancyZonesData.h"
#include "lib/FancyZonesDataTypes.h"
// Telemetry strings should not be localized.
#define LoggingProviderKey "Microsoft.PowerToys"
#define EventEnableFancyZonesKey "FancyZones_EnableFancyZones"
#define EventKeyDownKey "FancyZones_OnKeyDown"
#define EventZoneSettingsChangedKey "FancyZones_ZoneSettingsChanged"
#define EventEditorLaunchKey "FancyZones_EditorLaunch"
#define EventSettingsChangedKey "FancyZones_SettingsChanged"
#define EventDesktopChangedKey "FancyZones_VirtualDesktopChanged"
#define EventZoneWindowKeyUpKey "FancyZones_ZoneWindowKeyUp"
#define EventMoveSizeEndKey "FancyZones_MoveSizeEnd"
#define EventCycleActiveZoneSetKey "FancyZones_CycleActiveZoneSet"
#define EventEnabledKey "Enabled"
#define PressedKeyCodeKey "Hotkey"
#define PressedWindowKey "WindowsKey"
#define PressedControlKey "ControlKey"
#define MoveSizeActionKey "InMoveSize"
#define AppsInHistoryCountKey "AppsInHistoryCount"
#define CustomZoneSetCountKey "CustomZoneSetCount"
#define NumberOfZonesForEachCustomZoneSetKey "NumberOfZonesForEachCustomZoneSet"
#define ActiveZoneSetsCountKey "ActiveZoneSetsCount"
#define ActiveZoneSetsListKey "ActiveZoneSetsList"
#define EditorLaunchValueKey "Value"
#define ShiftDragKey "ShiftDrag"
#define MouseSwitchKey "MouseSwitch"
#define MoveWindowsOnDisplayChangeKey "MoveWindowsOnDisplayChange"
#define FlashZonesOnZoneSetChangeKey "FlashZonesOnZoneSetChange"
#define MoveWindowsOnZoneSetChangeKey "MoveWindowsOnZoneSetChange"
#define OverrideSnapHotKeysKey "OverrideSnapHotKeys"
#define MoveWindowAcrossMonitorsKey "MoveWindowAcrossMonitors"
#define MoveWindowsToLastZoneOnAppOpeningKey "MoveWindowsToLastZoneOnAppOpening"
#define OpenWindowOnActiveMonitorKey "OpenWindowOnActiveMonitor"
#define RestoreSizeKey "RestoreSize"
#define UseCursorPosOnEditorStartupKey "UseCursorPosOnEditorStartup"
#define ShowZonesOnAllMonitorsKey "ShowZonesOnAllMonitors"
#define SpanZonesAcrossMonitorsKey "SpanZonesAcrossMonitors"
#define MakeDraggedWindowTransparentKey "MakeDraggedWindowTransparent"
#define ZoneColorKey "ZoneColor"
#define ZoneBorderColorKey "ZoneBorderColor"
#define ZoneHighlightColorKey "ZoneHighlightColor"
#define ZoneHighlightOpacityKey "ZoneHighlightOpacity"
#define HotkeyKey "Hotkey"
#define ExcludedAppsCountKey "ExcludedAppsCount"
#define KeyboardValueKey "KeyboardValue"
#define ActiveSetKey "ActiveSet"
#define NumberOfZonesKey "NumberOfZones"
#define NumberOfWindowsKey "NumberOfWindows"
#define InputModeKey "InputMode"
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
LoggingProviderKey,
// {38e8889b-9731-53f5-e901-e8a7c1753074}
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
@ -51,23 +101,23 @@ void Trace::FancyZones::EnableFancyZones(bool enabled) noexcept
{
TraceLoggingWrite(
g_hProvider,
"FancyZones_EnableFancyZones",
EventEnableFancyZonesKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(enabled, "Enabled"));
TraceLoggingBoolean(enabled, EventEnabledKey));
}
void Trace::FancyZones::OnKeyDown(DWORD vkCode, bool win, bool control, bool inMoveSize) noexcept
{
TraceLoggingWrite(
g_hProvider,
"FancyZones_OnKeyDown",
EventKeyDownKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(vkCode, "Hotkey"),
TraceLoggingBoolean(win, "WindowsKey"),
TraceLoggingBoolean(control, "ControlKey"),
TraceLoggingBoolean(inMoveSize, "InMoveSize"));
TraceLoggingValue(vkCode, PressedKeyCodeKey),
TraceLoggingBoolean(win, PressedWindowKey),
TraceLoggingBoolean(control, PressedControlKey),
TraceLoggingBoolean(inMoveSize, MoveSizeActionKey));
}
void Trace::FancyZones::DataChanged() noexcept
@ -142,24 +192,24 @@ void Trace::FancyZones::DataChanged() noexcept
TraceLoggingWrite(
g_hProvider,
"FancyZones_ZoneSettingsChanged",
EventZoneSettingsChangedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingInt32(appsHistorySize, "AppsInHistoryCount"),
TraceLoggingInt32(static_cast<int>(customZones.size()), "CustomZoneSetCount"),
TraceLoggingInt32Array(customZonesArray.get(), static_cast<int>(customZones.size()), "NumberOfZonesForEachCustomZoneSet"),
TraceLoggingInt32(static_cast<int>(devices.size()), "ActiveZoneSetsCount"),
TraceLoggingWideString(activeZoneSetInfo.c_str(), "ActiveZoneSetsList"));
TraceLoggingInt32(appsHistorySize, AppsInHistoryCountKey),
TraceLoggingInt32(static_cast<int>(customZones.size()), CustomZoneSetCountKey),
TraceLoggingInt32Array(customZonesArray.get(), static_cast<int>(customZones.size()), NumberOfZonesForEachCustomZoneSetKey),
TraceLoggingInt32(static_cast<int>(devices.size()), ActiveZoneSetsCountKey),
TraceLoggingWideString(activeZoneSetInfo.c_str(), ActiveZoneSetsListKey));
}
void Trace::FancyZones::EditorLaunched(int value) noexcept
{
TraceLoggingWrite(
g_hProvider,
"FancyZones_EditorLaunch",
EventEditorLaunchKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingInt32(value, "Value"));
TraceLoggingInt32(value, EditorLaunchValueKey));
}
void Trace::SettingsChanged(const Settings& settings) noexcept
@ -174,36 +224,36 @@ void Trace::SettingsChanged(const Settings& settings) noexcept
TraceLoggingWrite(
g_hProvider,
"FancyZones_SettingsChanged",
EventSettingsChangedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(settings.shiftDrag, "ShiftDrag"),
TraceLoggingBoolean(settings.mouseSwitch, "MouseSwitch"),
TraceLoggingBoolean(settings.displayChange_moveWindows, "MoveWindowsOnDisplayChange"),
TraceLoggingBoolean(settings.zoneSetChange_flashZones, "FlashZonesOnZoneSetChange"),
TraceLoggingBoolean(settings.zoneSetChange_moveWindows, "MoveWindowsOnZoneSetChange"),
TraceLoggingBoolean(settings.overrideSnapHotkeys, "OverrideSnapHotKeys"),
TraceLoggingBoolean(settings.moveWindowAcrossMonitors, "MoveWindowAcrossMonitors"),
TraceLoggingBoolean(settings.appLastZone_moveWindows, "MoveWindowsToLastZoneOnAppOpening"),
TraceLoggingBoolean(settings.openWindowOnActiveMonitor, "OpenWindowOnActiveMonitor"),
TraceLoggingBoolean(settings.restoreSize, "RestoreSize"),
TraceLoggingBoolean(settings.use_cursorpos_editor_startupscreen, "UseCursorPosOnEditorStartup"),
TraceLoggingBoolean(settings.showZonesOnAllMonitors, "ShowZonesOnAllMonitors"),
TraceLoggingBoolean(settings.spanZonesAcrossMonitors, "SpanZonesAcrossMonitors"),
TraceLoggingBoolean(settings.makeDraggedWindowTransparent, "MakeDraggedWindowTransparent"),
TraceLoggingWideString(settings.zoneColor.c_str(), "ZoneColor"),
TraceLoggingWideString(settings.zoneBorderColor.c_str(), "ZoneBorderColor"),
TraceLoggingWideString(settings.zoneHighlightColor.c_str(), "ZoneHighlightColor"),
TraceLoggingInt32(settings.zoneHighlightOpacity, "ZoneHighlightOpacity"),
TraceLoggingWideString(hotkeyStr.c_str(), "Hotkey"),
TraceLoggingInt32(static_cast<int>(settings.excludedAppsArray.size()), "ExcludedAppsCount"));
TraceLoggingBoolean(settings.shiftDrag, ShiftDragKey),
TraceLoggingBoolean(settings.mouseSwitch, MouseSwitchKey),
TraceLoggingBoolean(settings.displayChange_moveWindows, MoveWindowsOnDisplayChangeKey),
TraceLoggingBoolean(settings.zoneSetChange_flashZones, FlashZonesOnZoneSetChangeKey),
TraceLoggingBoolean(settings.zoneSetChange_moveWindows, MoveWindowsOnZoneSetChangeKey),
TraceLoggingBoolean(settings.overrideSnapHotkeys, OverrideSnapHotKeysKey),
TraceLoggingBoolean(settings.moveWindowAcrossMonitors, MoveWindowAcrossMonitorsKey),
TraceLoggingBoolean(settings.appLastZone_moveWindows, MoveWindowsToLastZoneOnAppOpeningKey),
TraceLoggingBoolean(settings.openWindowOnActiveMonitor, OpenWindowOnActiveMonitorKey),
TraceLoggingBoolean(settings.restoreSize, RestoreSizeKey),
TraceLoggingBoolean(settings.use_cursorpos_editor_startupscreen, UseCursorPosOnEditorStartupKey),
TraceLoggingBoolean(settings.showZonesOnAllMonitors, ShowZonesOnAllMonitorsKey),
TraceLoggingBoolean(settings.spanZonesAcrossMonitors, SpanZonesAcrossMonitorsKey),
TraceLoggingBoolean(settings.makeDraggedWindowTransparent, MakeDraggedWindowTransparentKey),
TraceLoggingWideString(settings.zoneColor.c_str(), ZoneColorKey),
TraceLoggingWideString(settings.zoneBorderColor.c_str(), ZoneBorderColorKey),
TraceLoggingWideString(settings.zoneHighlightColor.c_str(), ZoneHighlightColorKey),
TraceLoggingInt32(settings.zoneHighlightOpacity, ZoneHighlightOpacityKey),
TraceLoggingWideString(hotkeyStr.c_str(), HotkeyKey),
TraceLoggingInt32(static_cast<int>(settings.excludedAppsArray.size()), ExcludedAppsCountKey));
}
void Trace::VirtualDesktopChanged() noexcept
{
TraceLoggingWrite(
g_hProvider,
"FancyZones_VirtualDesktopChanged",
EventDesktopChangedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}
@ -212,10 +262,10 @@ void Trace::ZoneWindow::KeyUp(WPARAM wParam) noexcept
{
TraceLoggingWrite(
g_hProvider,
"FancyZones_ZoneWindowKeyUp",
EventZoneWindowKeyUpKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(wParam, "KeyboardValue"));
TraceLoggingValue(wParam, KeyboardValueKey));
}
void Trace::ZoneWindow::MoveSizeEnd(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept
@ -223,12 +273,12 @@ void Trace::ZoneWindow::MoveSizeEnd(_In_opt_ winrt::com_ptr<IZoneSet> activeSet)
auto const zoneInfo = GetZoneSetInfo(activeSet);
TraceLoggingWrite(
g_hProvider,
"FancyZones_MoveSizeEnd",
EventMoveSizeEndKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(reinterpret_cast<void*>(activeSet.get()), "ActiveSet"),
TraceLoggingValue(zoneInfo.NumberOfZones, "NumberOfZones"),
TraceLoggingValue(zoneInfo.NumberOfWindows, "NumberOfWindows"));
TraceLoggingValue(reinterpret_cast<void*>(activeSet.get()), ActiveSetKey),
TraceLoggingValue(zoneInfo.NumberOfZones, NumberOfZonesKey),
TraceLoggingValue(zoneInfo.NumberOfWindows, NumberOfWindowsKey));
}
void Trace::ZoneWindow::CycleActiveZoneSet(_In_opt_ winrt::com_ptr<IZoneSet> activeSet, InputMode mode) noexcept
@ -236,11 +286,11 @@ void Trace::ZoneWindow::CycleActiveZoneSet(_In_opt_ winrt::com_ptr<IZoneSet> act
auto const zoneInfo = GetZoneSetInfo(activeSet);
TraceLoggingWrite(
g_hProvider,
"FancyZones_CycleActiveZoneSet",
EventCycleActiveZoneSetKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(reinterpret_cast<void*>(activeSet.get()), "ActiveSet"),
TraceLoggingValue(zoneInfo.NumberOfZones, "NumberOfZones"),
TraceLoggingValue(zoneInfo.NumberOfWindows, "NumberOfWindows"),
TraceLoggingValue(static_cast<int>(mode), "InputMode"));
TraceLoggingValue(reinterpret_cast<void*>(activeSet.get()), ActiveSetKey),
TraceLoggingValue(zoneInfo.NumberOfZones, NumberOfZonesKey),
TraceLoggingValue(zoneInfo.NumberOfWindows, NumberOfWindowsKey),
TraceLoggingValue(static_cast<int>(mode), InputModeKey));
}

View File

@ -7,10 +7,11 @@
#include <sstream>
namespace
// Non-Localizable strings
namespace NonLocalizable
{
const wchar_t POWER_TOYS_APP_POWER_LAUCHER[] = L"POWERLAUNCHER.EXE";
const wchar_t POWER_TOYS_APP_FANCY_ZONES_EDITOR[] = L"FANCYZONESEDITOR.EXE";
const wchar_t PowerToysAppPowerLauncher[] = L"POWERLAUNCHER.EXE";
const wchar_t PowerToysAppFZEditor[] = L"FANCYZONESEDITOR.EXE";
}
typedef BOOL(WINAPI* GetDpiForMonitorInternalFunc)(HMONITOR, UINT, UINT*, UINT*);
@ -167,11 +168,11 @@ bool IsInterestingWindow(HWND window, const std::vector<std::wstring>& excludedA
{
return false;
}
if (find_app_name_in_path(filtered.process_path, { POWER_TOYS_APP_POWER_LAUCHER }))
if (find_app_name_in_path(filtered.process_path, { NonLocalizable::PowerToysAppPowerLauncher }))
{
return false;
}
if (find_app_name_in_path(filtered.process_path, { POWER_TOYS_APP_FANCY_ZONES_EDITOR }))
if (find_app_name_in_path(filtered.process_path, { NonLocalizable::PowerToysAppFZEditor }))
{
return false;
}
@ -191,7 +192,7 @@ bool IsWindowMaximized(HWND window) noexcept
void SaveWindowSizeAndOrigin(HWND window) noexcept
{
HANDLE handle = GetPropW(window, RESTORE_SIZE_STAMP);
HANDLE handle = GetPropW(window, ZonedWindowProperties::PropertyRestoreSizeID);
if (handle)
{
// Size already set, skip
@ -213,15 +214,15 @@ void SaveWindowSizeAndOrigin(HWND window) noexcept
std::array<int, 2> windowOriginData = { originX, originY };
HANDLE rawData;
memcpy(&rawData, windowSizeData.data(), sizeof rawData);
SetPropW(window, RESTORE_SIZE_STAMP, rawData);
SetPropW(window, ZonedWindowProperties::PropertyRestoreSizeID, rawData);
memcpy(&rawData, windowOriginData.data(), sizeof rawData);
SetPropW(window, RESTORE_ORIGIN_STAMP, rawData);
SetPropW(window, ZonedWindowProperties::PropertyRestoreOriginID, rawData);
}
}
void RestoreWindowSize(HWND window) noexcept
{
auto windowSizeData = GetPropW(window, RESTORE_SIZE_STAMP);
auto windowSizeData = GetPropW(window, ZonedWindowProperties::PropertyRestoreSizeID);
if (windowSizeData)
{
std::array<int, 2> windowSize;
@ -238,13 +239,13 @@ void RestoreWindowSize(HWND window) noexcept
SizeWindowToRect(window, rect);
}
::RemoveProp(window, RESTORE_SIZE_STAMP);
::RemoveProp(window, ZonedWindowProperties::PropertyRestoreSizeID);
}
}
void RestoreWindowOrigin(HWND window) noexcept
{
auto windowOriginData = GetPropW(window, RESTORE_ORIGIN_STAMP);
auto windowOriginData = GetPropW(window, ZonedWindowProperties::PropertyRestoreOriginID);
if (windowOriginData)
{
std::array<int, 2> windowOrigin;
@ -266,7 +267,7 @@ void RestoreWindowOrigin(HWND window) noexcept
SizeWindowToRect(window, rect);
}
::RemoveProp(window, RESTORE_ORIGIN_STAMP);
::RemoveProp(window, ZonedWindowProperties::PropertyRestoreOriginID);
}
}