Реализация SetupAPI в C # (WinForms) для чтения физического размера экрана

Я пытаюсь прочитать физический размер моего двух мониторов, для изучения сумасшедших …

Я делаю это, потому что мне нужно точно знать расстояние, которое мышь проходит по экрану (в сантиметрах).

Я пробовал вариант DPI, но scren всегда возвращает 96 DPI (если масштаб равен 100%, Я прочитал следующее)

Но это не реально из-за этого:

Мой первый монитор имеет:

93 DPI

Разделив 600 пикселей / 6,417323 дюймов, мы получим = 93,4 … точек на дюйм

Апрокс, 93,4 DPI.

И мой второй монитор:

84,6 DPI

84,6 DPI, на 12 единиц меньше, чем у среднего монитора, я полагаю.

Итак, мы не можем принять это, потому что это очень неточно. И я хочу быть точным.


Я попробовал, получив настоящие сантиметры (читая это) и используя PInvoke для вызовов Interop.

Но, как сказал @Andreas Rejbrand, это возвращает большое значение (1600 x 900 мм, экран 1,6 метра на 90 сантиметров, это не логика, мой самый большой экран имеет 52 сантиметра на 29 сантиметров, деление 1600/900 возвращает почти то же самое, что 52 на 30, то есть 17777, но полезно ли это мне ???)

PD: Запрашивать у пользователя это не вариант, потому что они могут мне врать, у меня такого не было.


Другим вариантом был поиск решений в WinAPI, и я нашел следующее: (Я думаю, что за этот xD проголосую, но я хочу объяснить все, что я сделал)

Под последним ответом, которым я поделился, я обнаружил следующее:

https://stackoverflow.com/a/3858175/3286975

Это кто-то отредактировал, я щелкнул ревизии и пользователь поделился следующим:

Как получить правильный физический размер монитора?

В комментарии мы видим следующую ссылку:

https://ofekshilon.com/2014/06/19/reading-specific-monitor-dimensions/

Ну, мы можем найти следующий код:

#include <atlstr.h>
#include <SetupApi.h>
#pragma comment(lib, "setupapi.lib")

#define NAME_SIZE 128

const GUID GUID_CLASS_MONITOR = {0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18};

// Assumes hDevRegKey is valid
bool GetMonitorSizeFromEDID(const HKEY hDevRegKey, short& WidthMm, short& HeightMm)
{
DWORD dwType, AcutalValueNameLength = NAME_SIZE;
TCHAR valueName[NAME_SIZE];

BYTE EDIDdata[1024];
DWORD edidsize=sizeof(EDIDdata);

for (LONG i = 0, retValue = ERROR_SUCCESS; retValue != ERROR_NO_MORE_ITEMS; ++i)
{
retValue = RegEnumValue ( hDevRegKey, i, &valueName[0],
&AcutalValueNameLength, NULL, &dwType,
EDIDdata, // buffer
&edidsize); // buffer size

if (retValue != ERROR_SUCCESS || 0 != _tcscmp(valueName,_T("EDID")))
continue;

WidthMm  = ((EDIDdata[68] & 0xF0) << 4) + EDIDdata[66];
HeightMm = ((EDIDdata[68] & 0x0F) << 8) + EDIDdata[67];       return true; // valid EDID found    }   return false; // EDID not found } bool GetSizeForDevID(const CString& TargetDevID, short& WidthMm, short& HeightMm) {   HDEVINFO devInfo = SetupDiGetClassDevsEx(       &GUID_CLASS_MONITOR, //class GUID       NULL, //enumerator      NULL, //HWND        DIGCF_PRESENT, // Flags //DIGCF_ALLCLASSES|         NULL, // device info, create a new one.         NULL, // machine name, local machine        NULL);// reserved   if (NULL == devInfo)        return false;   bool bRes = false;  for (ULONG i=0; ERROR_NO_MORE_ITEMS != GetLastError(); ++i)     {       SP_DEVINFO_DATA devInfoData;        memset(&devInfoData,0,sizeof(devInfoData));         devInfoData.cbSize = sizeof(devInfoData);       if (SetupDiEnumDeviceInfo(devInfo,i,&devInfoData))      {           HKEY hDevRegKey = SetupDiOpenDevRegKey(devInfo,&devInfoData,                DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);          if(!hDevRegKey || (hDevRegKey == INVALID_HANDLE_VALUE))                 continue;           bRes = GetMonitorSizeFromEDID(hDevRegKey, WidthMm, HeightMm);           RegCloseKey(hDevRegKey);        }   }   SetupDiDestroyDeviceInfoList(devInfo);  return bRes; } int _tmain(int argc, _TCHAR* argv[]) {   short WidthMm, HeightMm;    DISPLAY_DEVICE dd;  dd.cb = sizeof(dd);     DWORD dev = 0; // device index  int id = 1; // monitor number, as used by Display Properties > Settings

CString DeviceID;
bool bFoundDevice = false;
while (EnumDisplayDevices(0, dev, &dd, 0) && !bFoundDevice)
{
DISPLAY_DEVICE ddMon;
ZeroMemory(&ddMon, sizeof(ddMon));
ddMon.cb = sizeof(ddMon);
DWORD devMon = 0;

while (EnumDisplayDevices(dd.DeviceName, devMon, &ddMon, 0) && !bFoundDevice)
{
if (ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE &&
!(ddMon.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
{
DeviceID.Format (L"%s", ddMon.DeviceID);
DeviceID = DeviceID.Mid (8, DeviceID.Find (L"\\", 9) - 8);

bFoundDevice = GetSizeForDevID(DeviceID, WidthMm, HeightMm);
}
devMon++;

ZeroMemory(&ddMon, sizeof(ddMon));
ddMon.cb = sizeof(ddMon);
}

ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
dev++;
}

return 0;
}

Я искал в PInvoke этот, и примеры, но я очень потерян, потому что я не знаю, сможем ли мы перевести все это на C #, или это только пример C ++, который не может быть переведен. Я предполагаю, что это может быть переведено, но я не знаю как, я очень новичок в вызовах взаимодействия.

PD: Я нашел это: http://www.programering.com/a/MDO2YjMwATc.html но я пока не знаю, какие методы мне нужно использовать для перевода кода в C # и параметры, которые я должен передать.

Так что, если кто-то может научить меня, как это понять, Если вы хотите дать мне несколько кодов, это хорошо, но я думаю, что хорошего объяснения достаточно. я не знаю.

И если есть лучшие варианты сделать это, пожалуйста, скажите мне.

Потому что мое окончательное решение будет применять это (сантиметры экрана) к этому: https://stackoverflow.com/a/422333/3286975

Кроме того, я вижу, что DPI отличаются от PPI, возможно, я ищу PPI.

Заранее спасибо!

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]