Valhalla Legends Forums Archive | General Programming | Clipboard, DIBs

AuthorMessageTime
Grok
I'm trying to copy an Excel range to a TIFF.

Through Word automation, I select the range and use .Copy to put it on the Clipboard. Then I create a blank TIFF using ImgEdit.DisplayBlankImage call making a 200 dpi, 1700x2200 (8.5"x11") letter page.

If I just ImgEdit.ClipBoardPaste, the image turns out different sizes per user, because the resolution for the rendering surface (graphics device context) on the client varies. Usually it is around 75dpi, but I've seen it 72dpi up to 96dpi so far. In addition, I really just need the total size of the DIB in x,y pixels, not the resolution.

After copying the Excel range, I search the Clipboard and get these results:

0xC1AB - CSV
0xC1FE - Hyperlink
0xC056 - Rich Text Format
0xC00B - Embed Source
0xC004 - Native
0xC003 - OwnerLink
0xC00E - Object Descriptor
0xC00D - Link Source
0xC00F - Link Source Descriptor
0xC12F - Link
0x0081 - DSPTEXT
0xC002 - ObjectLink
0xC013 - Ole Private Data
0x0010 - CF_LOCALE
0x0007 - CF_OEMTEXT
0x0008 - CF_DIB
0x0011 - CF_MAX

So as you can see, Excel was kind enough to render a DIB for the given copied range. It is this DIB for which I need the height and width.

I open the Clipboard, get a handle to the DIB, and try to read the header (stripped of return code checking for brevity, all values indicate success when run):

Dim lRet As Long
Dim hdcScreen As Long
Dim hMemTmp As Long
Dim uBI As BITMAPINFO
Dim arrBIHBuffer(50) As Byte

uBI.bmiHeader.biSize = 40
lRet = OpenClipboard(0)
hMemTmp = GetClipboardData(CF_DIB)
hdcScreen = GetDC(0)
lRet = GetDIBits(hdcScreen, hMemTmp, 0, 0, ByVal 0&, uBI, 0)
CopyMemory arrBIHBuffer(0), uBI.bmiHeader, 40
lRet = CloseClipboard

The call to GetDIBits succeeds. The problem is uBI.bmiHeader.Width and uBI.bmiHeader.Height are always 0. In fact, so is every element of the structure except bSize, which is 40.

Any ideas? The whole thing is with the intent to stretch the copied DIB to properly fit a 200dpi letter TIFF. So if you can solve that instead, let's hear it!
June 20, 2003, 1:14 PM
Adron
What you have is a handle to a memory object, not a HBITMAP. I wrote this code to test it and it seems to work:

[code]
#include <windows.h>
#include <stdio.h>

int main()
{
   if(!OpenClipboard(0)) {
      printf("OpenClipboard failed\n");
      return 0;
   }
   int format = 0;
   printf("Formats available: \n\n");
   while(format = EnumClipboardFormats(format)) {
      char formatname[128] = "";
      GetClipboardFormatName(format, formatname, 128);
      printf(" %04x %s\n", format, formatname);
   }

   HANDLE data = GetClipboardData(CF_DIB);
   if(!data) {
      printf("Unable to get CF_DIB format\n");
      return 0;
   }

   BITMAPINFO *bmi = (BITMAPINFO*)GlobalLock(data);

   if(!bmi) {
      printf("Unable to lock bitmapinfo\n");
      return 0;
   }

   BITMAPINFOHEADER &hdr = bmi->bmiHeader;
   if(hdr.biSize < sizeof(BITMAPINFOHEADER)) {
      printf("Header is too small\n");
      return 0;
   }

   printf("\nBitmap information: \n\n");

   printf(" biSize = %d\n", hdr.biSize);
   printf(" biWidth = %d\n", hdr.biWidth);
   printf(" biHeight = %d\n", hdr.biHeight);
   printf(" biPlanes = %d\n", hdr.biPlanes);
   printf(" biBitCount = %d\n", hdr.biBitCount);
   printf(" biCompression = %d\n", hdr.biCompression);
   printf(" biSizeImage = %d\n", hdr.biSizeImage);
   printf("biXPelsPerMeter = %d\n", hdr.biXPelsPerMeter);
   printf("biYPelsPerMeter = %d\n", hdr.biYPelsPerMeter);
   printf(" biClrUsed = %d\n", hdr.biClrUsed);
   printf(" biClrImportant = %d\n", hdr.biClrImportant);

   return 0;
}
[/code]
June 21, 2003, 2:37 PM
Grok
Thanks, that's what I missed.
June 21, 2003, 5:56 PM

Search