Как определить истинный размер пикселя моего монитора в.NET?
Я хочу отобразить изображение в "истинном размере" в моем приложении. Для этого мне нужно знать размер пикселя дисплея.
Я знаю, что разрешение экрана Windows номинально составляет 96 точек на дюйм, но для моих целей я хочу лучше угадать. Я понимаю, что эта информация не всегда может быть доступной или точной (например, старые ЭЛТ-дисплеи), но я полагаю, что при использовании ЖК-дисплеев это возможно!
Есть ли способ получить размер пикселя моего дисплея?
Есть ли способ определить, точен ли размер пикселя?
.NET API предпочтительнее (я не смог их найти), но с Win32 тоже все в порядке, я рад P/Invoke.
5 ответов
Для размера дисплея вы хотите Screen
.PrimaryScreen.Bounds.Size
(или же Screen.GetBounds(myform)
).
Если вы хотите использовать DPI, используйте свойства графики DpiX и DpiY:
PointF dpi = PointF.Empty;
using(Graphics g = this.CreateGraphics()){
dpi.X = g.DpiX;
dpi.Y = g.DpiY;
}
Ой, подожди! Вы хотели актуальный, поднесите линейку к монитору и измерьте размер?! Нет. Использование каких-либо служб ОС невозможно. ОС не знает фактических размеров монитора или того, как пользователь его откалибровал. Часть этой информации теоретически обнаружима, но она недостаточно детерминирована для того, чтобы операционная система использовала ее надежно, так что это не так.
Как обходной путь, вы можете попробовать несколько вещей.
- Вы можете попытаться запросить строку отображения установленного устройства монитора (я не уверен, как это сделать) и посмотреть, сможете ли вы разобрать разумный размер из этого. Например, монитор может представлять собой "ValueBin E17p", и из этого можно сделать вывод, что это 17-дюймовый монитор. Конечно, эта строка отображения, скорее всего, будет "Монитор Plug and Play". Эта схема в лучшем случае довольно схематична,
- Вы можете спросить пользователя, какой у него размер монитора. Может быть, они узнают.
Когда вы знаете (или думаете, что знаете) размер диагонали монитора, вам нужно найти его физическое соотношение сторон. Опять пара вещей:
- Предположим, что текущее соотношение сторон пикселя соответствует физическому соотношению сторон монитора. Это предполагает, что (A) пользователь выбрал разрешение, которое идеально подходит для его монитора, и что (B) монитор имеет квадратные пиксели. Я не знаю современного ориентированного на потребителя компьютерного монитора, у которого нет квадратных пикселей, но у старых были, а у более новых могли бы.
- Спросите пользователя. Может быть, они узнают.
Как только вы знаете (или думаете, что знаете), каковы размеры диагонали монитора и физическое соотношение сторон, вы можете рассчитать его физическую ширину и высоту. A 2 + B 2 = C 2, поэтому несколько расчетов принесут вам пользу:
Если вы узнали, что это 17-дюймовый монитор, и его текущее разрешение составляет 1280 x 1024:
1280 2 + 1024 2 = 2686976
Sqrt (2686976) = 1639,1998047828092637409837247032
17 "* 1280 / 1639,2 = 13,274768179599804782820888238165"
17 "* 1024 / 1639,2 = 10,619814543679843826256710590532"
Это устанавливает физическую ширину в 13,27 дюйма и физическую высоту в 10,62 дюйма. Это делает пиксели 13,27" / 1280 = 10,62" / 1024 = 0,01037"или около 0,263 мм.
Конечно, все это недопустимо, если у пользователя нет подходящего разрешения, монитор имеет дурацкие неквадратные пиксели, или это более старый аналоговый монитор, и элементы управления не настроены должным образом, чтобы дисплей заполнил всю физическую область. экран. Или еще хуже, это может быть проектор.
В конце концов, вам лучше всего выполнить шаг калибровки, когда пользователь фактически подносит линейку к экрану и измеряет размер чего-либо для вас. Вы могли бы:
- Попросите пользователя щелкнуть мышью на любых двух точках на расстоянии дюйма (или сантиметра).
- Нарисуйте на экране прямоугольник, и пусть пользователь нажимает стрелки вверх и вниз, чтобы отрегулировать его высоту, а стрелки влево и вправо, чтобы отрегулировать его ширину, пока размер прямоугольника не станет равным квадратному дюйму (или сантиметру) в соответствии с линейкой.
- Нарисуйте прямоугольник на экране и попросите пользователя указать, сколько дюймов / сантиметров в каждом измерении.
Независимо от того, что вы делаете, не ожидайте, что ваши результаты будут на 100% точными. Существует слишком много факторов для вас (или пользователя), чтобы каждый раз получать это точно.
Имейте в виду, что 96 точек на дюйм, как правило, довольно близко к точности. Современные пиксели на непроецированных экранах имеют тенденцию быть около 0,25 мм, сдаваемые или сдаваемые, поэтому обычно у вас получается около 100 физических пикселей на дюйм, сдаваемые или снимаемые, если для монитора установлено исходное разрешение. (Конечно, это огромное обобщение, которое применимо не ко всем мониторам. Например, Eee PC имеет пиксели размером около 0,19 мм, если я правильно помню спецификации.)
GetDeviceCaps
может быть P/Invoke'd, чтобы получить некоторые цифры, но я никогда не знал, что эти цифры заслуживают доверия...
Извините, вы получили P/Invoke для получения этой информации.
Вот ссылка, которую я использовал для этого некоторое время назад: http://www.davidthielen.info/programming/2007/05/get_screen_dpi_.html
Вы можете проверить, просто вручную рассчитав с вашего размера экрана
cos(45)*LCD_SCREEN_DIAGONAL_IN_INCHES/sqrt(HORZ_RES^2 + VERT_RES^2)
Это даст вам ширину пикселя в дюймах
Вы можете получить физические размеры дисплея, используя информацию EDID, хранящуюся в реестре. Вы можете получить соответствующий раздел реестра монитора с помощью вызова API окон EnumDisplayDevices.
TL;DR
Истинный размер WPF = Пиксели * Увеличение в точках на дюйм
Увеличение DPI:
Matrix dpiMagnification
= PresentationSource.FromVisual(MyUserControl).CompositionTarget.TransformToDevice;
double magnificationX = dpiMagnification.M11;
double magnificationY = dpiMagnification.M22;
Обсуждение
У меня были проблемы с решением этого вопроса еще в 2020 году. Когда в 2009 году этот вопрос задавали / отвечал на этот вопрос, .NET C#, вероятно, означал Windows Forms. НоWPF
де-факто стандарт дня...
Задав вопрос об "истинном размере", вы, вероятно, уже поняли, что операционная система выполняет некоторые вычисления с фактическими пикселями (скажем, 1366x768, что, как я понимаю, является обычным разрешением ноутбука) и DPI (трудно найти), чтобы дать элементу управления истинное значение. размер. И вы пытаетесь создать приложение, которое масштабируется для разных мониторов.
Это фактическое число DPI кажется скрытым, но оно было нормализовано (преобразовано в процент). Предположим, 100% = 96 точек на дюйм, просто потому, что фактическое число больше не имеет значения. Люди могут легко увеличить размер текста в масштабе всей системы, перейдя на Рабочий стол в Windows 10> щелкните правой кнопкой мыши> Параметры отображения> раздел Масштаб и макет> измените процентное значение для увеличения текста и других элементов.
Вы можете найти пиксели другим способом и умножить / разделить пиксель на процентное значение DPI, чтобы получить истинный размер. Например, я хочу перетащить UserControl вокруг элемента холста окна WPF с помощью мыши. Количество пикселей пользовательского элемента управления и xy-координаты мыши были отключены нормализованным DPI. Чтобы мышь двигалась с той же скоростью, что и пользовательский элемент управления, я использую:
double newXCoord = System.Windows.Forms.Cursor.Position.X;
double newYCoord = System.Windows.Forms.Cursor.Position.Y;
double deltaX = newXCoord - oldXCoord;
double deltaY = newYCoord - oldYCoord;
double magnificationX = 1;
double magnificationY = 1;
Matrix dpiMagnification
= PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice;
if (magnificationMatrix != null)
{
magnificationX = dpiMagnification.M11;
magnificationY = dpiMagnification.M22;
}
PixelsFromLeft += deltaX / m_magnificationX;
PixelsFromTop += deltaY / m_magnificationY;