下面是一个简单应用程序的代码,该应用程序在窗口中的画布上绘制一个矩形,然后在按下任何键时使用CopyFromScreen函数拍摄应用程序的屏幕截图。然而,在调用它之前,我调用canvas.Children.Clear()。然后我会期望结果图像中没有矩形,但确实如此。似乎在调用函数时不会从画布中删除实际的矩形图像,但是在一段时间之后。
我尝试输入System.Threading.Thread.Sleep(1000);在Clear()调用之后,矩形也会在屏幕上停留一整秒。显然,在按键功能完成后它会被删除,有没有办法在CopyFromScreen调用之前将其删除?
要运行此功能,您需要添加对System.Drawing的引用。
XAML代码
<Window x:Class="CanvasTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="210" Height="240"
KeyDown="keyPressed">
<Window.Background>
<SolidColorBrush Color="White"/>
</Window.Background>
<Grid>
<Canvas Name="canvas"
HorizontalAlignment="Left" VerticalAlignment="Top">
</Canvas>
</Grid>
</Window>
.cs代码
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace CanvasTest {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Left = 0;
Top = 0;
Rectangle rect = new Rectangle {
Stroke = System.Windows.Media.Brushes.Black,
StrokeThickness = 1,
Width = 100,
Height = 100
};
canvas.Children.Add(rect);
Canvas.SetLeft(rect, 50);
Canvas.SetTop(rect, 50);
}
private void keyPressed(object sender, System.Windows.Input.KeyEventArgs e) {
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap((int)Width, (int)Height);
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap);
canvas.Children.Clear();
graphics.CopyFromScreen(0, 0, 0, 0,
new System.Drawing.Size(bitmap.Width, bitmap.Height),
System.Drawing.CopyPixelOperation.SourceCopy);
String path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
path += "\\MuckleEwesPic.png";
bitmap.Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
}
}
如何在不发生此行为的情况下清除画布然后拍摄屏幕截图?没有'不添加矩形'不是解决方案,这只是一个发生问题的大型应用程序的最小示例。
感谢。
答案 0 :(得分:1)
使用像ColinSmith的链接:
static void WaitForRenderPass()
{
Application.Current.Dispatcher
.BeginInvoke( DispatcherPriority.ApplicationIdle, new Action( () => {} ) )
.Wait();
}
等待渲染过程的一些工作,但问题是不能(afaik)判断渲染过程是否包含你想要的一切。
在实践中,取决于系统负载/视频卡驱动程序/ ...必须多次调用它。我有一台机器,必须在一个循环中调用最多3次,每次调用大约需要2帧@ 60Hz才能完成。只有这样,对上面的调用才会立即返回,表明渲染线程确实处于空闲状态,这可能意味着您想要的所有更改都已呈现,这反过来意味着屏幕捕获包含它们应具有的所有内容。所以我们最终使用了
for( int i = 0 ; i < 5 ; ++i )
{
WaitForRenderPass();
Thread.Sleep( 10 );
}
它丑陋而且它是一个黑客,但它还没有失败(还)。
关于HighCore的评论:您也可以捕获屏幕with Wpf-only classes,但是: