Jump to content

_GDIPlus_BitmapCreateFromHBITMAP seems to corrupt some bitmap images from clipboard


Recommended Posts

I'm creating a tool which automatically saves screenshots.  I've found that some images appear corrupt after saving.  I've narrowed the source down to screenshots taken from within an RDP session via the Ctrl+Alt+Plus (PrtScn equivalent) and Ctrl+Alt+Minus (Alt+PrtScn equivalent) key combos.

Here is the example code:

#include <ClipBoard.au3>
#include <GDIPlus.au3>

If _ClipBoard_IsFormatAvailable($CF_BITMAP) Then
    ConsoleWrite("+Bitmap found on Clipboard" & @CRLF)

    If Not _ClipBoard_Open(0) Then
        MsgBox(16, "Error", "_ClipBoard_Open failed")
    $hClipboardImage = _ClipBoard_GetDataEx($CF_BITMAP)

    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hClipboardImage)
    $sCLSID = _GDIPlus_EncodersGetCLSID("JPG")
    _GDIPlus_ImageSaveToFileEx($hBitmap, @ScriptDir & "\" & TimerInit() & "_Clipboard_Image.jpg", $sCLSID, 0)
    MsgBox(48, @ScriptName, "No Bitmap found on Clipboard")

If you copy a local window to the clipboard via Alt+PrtScn the above works fine.  If you copy a window in an RDP session via Ctrl+Alt+Minus it saves the image, but the left-hand edge appears to contain a few pixels sliced off the right-hand side of the bitmap (see two attached images for examples; one good, one bad).  If you paste directly into MSPaint, the image appears correctly, so the clipboard contents is good. It seems to be the process of converting the bitmap handle to an image file via GDIPlus which corrupts it (though I may be wrong about this).

I've tried inspecting the contents of the clipboard via the _ClipBoard_EnumFormats example and I've noticed the clipboard from the RDP session contains a couple more formats;


Clipboard formats ..: 3
Clipboard format 1 .: Bitmap
Clipboard format 2 .: DIB
Clipboard format 3 .: DIB V5


Clipboard formats ..: 5
Clipboard format 1 .: DataObject
Clipboard format 2 .: DIB
Clipboard format 3 .: DIB V5
Clipboard format 4 .: Ole Private Data
Clipboard format 5 .: Bitmap

However the _ClipBoard_GetDataEx function is specifying the $CF_BITMAP constant for the format, which both instances contain, so I'm not sure the extra formats have any impact?

I've tried using a combination of _ClipBoard_GetDataEx($CF_DIB) and _GDIPlus_BitmapCreateFromMemory in an effort to write the binary directly to a file, instead of using a bitmap handle, however this doesn't appear to work and just returns a zero and doesn't set @error to anything, which isn't covered in the help file (a failure should return a zero and set the @error level to something).

I've hunted around the forums and tried everything I can think of. I can normally figure most things out without posting but I've been dipping in and out of this script for a few months now and have finally thrown in the towel and must ask you guys for help, which isn't a decision I take lightly.  Your help is, as always, greatly appreciated.



Link to comment
Share on other sites

Have you try a simple save without encoder :   

_GDIPlus_ImageSaveToFile ($hBitmap, "_Clipboard_Image.jpg")
_WinAPI_DeleteObject ($hClipboardImage)

Don't forget to delete the hbitmap object :)

Link to comment
Share on other sites

Yes, sorry - I should have mentioned that on the original post.  I was actually using _GDIPlus_ImageSaveToFile originally, then changed to _GDIPlus_ImageSaveToFileEx so I had more control over the encoder, but this made no difference - the above is just the latest iteration having tried all encoders.  You get the same behaviour with the simpler _GDIPlus_ImageSaveToFile.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Create New...