In my app I take a screenshot of the desktop. Right before that I hide my app's Window
, so It will not cover part of the desktop:
MainWindow.Hide();
TakeScreenShot();
The problem is that sometimes the Window does not get hidden fast enough, so I ended up taking a screenshot of it too. I have tried taking the screenshot from a Window.IsVisibleChanged
event handler, but the result is the same.
Of course, I can use Thread.Sleep
or similar, but I am looking for a better solution.
Update
I have just switched to Aero theme and enabled Desktop Composition, and now the situation is even worse. Now the window "fade out" instead of instantly hidden when calling Window.Hide
. So now my app always take a screenshot of a fading window... I will try winapi with SetWindowPos
or ShowWindow
and will post an update.
Update 2
ShowWindow
and SetWindowPos
give the same result as Window.Hide
( Window.Hide
uses ShowWindow(HWND, SW_HIDE)
internally).
In order to disable the fade-out effect when hiding the window, I use DwmSetWindowAttribute
.
like this:
using System.Windows.Interop;
using System.Runtime.InteropServices;
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
private const int DWMWA_TRANSITIONS_FORCEDISABLED = 3;
and in the Window.Loaded
event handler:
if (Environment.OSVersion.Version.Major >= 6) {
IntPtr WinHandle = new WindowInteropHelper(this).Handle;
int BOOL_TRUE = 1;
int HR = DwmSetWindowAttribute(WinHandle, DWMWA_TRANSITIONS_FORCEDISABLED, BOOL_TRUE, Marshal.SizeOf(BOOL_TRUE));
if (HR != 0)
Marshal.ThrowExceptionForHR(HR);
}
So beside the fade-out effect, the problem remain.
You can start with punting your window outside the area you are trying to copy(when a sub window restore issue was taken into account).
public partial class MainWindow : Window
{
private DispatcherOperation _action;
private int _width = 2000;
private int _height = 1000;
private double _top;
public MainWindow()
{
InitializeComponent();
Dispatcher.Hooks.OperationCompleted += HooksOnOperationCompleted;
}
private void HooksOnOperationCompleted(object sender, DispatcherHookEventArgs dispatcherHookEventArgs)
{
if(dispatcherHookEventArgs.Operation != _action) return;
_action.Task.ContinueWith((t) =>
{
Rectangle rect = new Rectangle(0, 0, _width, _height);
Bitmap bmp = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
bmp.Save("help" + DateTime.Now.Ticks + ".jpg", ImageFormat.Jpeg);
}).ContinueWith(t =>
{
Dispatcher.BeginInvoke((Action)(() =>
{
Top = _top;
}));
});
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
_top = Top;
_action = Dispatcher.BeginInvoke((Action) (() =>
{
Top = 10000;
}));
}
}
Try minimizing the Window
before hiding the Window
and run it Asynchronously
with least priority . Something like this.
private void Button_Click(object sender, RoutedEventArgs e)
{
//Minimize here before hiding. .
this.WindowState = WindowState.Minimized; //this is the key
this.Visibility = Visibility.Hidden;
this.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle, new Action(() =>
{
CaptureImage();
}));
}
private void CaptureImage()
{
System.Drawing.Rectangle bounds = new System.Drawing.Rectangle(0, 0, (int)System.Windows.SystemParameters.PrimaryScreenWidth, (int)System.Windows.SystemParameters.PrimaryScreenHeight);
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(System.Drawing.Point.Empty, System.Drawing.Point.Empty, bounds.Size);
}
bitmap.Save("test.jpg", ImageFormat.Jpeg);
}
}
Hope this helps. Thanks.
You can use something like this:
Visibility = Visibility.Collapsed;
Dispatcher.BeginInvoke(()=>{
Thread.Sleep(2000);
TakeScreenShot();
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.