5

The example provided in Microsoft's documentation for Clipboard.ContainsImage() includes the following:

System.Drawing.Image returnImage = null;
if (Clipboard.ContainsImage())
{
    returnImage = Clipboard.GetImage();
    ....
}

The superficial / nominal behavior of this method is to first check if the clipboard contains an image, and if so acquire that image for use. Return null otherwise.

However, isn't it possible that in-between the call to ContainsImage() and the call to GetImage() another application has changed the contents of the clipboard? There might be no image data after all.

When the clipboard does not contain an image, GetImage() is documented to return null. Fine, but then what is the point of calling ContainsImage() in the first place, if when you call GetImage() it is mandatory to inspect the result anyway?

This doesn't just apply to this example - what ever would be the use of calling ContainsImage() if you actually need the clipboard contents?

Maybe ...

  • It is more performant than calling GetImage(), therefore its worth doing even though in a small % of cases GetImage() will fail?

  • Some magic locking is going on which solves this problem automatically (highly doubtful)?


A case where ContainsImage() might be useful would be if you do not need to acquire the clipboard contents, just to see if they are imagery.

Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
  • What if I copy text and an image from a word document together ? Will ContainsImage return true or false ? And what will GetImage do ? Maybe the GetImage is ment to fetch only the image from the clipboard in that case ? – GuidoG Mar 28 '19 at 15:51
  • 2
    It's probably more reliable if you get the content first and then test whether it has the right format by using the [Clipboard.GetDataObject Method](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.clipboard.getdataobject?view=netframework-4.7.2). My experience is that the clipboard is not very reliable and that clipboard operations can fail. – Olivier Jacot-Descombes Mar 28 '19 at 16:03
  • As with any shared resource, its state is subject to change without an appropriate locking mechanism (the old check if a file exists before trying to access it prevents exceptions fallacy for example). The WinForm Clipboard Class does not provide a locking mechanism, so yes all that checking its state does is tell the state at the time of the check's execution. The state may change before the next instruction executes. – TnTinMn Mar 28 '19 at 16:18
  • @TnTinMn thanks that is what I had imagined. At least with files in some cases they are controlled by your app and so the likelihood of their disappearance is small - not true with the Clipboard! Still I'm wondering what (if any) specific reason this function exists for. – StayOnTarget Mar 28 '19 at 16:20
  • You could also add you app to the Clipboard chain, using [AddClipboardFormatListener](https://learn.microsoft.com/en-us/windows/desktop/api/Winuser/nf-winuser-addclipboardformatlistener), so you can pretty safely check the content of the Clipboard, if it's changed, without someone else getting in the way. Better than polling. – Jimi Mar 28 '19 at 22:50
  • Note that images can be put on the clipboard in ways that fall outside the normal "image", [like DIB and PNG memory streams](https://stackoverflow.com/q/44177115/395685). – Nyerguds Mar 28 '19 at 22:51

1 Answers1

1

Imagine that you have a button and you want to Enable whenever there is an Image in Clipboard and disable it otherwise.

calling ContainsImage() regularly does not have a big cost as it is a flag that is set just once when an Image is set to Clipboard). but getting the Image itself every time just to make sure that there is an image in the Clipboard is costly.

A different Example:

Imagine that you have byte[] that can contain Video, Image or Audio.

public enum MediaType
{
    Audio,
    Video,
    Image,
    None
}

class MyData
{
     private byte mydata = null;
     private MediaType type = MediaType.None;
     public void SetData(byte[] data)
     {
          mydata = data;
          if(ImageValidation())  // a method that validates data is a valid image
              type = MediaType.Image;
          else if(VideoValidation())
              type = MediaType.Video;
          else if(AutioValidation())
              type = MediaType.Audio;
          else
              type = MediaType.None;
     }

     //I'm not going to create all get functions but just for one type

     public bool ContainsImage()   //costless
     {
          return type == MediaType.Image;
     }

     public Image GetImage()  //costly if there is an image
     {
          if(type == MediaType.Image)
              using (var ms = new MemoryStream(mydata))
              {
                   return Image.FromStream(ms);    
              }
          else
              return null;
     }
}
Ashkan Mobayen Khiabani
  • 33,575
  • 33
  • 102
  • 171
  • You can do this with `Clipboard.GetDataObject()`, and then performing `.GetDataPresent(identifier)` on that. The identifiers can be looked up. The ones for images include "Bitmap", "DeviceIndependentBitmap", "Format17", and "PNG", but all of them need slightly different handling in how they are retrieved. – Nyerguds Mar 28 '19 at 23:20