更新资料

在写回复之前,您可以先检查一下SamTheDev的答案及其评论。 SamTheDev的答案解决了两个问题,但是我不明白为什么它可以解决第一个问题。



我遇到以下XPS问题,需要您的帮助来解决。赏金正在运行。

问题1:WPF中10厘米长的线在XPS中不是10厘米长

我正在画这条10厘米长的黑线:
c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

对其进行截图,然后将其粘贴到Word上并打印出来,可以看到它确实长10厘米:

c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

但是,当打印生成的XPS文件时,该行仅约9.7 cm长:

c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

用于绘制黑线的代码如下。我假设分辨率为每英寸96点,我想我需要在创建XPS文件之前进行一些缩放,但是我不知道该怎么做。

XAML:

<Window x:Class="MWEXps.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MWEXps"
        mc:Ignorable="d"
        Title="Sample 1 - 10 cm long black line" Height="300" Width="700">
    <Canvas x:Name="canvas">
        <!-- will be filled by code behind -->
    </Canvas>
</Window>


后面的代码:
(基本上只有构造函数和printCanvas方法是相关的)

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // a 10 cm long line
        PathFigure lineFigure1 = new PathFigure();
        lineFigure1.StartPoint = cmPoint(3, 1);

        LineSegment lineSegment1 = new LineSegment();
        lineSegment1.Point = cmPoint(13, 1);
        lineFigure1.Segments.Add(lineSegment1);

        drawPathFigure(lineFigure1, canvas, Colors.Black);

        // save as XPS
        printCanvas();
    }


    public void printCanvas()
    {
        XpsDocument doc = new XpsDocument(@".\canvas-10cm.xps", System.IO.FileAccess.Write);
        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);

        writer.Write(canvas);
        doc.Close();
    }

    // helper creating a point in centimeters
    public Point cmPoint(double x, double y)
    {
        return new Point(cmToWpf(x), cmToWpf(y));
    }


    // helper converting a length in device independent pixels to centimeters
    public double wpfToCm(double wpfValue)
    {
        double factor = (96 / 2.54);
        return wpfValue / factor;
    }

    // helper converting a length in centimeters to device independent pixels
    public double cmToWpf(double cmValue)
    {
        double factor = (96 / 2.54);
        return cmValue * factor;
    }


    // helper for drawing a figure
    public void drawPathFigure(PathFigure figure, Canvas canvas, Color color)
    {
        PathGeometry pathGeometry = new PathGeometry();
        pathGeometry.Figures.Add(figure);


        Path path = new Path();
        path.Stretch = Stretch.None;
        path.StrokeLineJoin = PenLineJoin.Miter;
        path.Stroke = new SolidColorBrush(color);
        path.StrokeThickness = 1;

        path.Data = pathGeometry;
        canvas.Children.Add(path);
    }
}


问题2:在创建的XPS上切断100厘米长的线

在第二个示例中,我绘制了一条100厘米长的红线。显然,它比窗口大小长。没问题,问题在于,它也已在生成的XPS文件上切断。

c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

生成的XPS文件如下所示:
c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

用于绘制红线的代码如下。可以看到,红线只是被切断了。我需要XPS中完整的100厘米红线-我该怎么做?

XAML:

<Window x:Class="MWEXps.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MWEXps"
        mc:Ignorable="d"
        Title="Sample 2 - 100 cm long red line" Height="300" Width="700">
    <Canvas x:Name="canvas">
        <!-- will be filled by code behind -->
    </Canvas>
</Window>


后面的代码:
(基本上只有构造函数和printCanvas方法是相关的)

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // a 100 cm long line
        PathFigure lineFigure1 = new PathFigure();
        lineFigure1.StartPoint = cmPoint(3, 1);

        LineSegment lineSegment1 = new LineSegment();
        lineSegment1.Point = cmPoint(103, 1);
        lineFigure1.Segments.Add(lineSegment1);

        drawPathFigure(lineFigure1, canvas, Colors.Red);

        // save as XPS
        printCanvas();
    }


    public void printCanvas()
    {
        XpsDocument doc = new XpsDocument(@".\canvas-100cm.xps", System.IO.FileAccess.Write);
        XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);

        writer.Write(canvas);
        doc.Close();
    }

    // helper creating a point in centimeters
    public Point cmPoint(double x, double y)
    {
        return new Point(cmToWpf(x), cmToWpf(y));
    }


    // helper converting a length in device independent pixels to centimeters
    public double wpfToCm(double wpfValue)
    {
        double factor = (96 / 2.54);
        return wpfValue / factor;
    }

    // helper converting a length in centimeters to device independent pixels
    public double cmToWpf(double cmValue)
    {
        double factor = (96 / 2.54);
        return cmValue * factor;
    }


    // helper for drawing a figure
    public void drawPathFigure(PathFigure figure, Canvas canvas, Color color)
    {
        PathGeometry pathGeometry = new PathGeometry();
        pathGeometry.Figures.Add(figure);


        Path path = new Path();
        path.Stretch = Stretch.None;
        path.StrokeLineJoin = PenLineJoin.Miter;
        path.Stroke = new SolidColorBrush(color);
        path.StrokeThickness = 1;

        path.Data = pathGeometry;
        canvas.Children.Add(path);
    }
}


感谢您对此的支持!

最佳答案

快速提醒一下,像素大小取决于两个因素:显示分辨率和显示器的物理尺寸,因此物理英寸和像素之间没有固定的关系,因此WPF使用逻辑英寸并通过转换:为96像素,但是可以根据用户偏好进行更改。

因此,在wpf上并不真正存在“标尺”英寸或厘米,只有从一个屏幕到另一个屏幕的逻辑屏幕才可以。

例如,在我的两个屏幕上,黑线的大小如下:

c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP

c# - 将Canvas打印到XPS不必要的缩放并切断-LMLPHP


关于红线,您可以使用Arrange度量标准基于子级固定画布大小,将PrintCanvas方法更新为以下内容:

  public void printCanvas()
  {
     XpsDocument doc = new XpsDocument(@".\canvas.xps", System.IO.FileAccess.Write);
    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);

    // The size of the canvas
    System.Windows.Size size = new System.Windows.Size(cmToWpf(102), cmToWpf(6));
    // Arrange canvas
    canvas.Arrange(new Rect(size));



    writer.Write(canvas);
    doc.Close();
}





参考文献

DPI and Device-Independent Pixels

What measurement units does Silverlight and WPF use?

关于c# - 将Canvas打印到XPS不必要的缩放并切断,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35245003/

10-13 09:07