0

I'm trying to capture a screenshot from my application and set it as the picturebox.Image when a certain condition is true at a certain point of time. This condition has to be checked repeatedly. For checking this condition, I am using a System.Timers.Timer. But Clipboard.GetImage() isn't working.

I have tried the following code, but that's not working.

timer = new System.Timers.Timer();
timer.Interval = 10000; //I'm checking the condition every 10 second or so
timer.Elapsed += OnTimedEvent;
timer.AutoReset = true;
timer.Enabled = true;
void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
            if(myCondition==true)
               GetScreenshot();
}
void GetScreenshot()
{
            try
            {
                SendKeys.SendWait("{PRTSC}");
                Thread.Sleep(500);

                var image = Clipboard.GetImage();

                pictureBox1.Image = image;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
}

This doesn't work and if i try to save the image then it gives Object reference not set kind of exception.

I've read somewhere that it happens due to the timer being MTA , so it can't get access to clipboard. I have tried using System.Windows.Forms.Timer, but that slows the program down due to the continuous check I guess.

Is there any simple way I can get it to work without slowing down the performance. I'm quite new to C#, so a little description of how a certain solution works will be very helpful.

Anthony
  • 3,595
  • 2
  • 29
  • 38
wannaknow
  • 39
  • 3
  • 1
    Did you try to take the screenshot in code instead of sending keys somewhere? – TaW Apr 30 '19 at 22:28
  • While what you're doing doesn't sound wrong, a similar result can be achieved quite nicely using code like from here: https://code.msdn.microsoft.com/windowsdesktop/Saving-a-screenshot-using-C-6883abb3 – Jack Apr 30 '19 at 22:34
  • It sounds like you only need to capture the screenshot when `myCondition == true`. Have you considered making `myCondition` into a property, and then calling `GetScreenshot()` from there (in the setter, and only when `value == true`)? – Rufus L May 01 '19 at 21:51

1 Answers1

0

Clipboard.GetImage returns an image which is stored in the clipboard. Clipboard is somewhat complicated storage; with a possibility of simultaneous staroge of different types of different datas, and should be discussed as a whole new topic.

But, you mentioned you want a screenshot of your screen. Clipboard itself doesn't have functionality of capturing your screen, unless a specific software takes the screenshot and puts it into the clipboard. For instance PrtScr button does jsutjust that.

This link however, may be of help, if you want to capture the screen yourself:

Bitmap bmpScreenshot = new Bitmap(Screen.PrimaryScreen.WorkingArea.Width,
                       Screen.PrimaryScreen.WorkingArea.Height,
                       PixelFormat.Format32bppArgb);

Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot);


gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.WorkingArea.X,
                        Screen.PrimaryScreen.WorkingArea.Y,
                        0,
                        0,
                        Screen.PrimaryScreen.WorkingArea.Size,
                        CopyPixelOperation.SourceCopy);

bmpScreenshot.Save("Screenshot.png", ImageFormat.Png);
AgentFire
  • 8,944
  • 8
  • 43
  • 90
  • 1
    Instead of copying code from another post, please vote to close as a duplicate of the other post instead. – Rufus L Apr 30 '19 at 22:49
  • @RufusL along with the copied code I have provided some explanation, which other posts lack. Without it, OP might have had wrong grasp on these things. – AgentFire May 01 '19 at 09:09
  • Yeah, but was the additional information that "Clipboard is complicated" really an answer? The OP's code works absolutely fine on my machine after switching from a `System.Timers.Timer` to a `System.Windows.Forms.Timer`. – Rufus L May 01 '19 at 21:13