Click here to Skip to main content
15,885,537 members
Articles / Programming Languages / C++
Article

Copying a DIB to the Clipboard

Rate me:
Please Sign up or sign in to vote.
3.78/5 (33 votes)
15 Apr 2008CPOL3 min read 171.2K   1.6K   55   33
Helps with copying a device independant bitmap to the clipboard.

Introduction

Recently, I had cause to save a DIB to the clipboard. I tried numerous methods over a four-week period, but none of them worked (many thanks to Chris Losinger and Christian Graus for their willingness to try and provide me with guidance, an answer, or both). This article describes how I finally attained my goal, but also falls neatly into the category It Ain't Pretty But It Works.

Trials and Tribulations

Since the reason I need to do this is fairly well out of the scope of this article, suffice it to say that my starting point was a BITMAPINFOHEADER struct and a pointer to an array of bits which represented the actual bitmap data. The bitmap was of the 24-bit variety.

At first, I wandered around trying to create a bitmap handle with the info I had. I was sure I was doing it right, but with failure after failure where moving that bitmap to the clipboard was concerned, I (naturally) assumed I must have really mucked it up, so I went looking for help, and ended up using Chris Maunder's CDIBSectionLite class.

Chris's class contains all the code necessary to turn my captured bitmap into a DIBSection, but it lacked the code to move the DIB to the clipboard. This turned out to be a great place to start. However, no matter what I tried, I couldn't get the bitmap to the clipboard.

How It all Came Together

After doinking around for a week trying to coerce the desired functionality out of my code (and CDIBSectionLite), I called the Microsoft Software Developer Hotline (using one of two available free incidents on my MSDN subscription). The guy at MS steered me to a sample that evidently comes with the compiler called wincap32. This sample program will capture the contents of the selected window and convert it to a DIB, and store it on the clipboard. Perfect.

After changing a one or two #include statements, and changing the name of a file, I compiled my code, ran the resulting program, and bingo - DIB on the clipboard!

What I did

The first thing I did was to add this function to the CDIBSectionLite class (remember, it ain't pretty, but it works:

HANDLE CDIBSectionLite::PutOnClipboard()
{
   HANDLE hResult = NULL;

   if (::OpenClipboard(NULL))
   {
      ::EmptyClipboard();
      ::GdiFlush();

      // borrowed these variables from the sample app
      HDIB     hDib    = NULL;
      HBITMAP  hBitmap = NULL;
      HPALETTE ghPal   = NULL;

      if (m_hBitmap)
      {
         // call the function that converts the bitmap to a DIB
         hDib = BitmapToDIB(m_hBitmap, ghPal);
         if (hDib)
         {
            // ahhh, the sweet smell of success
            hResult = ::SetClipboardData(CF_DIB, hDib);
            if (hResult == NULL)
            {
               _ShowLastError();
            }
         }
         else
         {
            MessageBeep(0);
         }
      }
      ::CloseClipboard();
   }
   return hResult;
}

From the Microsoft sample application, I copied the following files into my project directory:

DIBUTIL.C
DIBUTIL.H
DIBAPI.H

I then renamed the DIBUTIL.C file to DIBUTIL.CPP. After that, I had to make the following changes in that file so that it would compile. The sample app compiled as is, but because I included stdafx.h, the compiler puked on some type mismatches, hence the following changes:

Line  30:    #include <windows.h>
      to:    #include "stdafx.h"

Line 381:    lpbi = GlobalLock(hDIB);
      to:    lpbi = (LPSTR)GlobalLock(hDIB);

Line 524:    lpDIBHdr = GlobalLock(hDIB);
      to:    lpDIBHdr = (LPSTR)GlobalLock(hDIB);

Line 608:    hPal = GetStockObject(DEFAULT_PALETTE);
      to:    hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);

Finally, I was using the whole shebang as follows:

// I needed to construct the BITMAPINFO structure to be passed to the
// CDIBSectionLite object would be happy
HBITMAP hBitmap;
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
// use the BITMAPINFOHEADER structure that we captured
bmi.bmiHeader = cb.bih;

CDIBSectionLite dib;
// use the BITMAPINFO struct that we created above and the bits we captured
dib.SetBitmap(&bmi, cb.pBuffer);
dib.PutOnClipboard();

