.net GDI+;:我如何画一条线';s在任何设备上都有一英寸长';谁被吸引了?

.net GDI+;:我如何画一条线';s在任何设备上都有一英寸长';谁被吸引了?,.net,graphics,gdi+,.net,Graphics,Gdi+,我需要在任何设备上画一条一英寸长的线,只要有Graphics参考就可以了。无论Transform设置为什么,我都需要它有一英寸长。假设变换的比例因子由水平和垂直方向上的scale给出 一些C++/CLI代码: g->DrawLine(Pens::Black, 50.0f, 50.0f, 50.0f + oneInchEquivalent / scale, 50.0f); 这一点都不难!现在我们所需要做的就是计算一英寸的当量 g->DpiX给了我一个屏幕上看起来像一英寸的距离,但打印机上没

我需要在任何设备上画一条一英寸长的线,只要有
Graphics
参考就可以了。无论
Transform
设置为什么,我都需要它有一英寸长。假设变换的比例因子由水平和垂直方向上的
scale
给出

一些C++/CLI代码:

g->DrawLine(Pens::Black, 50.0f, 50.0f, 50.0f + oneInchEquivalent / scale, 50.0f);
这一点都不难!现在我们所需要做的就是计算一英寸的当量

g->DpiX
给了我一个屏幕上看起来像一英寸的距离,但打印机上没有。在打印机上,如果将
g->PageUnit
设置为GraphicsUnit::Display,绘制一条100个单位的线,我会得到一英寸长的线。但是,我真的需要它工作,不管
PageUnit
设置如何。事实上,更改
PageUnit
将更改笔的宽度


编辑:我暂时接受了这里唯一的答案,因为它与我想要的答案非常接近。

经过几次编辑后,答案变得相当长,因此这里是最终结果:

Graphics
对象的
PageUnit
属性设置为
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;
}
您可以让它在窗体(或某些控件)上绘制:

…或将输出发送到打印机:

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

,您可以尝试使用CutePDF作为打印机仿真器。你可以看到这里的区别。我刚刚意识到我有一台打印机站在这里;试图在上面打印;精确到一英寸。将使用代码更新。谢谢Fredrik,但我需要单独使用数学来完成此操作,而不更改页面单位设置。更改PageUnit将影响笔的宽度。看我问题的最后一部分。啊,错过了那一部分。。。不幸的是,除了使用
Pixel
作为所有绘图的基本单位,并使用
DpiX
DpiY
将其缩放到目标设备之外,我看不到简单的解决方案。我现在用打印样本更新了我的答案
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();
}