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;