diff --git a/PowerEditor/src/WinControls/AboutDlg/AboutDlg.cpp b/PowerEditor/src/WinControls/AboutDlg/AboutDlg.cpp
index e608a40f9..a7dad2215 100644
--- a/PowerEditor/src/WinControls/AboutDlg/AboutDlg.cpp
+++ b/PowerEditor/src/WinControls/AboutDlg/AboutDlg.cpp
@@ -15,6 +15,7 @@
// along with this program. If not, see .
+#include
#include "AboutDlg.h"
#include "Parameters.h"
#include "localization.h"
@@ -30,6 +31,75 @@ using namespace std;
#pragma warning(disable : 4996) // for GetVersion()
#endif
+
+// local DebugInfo helper
+void AppendDisplayAdaptersInfo(wstring& strOut, const unsigned int maxAdaptersIn)
+{
+ strOut += L"\n installed Display Class adapters: ";
+
+ const wchar_t wszRegDisplayClassWinNT[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}";
+ HKEY hkDisplayClass = nullptr;
+ LSTATUS lStatus = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegDisplayClassWinNT, 0,
+ KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hkDisplayClass);
+ if ((lStatus != ERROR_SUCCESS) || !hkDisplayClass)
+ {
+ strOut += L"\n - error, failed to open the Registry Display Class key!";
+ return;
+ }
+
+ DWORD dwSubkeysCount = 0;
+ lStatus = ::RegQueryInfoKeyW(hkDisplayClass, nullptr, nullptr, nullptr, &dwSubkeysCount,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ if ((lStatus == ERROR_SUCCESS) && (dwSubkeysCount > 0))
+ {
+ for (DWORD i = 0; i < dwSubkeysCount; ++i)
+ {
+ if (i >= maxAdaptersIn)
+ {
+ strOut += L"\n - warning, search has been limited to maximum number of adapter records: "
+ + std::to_wstring(maxAdaptersIn);
+ break;
+ }
+
+ wstring strAdapterNo = std::format(L"{:#04d}", i); // 0000, 0001, 0002, etc...
+ wstring strAdapterSubKey = wszRegDisplayClassWinNT;
+ strAdapterSubKey += L'\\' + strAdapterNo;
+ HKEY hkAdapterSubKey = nullptr;
+ lStatus = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, strAdapterSubKey.c_str(), 0, KEY_READ, &hkAdapterSubKey);
+ if ((lStatus == ERROR_SUCCESS) && hkAdapterSubKey)
+ {
+ strAdapterNo.insert(0, L"\n "); // doubling the output indentation
+ const unsigned int nKeyValMaxLen = 127;
+ const DWORD dwKeyValMaxSize = nKeyValMaxLen * sizeof(wchar_t);
+ wchar_t wszKeyVal[nKeyValMaxLen + 1]{}; // +1 ... to ensure NUL termination
+ DWORD dwType = REG_SZ;
+ DWORD dwSize = dwKeyValMaxSize;
+ if (::RegQueryValueExW(hkAdapterSubKey, L"DriverDesc", nullptr, &dwType, (LPBYTE)wszKeyVal, &dwSize)
+ == ERROR_SUCCESS)
+ {
+ strOut += strAdapterNo + L": Description - ";
+ strOut += wszKeyVal;
+ }
+ // for exact HW identification, query about the "MatchingDeviceId"
+ dwSize = dwKeyValMaxSize;
+ if (::RegQueryValueExW(hkAdapterSubKey, L"DriverVersion", nullptr, &dwType, (LPBYTE)wszKeyVal, &dwSize)
+ == ERROR_SUCCESS)
+ {
+ strOut += strAdapterNo + L": DriverVersion - ";
+ strOut += wszKeyVal;
+ }
+ // to obtain also the above driver date, query about the "DriverDate"
+ ::RegCloseKey(hkAdapterSubKey);
+ hkAdapterSubKey = nullptr;
+ }
+ }
+ }
+
+ ::RegCloseKey(hkDisplayClass);
+ hkDisplayClass = nullptr;
+}
+
+
intptr_t CALLBACK AboutDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
@@ -329,6 +399,23 @@ intptr_t CALLBACK DebugInfoDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
_debugInfoStr += nppGui._darkmode._isEnabled ? L"ON" : L"OFF";
_debugInfoStr += L"\r\n";
+ // Display Info
+ _debugInfoStr += L"Display Info : ";
+ {
+ HDC hdc = ::GetDC(nullptr); // desktop DC
+ if (hdc)
+ {
+ _debugInfoStr += L"\n primary monitor: " + std::to_wstring(::GetDeviceCaps(hdc, HORZRES));
+ _debugInfoStr += L"x" + std::to_wstring(::GetDeviceCaps(hdc, VERTRES));
+ _debugInfoStr += L", scaling " + std::to_wstring(::GetDeviceCaps(hdc, LOGPIXELSX) * 100 / 96);
+ _debugInfoStr += L"%";
+ ::ReleaseDC(nullptr, hdc);
+ }
+ _debugInfoStr += L"\n visible monitors count: " + std::to_wstring(::GetSystemMetrics(SM_CMONITORS));
+ AppendDisplayAdaptersInfo(_debugInfoStr, 4); // survey up to 4 potential graphics card Registry records
+ }
+ _debugInfoStr += L"\r\n";
+
// OS information
HKEY hKey = nullptr;
DWORD dataSize = 0;