Unable to create icon using bits and maskbits CreateDIBSection() returns NULL for bmpcolor

  • Thread starter Thread starter Vin Y
  • Start date Start date
V

Vin Y

Guest
Hi All,

I want to create a icon using SetDIBits() but it returns me a black rectangle. It seems to me like the below line code is returning me a NULL HBITMAP handle.

bmpcolor = CreateDIBSection(dc.GetSafeHdc(), &bmInfo, DIB_RGB_COLORS,(void**)&bits,0, 0);

Please find the entire code below.

#include<iostream>
#include<stdio.h>
#include <afx.h>
#include <afxwin.h>
#include <atlbase.h>
#include <vector> // for vector
#include <iterator> // for std::istream_iterator and std::ostream_iterator
#include <algorithm> // for std::copy
#include <string>
#include <fstream>
#include <sstream>

#include<Windows.h>
#include<list>


int _tmain(int argc, _TCHAR* argv[])
{
int nColorBits = 32;
CURSORINFO ci;
ci.cbSize = sizeof(ci);
GetCursorInfo(&ci);
HCURSOR hcursor = ci.hCursor;
struct ICONDIRENTRY
{
UCHAR nWidth;
UCHAR nHeight;
UCHAR nNumColorsInPalette; // 0 if no palette
UCHAR nReserved; // should be 0
WORD nNumColorPlanes; // 0 or 1
WORD nBitsPerPixel;
ULONG nDataLength; // length in bytes
ULONG nOffset; // offset of BMP or PNG data from beginning of file
};

ASSERT(nColorBits == 4 || nColorBits == 8 || nColorBits == 24 || nColorBits == 32);

if (offsetof(ICONDIRENTRY, nOffset) != 12)
{
return false;
}

CDC dc;
dc.Attach(::GetDC(NULL)); // ensure that DC is released when function ends

// Write header:
UCHAR icoHeader[6] = {0, 0, 1, 0, 1, 0}; // ICO file with 1 image

// Get information about icon:
ICONINFO iconInfo;
GetIconInfo(ci.hCursor, &iconInfo);

BITMAPINFO bmInfo = {0};
bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biBitCount = 0; // don't get the color table
if (!GetDIBits(dc, iconInfo.hbmColor, 0, 0, NULL, &bmInfo, DIB_RGB_COLORS))
{
return false;
}

// Allocate size of bitmap info header plus space for color table:
int nBmInfoSize = sizeof(BITMAPINFOHEADER);
if (nColorBits < 24)
{
nBmInfoSize += sizeof(RGBQUAD) * (int)(1 << nColorBits);
}

CAutoVectorPtr<UCHAR> bitmapInfo;
bitmapInfo.Allocate(nBmInfoSize);
BITMAPINFO* pBmInfo = (BITMAPINFO*)(UCHAR*)bitmapInfo;
memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER));

// Get bitmap data:
ASSERT(bmInfo.bmiHeader.biSizeImage != 0);
CAutoVectorPtr<UCHAR> bits;
bits.Allocate(bmInfo.bmiHeader.biSizeImage);
pBmInfo->bmiHeader.biBitCount = nColorBits;
pBmInfo->bmiHeader.biCompression = BI_RGB;
if (!GetDIBits(dc, iconInfo.hbmColor, 0, bmInfo.bmiHeader.biHeight, (UCHAR*)bits, pBmInfo, DIB_RGB_COLORS))
{
return false;
}


// Get mask data:
BITMAPINFO maskInfo = {0};
maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
maskInfo.bmiHeader.biBitCount = 0; // don't get the color table
if (!GetDIBits(dc, iconInfo.hbmMask, 0, 0, NULL, &maskInfo, DIB_RGB_COLORS))
{
return false;
}
ASSERT(maskInfo.bmiHeader.biBitCount == 1);
CAutoVectorPtr<UCHAR> maskBits;
maskBits.Allocate(maskInfo.bmiHeader.biSizeImage);
CAutoVectorPtr<UCHAR> maskInfoBytes;
maskInfoBytes.Allocate(sizeof(BITMAPINFO) + 2 * sizeof(RGBQUAD));
BITMAPINFO* pMaskInfo = (BITMAPINFO*)(UCHAR*)maskInfoBytes;
memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo));
if (!GetDIBits(dc, iconInfo.hbmMask, 0, maskInfo.bmiHeader.biHeight, (UCHAR*)maskBits, pMaskInfo, DIB_RGB_COLORS))
{
return false;
}

// Write directory entry:
ICONDIRENTRY dir;
dir.nWidth = (UCHAR) pBmInfo->bmiHeader.biWidth;
dir.nHeight = (UCHAR) pBmInfo->bmiHeader.biHeight;
dir.nNumColorsInPalette = (nColorBits == 4 ? 16 : 0);
dir.nReserved = 0;
dir.nNumColorPlanes = 0;
dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount;
dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage + nBmInfoSize;
dir.nOffset = sizeof(dir) + sizeof(icoHeader);

// Write DIB header (including color table):
int nBitsSize = pBmInfo->bmiHeader.biSizeImage;
pBmInfo->bmiHeader.biHeight *= 2; // because the header is for both image and mask
pBmInfo->bmiHeader.biCompression = 0;
pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // because the header is for both image and mask

HBITMAP bmpmask = NULL;
HBITMAP bmpcolor = NULL;
unsigned char* lpBitmapBits = NULL;

bmpcolor = CreateDIBSection(dc.GetSafeHdc(), &bmInfo, DIB_RGB_COLORS,(void**)&bits,0, 0);
bmpmask = CreateDIBSection(NULL, &maskInfo, DIB_RGB_COLORS,(void **)&maskBits, NULL, 0);
int mask = SetDIBits(NULL, bmpmask, 0, maskInfo.bmiHeader.biHeight, (UCHAR*)maskBits, pMaskInfo, DIB_RGB_COLORS);
int colo = SetDIBits(NULL, bmpcolor, 0, bmInfo.bmiHeader.biHeight, (UCHAR*)bits, pBmInfo, DIB_PAL_COLORS);

ICONINFO in;
HICON ii = NULL;
in.hbmColor = bmpcolor;// iconinfo.hbmColor;
in.hbmMask = bmpmask;// iconinfo.hbmMask;
in.fIcon = TRUE;
ii = CreateIconIndirect(&in);
if(ii == NULL)
MessageBox(NULL,L"Couldn't create Cursor NULL",L"NULL",0);
::SetSystemCursor((HCURSOR)ii,32512);
getchar();
}

Could you please let me know why the bmpcolor is returning NULL ? or is there anything I'm passing is wrong.

Thanks,

Vinay

Continue reading...
 
Back
Top