/**************************************************************************** * * MODULE : DIB.C * * DESCRIPTION : Routines for dealing with Device Independent Bitmaps. * * FUNCTION :bmfNumDIBColors(HANDLE hDib) * * FUNCTION :bmfCreateDIBPalette(HANDLE hDib) * * FUNCTION :bmfDIBSize(HANDLE hDIB) * * FUNCTION :bmfDIBFromBitmap(HBITMAP hBmp, DWORD biStyle, WORD biBits, * HPALETTE hPal) * * FUNCTION :bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal) * * FUNCTION :bmfBitmapFromIcon (HICON hIcon, DWORD dwColor) * * FUNCTION :bmfDrawBitmap(HDC hdc, int xpos, int ypos, HBITMAP hBmp, * DWORD rop) * * FUNCTION :bmfDrawBitmapSize(HDC hdc, int x, int y, int xSize, * int ySize, HBITMAP hBmp, DWORD rop) * * FUNCTION :DIBInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi) * * FUNCTION :CreateBIPalette(LPBITMAPINFOHEADER lpbi) * * FUNCTION :PaletteSize(VOID FAR * pv) * * FUNCTION :NumDIBColors(VOID FAR * pv) * * FUNCTION :LoadUIBitmap(HANDLE hInstance, LPCTSTR szName, * COLORREF rgbText, * COLORREF rgbFace, COLORREF rgbShadow, * COLORREF rgbHighlight, COLORREF rgbWindow, * COLORREF rgbFrame) * ****************************************************************************/ #include #include #include #include #include #include "draw.h" /* global variables */ extern HANDLE ghInstance; //instance handle of DIB.DLL /*************************************************************************** * * FUNCTION :bmfNumDIBColors(HANDLE hDib) * * PURPOSE :Returns the number of colors required to display the DIB * indicated by hDib. * * RETURNS :The number of colors in the DIB. Possibilities are * 2, 16, 256, and 0 (0 indicates a 24-bit DIB). In * the case of an error, -1 is returned. * ****************************************************************************/ WORD WINAPI bmfNumDIBColors (HANDLE hDib) { WORD bits; LPBITMAPINFOHEADER lpbi; lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); if (!lpbi) return ((WORD)-1); /* The function NumDIBColors will return the number of colors in the * DIB by looking at the BitCount field in the info block */ bits = NumDIBColors(lpbi); GlobalUnlock(hDib); return(bits); } /*************************************************************************** * * FUNCTION :bmfCreateDIBPalette(HANDLE hDib) * * PURPOSE :Creates a palette suitable for displaying hDib. * * RETURNS :A handle to the palette if successful, NULL otherwise. * ****************************************************************************/ HPALETTE WINAPI bmfCreateDIBPalette (HANDLE hDib) { HPALETTE hPal; LPBITMAPINFOHEADER lpbi; if (!hDib) return NULL; //bail out if handle is invalid lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); if (!lpbi) return NULL; hPal = CreateBIPalette(lpbi); GlobalUnlock(hDib); return hPal; } /*************************************************************************** * * FUNCTION :bmfDIBSize(HANDLE hDIB) * * PURPOSE :Return the size of a DIB. * * RETURNS :DWORD with size of DIB, include BITMAPINFOHEADER and * palette. Returns 0 if failed. * * HISTORY: * 92/08/13 - BUG 1642: (w-markd) * Added this function so Quick Recorder could find out the * size of a DIB. * 92/08/29 - BUG 2123: (w-markd) * If the biSizeImage field of the structure we get is zero, * then we have to calculate the size of the image ourselves. * Also, after size is calculated, we bail out if the * size we calculated is larger than the size of the global * object, since this indicates that the structure data * we used to calculate the size was invalid. * ****************************************************************************/ DWORD WINAPI bmfDIBSize(HANDLE hDIB) { LPBITMAPINFOHEADER lpbi; DWORD dwSize; /* Lock down the handle, and cast to a LPBITMAPINFOHEADER ** so we can read the fields we need */ lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); if (!lpbi) return 0; /* BUG 2123: (w-markd) ** Since the biSizeImage could be zero, we may have to calculate ** the size ourselves. */ dwSize = lpbi->biSizeImage; if (dwSize == 0) dwSize = WIDTHBYTES((WORD)(lpbi->biWidth) * lpbi->biBitCount) * lpbi->biHeight; /* The size of the DIB is the size of the BITMAPINFOHEADER ** structure (lpbi->biSize) plus the size of our palette plus ** the size of the actual data (calculated above). */ dwSize += lpbi->biSize + (DWORD)PaletteSize(lpbi); /* BUG 2123: (w-markd) ** Check to see if the size is greater than the size ** of the global object. If it is, the hDIB is corrupt. */ GlobalUnlock(hDIB); if (dwSize > GlobalSize(hDIB)) return 0; else return(dwSize); } /*************************************************************************** * * FUNCTION :bmfDIBFromBitmap(HBITMAP hBmp, DWORD biStyle, WORD biBits, * HPALETTE hPal) * * PURPOSE :Converts the device-dependent BITMAP indicated by hBmp into * a DIB. biStyle indicates whether the palette contains * DIB_RGB_COLORS or DIB_PAL_COLORS. biBits indicates the * desired number of bits in the destination DIB. If biBits * is zero, the destination DIB will be created with the * minimum required bits. hPal is a handle to the palette to be * stored with the DIB data. If hPal is NULL, the default * system palette is used. * * RETURNS :A global handle to a memory block containing the DIB * information in CF_DIB format. NULL is returned if errors * are encountered. * * HISTORY: * * 92/08/12 - BUG 1642: (angeld) * Check the return value from GetObject, it will tell us * if the handle hBmp was valid. bail out right away if it isn't * 92/08/29 - BUG 2123: (w-markd) * Use temporary variable to store old palette, then * reselect the old palette when we are done. * ****************************************************************************/ HANDLE WINAPI bmfDIBFromBitmap (HBITMAP hBmp, DWORD biStyle, WORD biBits, HPALETTE hPal) { BITMAP bm; BITMAPINFOHEADER bi; BITMAPINFOHEADER FAR *lpbi; DWORD dwLen; HANDLE hDib; HANDLE hMem; HDC hdc; HPALETTE hOldPal; if (!hBmp || !(GetObject(hBmp,sizeof(bm),(LPSTR)&bm))) { #if DEBUG OutputDebugString(TEXT("bmfDIBFromBitmap: INVALID HBITMAP!!!\n\r")); #endif return NULL; //bail out if handle is invalid } /* get default system palette if hPal is invalid */ if (hPal == NULL) hPal = GetStockObject(DEFAULT_PALETTE); if (biBits == 0) biBits = bm.bmPlanes * bm.bmBitsPixel; /* set up BITMAPINFOHEADER structure */ bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; bi.biBitCount = biBits; bi.biCompression = biStyle; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; dwLen = bi.biSize + PaletteSize(&bi); hdc = GetDC(NULL); /* BUG 2123: (w-markd) ** Store the previous palette in hOldPal, restore it on exit. */ hOldPal = SelectPalette(hdc,hPal,FALSE); RealizePalette(hdc); /* get global memory for DIB */ hDib = GlobalAlloc(GHND,dwLen); if (!hDib) { /* could not allocate memory; clean up and exit */ SelectPalette(hdc,hOldPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } lpbi = (VOID FAR *)GlobalLock(hDib); if (!lpbi) { /* could not lock memory; clean up and exit */ SelectPalette(hdc,hOldPal,FALSE); ReleaseDC(NULL,hdc); GlobalFree(hDib); return NULL; } *lpbi = bi; /* call GetDIBits with a NULL lpBits param, so it will calculate the * biSizeImage field for us */ GetDIBits(hdc, hBmp, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); bi = *lpbi; GlobalUnlock(hDib); /* If the driver did not fill in the biSizeImage field, make one up */ if (bi.biSizeImage == 0) { bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight; if (biStyle != BI_RGB) bi.biSizeImage = (bi.biSizeImage * 3) / 2; } /* realloc the buffer big enough to hold all the bits */ dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage; hMem = GlobalReAlloc(hDib,dwLen,GMEM_MOVEABLE); if (!hMem) { /* could not allocate memory; clean up and exit */ GlobalFree(hDib); SelectPalette(hdc,hOldPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } else hDib = hMem; /* call GetDIBits with a NON-NULL lpBits param, and actualy get the * bits this time */ lpbi = (VOID FAR *)GlobalLock(hDib); if (!lpbi) { /* could not lock memory; clean up and exit */ GlobalFree(hDib); SelectPalette(hdc,hOldPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } if (GetDIBits( hdc, hBmp, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0) { /* clean up and exit */ GlobalUnlock(hDib); GlobalFree(hDib); SelectPalette(hdc,hOldPal,FALSE); ReleaseDC(NULL,hdc); return NULL; } bi = *lpbi; /* clean up and exit */ GlobalUnlock(hDib); SelectPalette(hdc,hOldPal,FALSE); ReleaseDC(NULL,hdc); return hDib; } /*************************************************************************** * * FUNCTION :bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal) * * PURPOSE :Converts DIB information into a device-dependent BITMAP * suitable for display on the current display device. hDib is * a global handle to a memory block containing the DIB * information in CF_DIB format. hPal is a handle to a palette * to be used for displaying the bitmap. If hPal is NULL, the * default system palette is used during the conversion. * * RETURNS :Returns a handle to a bitmap is successful, NULL otherwise. * * HISTORY: * 92/08/29 - BUG 2123: (w-markd) * Check if DIB is has a valid size, and bail out if not. * If no palette is passed in, try to create one. If we * create one, we must destroy it before we exit. * ****************************************************************************/ HBITMAP WINAPI bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal) { LPBITMAPINFOHEADER lpbi; HPALETTE hPalT; HDC hdc; HBITMAP hBmp; DWORD dwSize; BOOL bMadePalette = FALSE; if (!hDib) return NULL; //bail out if handle is invalid /* BUG 2123: (w-markd) ** Check to see if we can get the size of the DIB. If this call ** fails, bail out. */ dwSize = bmfDIBSize(hDib); if (!dwSize) return NULL; lpbi = (VOID FAR *)GlobalLock(hDib); if (!lpbi) return NULL; /* prepare palette */ /* BUG 2123: (w-markd) ** If the palette is NULL, we create one suitable for displaying ** the dib. */ if (!hPal) { hPal = bmfCreateDIBPalette(hDib); if (!hPal) { GlobalUnlock(hDib); #ifdef V101 #else bMadePalette = TRUE; #endif return NULL; } #ifdef V101 /* BUGFIX: mikeroz 2123 - this flag was in the wrong place */ bMadePalette = TRUE; #endif } hdc = GetDC(NULL); hPalT = SelectPalette(hdc,hPal,FALSE); RealizePalette(hdc); // GDI Bug...???? /* Create the bitmap. Note that a return value of NULL is ok here */ hBmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT, (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS ); /* clean up and exit */ /* BUG 2123: (w-markd) ** If we made the palette, we need to delete it. */ if (bMadePalette) DeleteObject(SelectPalette(hdc,hPalT,FALSE)); else SelectPalette(hdc,hPalT,FALSE); ReleaseDC(NULL,hdc); GlobalUnlock(hDib); return hBmp; } /*************************************************************************** * * FUNCTION :bmfBitmapFromIcon (HICON hIcon, DWORD dwColor) * * PURPOSE :Converts an icon into a bitmap. hIcon is a handle to a * windows ICON object. dwColor sets the background color for * the bitmap. * * RETURNS :A handle to the bitmap is successful, NULL otherwise. * ****************************************************************************/ HBITMAP WINAPI bmfBitmapFromIcon (HICON hIcon, DWORD dwColor) { HDC hDC; HDC hMemDC = 0; HBITMAP hBitmap = 0; HBITMAP hOldBitmap; HBRUSH hBrush = 0; HBRUSH hOldBrush; int xIcon, yIcon; hDC = GetDC(NULL); hMemDC = CreateCompatibleDC( hDC ); if (hMemDC) { /* get the size for the destination bitmap */ xIcon = GetSystemMetrics(SM_CXICON); yIcon = GetSystemMetrics(SM_CYICON); hBitmap = CreateCompatibleBitmap(hDC, xIcon, yIcon); if (hBitmap) { hBrush = CreateSolidBrush(dwColor); if (hBrush) { hOldBitmap = SelectObject (hMemDC, hBitmap); hOldBrush = SelectObject (hMemDC, hBrush); /* draw the icon on the memory device context */ PatBlt (hMemDC, 0, 0, xIcon, yIcon, PATCOPY); DrawIcon (hMemDC, 0, 0, hIcon); /* clean up and exit */ DeleteObject(SelectObject(hMemDC, hOldBrush)); SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); ReleaseDC(NULL, hDC); return hBitmap; } } } /* clean up resources and exit */ if (hBitmap) DeleteObject(hBitmap); if (hMemDC) DeleteDC(hMemDC); ReleaseDC (NULL, hDC); return NULL; } /*************************************************************************** * * FUNCTION :bmfDrawBitmap(HDC hdc, int xpos, int ypos, HBITMAP hBmp, * DWORD rop) * * PURPOSE :Draws bitmap hBmp at the specifed position in DC hdc * * RETURNS :Return value of BitBlt() or FALSE if in an error is * encountered. Note that BitBlt returns true if successful. * ****************************************************************************/ BOOL WINAPI bmfDrawBitmap (HDC hdc, int xpos, int ypos, HBITMAP hBmp, DWORD rop) { HDC hdcBits; BITMAP bm; BOOL bResult; if (!hdc || !hBmp) return FALSE; hdcBits = CreateCompatibleDC(hdc); if (!hdcBits) return FALSE; GetObject(hBmp,sizeof(BITMAP),(LPSTR)&bm); SelectObject(hdcBits,hBmp); bResult = BitBlt(hdc,xpos,ypos,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop); DeleteDC(hdcBits); return bResult; } /*************************************************************************** * * FUNCTION :DIBInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi) * * PURPOSE :Retrieves the DIB info associated with a CF_DIB * format memory block. * * RETURNS :TRUE (non-zero) if successful; FALSE (zero) otherwise. * ****************************************************************************/ BOOL DIBInfo (HANDLE hbi, LPBITMAPINFOHEADER lpbi) { if (!hbi) return FALSE; *lpbi = *(LPBITMAPINFOHEADER)GlobalLock (hbi); if (!lpbi) return FALSE; /* fill in the default fields */ if (lpbi->biSize != sizeof (BITMAPCOREHEADER)) { if (lpbi->biSizeImage == 0L) lpbi->biSizeImage = WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) * lpbi->biHeight; if (lpbi->biClrUsed == 0L) lpbi->biClrUsed = NumDIBColors (lpbi); } GlobalUnlock (hbi); return TRUE; } /*************************************************************************** * * FUNCTION :CreateBIPalette(LPBITMAPINFOHEADER lpbi) * * PURPOSE :Given a Pointer to a BITMAPINFO struct will create a * a GDI palette object from the color table. * * RETURNS :A handle to the palette if successful, NULL otherwise. * ****************************************************************************/ HPALETTE CreateBIPalette (LPBITMAPINFOHEADER lpbi) { LPLOGPALETTE pPal; HPALETTE hPal = NULL; WORD nNumColors; BYTE red; BYTE green; BYTE blue; int i; RGBQUAD FAR *pRgb; HANDLE hMem; if (!lpbi) return NULL; if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) return NULL; /* Get a pointer to the color table and the number of colors in it */ pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize); nNumColors = NumDIBColors(lpbi); if (nNumColors) { /* Allocate for the logical palette structure */ hMem = GlobalAlloc(GMEM_MOVEABLE, sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); if (!hMem) return NULL; pPal = (LPLOGPALETTE)GlobalLock(hMem); if (!pPal) { GlobalFree(hMem); return NULL; } pPal->palNumEntries = nNumColors; pPal->palVersion = PALVERSION; /* Fill in the palette entries from the DIB color table and * create a logical color palette. */ for (i = 0; (unsigned)i < nNumColors; i++) { pPal->palPalEntry[i].peRed = pRgb[i].rgbRed; pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen; pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue; pPal->palPalEntry[i].peFlags = (BYTE)0; } hPal = CreatePalette(pPal); /* note that a NULL return value for the above CreatePalette call * is acceptable, since this value will be returned, and is not * used again here */ GlobalUnlock(hMem); GlobalFree(hMem); } else if (lpbi->biBitCount == 24) { /* A 24 bitcount DIB has no color table entries so, set the number of * to the maximum value (256). */ nNumColors = MAXPALETTE; hMem =GlobalAlloc(GMEM_MOVEABLE, sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); if (!hMem) return NULL; pPal = (LPLOGPALETTE)GlobalLock(hMem); if (!pPal) { GlobalFree(hMem); return NULL; } pPal->palNumEntries = nNumColors; pPal->palVersion = PALVERSION; red = green = blue = 0; /* Generate 256 (= 8*8*4) RGB combinations to fill the palette * entries. */ for (i = 0; (unsigned)i < pPal->palNumEntries; i++) { pPal->palPalEntry[i].peRed = red; pPal->palPalEntry[i].peGreen = green; pPal->palPalEntry[i].peBlue = blue; pPal->palPalEntry[i].peFlags = (BYTE)0; if (!(red += 32)) if (!(green += 32)) blue += 64; } hPal = CreatePalette(pPal); /* note that a NULL return value for the above CreatePalette call * is acceptable, since this value will be returned, and is not * used again here */ GlobalUnlock(hMem); GlobalFree(hMem); } return hPal; } /*************************************************************************** * * FUNCTION :PaletteSize(VOID FAR * pv) * * PURPOSE :Calculates the palette size in bytes. If the info. block * is of the BITMAPCOREHEADER type, the number of colors is * multiplied by 3 to give the palette size, otherwise the * number of colors is multiplied by 4. * * RETURNS :Palette size in number of bytes. * ****************************************************************************/ WORD PaletteSize (VOID FAR *pv) { LPBITMAPINFOHEADER lpbi; WORD NumColors; lpbi = (LPBITMAPINFOHEADER)pv; NumColors = NumDIBColors(lpbi); if (lpbi->biSize == sizeof(BITMAPCOREHEADER)) return (NumColors * sizeof(RGBTRIPLE)); else return (NumColors * sizeof(RGBQUAD)); } /*************************************************************************** * * FUNCTION :NumDIBColors(VOID FAR * pv) * * PURPOSE :Determines the number of colors in the DIB by looking at * the BitCount field in the info block. * For use only internal to DLL. * * RETURNS :The number of colors in the DIB. * ****************************************************************************/ WORD NumDIBColors (VOID FAR * pv) { int bits; LPBITMAPINFOHEADER lpbi; LPBITMAPCOREHEADER lpbc; lpbi = ((LPBITMAPINFOHEADER)pv); lpbc = ((LPBITMAPCOREHEADER)pv); /* With the BITMAPINFO format headers, the size of the palette * is in biClrUsed, whereas in the BITMAPCORE - style headers, it * is dependent on the bits per pixel ( = 2 raised to the power of * bits/pixel). */ if (lpbi->biSize != sizeof(BITMAPCOREHEADER)) { if (lpbi->biClrUsed != 0) return (WORD)lpbi->biClrUsed; bits = lpbi->biBitCount; } else bits = lpbc->bcBitCount; switch (bits) { case 1: return 2; case 4: return 16; case 8: return 256; default: /* A 24 bitcount DIB has no color table */ return 0; } } /*************************************************************************** * * FUNCTION :bmfDrawBitmapSize(HDC hdc, int x, int y, int xSize, * int ySize, HBITMAP hBmp, DWORD rop) * * PURPOSE :Draws bitmap at the specifed position in DC with * a specified size. * * RETURNS :Return value of BitBlt() or false in an error is * encountered. Note that BitBlt returns true if successful. * * HISTORY: * 92/08/13 - BUG 1642: (w-markd) * Exported this function. * Also stored object that was returned from SelectObject, * and selected this back into the hdc before deleting. * ****************************************************************************/ BOOL WINAPI bmfDrawBitmapSize (HDC hdc, int xpos, int ypos, int xSize, int ySize, HBITMAP hBmp, DWORD rop) { HDC hdcBits; BOOL bResult; HBITMAP hOldBmp; if (!hdc || !hBmp) return FALSE; hdcBits = CreateCompatibleDC(hdc); if (!hdcBits) return FALSE; /* BUG 1642: (w-markd) ** Remeber old bmp and reselect into hdc before DeleteDC */ hOldBmp = SelectObject(hdcBits,hBmp); bResult = BitBlt(hdc,xpos,ypos,xSize, ySize,hdcBits, 0,0,rop); SelectObject(hdcBits, hOldBmp); DeleteDC(hdcBits); return bResult; } //---------------------------------------------------------------------------- // LoadUIBitmap() - load a bitmap resource // // load a bitmap resource from a resource file, converting all // the standard UI colors to the current user specifed ones. // // this code is designed to load bitmaps used in "gray ui" or // "toolbar" code. // // the bitmap must be a 4bpp windows 3.0 DIB, with the standard // VGA 16 colors. // // the bitmap must be authored with the following colors // // Button Text Black (index 0) // Button Face lt gray (index 7) // Button Shadow gray (index 8) // Button Highlight white (index 15) // Window Color yellow (index 11) // Window Frame green (index 10) // // Example: // // hbm = LoadUIBitmap(hInstance, "TestBmp", // GetSysColor(COLOR_BTNTEXT), // GetSysColor(COLOR_BTNFACE), // GetSysColor(COLOR_BTNSHADOW), // GetSysColor(COLOR_BTNHIGHLIGHT), // GetSysColor(COLOR_WINDOW), // GetSysColor(COLOR_WINDOWFRAME)); // // Author: JimBov, ToddLa // History: 5/13/92 - added to dib.c in sndcntrl.dll, t-chrism // //---------------------------------------------------------------------------- HBITMAP WINAPI LoadUIBitmap( HANDLE hInstance, // EXE file to load resource from LPCTSTR szName, // name of bitmap resource COLORREF rgbText, // color to use for "Button Text" COLORREF rgbFace, // color to use for "Button Face" COLORREF rgbShadow, // color to use for "Button Shadow" COLORREF rgbHighlight, // color to use for "Button Hilight" COLORREF rgbWindow, // color to use for "Window Color" COLORREF rgbFrame) // color to use for "Window Frame" { LPBYTE lpb; HBITMAP hbm; LPBITMAPINFOHEADER lpbi = NULL; HANDLE h; HDC hdc; LPDWORD lprgb; HRSRC hrsrc; // convert a RGB into a RGBQ #define RGBQ(dw) RGB(GetBValue(dw),GetGValue(dw),GetRValue(dw)) hrsrc = FindResource(hInstance, szName, RT_BITMAP); if (hrsrc) { h = LoadResource(hInstance,hrsrc); if (h) lpbi = (LPBITMAPINFOHEADER)LockResource(h); } if (!lpbi) return(NULL); if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) return NULL; if (lpbi->biBitCount != 4) return NULL; lprgb = (LPDWORD)((LPBYTE)lpbi + (int)lpbi->biSize); lpb = (LPBYTE)(lprgb + 16); lprgb[0] = RGBQ(rgbText); // Black lprgb[7] = RGBQ(rgbFace); // lt gray lprgb[8] = RGBQ(rgbShadow); // gray lprgb[15] = RGBQ(rgbHighlight); // white lprgb[11] = RGBQ(rgbWindow); // yellow lprgb[10] = RGBQ(rgbFrame); // green hdc = GetDC(NULL); hbm = CreateDIBitmap(hdc, lpbi, CBM_INIT, (LPVOID)lpb, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS); ReleaseDC(NULL, hdc); UnlockResource(h); FreeResource(h); return(hbm); }// LoadUIBitmap