Skip to content

Feature/high dpi awareness#10

Merged
erikdarlingdata merged 3 commits intoerikdarlingdata:devfrom
ClaudioESSilva:feature/high-dpi-awareness
Feb 13, 2026
Merged

Feature/high dpi awareness#10
erikdarlingdata merged 3 commits intoerikdarlingdata:devfrom
ClaudioESSilva:feature/high-dpi-awareness

Conversation

@ClaudioESSilva
Copy link
Contributor

@ClaudioESSilva ClaudioESSilva commented Feb 12, 2026

What does this PR do?

Fixes #9

Claude summary

I used the help of my cousin Claude.

Here is the summary of the changes made.

Changes Made:

  1. Created app.manifest
  • Added PerMonitorV2 DPI awareness declaration
  • Configured the application to be DPI-aware at the manifest level
  • Set long path awareness for compatibility
  1. Updated PerformanceMonitorLite.csproj
    Added <ApplicationManifest>app.manifest</ApplicationManifest> to include the manifest in the build
  • Updated App.xaml.cs
  • Added P/Invoke declarations for Windows DPI APIs
  • Created EnableDpiAwareness()] method that programmatically sets DPI awareness
  • Added call to EnableDpiAwareness() at the start of OnStartup() before any UI is created
  • Tries PerMonitorV2 mode first (Windows 10 1703+) for best quality
  • Falls back to PerMonitor mode (Windows 8.1+) if V2 is not available

How It Works:

The application now properly declares itself as per-monitor DPI aware in two ways:

  1. Manifest-level declaration for system-wide DPI handling
  2. Programmatic DPI awareness setting for runtime configuration

This means:

✅ Charts and text will automatically scale correctly on high DPI displays
✅ No need to manually adjust executable properties anymore
✅ Works properly on multi-monitor setups with different DPI settings
✅ The application adapts when moved between monitors with different DPI
✅ Font sizes remain readable at any DPI scale (100%, 125%, 150%, 200%, etc.)

Which component(s) does this affect?

  • Full Dashboard
  • Lite
  • SQL collection scripts
  • Installer
  • Documentation

How was this tested?

Lite

Before:
Image

After:
image

Dashboard

Before:
Image

After:
Image

Checklist

  • I have read the contributing guide
  • My code builds with zero warnings (dotnet build -c Debug)
  • I have tested my changes against at least one SQL Server version
  • I have not introduced any hardcoded credentials or server names

Copy link
Owner

@erikdarlingdata erikdarlingdata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR and for filing the issue — the High DPI fix is a real improvement and the before/after screenshots demonstrate the problem clearly.

The manifest files are great. The app.manifest approach with <dpiAwareness>PerMonitorV2</dpiAwareness> is the Microsoft-recommended way to declare DPI awareness for WPF apps. The .csproj references are correct. This is the right solution.

The P/Invoke code in both App.xaml.cs files should be removed. Here's why:

  1. The Windows loader processes the manifest during CreateProcessInternalW, before the CLR initializes or any managed code runs. By the time OnStartup() calls EnableDpiAwareness(), PerMonitorV2 awareness is already set.

  2. Calling SetProcessDpiAwareness() after the manifest has already set DPI awareness returns E_ACCESSDENIED (documented here): "The DPI awareness is already set, either by calling this API previously or through the application (.exe) manifest." Similarly, SetProcessDpiAwarenessContext() returns FALSE with ERROR_ACCESS_DENIED (documented here).

  3. The try/catch blocks won't catch these failures — P/Invoke calls return error codes, they don't throw .NET exceptions. The catches would only fire for DllNotFoundException or EntryPointNotFoundException.

  4. There's also a subtle marshaling issue: SetProcessDpiAwareness returns HRESULT (not BOOL), but the P/Invoke declares it as bool. E_ACCESSDENIED (0x80070005) would marshal as true, so even if you checked the return value, it would look like success.

In short: the manifests do all the work. The ~60 lines of P/Invoke per app (enums, DllImports, EnableDpiAwareness()) are dead code that silently fails every time. Removing them keeps the fix clean and correct.

If you'd like, I can trim the P/Invoke code on my end after merge — or you can update the PR to include only the manifest changes. Either way works. The manifests themselves are good to go.

@ClaudioESSilva
Copy link
Contributor Author

Done!
Compiled, tested, and it's good to go 😄

@erikdarlingdata erikdarlingdata merged commit 90170ed into erikdarlingdata:dev Feb 13, 2026
@erikdarlingdata
Copy link
Owner

Thanks so much Claudio (and cousin Claude)! This is a great contribution — the manifest-only approach is clean and the before/after screenshots speak for themselves. Really appreciate you taking the time to fix this for both Dashboard and Lite.

You'll get credit in the upcoming release notes. 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants