我已经实现了一个类似于WPF DrawTools(http://www.codeproject.com/Articles/22776/WPF-DrawTools)的自定义画布。我通过将画布转换为位图,执行泛光填充算法,然后将位图写回画布来实现泛光填充工具。
我遇到的问题是画布重绘不正确。画布相对于窗口保持在正确的位置,但画布中的绘图将根据偏移量移动。以下是执行转换的相关代码:
public static WriteableBitmap GetBitmap(CCDrawingCanvas canvas) {
// Local variables
double dpi = 96d;
// Get the size of the canvas
System.Windows.Size size = new System.Windows.Size((int)canvas.ActualWidth, (int)canvas.ActualHeight);
// Measure and arrange the surface
Point relativePoint = canvas.TransformToAncestor(Application.Current.MainWindow)
.Transform(new Point(0, 0));
canvas.Measure(size);
canvas.Arrange(new Rect(size));
RenderTargetBitmap source = new RenderTargetBitmap(
(int)canvas.ActualWidth,
(int)canvas.ActualHeight,
dpi,
dpi,
PixelFormats.Pbgra32);
canvas.RenderTransform = new TranslateTransform(relativePoint.X, relativePoint.Y);
source.Render(canvas);
return new WriteableBitmap(source);
}
绘制第一条线时,画布和绘图将正确渲染。之后添加的每个新行都会将画布的每个子元素向下移动relativePoint.Y
,然后移过relativePoint.X
。
如果我删除了relativePoint变换并返回WriteableBitmap,则画布将在相对于整个Window的位置(0,0)处绘制。这会通过重叠处于此位置的其他控制元素来导致问题。
我已经包含了两张图像,显示了绘制第一条线后的位置以及绘制第二条线后的位置。
在canvas元素的最顶部绘制的第一行。 第二行是在画布的最顶部绘制的,但重绘会通过relativePoint.Y强制它
更新04/05/2014:我发现了一个临时解决方案。通过首先获取可视元素相对于窗口的位置,然后基于(0,0)位置排列画布来更改该过程。调用RenderTargetBitmap.Render()
方法后,画布将相对于存储的点再次排列。这是更新的代码。我仍然想知道如何更优雅地执行此操作,因为此修复程序相当草率。
public static WriteableBitmap GetBitmap(CCDrawingCanvas canvas) {
// Local variables
double dpi = 96d;
// Get the size of the canvas
System.Windows.Size size = new System.Windows.Size((int)canvas.ActualWidth, (int)canvas.ActualHeight);
// Measure and arrange the surface based at a location of (0, 0) to write the bitmap properly
canvas.Measure(size);
Point relativePoint = canvas.TransformToAncestor(Application.Current.MainWindow)
.Transform(new Point(0, 0));
canvas.Arrange(new Rect(size));
RenderTargetBitmap source = new RenderTargetBitmap(
(int)canvas.Width,
(int)canvas.Height,
dpi,
dpi,
PixelFormats.Pbgra32);
source.Render(canvas);
// Arrange the canvas back to its original position.
canvas.Arrange(new Rect(relativePoint, size));
return new WriteableBitmap(source);
}