mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
Fix for different per-monitor scaling (#657)
* Use DPIAware::DEFAULT_DPI * Make runner DPI-unaware, since it doesn't need to use a Per Monitor V2 DPI. * Programmatically enable "Per Monitor V2 DPI" for the runner proccess and use a separate DPI-unaware thread for the corresponding API calls * Increase PCH memory limit for settings project * Address review issues * Draw zoneWindows properly scaled
This commit is contained in:
@@ -98,6 +98,7 @@
|
||||
<ClInclude Include="d2d_window.h" />
|
||||
<ClInclude Include="dpi_aware.h" />
|
||||
<ClInclude Include="monitors.h" />
|
||||
<ClInclude Include="on_thread_executor.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="settings_helpers.h" />
|
||||
<ClInclude Include="settings_objects.h" />
|
||||
@@ -117,6 +118,7 @@
|
||||
<ClCompile Include="d2d_window.cpp" />
|
||||
<ClCompile Include="dpi_aware.cpp" />
|
||||
<ClCompile Include="monitors.cpp" />
|
||||
<ClCompile Include="on_thread_executor.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
<ClInclude Include="version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="on_thread_executor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="d2d_svg.cpp">
|
||||
@@ -108,5 +111,8 @@
|
||||
<ClCompile Include="dpi_aware.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="on_thread_executor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -37,4 +37,8 @@ void DPIAware::Convert(HMONITOR monitor_handle, int &width, int &height) {
|
||||
width = width * dpi_x / DEFAULT_DPI;
|
||||
height = height * dpi_y / DEFAULT_DPI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DPIAware::EnableDPIAwarenessForThisProcess() {
|
||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
#pragma once
|
||||
#include "windef.h"
|
||||
|
||||
class DPIAware {
|
||||
private:
|
||||
static const int DEFAULT_DPI = 96;
|
||||
struct DPIAware {
|
||||
static constexpr int DEFAULT_DPI = 96;
|
||||
|
||||
public:
|
||||
static HRESULT GetScreenDPIForWindow(HWND hwnd, UINT & dpi_x, UINT & dpi_y);
|
||||
static HRESULT GetScreenDPIForPoint(POINT p, UINT& dpi_x, UINT& dpi_y);
|
||||
static void Convert(HMONITOR monitor_handle, int &width, int &height);
|
||||
static void EnableDPIAwarenessForThisProcess();
|
||||
};
|
||||
|
||||
38
src/common/on_thread_executor.cpp
Normal file
38
src/common/on_thread_executor.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "on_thread_executor.h"
|
||||
|
||||
OnThreadExecutor::OnThreadExecutor()
|
||||
:_worker_thread{[this]() { worker_thread(); }}
|
||||
{}
|
||||
|
||||
std::future<void> OnThreadExecutor::submit(task_t task) {
|
||||
auto future = task.get_future();
|
||||
std::lock_guard lock{_task_mutex};
|
||||
_task_queue.emplace(std::move(task));
|
||||
_task_cv.notify_one();
|
||||
return future;
|
||||
}
|
||||
|
||||
void OnThreadExecutor::worker_thread() {
|
||||
while(_active) {
|
||||
task_t task;
|
||||
{
|
||||
std::unique_lock task_lock{_task_mutex};
|
||||
_task_cv.wait(task_lock, [this] { return !_task_queue.empty() || !_active; });
|
||||
if(!_active) {
|
||||
break;
|
||||
}
|
||||
task = std::move(_task_queue.front());
|
||||
_task_queue.pop();
|
||||
}
|
||||
task();
|
||||
}
|
||||
}
|
||||
|
||||
OnThreadExecutor::~OnThreadExecutor() {
|
||||
_active = false;
|
||||
_task_cv.notify_one();
|
||||
_worker_thread.join();
|
||||
}
|
||||
|
||||
30
src/common/on_thread_executor.h
Normal file
30
src/common/on_thread_executor.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <future>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <atomic>
|
||||
|
||||
// OnThreadExecutor allows its caller to off-load some work to a persistently running background thread.
|
||||
// This might come in handy if you use the API which sets thread-wide global state and the state needs
|
||||
// to be isolated.
|
||||
|
||||
class OnThreadExecutor final {
|
||||
public:
|
||||
using task_t = std::packaged_task<void()>;
|
||||
|
||||
OnThreadExecutor();
|
||||
~OnThreadExecutor();
|
||||
std::future<void> submit(task_t task);
|
||||
|
||||
private:
|
||||
void worker_thread();
|
||||
|
||||
std::thread _worker_thread;
|
||||
|
||||
std::mutex _task_mutex;
|
||||
std::condition_variable _task_cv;
|
||||
std::atomic_bool _active;
|
||||
std::queue<std::packaged_task<void()>> _task_queue;
|
||||
};
|
||||
@@ -23,6 +23,9 @@ namespace FancyZonesEditor
|
||||
/// </summary>
|
||||
public partial class MainWindow : MetroWindow
|
||||
{
|
||||
// TODO: share the constants b/w C# Editor and FancyZoneLib
|
||||
public static int MAX_ZONES = 40;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -57,7 +60,7 @@ namespace FancyZonesEditor
|
||||
|
||||
private void IncrementZones_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_settings.ZoneCount < 40)
|
||||
if (_settings.ZoneCount < MAX_ZONES)
|
||||
{
|
||||
_settings.ZoneCount++;
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ namespace FancyZonesEditor
|
||||
// 1 = unique key for per-monitor settings
|
||||
// 2 = layoutid used to generate current layout (used to pick the default layout to show)
|
||||
// 3 = handle to monitor (passed back to engine to persist data)
|
||||
// 4 = X_Y_Width_Height (where EditorOverlay shows up)
|
||||
// 4 = X_Y_Width_Height in a dpi-scaled-but-unaware coords (where EditorOverlay shows up)
|
||||
// 5 = resolution key (passed back to engine to persist data)
|
||||
// 6 = monitor DPI (float)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "common/dpi_aware.h"
|
||||
#include "common/on_thread_executor.h"
|
||||
|
||||
struct FancyZones : public winrt::implements<FancyZones, IFancyZones, IFancyZonesCallback, IZoneWindowHost>
|
||||
{
|
||||
@@ -88,6 +89,8 @@ private:
|
||||
GUID m_currentVirtualDesktopId{};
|
||||
wil::unique_handle m_terminateEditorEvent;
|
||||
|
||||
OnThreadExecutor m_dpiUnawareThread;
|
||||
|
||||
static UINT WM_PRIV_VDCHANGED;
|
||||
static UINT WM_PRIV_EDITOR;
|
||||
|
||||
@@ -120,6 +123,11 @@ IFACEMETHODIMP_(void) FancyZones::Run() noexcept
|
||||
|
||||
RegisterHotKey(m_window, 1, m_settings->GetSettings().editorHotkey.get_modifiers(), m_settings->GetSettings().editorHotkey.get_code());
|
||||
VirtualDesktopChanged();
|
||||
|
||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{[]{
|
||||
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR_MIXED);
|
||||
}}).wait();
|
||||
}
|
||||
|
||||
// IFancyZones
|
||||
@@ -239,22 +247,22 @@ void FancyZones::ToggleEditor() noexcept
|
||||
}
|
||||
|
||||
HMONITOR monitor{};
|
||||
UINT dpi_x = 96;
|
||||
UINT dpi_y = 96;
|
||||
HWND foregroundWindow{};
|
||||
|
||||
if (m_settings->GetSettings().use_cursorpos_editor_startupscreen)
|
||||
UINT dpi_x = DPIAware::DEFAULT_DPI;
|
||||
UINT dpi_y = DPIAware::DEFAULT_DPI;
|
||||
|
||||
const bool use_cursorpos_editor_startupscreen = m_settings->GetSettings().use_cursorpos_editor_startupscreen;
|
||||
POINT currentCursorPos{};
|
||||
if (use_cursorpos_editor_startupscreen)
|
||||
{
|
||||
POINT currentCursorPos{};
|
||||
GetCursorPos(¤tCursorPos);
|
||||
|
||||
monitor = MonitorFromPoint(currentCursorPos, MONITOR_DEFAULTTOPRIMARY);
|
||||
DPIAware::GetScreenDPIForPoint(currentCursorPos, dpi_x, dpi_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
const HWND foregroundWindow = GetForegroundWindow();
|
||||
foregroundWindow = GetForegroundWindow();
|
||||
monitor = MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTOPRIMARY);
|
||||
DPIAware::GetScreenDPIForWindow(foregroundWindow, dpi_x, dpi_y);
|
||||
}
|
||||
|
||||
|
||||
@@ -272,21 +280,33 @@ void FancyZones::ToggleEditor() noexcept
|
||||
|
||||
MONITORINFOEX mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(monitor, &mi);
|
||||
|
||||
// X/Y need to start in unscaled screen coordinates to get to the proper top/left of the monitor
|
||||
// From there, we need to scale the difference between the monitor and workarea rects to get the
|
||||
// appropriate offset where the overlay should appear.
|
||||
// This covers the cases where the taskbar is not at the bottom of the screen.
|
||||
const auto x = mi.rcMonitor.left + MulDiv(mi.rcWork.left - mi.rcMonitor.left, 96, dpi_x);
|
||||
const auto y = mi.rcMonitor.top + MulDiv(mi.rcWork.top - mi.rcMonitor.top, 96, dpi_y);
|
||||
m_dpiUnawareThread.submit(OnThreadExecutor::task_t{[&]{
|
||||
GetMonitorInfo(monitor, &mi);
|
||||
}}).wait();
|
||||
|
||||
// Location that the editor should occupy, scaled by DPI
|
||||
std::wstring editorLocation =
|
||||
if(use_cursorpos_editor_startupscreen)
|
||||
{
|
||||
DPIAware::GetScreenDPIForPoint(currentCursorPos, dpi_x, dpi_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPIAware::GetScreenDPIForWindow(foregroundWindow, dpi_x, dpi_y);
|
||||
}
|
||||
|
||||
const auto taskbar_x_offset = MulDiv(mi.rcWork.left - mi.rcMonitor.left, DPIAware::DEFAULT_DPI, dpi_x);
|
||||
const auto taskbar_y_offset = MulDiv(mi.rcWork.top - mi.rcMonitor.top, DPIAware::DEFAULT_DPI, dpi_y);
|
||||
|
||||
// Do not scale window params by the dpi, that will be done in the editor - see LayoutModel.Apply
|
||||
const auto x = mi.rcMonitor.left + taskbar_x_offset;
|
||||
const auto y = mi.rcMonitor.top + taskbar_y_offset;
|
||||
const auto width = mi.rcWork.right - mi.rcWork.left;
|
||||
const auto height = mi.rcWork.bottom - mi.rcWork.top;
|
||||
const std::wstring editorLocation =
|
||||
std::to_wstring(x) + L"_" +
|
||||
std::to_wstring(y) + L"_" +
|
||||
std::to_wstring(MulDiv(mi.rcWork.right - mi.rcWork.left, 96, dpi_x)) + L"_" +
|
||||
std::to_wstring(MulDiv(mi.rcWork.bottom - mi.rcWork.top, 96, dpi_y));
|
||||
std::to_wstring(width) + L"_" +
|
||||
std::to_wstring(height);
|
||||
|
||||
const std::wstring params =
|
||||
iter->second->UniqueId() + L" " +
|
||||
@@ -294,7 +314,7 @@ void FancyZones::ToggleEditor() noexcept
|
||||
std::to_wstring(reinterpret_cast<UINT_PTR>(monitor)) + L" " +
|
||||
editorLocation + L" " +
|
||||
iter->second->WorkAreaKey() + L" " +
|
||||
std::to_wstring(static_cast<float>(dpi_x) / 96.0f);
|
||||
std::to_wstring(static_cast<float>(dpi_x) / DPIAware::DEFAULT_DPI);
|
||||
|
||||
SHELLEXECUTEINFO sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
@@ -652,34 +672,40 @@ void FancyZones::MoveSizeStartInternal(HWND window, HMONITOR monitor, POINT cons
|
||||
RECT windowRect{};
|
||||
::GetWindowRect(window, &windowRect);
|
||||
|
||||
windowRect.top += 6;
|
||||
windowRect.left += 8;
|
||||
windowRect.right -= 8;
|
||||
windowRect.bottom -= 6;
|
||||
const auto padding_x = 8;
|
||||
const auto padding_y = 6;
|
||||
windowRect.top += padding_y;
|
||||
windowRect.left += padding_x;
|
||||
windowRect.right -= padding_x;
|
||||
windowRect.bottom -= padding_y;
|
||||
|
||||
if (PtInRect(&windowRect, ptScreen))
|
||||
if (PtInRect(&windowRect, ptScreen) == FALSE)
|
||||
{
|
||||
m_inMoveSize = true;
|
||||
return;
|
||||
}
|
||||
|
||||
auto iter = m_zoneWindowMap.find(monitor);
|
||||
if (iter != m_zoneWindowMap.end())
|
||||
{
|
||||
m_windowMoveSize = window;
|
||||
m_inMoveSize = true;
|
||||
|
||||
// This updates m_dragEnabled depending on if the shift key is being held down.
|
||||
UpdateDragState(writeLock);
|
||||
auto iter = m_zoneWindowMap.find(monitor);
|
||||
if (iter == end(m_zoneWindowMap))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_dragEnabled)
|
||||
{
|
||||
m_zoneWindowMoveSize = iter->second;
|
||||
m_zoneWindowMoveSize->MoveSizeEnter(window, m_dragEnabled);
|
||||
}
|
||||
else if (m_zoneWindowMoveSize)
|
||||
{
|
||||
m_zoneWindowMoveSize->MoveSizeCancel();
|
||||
m_zoneWindowMoveSize = nullptr;
|
||||
}
|
||||
}
|
||||
m_windowMoveSize = window;
|
||||
|
||||
// This updates m_dragEnabled depending on if the shift key is being held down.
|
||||
UpdateDragState(writeLock);
|
||||
|
||||
if (m_dragEnabled)
|
||||
{
|
||||
m_zoneWindowMoveSize = iter->second;
|
||||
m_zoneWindowMoveSize->MoveSizeEnter(window, m_dragEnabled);
|
||||
}
|
||||
else if (m_zoneWindowMoveSize)
|
||||
{
|
||||
m_zoneWindowMoveSize->MoveSizeCancel();
|
||||
m_zoneWindowMoveSize = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,13 +34,15 @@ interface __declspec(uuid("{E4839EB7-669D-49CF-84A9-71A2DFD851A3}")) IZoneSet :
|
||||
#define VERSION_PERSISTEDDATA 0x0000F00D
|
||||
struct ZoneSetPersistedData
|
||||
{
|
||||
static constexpr inline size_t MAX_ZONES = 40;
|
||||
|
||||
DWORD Version{VERSION_PERSISTEDDATA};
|
||||
WORD LayoutId{};
|
||||
DWORD ZoneCount{};
|
||||
ZoneSetLayout Layout{};
|
||||
DWORD PaddingInner{};
|
||||
DWORD PaddingOuter{};
|
||||
RECT Zones[40]{};
|
||||
RECT Zones[MAX_ZONES]{};
|
||||
};
|
||||
|
||||
struct ZoneSetConfig
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include <common/dpi_aware.h>
|
||||
|
||||
#include <ShellScalingApi.h>
|
||||
|
||||
struct ZoneWindow : public winrt::implements<ZoneWindow, IZoneWindow>
|
||||
@@ -116,78 +118,79 @@ ZoneWindow::ZoneWindow(
|
||||
|
||||
MONITORINFO mi{};
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (GetMonitorInfoW(m_monitor, &mi))
|
||||
if (!GetMonitorInfoW(m_monitor, &mi))
|
||||
{
|
||||
const UINT dpi = GetDpiForMonitor();
|
||||
const Rect monitorRect(mi.rcMonitor);
|
||||
const Rect workAreaRect(mi.rcWork, dpi);
|
||||
return;
|
||||
}
|
||||
const UINT dpi = GetDpiForMonitor();
|
||||
const Rect monitorRect(mi.rcMonitor);
|
||||
const Rect workAreaRect(mi.rcWork, dpi);
|
||||
|
||||
StringCchPrintf(m_workArea, ARRAYSIZE(m_workArea), L"%d_%d", monitorRect.width(), monitorRect.height());
|
||||
StringCchPrintf(m_workArea, ARRAYSIZE(m_workArea), L"%d_%d", monitorRect.width(), monitorRect.height());
|
||||
|
||||
InitializeId(deviceId, virtualDesktopId);
|
||||
LoadSettings();
|
||||
InitializeZoneSets();
|
||||
InitializeId(deviceId, virtualDesktopId);
|
||||
LoadSettings();
|
||||
InitializeZoneSets();
|
||||
|
||||
WNDCLASSEXW wcex{};
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.lpfnWndProc = s_WndProc;
|
||||
wcex.hInstance = hinstance;
|
||||
wcex.lpszClassName = L"SuperFancyZones_ZoneWindow";
|
||||
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
|
||||
RegisterClassExW(&wcex);
|
||||
WNDCLASSEXW wcex{};
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.lpfnWndProc = s_WndProc;
|
||||
wcex.hInstance = hinstance;
|
||||
wcex.lpszClassName = L"SuperFancyZones_ZoneWindow";
|
||||
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
|
||||
RegisterClassExW(&wcex);
|
||||
|
||||
m_window = wil::unique_hwnd {
|
||||
CreateWindowExW(WS_EX_TOOLWINDOW, L"SuperFancyZones_ZoneWindow", L"", WS_POPUP,
|
||||
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)
|
||||
};
|
||||
};
|
||||
|
||||
if (m_window)
|
||||
if (m_window)
|
||||
{
|
||||
MakeWindowTransparent(m_window.get());
|
||||
UpdateGrid(0, 0);
|
||||
if (flashZones)
|
||||
{
|
||||
MakeWindowTransparent(m_window.get());
|
||||
UpdateGrid(0, 0);
|
||||
if (flashZones)
|
||||
{
|
||||
FlashZones();
|
||||
}
|
||||
FlashZones();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ZoneWindow::ShowZoneWindow(bool activate, bool fadeIn) noexcept
|
||||
{
|
||||
if (m_window)
|
||||
if (!m_window)
|
||||
{
|
||||
m_flashMode = false;
|
||||
|
||||
UINT flags = SWP_NOSIZE | SWP_NOMOVE;
|
||||
if (!activate)
|
||||
{
|
||||
WI_SetFlag(flags, SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
if (!fadeIn)
|
||||
{
|
||||
WI_SetFlag(flags, SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
HWND windowInsertAfter = m_windowMoveSize;
|
||||
if (windowInsertAfter == nullptr)
|
||||
{
|
||||
windowInsertAfter = HWND_TOPMOST;
|
||||
}
|
||||
|
||||
SetWindowPos(m_window.get(), windowInsertAfter, 0, 0, 0, 0, flags);
|
||||
|
||||
if (fadeIn)
|
||||
{
|
||||
AnimateWindow(m_window.get(), m_showAnimationDuration, AW_BLEND);
|
||||
InvalidateRect(m_window.get(), nullptr, true);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return E_FAIL;
|
||||
}
|
||||
return E_FAIL;
|
||||
|
||||
m_flashMode = false;
|
||||
|
||||
UINT flags = SWP_NOSIZE | SWP_NOMOVE;
|
||||
if (!activate)
|
||||
{
|
||||
WI_SetFlag(flags, SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
if (!fadeIn)
|
||||
{
|
||||
WI_SetFlag(flags, SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
HWND windowInsertAfter = m_windowMoveSize;
|
||||
if (windowInsertAfter == nullptr)
|
||||
{
|
||||
windowInsertAfter = HWND_TOPMOST;
|
||||
}
|
||||
|
||||
SetWindowPos(m_window.get(), windowInsertAfter, 0, 0, 0, 0, flags);
|
||||
|
||||
if (fadeIn)
|
||||
{
|
||||
AnimateWindow(m_window.get(), m_showAnimationDuration, AW_BLEND);
|
||||
InvalidateRect(m_window.get(), nullptr, true);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ZoneWindow::HideZoneWindow() noexcept
|
||||
@@ -356,54 +359,56 @@ void ZoneWindow::InitializeZoneSets() noexcept
|
||||
|
||||
void ZoneWindow::LoadZoneSetsFromRegistry() noexcept
|
||||
{
|
||||
if (wil::unique_hkey key{ RegistryHelpers::OpenKey(m_workArea) })
|
||||
wil::unique_hkey key{RegistryHelpers::OpenKey(m_workArea)};
|
||||
if (!key)
|
||||
{
|
||||
ZoneSetPersistedData data{};
|
||||
DWORD dataSize = sizeof(data);
|
||||
wchar_t value[256]{};
|
||||
DWORD valueLength = ARRAYSIZE(value);
|
||||
DWORD i = 0;
|
||||
while (RegEnumValueW(key.get(), i++, value, &valueLength, nullptr, nullptr, reinterpret_cast<BYTE*>(&data), &dataSize) == ERROR_SUCCESS)
|
||||
return;
|
||||
}
|
||||
ZoneSetPersistedData data{};
|
||||
DWORD dataSize = sizeof(data);
|
||||
wchar_t value[256]{};
|
||||
DWORD valueLength = ARRAYSIZE(value);
|
||||
DWORD i = 0;
|
||||
while (RegEnumValueW(key.get(), i++, value, &valueLength, nullptr, nullptr, reinterpret_cast<BYTE*>(&data), &dataSize) == ERROR_SUCCESS)
|
||||
{
|
||||
if (data.Version == VERSION_PERSISTEDDATA)
|
||||
{
|
||||
if (data.Version == VERSION_PERSISTEDDATA)
|
||||
GUID zoneSetId;
|
||||
if (SUCCEEDED_LOG(CLSIDFromString(value, &zoneSetId)))
|
||||
{
|
||||
GUID zoneSetId;
|
||||
if (SUCCEEDED_LOG(CLSIDFromString(value, &zoneSetId)))
|
||||
auto zoneSet = MakeZoneSet(ZoneSetConfig(
|
||||
zoneSetId,
|
||||
data.LayoutId,
|
||||
m_monitor,
|
||||
m_workArea,
|
||||
data.Layout,
|
||||
0,
|
||||
static_cast<int>(data.PaddingInner),
|
||||
static_cast<int>(data.PaddingOuter)));
|
||||
|
||||
if (zoneSet)
|
||||
{
|
||||
auto zoneSet = MakeZoneSet(ZoneSetConfig(
|
||||
zoneSetId,
|
||||
data.LayoutId,
|
||||
m_monitor,
|
||||
m_workArea,
|
||||
data.Layout,
|
||||
0,
|
||||
static_cast<int>(data.PaddingInner),
|
||||
static_cast<int>(data.PaddingOuter)));
|
||||
|
||||
if (zoneSet)
|
||||
for (UINT j = 0; j < data.ZoneCount; j++)
|
||||
{
|
||||
for (UINT j = 0; j < data.ZoneCount; j++)
|
||||
{
|
||||
zoneSet->AddZone(MakeZone(data.Zones[j]), false);
|
||||
}
|
||||
|
||||
m_zoneSets.emplace_back(zoneSet);
|
||||
|
||||
if (zoneSetId == m_activeZoneSetId)
|
||||
{
|
||||
UpdateActiveZoneSet(zoneSet.get());
|
||||
}
|
||||
zoneSet->AddZone(MakeZone(data.Zones[j]), false);
|
||||
}
|
||||
|
||||
if (zoneSetId == m_activeZoneSetId)
|
||||
{
|
||||
UpdateActiveZoneSet(zoneSet.get());
|
||||
}
|
||||
|
||||
m_zoneSets.emplace_back(std::move(zoneSet));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Migrate from older settings format
|
||||
}
|
||||
|
||||
valueLength = ARRAYSIZE(value);
|
||||
dataSize = sizeof(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Migrate from older settings format
|
||||
}
|
||||
|
||||
valueLength = ARRAYSIZE(value);
|
||||
dataSize = sizeof(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,37 +721,38 @@ void ZoneWindow::DrawZone(wil::unique_hdc& hdc, ColorSetting const& colorSetting
|
||||
}
|
||||
FillRectARGB(hdc, &zoneRect, colorSetting.fillAlpha, colorSetting.fill, false);
|
||||
|
||||
if (!m_flashMode)
|
||||
if (m_flashMode)
|
||||
{
|
||||
COLORREF const colorFill = RGB(255, 255, 255);
|
||||
|
||||
size_t const index = zone->Id();
|
||||
int const padding = 5;
|
||||
int const size = 10;
|
||||
POINT offset = { zoneRect.left + padding, zoneRect.top + padding };
|
||||
if (!IsOccluded(offset, index))
|
||||
{
|
||||
DrawIndex(hdc, offset, index, padding, size, false, false, colorFill); // top left
|
||||
return;
|
||||
}
|
||||
|
||||
offset.x = zoneRect.right - ((padding + size) * 3);
|
||||
if (!IsOccluded(offset, index))
|
||||
{
|
||||
DrawIndex(hdc, offset, index, padding, size, true, false, colorFill); // top right
|
||||
return;
|
||||
}
|
||||
|
||||
offset.y = zoneRect.bottom - ((padding + size) * 3);
|
||||
if (!IsOccluded(offset, index))
|
||||
{
|
||||
DrawIndex(hdc, offset, index, padding, size, true, true, colorFill); // bottom right
|
||||
return;
|
||||
}
|
||||
|
||||
offset.x = zoneRect.left + padding;
|
||||
DrawIndex(hdc, offset, index, padding, size, false, true, colorFill); // bottom left
|
||||
return;
|
||||
}
|
||||
COLORREF const colorFill = RGB(255, 255, 255);
|
||||
|
||||
size_t const index = zone->Id();
|
||||
int const padding = 5;
|
||||
int const size = 10;
|
||||
POINT offset = { zoneRect.left + padding, zoneRect.top + padding };
|
||||
if (!IsOccluded(offset, index))
|
||||
{
|
||||
DrawIndex(hdc, offset, index, padding, size, false, false, colorFill); // top left
|
||||
return;
|
||||
}
|
||||
|
||||
offset.x = zoneRect.right - ((padding + size) * 3);
|
||||
if (!IsOccluded(offset, index))
|
||||
{
|
||||
DrawIndex(hdc, offset, index, padding, size, true, false, colorFill); // top right
|
||||
return;
|
||||
}
|
||||
|
||||
offset.y = zoneRect.bottom - ((padding + size) * 3);
|
||||
if (!IsOccluded(offset, index))
|
||||
{
|
||||
DrawIndex(hdc, offset, index, padding, size, true, true, colorFill); // bottom right
|
||||
return;
|
||||
}
|
||||
|
||||
offset.x = zoneRect.left + padding;
|
||||
DrawIndex(hdc, offset, index, padding, size, false, true, colorFill); // bottom left
|
||||
}
|
||||
|
||||
void ZoneWindow::DrawIndex(wil::unique_hdc& hdc, POINT offset, size_t index, int padding, int size, bool flipX, bool flipY, COLORREF colorFill)
|
||||
@@ -933,7 +939,7 @@ void ZoneWindow::OnPaint(wil::unique_hdc& hdc) noexcept
|
||||
RECT clientRect;
|
||||
GetClientRect(m_window.get(), &clientRect);
|
||||
|
||||
wil::unique_hdc hdcMem;;
|
||||
wil::unique_hdc hdcMem;
|
||||
HPAINTBUFFER bufferedPaint = BeginBufferedPaint(hdc.get(), &clientRect, BPBF_TOPDOWNDIB, nullptr, &hdcMem);
|
||||
if (bufferedPaint)
|
||||
{
|
||||
@@ -1287,7 +1293,7 @@ UINT ZoneWindow::GetDpiForMonitor() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
return (dpi == 0) ? 96 : dpi;
|
||||
return (dpi == 0) ? DPIAware::DEFAULT_DPI : dpi;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "trace.h"
|
||||
#include "general_settings.h"
|
||||
|
||||
#include <common/dpi_aware.h>
|
||||
|
||||
#if _DEBUG && _WIN64
|
||||
#include "unhandled_exception_handler.h"
|
||||
#endif
|
||||
@@ -31,6 +33,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
// The app is already running
|
||||
return 0;
|
||||
}
|
||||
|
||||
DPIAware::EnableDPIAwarenessForThisProcess();
|
||||
|
||||
#if _DEBUG && _WIN64
|
||||
//Global error handlers to diagnose errors.
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
<EnableDpiAwareness>false</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
@@ -92,7 +92,7 @@
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
<Manifest>
|
||||
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
|
||||
<EnableDpiAwareness>false</EnableDpiAwareness>
|
||||
</Manifest>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/Zm150 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<CustomBuildStep>
|
||||
<Command>
|
||||
@@ -88,6 +89,7 @@
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/Zm150 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
|
||||
Reference in New Issue
Block a user