Преобразование пикселей в дюймы и наоборот в С#

Я хочу конвертировать пиксели в дюймы и наоборот. Я понимаю, что мне нужен DPI, но не знаю, как получить эту информацию (например, у меня нет объекта Graphics, так что это не вариант).

Есть ли способ?


person AngryHacker    schedule 23.01.2009    source источник
comment
ДПИ чего? экран? принтер? ...?   -  person mmx    schedule 24.01.2009


Ответы (3)


На видеоустройстве любой ответ на этот вопрос, как правило, не очень точен. Самый простой пример, чтобы понять, почему это так, — это проектор. Выходное разрешение, скажем, 1024x768, но DPI зависит от того, насколько далеко экран находится от отверстия проектора. WPF, например, всегда предполагает 96 точек на дюйм на видеоустройстве.

Предполагая, что вам все еще нужен ответ, независимо от точности, и у вас нет объекта Graphics, вы можете создать его на экране с помощью некоторого P/Invoke и получить от него ответ.

Single xDpi, yDpi;

IntPtr dc = GetDC(IntPtr.Zero);

using(Graphics g = Graphics.FromHdc(dc))
{
    xDpi = g.DpiX;
    yDpi = g.DpiY;
}

if (ReleaseDC(IntPtr.Zero) != 0)
{
    // GetLastError and handle...
}


[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);    
[DllImport("user32.dll")]
private static extern Int32 ReleaseDC(IntPtr hwnd);
person codekaizen    schedule 23.01.2009
comment
Исходя из того, что просил пользователь, это должен быть принятый ответ. - person epotter; 07.08.2009

Физически нет реального способа без знания DPI. Пиксели дискретны, дюймы - нет, если вы говорите о дюймах на своем мониторе, вам нужно знать (как минимум) разрешение (и соотношение сторон пикселя) и размер видимой области монитора, чтобы рассчитать ваш DPI . Разрешение обычно можно где-то взять (я не программист на C# или .NET, поэтому ничем не могу вам помочь), но размер монитора обычно недоступен. Если оценка достаточно хороша, попросите пользователя ввести размер монитора (например, 21 дюйм или что-то еще) и решить для DPI:

(resX/DPI)^2 + (resY/DPI)^2 = screenDiagonal^2

давая (при условии, что вы знаете диагональ и разрешение)

DPI = sqrt(resX^2+resY^2)/screenDiagonal

Это всего лишь оценка, так как мониторы никогда не бывают точно 21 дюйм (.. или что-то еще), а соотношение сторон пикселя редко бывает точно 1: 1.

Если вы говорите о дюймах на бумаге, то, вполне естественно, вам нужно знать DPI вашего принтера (или, точнее, текущие настройки принтера).

person falstro    schedule 23.01.2009
comment
Итак, учитывая, что у меня нет доступа к объекту Graphics, как мне рассчитать DPI? - person AngryHacker; 24.01.2009
comment
Решите уравнение для DPI, предполагая, что остальное известно. - person falstro; 24.01.2009
comment
Как узнать длину диагонали монитора? Мое приложение будет работать на компьютерах, которые я не контролирую. - person AngryHacker; 24.01.2009
comment
Либо вы делаете грубую оценку и предполагаете, что у всех есть 19 или 21 или что-то в этом роде; если это действительно важно, то вы должны спросить пользователя, никто другой не знает (см. ответ, комментирующий проекторы), но в этом случае вы, вероятно, захотите использовать какую-то другую технологию, чтобы получить более точный ответ. - person falstro; 24.01.2009
comment
Это довольно бесполезный ответ. Он ищет системный вызов, чтобы сообщить ему, что Windows принимает за DPI (как и я). - person mmr; 16.07.2009
comment
@mmr - проверьте ответ ниже. - person codekaizen; 11.08.2009

Вы можете создать объект Graphics, просто вызвав this.CreateGraphics() (или, в более общем случае, Control.CreateGraphics()), а затем использовать свойства DpiX и DpiY, как вам известно. Просто не забудьте удалить графический объект после его создания (в идеале с помощью оператора Using).

Если вы не используете WinForms, сообщите нам, что это за приложение.

person Noldorin    schedule 23.01.2009
comment
Я не могу. Я пишу код в файле кода программной части листа отчета ActiveReports. У него нет этих свойств. - person AngryHacker; 24.01.2009
comment
Он заявил, что использует WPF, а не WinForms. Использование этих двух вместе может вызвать серьезные головные боли. - person mmr; 16.07.2009
comment
@mmr: Нет, он не заявлял, что использует WPF. На самом деле ссылка на Graphic явно подразумевает WinForms. В любом случае, спасибо за отрицательный голос. - person Noldorin; 16.07.2009