GDI +: Как нарисовать линию длиной в один дюйм на любом устройстве? - PullRequest
12 голосов
/ 27 августа 2009

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

Некоторые коды C ++ / 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 Ответ

12 голосов
/ 27 августа 2009

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

Если для свойства 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.

...