如何将WPF控件的图像输出到剪贴板
我有下面的代码,它接受一个控件(作为一个可视对象),使用一个可视笔刷将控件绘制成一个RenderTargetBitmap,然后保存到磁盘上。这是成功的 我想使用相同的代码将图像放置在剪贴板中。这似乎不起作用;尽管剪贴板接受数据,但它不接受数据是图像。 这显然是一个格式问题,但我不知道如何排序 守则如下:-如何将WPF控件的图像输出到剪贴板,wpf,clipboard,bitmapsource,Wpf,Clipboard,Bitmapsource,我有下面的代码,它接受一个控件(作为一个可视对象),使用一个可视笔刷将控件绘制成一个RenderTargetBitmap,然后保存到磁盘上。这是成功的 我想使用相同的代码将图像放置在剪贴板中。这似乎不起作用;尽管剪贴板接受数据,但它不接受数据是图像。 这显然是一个格式问题,但我不知道如何排序 守则如下:- public void CopyToClipBoard(Visual forDrawing) { RenderTargetBitmap bmp = Control
public void CopyToClipBoard(Visual forDrawing)
{
RenderTargetBitmap bmp = ControlToImage(forDrawing, 96, 96);
CopyToClipBoard(bmp);
}
private void CopyToClipBoard(BitmapSource bmp)
{
Thread thread = new Thread(() =>
{
Clipboard.SetImage(bmp);
});
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
thread.Start();
}
private static RenderTargetBitmap ControlToImage(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
// render control content
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX, dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
在检查代码之后,我希望在线程委托中抛出一个跨线程异常(
CopyToClipBoard(BitmapSource):void
)BitmapSource
是一个DispatcherObject
,它是在不同的调度程序线程(在主线程上)上创建的,而不是在主线程上处理的。不能在线程之间传递DispatcherObject
实例。除了实例extendsFreezable
和Freezable.Freeze()
之外,此实例上调用了
这意味着,为了将bmp
引用传递给处理剪贴板的线程(或通常相关线程以外的任何其他线程),您必须调用bmp.Freeze()
我假设异常被线程
吞没,并且您从未在调试模式下运行应用程序。这就是为什么你从未意识到这个例外
正如我之前所写的,您不需要生成新的STA线程来访问剪贴板。我不推荐这个
如果继续使用专用线程,只需在将其传递给线程之前冻结Freezable
:
public void CopyToClipBoard(Visual forDrawing)
{
RenderTargetBitmap bmp = ControlToImage(forDrawing, 96, 96);
// Freeze the freezable DispatcherObject so that it can be consumed by other threads
bmp.Freeze();
CopyToClipBoard(bmp);
}
剪贴板操作必须在应用程序的主线程上进行。无需为剪贴板集操作生成新的UI线程。如果您有后台线程,则至少应通过调用其Freeze()方法确保可从该线程(或从创建RenderTargetBitmap的线程以外的任何线程)访问该RenderTargetBitmap。冻结BitmapSource就可以做到这一点。我使用线程是因为它不在应用程序的主线程上。实际上,我是在调试模式下运行软件的,但出于某种原因,VS2019没有捕获异常-因此我假设(总是一个错误!)某些内容正在以不友好的格式传递到剪贴板。您应该至少启用所有CLR异常:按Ctrl+Alt+E并选中相关框。默认情况下,VS不会因所有异常而中断。事实证明,这非常有用-谢谢