c# - Printing Canvas to XPS unwanted scaling and cut off -
update
before writing reply 1 might check out samthedev's answer , comments of it. samthedev's answer fixed both problems, don't understand, why fixes first problem.
i experiencing following xps problems , need in resolving issues. bounty running.
issue 1: 10 cm long line in wpf not 10 cm long in xps
i drawing 10 cm long black line: 
making screenshot of it, pasting word , printing shows me, 10 cm long:
when printing generated xps file, line 9.7 cm long:
the code used drawing black line follows. assumed resolution of 96 dotchs per inch, guess need scaling before creating xps file, don't know how that.
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"> <!-- filled code behind --> </canvas> </window> code behind: (basically constructor , printcanvas method relevant)
public partial class mainwindow : window { public mainwindow() { initializecomponent(); // 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 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 point in centimeters public point cmpoint(double x, double y) { return new point(cmtowpf(x), cmtowpf(y)); } // helper converting length in device independent pixels centimeters public double wpftocm(double wpfvalue) { double factor = (96 / 2.54); return wpfvalue / factor; } // helper converting length in centimeters device independent pixels public double cmtowpf(double cmvalue) { double factor = (96 / 2.54); return cmvalue * factor; } // helper drawing 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); } } issue 2: 100 cm long line cut off on created xps
in second example drawing 100 cm long red line. longer window size. that's not problem, problem is, it's cut off on generated xps file.
the generated xps file looks follows: 
the code used drawing red line follows. 1 can see, red line cut off. need full 100 cm red line in xps - how can that?
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"> <!-- filled code behind --> </canvas> </window> code behind: (basically constructor , printcanvas method relevant)
public partial class mainwindow : window { public mainwindow() { initializecomponent(); // 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 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 point in centimeters public point cmpoint(double x, double y) { return new point(cmtowpf(x), cmtowpf(y)); } // helper converting length in device independent pixels centimeters public double wpftocm(double wpfvalue) { double factor = (96 / 2.54); return wpfvalue / factor; } // helper converting length in centimeters device independent pixels public double cmtowpf(double cmvalue) { double factor = (96 / 2.54); return cmvalue * factor; } // helper drawing 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); } } thanks support on this!
as quick reminder, pixel size depends on 2 factors: the display resolution, , the physical size of monitor, there no fixed relation between physical inches , pixels, there wpf used logical inches , conversion: 1 logical inch 96 pixels can changed based on user preferences.
so "ruler" inch or centimeter doesn't exist on wpf, logical ones deffer 1 screen another.
for example here size of black line on 2 of screens :
regarding red line, fix canvas size based on children using
arrangemethold, updateprintcanvasmethod this:public void printcanvas() { xpsdocument doc = new xpsdocument(@".\canvas.xps", system.io.fileaccess.write); xpsdocumentwriter writer = xpsdocument.createxpsdocumentwriter(doc); // size of 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(); }
references






Comments
Post a Comment