GDI +: Как рисовать линию длиной в один дюйм на любом устройстве, на которое она нарисована?

Мне нужно нарисовать линию длиной в один дюйм на любом устройстве с ссылкой на Graphics. Мне нужно, чтобы он был длиной в дюйм, независимо от того, для чего установлен Transform. Предположим, что масштабный коэффициент преобразования задается выражением scale как в горизонтальном, так и в вертикальном направлениях.

Некоторый код С++/CLI:

g->DrawLine(Pens::Black, 50.0f, 50.0f, 50.0f + oneInchEquivalent / scale, 50.0f);

Теперь это было совсем не сложно! Теперь нам нужно всего лишь рассчитать oneInchEquivalent.

g->DpiX дает мне расстояние от того, что выглядит как один дюйм на экране, но не на принтере. Похоже, что на принтерах линия 100 единиц с g->PageUnit, установленная в GraphicsUnit:: Display, даст мне линию длиной в один дюйм. Но мне действительно нужно, чтобы это работало независимо от настройки PageUnit. Фактически, изменение PageUnit изменит ширину пера!!

Изменить: Я предварительно принял единственный ответ здесь, поскольку он довольно близок к тому, что я ищу.

Ответ 1

Ответ прошел довольно долго после нескольких изменений, так что вот окончательный результат:

Настройка свойства PageUnit объекта Graphics на GraphicsUnit.Pixel и принятие в умножении координат значений DpiX и DpiY отобразит ожидаемый результат как на устройствах отображения, так и на принтере.

private static void DrawInchLine(Graphics g, Color color, Point start, Point end)
{
    GraphicsUnit originalUnit = g.PageUnit;
    g.PageUnit = GraphicsUnit.Pixel;
    using (Pen pen = new Pen(color, 1))
    {
        g.DrawLine(pen,
            start.X * g.DpiX,
            start.Y * g.DpiY,
            end.X * g.DpiX,
            end.Y * g.DpiY);
    }
    g.PageUnit = originalUnit;
}

Вы можете нарисовать его на форме (или каком-то элементе управления):

using (Graphics g = this.CreateGraphics())
{
    Point start = new Point(1, 1);
    Point end = new Point(2, 1);
    DrawInchLine(g, Color.Black, start, end);
}

... или отправить вывод на принтер:

PrintDialog dialog = new PrintDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
    PrintDocument pd = new PrintDocument();
    pd.PrinterSettings = dialog.PrinterSettings;
    pd.PrintPage += (psender, pe) =>
    {
        Point start = new Point(1, 1);
        Point end = new Point(2, 1);
        DrawInchLine(pe.Graphics, Color.Black, start, end);
        pe.HasMorePages = false;
    };

    pd.Print();
}

Это, однако, полагается на установку PageUnit.