Need Help Setting an Image with Transparent Background to Clipboard

Posted by AMissico on Stack Overflow See other posts from Stack Overflow or by AMissico
Published on 2010-05-09T22:32:47Z Indexed on 2010/05/10 16:54 UTC
Read the original article Hit count: 782

Filed under:
|
|
|
|

I need help setting a transparent image to the clipboard. I keep getting "handle is invalid". Basically, I need a "second set of eyes" to look over the following code. (The complete working project at ftp://missico.net/ImageVisualizer.zip.)

This is an image Debug Visualizer class library, but I made the included project to run as an executable for testing. (Note that window is a toolbox window and show in taskbar is set to false.) I was tired of having to perform a screen capture on the toolbox window, open the screen capture with an image editor, and then deleting the background added because it was a screen capture. So I thought I would quickly put the transparent image onto the clipboard. Well, the problem is...no transparency support for Clipboard.SetImage. Google to the rescue...not quite.

This is what I have so far. I pulled from a number of sources. See the code for the main reference. My problem is the "invalid handle" when using CF_DIBV5. Do I need to use BITMAPV5HEADER and CreateDIBitmap?

Any help from you GDI/GDI+ Wizards would be greatly appreciated.

    public static void SetClipboardData(Bitmap bitmap, IntPtr hDC) {

        const uint SRCCOPY = 0x00CC0020;
        const int CF_DIBV5 = 17;
        const int CF_BITMAP = 2;

        //'reference
        //'http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/816a35f6-9530-442b-9647-e856602cc0e2

        IntPtr memDC = CreateCompatibleDC(hDC);
        IntPtr memBM = CreateCompatibleBitmap(hDC, bitmap.Width, bitmap.Height);

        SelectObject(memDC, memBM);

        using (Graphics g = Graphics.FromImage(bitmap)) {

            IntPtr hBitmapDC = g.GetHdc();
            IntPtr hBitmap = bitmap.GetHbitmap();

            SelectObject(hBitmapDC, hBitmap);

            BitBlt(memDC, 0, 0, bitmap.Width, bitmap.Height, hBitmapDC, 0, 0, SRCCOPY);

            if (!OpenClipboard(IntPtr.Zero)) {
                throw new System.Runtime.InteropServices.ExternalException("Could not open Clipboard", new Win32Exception());
            }

            if (!EmptyClipboard()) {
                throw new System.Runtime.InteropServices.ExternalException("Unable to empty Clipboard", new Win32Exception());
            }

            //IntPtr hClipboard = SetClipboardData(CF_BITMAP, memBM); //works but image is not transparent

            //all my attempts result in SetClipboardData returning hClipboard = IntPtr.Zero
            IntPtr hClipboard = SetClipboardData(CF_DIBV5, memBM);


            //because 
            if (hClipboard == IntPtr.Zero) {

                //    InnerException: System.ComponentModel.Win32Exception
                //         Message="The handle is invalid"
                //         ErrorCode=-2147467259
                //         NativeErrorCode=6
                //         InnerException: 

                throw new System.Runtime.InteropServices.ExternalException("Could not put data on Clipboard", new Win32Exception());
            }

            if (!CloseClipboard()) {
                throw new System.Runtime.InteropServices.ExternalException("Could not close Clipboard", new Win32Exception());
            }

            g.ReleaseHdc(hBitmapDC);

        }

    }

    private void __copyMenuItem_Click(object sender, EventArgs e) {

        using (Graphics g = __pictureBox.CreateGraphics()) {

            IntPtr hDC = g.GetHdc();

            MemoryStream ms = new MemoryStream();

            __pictureBox.Image.Save(ms, ImageFormat.Png);

            ms.Seek(0, SeekOrigin.Begin);

            Image imag = Image.FromStream(ms);

            // Derive BitMap object using Image instance, so that you can avoid the issue 
            //"a graphics object cannot be created from an image that has an indexed pixel format"

            Bitmap img = new Bitmap(new Bitmap(imag));

            SetClipboardData(img, hDC);

            g.ReleaseHdc();

        }

    }

© Stack Overflow or respective owner

Related posts about gdi

Related posts about gdi+