diff --git a/CHANGELOG.md b/CHANGELOG.md
index ee45422..577d2dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,32 @@ All notable changes to ConfigurO are recorded here. The updater reads the
heading for the running version to decide what to show, so keep the
`## [x.y]` format.
+## [3.3]
+
+### Fixes
+- **The whole interface has been rendering at 1.0 scale since 1.0.** The
+ Per-Monitor-V2 switches Windows Forms needs live in `App.config`, and the
+ release ships a single executable with no `ConfigurO.exe.config` beside it.
+ Run that way -- which is how everyone runs it -- `Control.DeviceDpi` answers
+ 96 on every machine, so the layout was computed at 100% and drawn two-thirds
+ size on a 150% display. Not blurry: the manifest still makes the process
+ Per-Monitor-V2 aware, so the window was measured at exactly the size it asked
+ for. Just small and dense, which reads as an older build rather than as a
+ fault. Scale now comes from `GetDpiForWindow`, falling back to
+ `GetDpiForMonitor` on 8.1 and `GetDeviceCaps` before that. Win32 always knew;
+ nothing was asking it. Verified against the bare executable with no config
+ file present: 96/1.00 before, 144/1.50 after.
+- **80 of the 139 app icons were drawn as logos in a black box.** They had been
+ flattened onto an opaque black background with no alpha channel, which is
+ invisible against a black page and a hard black square against the app's
+ `#232532` cards. Alpha is restored by flooding inward from the border, so
+ only black actually connected to the outside is removed and a dark detail
+ inside a mark survives -- Opera keeps its counter, 7-Zip keeps its grey
+ field, Vivaldi keeps its red tile. The one-pixel fringe where each logo was
+ antialiased against the black is un-premultiplied so the edges stay smooth
+ instead of leaving a halo. No black-matted icon remains; the five still
+ without an alpha channel are square by design.
+
## [3.2]
### Fixes
diff --git a/feed/icons.zip b/feed/icons.zip
index e2c57b6..ae12dc2 100644
Binary files a/feed/icons.zip and b/feed/icons.zip differ
diff --git a/feed/icons/7zip.png b/feed/icons/7zip.png
index 2843b65..ac8d043 100644
Binary files a/feed/icons/7zip.png and b/feed/icons/7zip.png differ
diff --git a/feed/icons/adobereader.png b/feed/icons/adobereader.png
index 5194572..878f12d 100644
Binary files a/feed/icons/adobereader.png and b/feed/icons/adobereader.png differ
diff --git a/feed/icons/androidstudio.png b/feed/icons/androidstudio.png
index 63621ca..86d2ed4 100644
Binary files a/feed/icons/androidstudio.png and b/feed/icons/androidstudio.png differ
diff --git a/feed/icons/antiexploit.png b/feed/icons/antiexploit.png
index 50e18ef..439ad1e 100644
Binary files a/feed/icons/antiexploit.png and b/feed/icons/antiexploit.png differ
diff --git a/feed/icons/anydesk.png b/feed/icons/anydesk.png
index b9ee773..76d9108 100644
Binary files a/feed/icons/anydesk.png and b/feed/icons/anydesk.png differ
diff --git a/feed/icons/atom.png b/feed/icons/atom.png
index 52f93ef..1090cf4 100644
Binary files a/feed/icons/atom.png and b/feed/icons/atom.png differ
diff --git a/feed/icons/audacity.png b/feed/icons/audacity.png
index 17b5c3f..177cc02 100644
Binary files a/feed/icons/audacity.png and b/feed/icons/audacity.png differ
diff --git a/feed/icons/balena.png b/feed/icons/balena.png
index b37195c..9134d28 100644
Binary files a/feed/icons/balena.png and b/feed/icons/balena.png differ
diff --git a/feed/icons/bittorrent.png b/feed/icons/bittorrent.png
index 7a6e73d..6726f0f 100644
Binary files a/feed/icons/bittorrent.png and b/feed/icons/bittorrent.png differ
diff --git a/feed/icons/blender.png b/feed/icons/blender.png
index cb4a50f..cd49672 100644
Binary files a/feed/icons/blender.png and b/feed/icons/blender.png differ
diff --git a/feed/icons/bsplayer.png b/feed/icons/bsplayer.png
index 69de023..adc1792 100644
Binary files a/feed/icons/bsplayer.png and b/feed/icons/bsplayer.png differ
diff --git a/feed/icons/chrome.png b/feed/icons/chrome.png
index 1e9a598..047bdf6 100644
Binary files a/feed/icons/chrome.png and b/feed/icons/chrome.png differ
diff --git a/feed/icons/chromium.png b/feed/icons/chromium.png
index 8d6799e..7c01a06 100644
Binary files a/feed/icons/chromium.png and b/feed/icons/chromium.png differ
diff --git a/feed/icons/deluge.png b/feed/icons/deluge.png
index c65ca6f..68a5bc1 100644
Binary files a/feed/icons/deluge.png and b/feed/icons/deluge.png differ
diff --git a/feed/icons/discord.png b/feed/icons/discord.png
index a2704f0..f12f924 100644
Binary files a/feed/icons/discord.png and b/feed/icons/discord.png differ
diff --git a/feed/icons/dropbox.png b/feed/icons/dropbox.png
index 9d99bfe..344d169 100644
Binary files a/feed/icons/dropbox.png and b/feed/icons/dropbox.png differ
diff --git a/feed/icons/eclipse.png b/feed/icons/eclipse.png
index 400b3ae..ba9e513 100644
Binary files a/feed/icons/eclipse.png and b/feed/icons/eclipse.png differ
diff --git a/feed/icons/epic.png b/feed/icons/epic.png
index dbc62e0..e1e9863 100644
Binary files a/feed/icons/epic.png and b/feed/icons/epic.png differ
diff --git a/feed/icons/evernote.png b/feed/icons/evernote.png
index 66c93b1..13418ca 100644
Binary files a/feed/icons/evernote.png and b/feed/icons/evernote.png differ
diff --git a/feed/icons/filezilla.png b/feed/icons/filezilla.png
index fe2f92d..83a70a5 100644
Binary files a/feed/icons/filezilla.png and b/feed/icons/filezilla.png differ
diff --git a/feed/icons/firefox.png b/feed/icons/firefox.png
index 43c35ad..981a9ce 100644
Binary files a/feed/icons/firefox.png and b/feed/icons/firefox.png differ
diff --git a/feed/icons/flux.png b/feed/icons/flux.png
index b3c3d55..3b77afa 100644
Binary files a/feed/icons/flux.png and b/feed/icons/flux.png differ
diff --git a/feed/icons/foobar.png b/feed/icons/foobar.png
index 1a2550b..1060c3a 100644
Binary files a/feed/icons/foobar.png and b/feed/icons/foobar.png differ
diff --git a/feed/icons/foxit.png b/feed/icons/foxit.png
index 48901a6..5671102 100644
Binary files a/feed/icons/foxit.png and b/feed/icons/foxit.png differ
diff --git a/feed/icons/gimp.png b/feed/icons/gimp.png
index 4e09c94..18d1f8b 100644
Binary files a/feed/icons/gimp.png and b/feed/icons/gimp.png differ
diff --git a/feed/icons/github.png b/feed/icons/github.png
index 9082c8c..cba145b 100644
Binary files a/feed/icons/github.png and b/feed/icons/github.png differ
diff --git a/feed/icons/gyazo.png b/feed/icons/gyazo.png
index 42f4944..d309696 100644
Binary files a/feed/icons/gyazo.png and b/feed/icons/gyazo.png differ
diff --git a/feed/icons/iobitdefrag.png b/feed/icons/iobitdefrag.png
index b190056..3c5049d 100644
Binary files a/feed/icons/iobitdefrag.png and b/feed/icons/iobitdefrag.png differ
diff --git a/feed/icons/iobitdrivers.png b/feed/icons/iobitdrivers.png
index 4edf47d..be0f785 100644
Binary files a/feed/icons/iobitdrivers.png and b/feed/icons/iobitdrivers.png differ
diff --git a/feed/icons/iobituninstall.png b/feed/icons/iobituninstall.png
index 68ae310..052010d 100644
Binary files a/feed/icons/iobituninstall.png and b/feed/icons/iobituninstall.png differ
diff --git a/feed/icons/iobitupdater.png b/feed/icons/iobitupdater.png
index 348e77a..0043e25 100644
Binary files a/feed/icons/iobitupdater.png and b/feed/icons/iobitupdater.png differ
diff --git a/feed/icons/irfanview.png b/feed/icons/irfanview.png
index 0a29c6b..c0b4d69 100644
Binary files a/feed/icons/irfanview.png and b/feed/icons/irfanview.png differ
diff --git a/feed/icons/itunes.png b/feed/icons/itunes.png
index 148a944..d92a7f0 100644
Binary files a/feed/icons/itunes.png and b/feed/icons/itunes.png differ
diff --git a/feed/icons/java.png b/feed/icons/java.png
index 0ec7c2d..ceb6b5e 100644
Binary files a/feed/icons/java.png and b/feed/icons/java.png differ
diff --git a/feed/icons/klite.png b/feed/icons/klite.png
index 3ecd3d0..2a0c070 100644
Binary files a/feed/icons/klite.png and b/feed/icons/klite.png differ
diff --git a/feed/icons/libreoffice.png b/feed/icons/libreoffice.png
index 07b1283..341a660 100644
Binary files a/feed/icons/libreoffice.png and b/feed/icons/libreoffice.png differ
diff --git a/feed/icons/lightshot.png b/feed/icons/lightshot.png
index 3e344c1..dfa9a58 100644
Binary files a/feed/icons/lightshot.png and b/feed/icons/lightshot.png differ
diff --git a/feed/icons/malwarebytes.png b/feed/icons/malwarebytes.png
index ca04da3..ab186f1 100644
Binary files a/feed/icons/malwarebytes.png and b/feed/icons/malwarebytes.png differ
diff --git a/feed/icons/maxthon.png b/feed/icons/maxthon.png
index 9e65580..7a6131d 100644
Binary files a/feed/icons/maxthon.png and b/feed/icons/maxthon.png differ
diff --git a/feed/icons/mega.png b/feed/icons/mega.png
index d00027e..95ba6d2 100644
Binary files a/feed/icons/mega.png and b/feed/icons/mega.png differ
diff --git a/feed/icons/mp3tag.png b/feed/icons/mp3tag.png
index 0c6f182..e27f836 100644
Binary files a/feed/icons/mp3tag.png and b/feed/icons/mp3tag.png differ
diff --git a/feed/icons/nodejs.png b/feed/icons/nodejs.png
index 0b2a88f..41cf0e3 100644
Binary files a/feed/icons/nodejs.png and b/feed/icons/nodejs.png differ
diff --git a/feed/icons/notepadpp.png b/feed/icons/notepadpp.png
index 5a69094..80acb55 100644
Binary files a/feed/icons/notepadpp.png and b/feed/icons/notepadpp.png differ
diff --git a/feed/icons/onedrive.png b/feed/icons/onedrive.png
index c940ff2..7ab5fe6 100644
Binary files a/feed/icons/onedrive.png and b/feed/icons/onedrive.png differ
diff --git a/feed/icons/opera.png b/feed/icons/opera.png
index f4b616a..11bb2b5 100644
Binary files a/feed/icons/opera.png and b/feed/icons/opera.png differ
diff --git a/feed/icons/origin.png b/feed/icons/origin.png
index 74f3cb7..e326e2c 100644
Binary files a/feed/icons/origin.png and b/feed/icons/origin.png differ
diff --git a/feed/icons/peazip.png b/feed/icons/peazip.png
index 28f6292..105bf3c 100644
Binary files a/feed/icons/peazip.png and b/feed/icons/peazip.png differ
diff --git a/feed/icons/photofiltre.png b/feed/icons/photofiltre.png
index 41fd405..e9fb493 100644
Binary files a/feed/icons/photofiltre.png and b/feed/icons/photofiltre.png differ
diff --git a/feed/icons/postman.png b/feed/icons/postman.png
index 8bc2196..8f5d0a4 100644
Binary files a/feed/icons/postman.png and b/feed/icons/postman.png differ
diff --git a/feed/icons/potplayer.png b/feed/icons/potplayer.png
index f6c5d43..f1e11ed 100644
Binary files a/feed/icons/potplayer.png and b/feed/icons/potplayer.png differ
diff --git a/feed/icons/putty.png b/feed/icons/putty.png
index 85d24f3..5455a55 100644
Binary files a/feed/icons/putty.png and b/feed/icons/putty.png differ
diff --git a/feed/icons/python.png b/feed/icons/python.png
index 516d3ab..6819009 100644
Binary files a/feed/icons/python.png and b/feed/icons/python.png differ
diff --git a/feed/icons/qbittorrent.png b/feed/icons/qbittorrent.png
index deced52..ca47f44 100644
Binary files a/feed/icons/qbittorrent.png and b/feed/icons/qbittorrent.png differ
diff --git a/feed/icons/revo.png b/feed/icons/revo.png
index c0fe123..c899bb3 100644
Binary files a/feed/icons/revo.png and b/feed/icons/revo.png differ
diff --git a/feed/icons/rufus.png b/feed/icons/rufus.png
index 16eac8f..c307e51 100644
Binary files a/feed/icons/rufus.png and b/feed/icons/rufus.png differ
diff --git a/feed/icons/skype.png b/feed/icons/skype.png
index 5ebabf9..676a31d 100644
Binary files a/feed/icons/skype.png and b/feed/icons/skype.png differ
diff --git a/feed/icons/spotify.png b/feed/icons/spotify.png
index 9633d6c..7f0d2e7 100644
Binary files a/feed/icons/spotify.png and b/feed/icons/spotify.png differ
diff --git a/feed/icons/steam.png b/feed/icons/steam.png
index 24b47e3..0b0eb70 100644
Binary files a/feed/icons/steam.png and b/feed/icons/steam.png differ
diff --git a/feed/icons/sublimemerge.png b/feed/icons/sublimemerge.png
index 3d35eff..9b6243c 100644
Binary files a/feed/icons/sublimemerge.png and b/feed/icons/sublimemerge.png differ
diff --git a/feed/icons/sublimetext.png b/feed/icons/sublimetext.png
index 83484e1..2ebdb1a 100644
Binary files a/feed/icons/sublimetext.png and b/feed/icons/sublimetext.png differ
diff --git a/feed/icons/sumatrapdf.png b/feed/icons/sumatrapdf.png
index dffaf76..2fcdcba 100644
Binary files a/feed/icons/sumatrapdf.png and b/feed/icons/sumatrapdf.png differ
diff --git a/feed/icons/teams.png b/feed/icons/teams.png
index 8f3d160..af603ca 100644
Binary files a/feed/icons/teams.png and b/feed/icons/teams.png differ
diff --git a/feed/icons/teamviewer.png b/feed/icons/teamviewer.png
index 2534e26..ea8b606 100644
Binary files a/feed/icons/teamviewer.png and b/feed/icons/teamviewer.png differ
diff --git a/feed/icons/thunderbird.png b/feed/icons/thunderbird.png
index 7182ad1..90bbcc8 100644
Binary files a/feed/icons/thunderbird.png and b/feed/icons/thunderbird.png differ
diff --git a/feed/icons/tor.png b/feed/icons/tor.png
index bd4a402..51f0908 100644
Binary files a/feed/icons/tor.png and b/feed/icons/tor.png differ
diff --git a/feed/icons/uplay.png b/feed/icons/uplay.png
index d5884e0..cbcbe28 100644
Binary files a/feed/icons/uplay.png and b/feed/icons/uplay.png differ
diff --git a/feed/icons/utorrent.png b/feed/icons/utorrent.png
index 1ce8af9..e232a3b 100644
Binary files a/feed/icons/utorrent.png and b/feed/icons/utorrent.png differ
diff --git a/feed/icons/uui.png b/feed/icons/uui.png
index 504de0c..ace9d05 100644
Binary files a/feed/icons/uui.png and b/feed/icons/uui.png differ
diff --git a/feed/icons/viber.png b/feed/icons/viber.png
index 2317b79..ea9f770 100644
Binary files a/feed/icons/viber.png and b/feed/icons/viber.png differ
diff --git a/feed/icons/viper.png b/feed/icons/viper.png
index e50d597..290542c 100644
Binary files a/feed/icons/viper.png and b/feed/icons/viper.png differ
diff --git a/feed/icons/visualstudio.png b/feed/icons/visualstudio.png
index db8bab3..999ab35 100644
Binary files a/feed/icons/visualstudio.png and b/feed/icons/visualstudio.png differ
diff --git a/feed/icons/vivaldi.png b/feed/icons/vivaldi.png
index e5c245b..38cab0d 100644
Binary files a/feed/icons/vivaldi.png and b/feed/icons/vivaldi.png differ
diff --git a/feed/icons/vlc.png b/feed/icons/vlc.png
index 1ddf0af..8ee990e 100644
Binary files a/feed/icons/vlc.png and b/feed/icons/vlc.png differ
diff --git a/feed/icons/vscode.png b/feed/icons/vscode.png
index 5038ba2..8aaac8e 100644
Binary files a/feed/icons/vscode.png and b/feed/icons/vscode.png differ
diff --git a/feed/icons/vscodium.png b/feed/icons/vscodium.png
index fc85e46..65d3c7e 100644
Binary files a/feed/icons/vscodium.png and b/feed/icons/vscodium.png differ
diff --git a/feed/icons/winamp.png b/feed/icons/winamp.png
index 4604f9a..b87cc06 100644
Binary files a/feed/icons/winamp.png and b/feed/icons/winamp.png differ
diff --git a/feed/icons/winrar.png b/feed/icons/winrar.png
index 89dbd9d..9f9564b 100644
Binary files a/feed/icons/winrar.png and b/feed/icons/winrar.png differ
diff --git a/feed/icons/winscp.png b/feed/icons/winscp.png
index 4ad7492..215c140 100644
Binary files a/feed/icons/winscp.png and b/feed/icons/winscp.png differ
diff --git a/feed/icons/xampp.png b/feed/icons/xampp.png
index 3d16946..52788ee 100644
Binary files a/feed/icons/xampp.png and b/feed/icons/xampp.png differ
diff --git a/feed/icons/zoom.png b/feed/icons/zoom.png
index a148da2..fbeabab 100644
Binary files a/feed/icons/zoom.png and b/feed/icons/zoom.png differ
diff --git a/src/ConfigurO/Forms/MainForm.cs b/src/ConfigurO/Forms/MainForm.cs
index 151c90b..55893a9 100644
--- a/src/ConfigurO/Forms/MainForm.cs
+++ b/src/ConfigurO/Forms/MainForm.cs
@@ -242,7 +242,7 @@ void OnLoaded(object sender, EventArgs e)
TitleBar == null ? "absent" : "present",
TitleBar == null ? "-" : TitleBar.Bounds.ToString(),
TitleBar == null ? 0 : TitleBar.Height,
- DeviceDpi,
+ NocturneScale.DpiOf(Handle),
NocturneScale.Factor.ToString("0.00",
System.Globalization.CultureInfo.InvariantCulture),
NocturneFonts.Bundled));
diff --git a/src/ConfigurO/Nocturne/NocturneScale.cs b/src/ConfigurO/Nocturne/NocturneScale.cs
index 9e9b626..e01f96c 100644
--- a/src/ConfigurO/Nocturne/NocturneScale.cs
+++ b/src/ConfigurO/Nocturne/NocturneScale.cs
@@ -1,5 +1,6 @@
using System;
using System.Drawing;
+using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ConfigurO
@@ -39,6 +40,79 @@ internal static void SetDpi(int dpi)
Factor = dpi / Base;
}
+ // ── Asking the system, not the framework ────────────────────────
+ const int LOGPIXELSX = 88;
+ const int MDT_EFFECTIVE_DPI = 0;
+ const int MONITOR_DEFAULTTONEAREST = 2;
+
+ [DllImport("user32.dll")] static extern uint GetDpiForWindow(IntPtr hwnd);
+ [DllImport("user32.dll")] static extern IntPtr MonitorFromWindow(IntPtr hwnd, int flags);
+ [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd);
+ [DllImport("user32.dll")] static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
+ [DllImport("gdi32.dll")] static extern int GetDeviceCaps(IntPtr hdc, int index);
+ [DllImport("shcore.dll")] static extern int GetDpiForMonitor(IntPtr monitor, int type, out uint x, out uint y);
+
+ ///
+ /// The DPI of the display is on, straight from
+ /// Win32.
+ ///
+ /// Deliberately not Control.DeviceDpi. WinForms on .NET Framework only
+ /// reports a real DPI when the DpiAwareness switches in App.config are
+ /// present, and those live in ConfigurO.exe.config -- a file the
+ /// release does not ship, because the app is distributed as one
+ /// executable. Run that way, DeviceDpi answers 96 on every machine,
+ /// the whole interface lays out at 1.0, and on a 150% display it comes
+ /// out two-thirds of the size it was drawn at. It is crisp, because
+ /// the manifest still makes the process Per-Monitor-V2 aware at the
+ /// Win32 level -- it is simply small, which reads as an older, denser
+ /// build of the app rather than as a bug.
+ ///
+ /// Win32 has always known the right answer; nothing was asking it.
+ /// Every version since 1.0 shipped this way.
+ ///
+ /// Falls back the way the API history goes: GetDpiForWindow is
+ /// Windows 10 1607, GetDpiForMonitor is 8.1, and GetDeviceCaps is the
+ /// system-wide value that works everywhere else.
+ ///
+ internal static int DpiOf(IntPtr hwnd)
+ {
+ if (hwnd != IntPtr.Zero)
+ {
+ try
+ {
+ uint d = GetDpiForWindow(hwnd);
+ if (d > 0) return (int)d;
+ }
+ catch (EntryPointNotFoundException) { } // pre-1607
+ catch (DllNotFoundException) { }
+
+ try
+ {
+ IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
+ uint x, y;
+ if (monitor != IntPtr.Zero &&
+ GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, out x, out y) == 0 && x > 0)
+ return (int)x;
+ }
+ catch (EntryPointNotFoundException) { } // pre-8.1
+ catch (DllNotFoundException) { }
+ }
+
+ try
+ {
+ IntPtr dc = GetDC(IntPtr.Zero);
+ if (dc != IntPtr.Zero)
+ {
+ int d = GetDeviceCaps(dc, LOGPIXELSX);
+ ReleaseDC(IntPtr.Zero, dc);
+ if (d > 0) return d;
+ }
+ }
+ catch (DllNotFoundException) { }
+
+ return 96;
+ }
+
/// Scales a design-token pixel value to the current display.
internal static int S(int v)
{
diff --git a/src/ConfigurO/Nocturne/NocturneShell.cs b/src/ConfigurO/Nocturne/NocturneShell.cs
index 7a49dc1..def625b 100644
--- a/src/ConfigurO/Nocturne/NocturneShell.cs
+++ b/src/ConfigurO/Nocturne/NocturneShell.cs
@@ -195,8 +195,9 @@ protected override void OnHandleCreated(EventArgs e)
// was computed at 96 DPI. Now that the target display is known,
// rescale before the first paint.
int previous = (int)Math.Round(NocturneScale.Factor * 96f);
- NocturneScale.SetDpi(DeviceDpi);
- if (DeviceDpi != previous)
+ int dpi = NocturneScale.DpiOf(Handle);
+ NocturneScale.SetDpi(dpi);
+ if (dpi != previous)
{
MinimumSize = NocturneScale.S(NocturneTheme.WindowMinimumSize);
if (WindowState == FormWindowState.Normal)