In The End

It works. I'm not really interested in culling out just the stuff I need from the files I harvested from the Microsoft sample app, so I intend on just leaving it all in there. This is an exercise I am leaving to the reader.

The zip file accompanying this article contains both the modified CDIBSectionLite class with the modified sample app files, as well as the entire sample app source in it's native form. One thing to note is that if compiled as is, the sample app project creates (or is supplied with) a DLL called DIBAPI.DLL. This DLL contains the code that I linked directly into my program (I didn't want it in DLL form).

Due to the size of the bitmaps I'm capturing, I didn't equip CDIBSectionLite with the ability to save the bitmap on the clipboard as anything other than a DIB. However, keep in mind that it is possible to save multiple items on the clipboard at one time, so you could simultaneously (using the sample app code) place a bitmap on the clipboard in DIB format, device dependent format, and metafile format if that's what trips your trigger. Any app that pastes from the clipboard will/should pull out the format that best fits it's requirements.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Paddedwall Software
United States United States
I've been paid as a programmer since 1982 with experience in Pascal, and C++ (both self-taught), and began writing Windows programs in 1991 using Visual C++ and MFC. In the 2nd half of 2007, I started writing C# Windows Forms and ASP.Net applications, and have since done WPF, Silverlight, WCF, web services, and Windows services.

My weakest point is that my moments of clarity are too brief to hold a meaningful conversation that requires more than 30 seconds to complete. Thankfully, grunts of agreement are all that is required to conduct most discussions without committing to any particular belief system.

Comments and Discussions

 
GeneralMy vote of 5 Pin
raveneyex5-Oct-10 0:36
raveneyex5-Oct-10 0:36 
GeneralA little bit of help... Pin
raveneyex23-Sep-10 2:01
raveneyex23-Sep-10 2:01 
Generalyes Pin
Karsten Schulz17-Mar-06 0:53
professionalKarsten Schulz17-Mar-06 0:53 
Questionwhat is the "cb" in your article? Pin
dxchen19-Dec-02 4:51
dxchen19-Dec-02 4:51 
GeneralThanks Pin
Shog98-Apr-02 9:46
sitebuilderShog98-Apr-02 9:46 
Generalplease send me the source codes for the drag and drop data transfer from dialog box to the view window. Pin
hari pandey3-Apr-02 21:06
hari pandey3-Apr-02 21:06 
GeneralHmmm... Pin
#realJSOP17-Oct-01 13:46
mve#realJSOP17-Oct-01 13:46 
GeneralRe: Hmmm... Pin
Christian Graus17-Oct-01 14:13
protectorChristian Graus17-Oct-01 14:13 
GeneralRe: Hmmm... Pin
#realJSOP18-Oct-01 1:09
mve#realJSOP18-Oct-01 1:09 
GeneralRe: Hmmm... Pin
Paul Selormey17-Oct-01 14:40
Paul Selormey17-Oct-01 14:40 
GeneralRe: Hmmm... Pin
#realJSOP18-Oct-01 0:40
mve#realJSOP18-Oct-01 0:40 
GeneralRe: Hmmm... Pin
#realJSOP19-Oct-01 0:56
mve#realJSOP19-Oct-01 0:56 
GeneralRe: Hmmm... Pin
Paul Selormey31-Oct-01 0:55
Paul Selormey31-Oct-01 0:55 
Sorry, I did not see your post in the forum-I am a bit busy these days Frown | :-(

> For the record, I have combined the code into Chris's DIBSection
> class (it only took about 10 minutes),

Well, this is all that you needed to do-10 minutes, right?

The next thing to do was to submit it to Chris for him to update his class, there is really no need to write article on this Cry | :((

Best regards,
Paul.


Paul Selormey, Bsc (Elect Eng), MSc (Mobile Communication) is currently Windows open source developer in Japan, and open for programming contract anywhere!
GeneralRe: Hmmm... Pin
19-Dec-01 23:54
suss19-Dec-01 23:54 
GeneralRe: Hmmm... Pin
Andrew Peace8-Feb-02 13:12
Andrew Peace8-Feb-02 13:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.