#include "ctlspriv.h" #include "image.h" #ifndef ILC_COLORMASK #define ILC_COLORMASK 0x00FE #define ILD_BLENDMASK 0x000E #endif #undef ILC_COLOR #undef ILC_BLEND #define CLR_WHITE 0x00FFFFFFL #define CLR_BLACK 0x00000000L #define NUM_OVERLAY_IMAGES 4 #ifdef IEWIN31_25 HPALETTE CreateHalftonePalette( HDC hdc ); #else //IEWIN31_25 #ifndef _WIN32 extern HPALETTE WINAPI CreateHalftonePalette(HDC hdc); #endif #endif //IEWIN31_25 #ifdef _WIN32 #define SetBrushOrg(hdc, x, y) SetBrushOrgEx(hdc, x, y, NULL) #endif typedef struct _IMAGELIST { DWORD wMagic; // int cImage; // count of images in image list int cAlloc; // # of images we have space for int cGrow; // # of images to grow bitmaps by int cx; // width of each image int cy; // height int cImages; // # images in horizontal strip UINT flags; // ILC_* flags COLORREF clrBlend; // last blend color COLORREF clrBk; // bk color or CLR_NONE for transparent. HBRUSH hbrBk; // bk brush or black BOOL fSolidBk; // is the bkcolor a solid color (in hbmImage) HBITMAP hbmImage; // all images are in here HBITMAP hbmMask; // all image masks are in here. HDC hdcImage; HDC hdcMask; HPALETTE hpal; int aOverlayIndexes[NUM_OVERLAY_IMAGES]; // array of special images int aOverlayX[NUM_OVERLAY_IMAGES]; // x offset of image int aOverlayY[NUM_OVERLAY_IMAGES]; // y offset of image int aOverlayDX[NUM_OVERLAY_IMAGES]; // cx offset of image int aOverlayDY[NUM_OVERLAY_IMAGES]; // cy offset of image int aOverlayF[NUM_OVERLAY_IMAGES]; // ILD_ flags for image #ifdef _WIN32 // used for "blending" effects on a HiColor display. // assumes layout of a DIBSECTION. // BUGBUG on a non-hicolor system we dont need to allocate this!! struct { BITMAP bm; BITMAPINFOHEADER bi; DWORD ct[256]; } dib; #endif } IMAGELIST, NEAR *HIMAGELIST; #define IsImageList(piml) (piml && ((IMAGELIST*)piml)->wMagic == IMAGELIST_MAGIC) #define IsImageListIndex(piml, i) ((i) >= 0 && (i) < piml->cImage) #define V_HIMAGELIST(himl) V_HIMAGELISTERR(himl, 0) #define V_HIMAGELISTERR(himl, err) \ if (!IsImageList(himl)) { \ Assert(FALSE); \ return err; \ } #define IMAGELIST_MAGIC ('I' + ('L' * 256)) #define IMAGELIST_VER 0x0101 #define BFTYPE_BITMAP 0x4D42 // "BM" #define CBDIBBUF 4096 // Define this structure such that it will read and write the same // format for both 16 and 32 bit applications... #pragma pack(2) typedef struct _ILFILEHEADER { WORD magic; WORD version; SHORT cImage; SHORT cAlloc; SHORT cGrow; SHORT cx; SHORT cy; COLORREF clrBk; SHORT flags; SHORT aOverlayIndexes[NUM_OVERLAY_IMAGES]; // array of special images } ILFILEHEADER; #pragma pack() #ifdef IMAGELIST_TRACE #define DM DebugMsg #else #define DM ; / ## / #endif HDC g_hdcSrc = NULL; HBITMAP g_hbmSrc = NULL; HBITMAP g_hbmDcDeselect = NULL; HDC g_hdcDst = NULL; HBITMAP g_hbmDst = NULL; int g_iILRefCount = 0; // global work buffer, this buffer is always a DDB never a DIBSection HBITMAP g_hbmWork = NULL; // work buffer. BITMAP g_bmWork; // work buffer size HBRUSH g_hbrMonoDither = NULL; // gray dither brush for dragging HBRUSH g_hbrColorDither = NULL; // gray dither brush for dragging HBRUSH g_hbrStripe = NULL; void NEAR PASCAL ImageList_Terminate(void); BOOL NEAR PASCAL ImageList_Replace2(IMAGELIST* piml, int i, int cImage, HBITMAP hbmImage, HBITMAP hbmMask, int xStart, int yStart); void NEAR PASCAL ImageList_DeleteBitmap(HBITMAP hbm); void NEAR PASCAL ImageList_SelectDstBitmap(HBITMAP hbmDst); void NEAR PASCAL ImageList_SelectSrcBitmap(HBITMAP hbmSrc); BOOL NEAR PASCAL ImageList_ReAllocBitmaps(IMAGELIST* piml, int cAlloc); BOOL NEAR PASCAL ImageList_SetIconBitmaps(IMAGELIST* piml, HICON hicon); void NEAR PASCAL ImageList_ResetBkColor(IMAGELIST* piml, int iFirst, int iLast, COLORREF clrBk); void NEAR PASCAL ImageList_Merge2(IMAGELIST* piml, IMAGELIST* pimlMerge, int i, int dx, int dy); void NEAR PASCAL ImageList_DeleteDragBitmaps(); void NEAR PASCAL ImageList_CopyOneImage(IMAGELIST* pimlDst, int iDst, int x, int y, IMAGELIST* pimlSrc, int iSrc); IMAGELIST * NEAR PASCAL ImageList_Create2(int cx, int cy, UINT flags, int cGrow); void NEAR PASCAL ImageList_SetOwners(IMAGELIST* piml); #ifdef IEWIN31_25 BOOL NEAR PASCAL ImageList_GetSpareImageRect(IMAGELIST* piml, RECT FAR* prcImage); #endif //IEWIN31_25 void NEAR PASCAL _InitColorDitherBrush(); BOOL WINAPI ImageList_SetDragImage(IMAGELIST* piml, int i, int dxHotspot, int dyHotspot); #define NOTSRCAND 0x00220326L #define ROP_PSo 0x00FC008A #define ROP_DPo 0x00FA0089 #define ROP_DPna 0x000A0329 #define ROP_DPSona 0x00020c89 #define ROP_SDPSanax 0x00E61ce8 #define ROP_DSna 0x00220326 #define ROP_PSDPxax 0x00b8074a #define ROP_PatNotMask 0x00b8074a // D <- S==0 ? P : D #define ROP_PatMask 0x00E20746 // D <- S==1 ? P : D #define ROP_MaskPat 0x00AC0744 // D <- P==1 ? D : S #define ROP_DSo 0x00EE0086L #define ROP_DSno 0x00BB0226L #define ROP_DSa 0x008800C6L static int g_iDither = 0; #pragma code_seg(CODESEG_INIT) void FAR PASCAL ColorDitherBrush_OnSysColorChange() { if (g_hbrColorDither) { ENTERCRITICAL; if (g_hbrColorDither) DeleteObject(g_hbrColorDither); g_hbrColorDither = NULL; _InitColorDitherBrush(); LEAVECRITICAL; } } void NEAR PASCAL _InitColorDitherBrush() { HDC hdc; HBITMAP hbmTemp; hdc = CreateCompatibleDC(NULL); hbmTemp = CreateColorBitmap(8, 8); if (hbmTemp) { HBITMAP hbm; HBRUSH hbr; COLORREF clrTx, clrBk; hbm = SelectObject(hdc, hbmTemp); hbr = SelectObject(hdc, g_hbrMonoDither); clrTx = SetTextColor(hdc, g_clrBtnHighlight); clrBk = SetBkColor(hdc, g_clrBtnFace); PatBlt(hdc, 0,0,8,8, PATCOPY); SelectObject(hdc, hbr); SelectObject(hdc, hbm); g_hbrColorDither = CreatePatternBrush(hbmTemp); SetObjectOwner(g_hbrColorDither, HINST_THISDLL); DeleteObject(hbmTemp); } DeleteDC(hdc); } void FAR PASCAL InitDitherBrush() { HBITMAP hbmTemp; WORD graybits[] = {0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555, 0xAAAA, 0x5555}; if (g_iDither) { g_iDither++; } else { // build the dither brush. this is a fixed 8x8 bitmap hbmTemp = CreateBitmap(8, 8, 1, 1, graybits); if (hbmTemp) { // now use the bitmap for what it was really intended... g_hbrMonoDither = CreatePatternBrush(hbmTemp); SetObjectOwner(g_hbrMonoDither, HINST_THISDLL); DeleteObject(hbmTemp); _InitColorDitherBrush(); g_iDither++; } } } #pragma code_seg() void FAR PASCAL TerminateDitherBrush() { g_iDither--; if (g_iDither == 0) { DeleteObject(g_hbrMonoDither); if (g_hbrColorDither) DeleteObject(g_hbrColorDither); g_hbrColorDither = g_hbrMonoDither = NULL; } } // should we use a DIB section on the current device? // the main goal of using DS is to save memory, but they draw slow // on some devices. // 4bpp Device (ie 16 color VGA) dont use DS // 8bpp Device (ie 256 color SVGA) use DS if DIBENG based. // >8bpp Device (ie 16bpp 24bpp) always use DS, saves memory #define CAPS1 94 /* other caps */ #define C1_DIBENGINE 0x0010 /* DIB Engine compliant driver */ BOOL UseDS(HDC hdc) { #ifdef WINNT return TRUE; #else BOOL f; int ScreenDepth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); f = (ScreenDepth > 8) || (ScreenDepth > 4 && (GetDeviceCaps(hdc, CAPS1) & C1_DIBENGINE)); #ifdef DEBUG f = GetProfileInt("windows", "UseDIBSection", f); #endif return f; #endif } // create a DIB section with the VGA "cosmic" colors. HBITMAP CreateDSBitmap(int cx, int cy, UINT flags) { HDC hdc; HBITMAP hbm; #ifndef IEWIN31_25 LPVOID lpBits; #endif struct { BITMAPINFOHEADER bi; DWORD ct[256]; } dib; hdc = GetDC(NULL); // no color depth was specifed // if we are on a DIBENG based DISPLAY, we use 4bit DIBSections to save // memory. if ((flags & ILC_COLORMASK) == 0) { if (UseDS(hdc)) flags |= ILC_COLOR4; else flags |= ILC_COLORDDB; } if ((flags & ILC_COLORMASK) != ILC_COLORDDB) { dib.bi.biSize = sizeof(BITMAPINFOHEADER); dib.bi.biWidth = cx; dib.bi.biHeight = cy; dib.bi.biPlanes = 1; dib.bi.biBitCount = (flags & ILC_COLORMASK); dib.bi.biCompression = BI_RGB; dib.bi.biSizeImage = 0; dib.bi.biXPelsPerMeter = 0; dib.bi.biYPelsPerMeter = 0; dib.bi.biClrUsed = 16; dib.bi.biClrImportant = 0; dib.ct[0] = 0x00000000; // 0000 black dib.ct[1] = 0x00800000; // 0001 dark red dib.ct[2] = 0x00008000; // 0010 dark green dib.ct[3] = 0x00808000; // 0011 mustard dib.ct[4] = 0x00000080; // 0100 dark blue dib.ct[5] = 0x00800080; // 0101 purple dib.ct[6] = 0x00008080; // 0110 dark turquoise dib.ct[7] = 0x00C0C0C0; // 1000 gray dib.ct[8] = 0x00808080; // 0111 dark gray dib.ct[9] = 0x00FF0000; // 1001 red dib.ct[10] = 0x0000FF00; // 1010 green dib.ct[11] = 0x00FFFF00; // 1011 yellow dib.ct[12] = 0x000000FF; // 1100 blue dib.ct[13] = 0x00FF00FF; // 1101 pink (magenta) dib.ct[14] = 0x0000FFFF; // 1110 cyan dib.ct[15] = 0x00FFFFFF; // 1111 white if (dib.bi.biBitCount == 8) { HPALETTE hpal; int i; if (hpal = CreateHalftonePalette(NULL)) { i = GetPaletteEntries(hpal, 0, 256, (LPPALETTEENTRY)&dib.ct[0]); DeleteObject(hpal); if (i > 64) { dib.bi.biClrUsed = i; for (i=0; i<(int)dib.bi.biClrUsed; i++) dib.ct[i] = RGB(GetBValue(dib.ct[i]),GetGValue(dib.ct[i]),GetRValue(dib.ct[i])); } } if (dib.bi.biClrUsed <= 16) dib.bi.biBitCount = 4; } #ifdef IEWIN31_25 hbm = CreateDIBitmap( hdc, &dib.bi, 0, NULL, NULL, DIB_RGB_COLORS ); #else hbm = CreateDIBSection(hdc, (LPBITMAPINFO)&dib, DIB_RGB_COLORS, &lpBits, NULL, 0); #endif } else { hbm = CreateCompatibleBitmap(hdc, cx, cy); } ReleaseDC(NULL, hdc); return hbm; } HBITMAP FAR PASCAL CreateColorBitmap(int cx, int cy) { HDC hdc; HBITMAP hbm; hdc = GetDC(NULL); hbm = CreateCompatibleBitmap(hdc, cx, cy); ReleaseDC(NULL, hdc); return hbm; } HBITMAP FAR PASCAL CreateMonoBitmap(int cx, int cy) { return CreateBitmap(cx, cy, 1, 1, NULL); } BOOL NEAR PASCAL ImageList_Init(void) { HDC hdcScreen; WORD stripebits[] = {0x7777, 0xdddd, 0x7777, 0xdddd, 0x7777, 0xdddd, 0x7777, 0xdddd}; HBITMAP hbmTemp; DM(DM_TRACE, "ImageList_Init"); // if already initialized, there is nothing to do if (g_hdcDst) return TRUE; hdcScreen = GetDC(HWND_DESKTOP); g_hdcSrc = CreateCompatibleDC(hdcScreen); g_hdcDst = CreateCompatibleDC(hdcScreen); SetObjectOwner(g_hdcSrc, HINST_THISDLL); SetObjectOwner(g_hdcDst, HINST_THISDLL); InitDitherBrush(); hbmTemp = CreateBitmap(8, 8, 1, 1, stripebits); if (hbmTemp) { // initialize the deselect 1x1 bitmap g_hbmDcDeselect = SelectBitmap(g_hdcDst, hbmTemp); SelectBitmap(g_hdcDst, g_hbmDcDeselect); g_hbrStripe = CreatePatternBrush(hbmTemp); SetObjectOwner(g_hbrStripe, HINST_THISDLL); DeleteObject(hbmTemp); } ReleaseDC(HWND_DESKTOP, hdcScreen); if (!g_hdcSrc || !g_hdcDst || !g_hbrMonoDither) { ImageList_Terminate(); DebugMsg(DM_ERROR, "ImageList: Unable to initialize"); return FALSE; } return TRUE; } void NEAR PASCAL ImageList_Terminate() { TerminateDitherBrush(); if (g_hbrStripe) { DeleteObject(g_hbrStripe); g_hbrStripe = NULL; } #ifdef _WIN32 ImageList_DeleteDragBitmaps(); #endif if (g_hdcDst) { ImageList_SelectDstBitmap(NULL); DeleteDC(g_hdcDst); g_hdcDst = NULL; } if (g_hdcSrc) { ImageList_SelectSrcBitmap(NULL); DeleteDC(g_hdcSrc); g_hdcSrc = NULL; } if (g_hbmWork) { DeleteBitmap(g_hbmWork); g_hbmWork = NULL; } } #ifdef DEBUG void NEAR PASCAL ImageList_SelectFailed(HBITMAP hbm) { DM(DM_TRACE, "Bitmap select has failed"); } #else #define ImageList_SelectFailed(hbm) #endif void NEAR PASCAL ImageList_SelectDstBitmap(HBITMAP hbmDst) { if (hbmDst != g_hbmDst) { // If it's selected in the source DC, then deselect it first if (hbmDst && hbmDst == g_hbmSrc) ImageList_SelectSrcBitmap(NULL); if (!SelectBitmap(g_hdcDst, hbmDst ? hbmDst : g_hbmDcDeselect)) ImageList_SelectFailed(hbmDst); g_hbmDst = hbmDst; } } void NEAR PASCAL ImageList_SelectSrcBitmap(HBITMAP hbmSrc) { if (hbmSrc != g_hbmSrc) { // If it's selected in the dest DC, then deselect it first if (hbmSrc && hbmSrc == g_hbmDst) ImageList_SelectDstBitmap(NULL); if (!SelectBitmap(g_hdcSrc, hbmSrc ? hbmSrc : g_hbmDcDeselect)) ImageList_SelectFailed(hbmSrc); g_hbmSrc = hbmSrc; } } HDC NEAR PASCAL ImageList_GetWorkDC(HDC hdc, int dx, int dy) { if (g_hbmWork == NULL || GetDeviceCaps(hdc, BITSPIXEL) != g_bmWork.bmBitsPixel || g_bmWork.bmWidth < dx || g_bmWork.bmHeight < dy) { ImageList_DeleteBitmap(g_hbmWork); g_hbmWork = NULL; if (dx == 0 || dy == 0) return NULL; if (g_hbmWork = CreateCompatibleBitmap(hdc, dx, dy)) { SetObjectOwner(g_hbmWork, HINST_THISDLL); GetObject(g_hbmWork, sizeof(g_bmWork), &g_bmWork); } } ImageList_SelectSrcBitmap(g_hbmWork); return g_hdcSrc; } #ifdef IEWIN31_25 void NEAR PASCAL ImageList_ReleaseWorkDC(HDC hdc) { // ASSERTCRITICAL; Assert(hdc == g_hdcSrc); if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) { SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE); } } #endif //IEWIN31_25 void NEAR PASCAL ImageList_DeleteBitmap(HBITMAP hbm) { if (hbm) { if (g_hbmDst == hbm) ImageList_SelectDstBitmap(NULL); if (g_hbmSrc == hbm) ImageList_SelectSrcBitmap(NULL); DeleteBitmap(hbm); } } IMAGELIST* WINAPI ImageList_Create(int cx, int cy, UINT flags, int cInitial, int cGrow) { IMAGELIST* piml = NULL; if (cx < 0 || cy < 0) return NULL; ENTERCRITICAL; if (!g_iILRefCount) { if (!ImageList_Init()) goto Error; } g_iILRefCount++; piml = ImageList_Create2(cx, cy, flags, cGrow); // allocate the bitmap PLUS one re-usable entry if (piml) { // make the hdc's piml->hdcImage = CreateCompatibleDC(NULL); if (piml->hdcImage == NULL) goto Error; // make a palette if asked to. if ((piml->flags & ILC_PALETTE) && (GetDeviceCaps(piml->hdcImage, RASTERCAPS) & RC_PALETTE)) { piml->hpal = CreateHalftonePalette(piml->hdcImage); } if (piml->flags & ILC_MASK) { piml->hdcMask = CreateCompatibleDC(NULL); // were they both made ok? if (!piml->hdcMask) goto Error; } ImageList_SetOwners(piml); if (!ImageList_ReAllocBitmaps(piml, cInitial + 1) && !ImageList_ReAllocBitmaps(piml, 1)) { goto Error; } } LEAVECRITICAL; return piml; Error: if (piml) ImageList_Destroy(piml); piml = NULL; LEAVECRITICAL; return piml; } #ifdef _WIN32 IMAGELIST* WINAPI ImageList_LoadImage(HINSTANCE hi, LPCSTR lpbmp, int cx, int cGrow, COLORREF crMask, UINT uType, UINT uFlags) { HBITMAP hbmImage; IMAGELIST *piml = NULL; BITMAP bm; int cy, cInitial; hbmImage = LoadImage(hi, lpbmp, uType, 0, 0, uFlags); if (!hbmImage || (sizeof(bm) != GetObject(hbmImage, sizeof(bm), &bm))) goto cleanup; // If cx is not stated assume it is the same as cy. // Assert(cx); cy = bm.bmHeight; if (cx == 0) cx = cy; cInitial = bm.bmWidth / cx; ENTERCRITICAL; piml = ImageList_Create(cx, cy, (crMask != CLR_NONE) ? ILC_MASK : 0, cInitial, cGrow); if (piml) { int added; if (crMask == CLR_NONE) added = ImageList_Add(piml, hbmImage, NULL); else added = ImageList_AddMasked(piml, hbmImage, crMask); if (added < 0) { ImageList_Destroy(piml); piml = NULL; } } LEAVECRITICAL; cleanup: if (hbmImage) DeleteObject(hbmImage); return piml; } #else #ifdef IEWIN31_25 IMAGELIST* WINAPI ImageList_LoadImage(HINSTANCE hi, LPCSTR lpbmp, int cx, int cGrow, COLORREF crMask, UINT uType, UINT uFlags) { HBITMAP hbmImage; IMAGELIST *piml = NULL; BITMAP bm; int cy, cInitial; hbmImage = LoadBitmap(hi, lpbmp); if (!hbmImage || (sizeof(bm) != GetObject(hbmImage, sizeof(bm), &bm))) goto cleanup; // If cx is not stated assume it is the same as cy. // Assert(cx); cy = bm.bmHeight; if (cx == 0) cx = cy; cInitial = bm.bmWidth / cx; ENTERCRITICAL; piml = ImageList_Create(cx, cy, (crMask != CLR_NONE) ? ILC_MASK : 0, cInitial, cGrow); if (piml) { int added; if (crMask == CLR_NONE) added = ImageList_Add(piml, hbmImage, NULL); else added = ImageList_AddMasked(piml, hbmImage, crMask); if (added < 0) { ImageList_Destroy(piml); piml = NULL; } } LEAVECRITICAL; cleanup: if (hbmImage) DeleteObject(hbmImage); return piml; } #endif //IEWIN31_25 #endif IMAGELIST* NEAR PASCAL ImageList_Create2(int cx, int cy, UINT flags, int cGrow) { IMAGELIST* piml; #ifdef _WIN32 if (flags & ILC_SHARED) piml = Alloc(sizeof(IMAGELIST)); // shared alloc else piml = (IMAGELIST*)LocalAlloc(LPTR, sizeof(IMAGELIST)); // non-shared #else piml = (IMAGELIST*)LocalAlloc(LPTR, sizeof(IMAGELIST)); // non-shared #endif if (piml) { if (cGrow < 4) cGrow = 4; else { // round up by 4's cGrow = (cGrow + 3) & ~3; } //piml->cImage = 0; //piml->cAlloc = 0; piml->cImages = 4; piml->cGrow = cGrow; piml->cx = cx; piml->cy = cy; piml->clrBlend = CLR_NONE; piml->clrBk = CLR_NONE; piml->hbrBk = GetStockObject(BLACK_BRUSH); piml->fSolidBk = TRUE; piml->flags = flags; //piml->hbmImage = NULL; //piml->hbmMask = NULL; //piml->hInstOwner = NULL; //piml->hdcImage = NULL; //piml->hdcMask = NULL; piml->wMagic = IMAGELIST_MAGIC; } else { DebugMsg(DM_ERROR, "ImageList: Out of near memory"); } return piml; } BOOL WINAPI ImageList_Destroy(IMAGELIST* piml) { V_HIMAGELIST(piml); ENTERCRITICAL; // nuke dc's if (piml->hdcImage) { SelectObject(piml->hdcImage, g_hbmDcDeselect); DeleteDC(piml->hdcImage); } if (piml->hdcMask) { SelectObject(piml->hdcMask, g_hbmDcDeselect); DeleteDC(piml->hdcMask); } // nuke bitmaps if (piml->hbmImage) ImageList_DeleteBitmap(piml->hbmImage); if (piml->hbmMask) ImageList_DeleteBitmap(piml->hbmMask); if (piml->hbrBk) DeleteObject(piml->hbrBk); if (piml->hpal) DeleteObject(piml->hpal); // one less use of imagelists. if it's the last, terminate the imagelist g_iILRefCount--; if (!g_iILRefCount) ImageList_Terminate(); LEAVECRITICAL; piml->wMagic = 0; #ifdef _WIN32 if (piml->flags & ILC_SHARED) Free(piml); else LocalFree((HLOCAL)piml); #else LocalFree((HLOCAL)piml); #endif return TRUE; } void NEAR PASCAL ImageList_SetOwners(IMAGELIST* piml) { if (IsImageList(piml) && (piml->flags & ILC_SHARED)) { if (piml->hbmImage) SetObjectOwner(piml->hbmImage, HINST_THISDLL); if (piml->hbmMask) SetObjectOwner(piml->hbmMask, HINST_THISDLL); if (piml->hbrBk) SetObjectOwner(piml->hbrBk, HINST_THISDLL); if (piml->hpal) SetObjectOwner(piml->hpal, HINST_THISDLL); if (piml->hdcImage) SetObjectOwner(piml->hdcImage, HINST_THISDLL); if (piml->hdcMask) SetObjectOwner(piml->hdcMask, HINST_THISDLL); } } int WINAPI ImageList_GetImageCount(IMAGELIST* piml) { V_HIMAGELIST(piml); return piml->cImage; } BOOL WINAPI ImageList_GetIconSize(IMAGELIST *piml, int FAR *cx, int FAR *cy) { V_HIMAGELIST(piml); *cx = piml->cx; *cy = piml->cy; return TRUE; } // change the size of a existing image list // also removes all items BOOL WINAPI ImageList_SetIconSize(IMAGELIST *piml, int cx, int cy) { V_HIMAGELIST(piml); if (piml->cx == cx && piml->cy == cy) return FALSE; // no change piml->cx = cx; piml->cy = cy; ImageList_Remove(piml, -1); return TRUE; } // reset the background color of images iFirst through iLast void NEAR PASCAL ImageList_ResetBkColor(IMAGELIST* piml, int iFirst, int iLast, COLORREF clr) { HBRUSH hbrT=NULL; DWORD rop; if (!IsImageList(piml) || piml->hdcMask == NULL) return; if (clr == CLR_BLACK || clr == CLR_NONE) { rop = ROP_DSna; } else if (clr == CLR_WHITE) { rop = ROP_DSo; } else { Assert(piml->hbrBk); Assert(piml->clrBk == clr); rop = ROP_PatMask; hbrT = SelectBrush(piml->hdcImage, piml->hbrBk); } for ( ;iFirst <= iLast; iFirst++) { RECT rc; ImageList_GetImageRect(piml, iFirst, &rc); BitBlt(piml->hdcImage, rc.left, rc.top, piml->cx, piml->cy, piml->hdcMask, rc.left, rc.top, rop); } if (hbrT) SelectBrush(piml->hdcImage, hbrT); } COLORREF WINAPI ImageList_SetBkColor(IMAGELIST* piml, COLORREF clrBk) { COLORREF clrBkOld; V_HIMAGELIST(piml); // Quick out if there is no change in color if (piml->clrBk == clrBk) { return clrBk; } if (piml->hbrBk != NULL) { DeleteBrush(piml->hbrBk); } clrBkOld = piml->clrBk; piml->clrBk = clrBk; if (clrBk == CLR_NONE) { piml->hbrBk = GetStockObject(BLACK_BRUSH); piml->fSolidBk = TRUE; } else { piml->hbrBk = CreateSolidBrush(clrBk); piml->fSolidBk = GetNearestColor(piml->hdcImage, clrBk) == clrBk; } Assert(piml->hbrBk); if (piml->cImage > 0) { ImageList_ResetBkColor(piml, 0, piml->cImage - 1, clrBk); } return clrBkOld; } COLORREF WINAPI ImageList_GetBkColor(IMAGELIST* piml) { V_HIMAGELIST(piml); return piml->clrBk; } BOOL NEAR PASCAL ImageList_ReAllocBitmaps(IMAGELIST* piml, int cAlloc) { HBITMAP hbmImageNew; HBITMAP hbmMaskNew; int cx, cy; V_HIMAGELIST(piml); if (piml->cAlloc >= cAlloc) return TRUE; hbmMaskNew = NULL; hbmImageNew = NULL; cx = piml->cx * piml->cImages; cy = piml->cy * ((cAlloc + piml->cImages - 1) / piml->cImages); if (cAlloc > 0) { if (piml->flags & ILC_MASK) { hbmMaskNew = CreateMonoBitmap(cx, cy); if (!hbmMaskNew) { DebugMsg(DM_ERROR, "ImageList: Can't create bitmap"); return FALSE; } } hbmImageNew = CreateDSBitmap(cx, cy, piml->flags); if (!hbmImageNew) { if (hbmMaskNew) ImageList_DeleteBitmap(hbmMaskNew); DebugMsg(DM_ERROR, "ImageList: Can't create bitmap"); return FALSE; } } if (piml->cImage > 0) { int cyCopy = piml->cy * ((min(cAlloc, piml->cImage) + piml->cImages - 1) / piml->cImages); if (piml->flags & ILC_MASK) { ImageList_SelectDstBitmap(hbmMaskNew); BitBlt(g_hdcDst, 0, 0, cx, cyCopy, piml->hdcMask, 0, 0, SRCCOPY); } ImageList_SelectDstBitmap(hbmImageNew); BitBlt(g_hdcDst, 0, 0, cx, cyCopy, piml->hdcImage, 0, 0, SRCCOPY); } // select into DC's, delete then assign ImageList_SelectDstBitmap(NULL); ImageList_SelectSrcBitmap(NULL); SelectObject(piml->hdcImage, hbmImageNew); if (piml->hdcMask) SelectObject(piml->hdcMask, hbmMaskNew); if (piml->hbmMask) ImageList_DeleteBitmap(piml->hbmMask); if (piml->hbmImage) ImageList_DeleteBitmap(piml->hbmImage); piml->hbmMask = hbmMaskNew; piml->hbmImage = hbmImageNew; piml->clrBlend = CLR_NONE; ImageList_SetOwners(piml); piml->cAlloc = cAlloc; return TRUE; } // in: // piml image list to add to // hbmImage & hbmMask the new image(s) to add, if multiple pass in horizontal strip // cImage number of images to add in hbmImage and hbmMask // returns: // index of new item, if more than one starting index of new items int WINAPI ImageList_Add2(IMAGELIST* piml, HBITMAP hbmImage, HBITMAP hbmMask, int cImage, int xStart, int yStart) { int i = -1; V_HIMAGELIST(piml); ENTERCRITICAL; if (piml->cImage + cImage + 1 > piml->cAlloc) { if (!ImageList_ReAllocBitmaps(piml, piml->cAlloc + max(cImage, piml->cGrow) + 1)) goto Cleanup; } i = piml->cImage; piml->cImage += cImage; if (hbmImage && !ImageList_Replace2(piml, i, cImage, hbmImage, hbmMask, xStart, yStart)) { piml->cImage -= cImage; i = -1; goto Cleanup; } Cleanup: LEAVECRITICAL; return i; } int WINAPI ImageList_Add(IMAGELIST* piml, HBITMAP hbmImage, HBITMAP hbmMask) { BITMAP bm; int cImage; Assert(piml); Assert(hbmImage); Assert(piml->cx); if (!piml || GetObject(hbmImage, sizeof(bm), &bm) != sizeof(bm) || bm.bmWidth < piml->cx) return -1; cImage = bm.bmWidth / piml->cx; // # of images in source // serialization handled within Add2. return(ImageList_Add2(piml, hbmImage, hbmMask, cImage, 0, 0)); } //#ifdef _WIN32 #if defined(_WIN32) || defined(IEWIN31_25) int WINAPI ImageList_AddMasked(IMAGELIST* piml, HBITMAP hbmImage, COLORREF crMask) { COLORREF crbO, crtO; HBITMAP hbmMask; int cImage; int retval; BITMAP bm; V_HIMAGELISTERR(piml, -1); if (GetObject(hbmImage, sizeof(bm), &bm) != sizeof(bm)) return -1; hbmMask = CreateMonoBitmap(bm.bmWidth, bm.bmHeight); if (!hbmMask) return -1; ENTERCRITICAL; // copy color to mono, with crMask turning 1 and all others 0, then // punch all crMask pixels in color to 0 ImageList_SelectSrcBitmap(hbmImage); ImageList_SelectDstBitmap(hbmMask); crbO = SetBkColor(g_hdcSrc, crMask); BitBlt(g_hdcDst, 0, 0, bm.bmWidth, bm.bmHeight, g_hdcSrc, 0, 0, SRCCOPY); SetBkColor(g_hdcSrc, 0x00FFFFFFL); crtO = SetTextColor(g_hdcSrc, 0x00L); BitBlt(g_hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, g_hdcDst, 0, 0, ROP_DSna); SetBkColor(g_hdcSrc, crbO); SetTextColor(g_hdcSrc, crtO); ImageList_SelectSrcBitmap(NULL); ImageList_SelectDstBitmap(NULL); Assert(piml->cx); cImage = bm.bmWidth / piml->cx; // # of images in source retval = ImageList_Add2(piml, hbmImage, hbmMask, cImage, 0, 0); DeleteObject(hbmMask); LEAVECRITICAL; return retval; } #endif #ifdef _WIN32 BOOL WINAPI ImageList_Replace(IMAGELIST* piml, int i, HBITMAP hbmImage, HBITMAP hbmMask) { BOOL fRet; V_HIMAGELIST(piml); if (!IsImageListIndex(piml, i)) return FALSE; ENTERCRITICAL; fRet = ImageList_Replace2(piml, i, 1, hbmImage, hbmMask, 0, 0); LEAVECRITICAL; return fRet; } #endif // replaces images in piml with images from bitmaps // in: // piml // i index in image list to start at (replace) // cImage count of images in source (hbmImage, hbmMask) BOOL NEAR PASCAL ImageList_Replace2(IMAGELIST* piml, int i, int cImage, HBITMAP hbmImage, HBITMAP hbmMask, int xStart, int yStart) { RECT rcImage; int x, iImage; V_HIMAGELIST(piml); Assert(hbmImage); ImageList_SelectSrcBitmap(hbmImage); if (piml->hdcMask) ImageList_SelectDstBitmap(hbmMask); // using as just a second source hdc for (x = xStart, iImage = 0; iImage < cImage; iImage++, x += piml->cx) { ImageList_GetImageRect(piml, i + iImage, &rcImage); if (piml->hdcMask) { BitBlt(piml->hdcMask, rcImage.left, rcImage.top, piml->cx, piml->cy, g_hdcDst, x, yStart, SRCCOPY); } BitBlt(piml->hdcImage, rcImage.left, rcImage.top, piml->cx, piml->cy, g_hdcSrc, x, yStart, SRCCOPY); } ImageList_ResetBkColor(piml, i, i + cImage - 1, piml->clrBk); // Bug fix : We should unselect hbmImage, so that the client can play with // it. (SatoNa) ImageList_SelectSrcBitmap(NULL); if (piml->hdcMask) ImageList_SelectDstBitmap(NULL); return TRUE; } #ifdef _WIN32 HICON WINAPI ImageList_GetIcon(IMAGELIST* piml, int i, UINT flags) { UINT cx, cy; HICON hIcon = NULL; HBITMAP hbmMask, hbmColor; ICONINFO ii; V_HIMAGELIST(piml); if (!IsImageListIndex(piml, i)) return NULL; cx = piml->cx; cy = piml->cy; hbmColor = CreateColorBitmap(cx,cy); if (!hbmColor) { goto Error1; } hbmMask = CreateMonoBitmap(cx,cy); if (!hbmMask) { goto Error2; } ENTERCRITICAL; ImageList_SelectDstBitmap(hbmMask); PatBlt(g_hdcDst, 0, 0, cx, cy, WHITENESS); ImageList_Draw(piml, i, g_hdcDst, 0, 0, ILD_MASK | flags); ImageList_SelectDstBitmap(hbmColor); PatBlt(g_hdcDst, 0, 0, cx, cy, BLACKNESS); ImageList_Draw(piml, i, g_hdcDst, 0, 0, ILD_TRANSPARENT | flags); ImageList_SelectDstBitmap(NULL); LEAVECRITICAL; ii.fIcon = TRUE; ii.xHotspot = 0; ii.yHotspot = 0; ii.hbmColor = hbmColor; ii.hbmMask = hbmMask; hIcon = CreateIconIndirect(&ii); DeleteObject(hbmMask); Error2:; DeleteObject(hbmColor); Error1:; return hIcon; } #endif #ifdef DEAD_CODE // this is essentially a BitBlt from one ImageList to another int WINAPI ImageList_AddFromImageList(IMAGELIST* pimlDest, IMAGELIST* pimlSrc, int iSrc) { RECT rcImage; V_HIMAGELISTERR(pimlDest, -1); V_HIMAGELISTERR(pimlSrc, -1); // Can't copy to itself (I'm lazy) if (pimlSrc == pimlDest) { return(-1); } // Check that the two image lists are "compatible" // BUGBUG: Should I check for the bitmaps being in the same format? if (pimlDest->cx!=pimlSrc->cx || pimlDest->cy!=pimlSrc->cy) { return(-1); } // Check that the source image is not out of bounds if (!ImageList_GetImageRect(pimlSrc, iSrc, &rcImage)) { return(-1); } // Go ahead and add it return(ImageList_Add2(pimlDest, pimlSrc->hbmImage, pimlSrc->hbmMask, 1, rcImage.left, rcImage.top)); } #endif // this removes an image from the bitmap but doing all the // proper shuffling. // this does the following: // if the bitmap being removed is not the last in the row // it blts the images to the right of the one being deleted // to the location of the one being deleted (covering it up) // for all rows until the last row (where the last image is) // move the image from the next row up to the last position // in the current row. then slide over all images in that // row to the left. void NEAR PASCAL ImageList_RemoveItemBitmap(IMAGELIST* piml, int i) { RECT rc1; RECT rc2; int dx, y; int x; ImageList_GetImageRect(piml, i, &rc1); ImageList_GetImageRect(piml, piml->cImage - 1, &rc2); // the row with the image being deleted, do we need to shuffle? // amount of stuff to shuffle dx = piml->cImages * piml->cx - rc1.right; if (dx) { // yes, shuffle things left BitBlt(piml->hdcImage, rc1.left, rc1.top, dx, piml->cy, piml->hdcImage, rc1.right, rc1.top, SRCCOPY); if (piml->hdcMask) BitBlt(piml->hdcMask, rc1.left, rc1.top, dx, piml->cy, piml->hdcMask, rc1.right, rc1.top, SRCCOPY); } y = rc1.top; // top of row we are working on x = piml->cx * (piml->cImages - 1); // x coord of last bitmaps in each row while (y < rc2.top) { // copy first from row below to last image position on this row BitBlt(piml->hdcImage, x, y, piml->cx, piml->cy, piml->hdcImage, 0, y + piml->cy, SRCCOPY); if (piml->hdcMask) BitBlt(piml->hdcMask, x, y, piml->cx, piml->cy, piml->hdcMask, 0, y + piml->cy, SRCCOPY); y += piml->cy; // jump to row to slide left if (y <= rc2.top) { // slide the rest over to the left BitBlt(piml->hdcImage, 0, y, x, piml->cy, piml->hdcImage, piml->cx, y, SRCCOPY); // slide the rest over to the left if (piml->hdcMask) BitBlt(piml->hdcMask, 0, y, x, piml->cy, piml->hdcMask, piml->cx, y, SRCCOPY); } } } // ImageList_Remove - remove a image from the image list // i - image to remove, or -1 to remove all images. // NOTE all images are "shifted" down, ie all image index's // above the one deleted are changed by 1 BOOL WINAPI ImageList_Remove(IMAGELIST* piml, int i) { BOOL bRet = TRUE; V_HIMAGELIST(piml); ENTERCRITICAL; if (i == -1) { piml->cImage = 0; piml->cAlloc = 0; for (i=0; iaOverlayIndexes[i] = 0; ImageList_ReAllocBitmaps(piml, piml->cGrow); } else { if (!IsImageListIndex(piml, i)) { bRet = FALSE; } else { ImageList_RemoveItemBitmap(piml, i); --piml->cImage; if (piml->cAlloc - (piml->cImage + 1) > piml->cGrow) ImageList_ReAllocBitmaps(piml, piml->cAlloc - piml->cGrow); } } LEAVECRITICAL; return bRet; } // Set the image iImage as one of the special images for us in combine // drawing. to draw with these specify the index of this // in: // piml imagelist // iImage image index to use in speical drawing // iOverlay index of special image, values 1-4 BOOL WINAPI ImageList_SetOverlayImage(IMAGELIST* piml, int iImage, int iOverlay) { RECT rcImage; RECT rc; int x,y; V_HIMAGELIST(piml); iOverlay--; // make zero based if (piml->hdcMask == NULL || iImage < 0 || iImage >= piml->cImage || iOverlay < 0 || iOverlay >= NUM_OVERLAY_IMAGES) return FALSE; if (piml->aOverlayIndexes[iOverlay] == (SHORT)iImage) return TRUE; piml->aOverlayIndexes[iOverlay] = (SHORT)iImage; // find minimal rect that bounds the image ImageList_GetImageRect(piml, iImage, &rcImage); SetRect(&rc, 0x7FFF, 0x7FFF, 0, 0); for (y=rcImage.top; yhdcMask, x, y) == CLR_BLACK) { rc.left = min(rc.left, x); rc.right = max(rc.right, x+1); rc.top = min(rc.top, y); rc.bottom = max(rc.bottom, y+1); } } } // did we find anything? if no, set it to 0 if (rc.left == 0x7FFF) { rc.left = 0; Assert(0); } if (rc.top == 0x7FFF) { rc.top = 0; Assert(0); } piml->aOverlayDX[iOverlay] = (SHORT)(rc.right - rc.left); piml->aOverlayDY[iOverlay] = (SHORT)(rc.bottom- rc.top); piml->aOverlayX[iOverlay] = (SHORT)(rc.left - rcImage.left); piml->aOverlayY[iOverlay] = (SHORT)(rc.top - rcImage.top); piml->aOverlayF[iOverlay] = 0; // see iff the image is non-rectanglar // if the overlay does not require a mask to be drawn set the // ILD_IMAGE flag, this causes ImageList_DrawEx to just // draw the image, ignoring the mask. for (y=rc.top; yhdcMask, x, y) == CLR_WHITE) break; } if (x != rc.right) break; } if (y == rc.bottom) piml->aOverlayF[iOverlay] = ILD_IMAGE; DebugMsg(DM_TRACE, "overlay #%d index=%d (%d,%d,%d,%d) mask:%d", iOverlay, iImage, piml->aOverlayX[iOverlay], piml->aOverlayY[iOverlay], piml->aOverlayDX[iOverlay], piml->aOverlayDY[iOverlay], piml->aOverlayF[iOverlay]); return TRUE; } #ifdef _WIN32 /* ** BlendCT */ void BlendCT(DWORD *pdw, DWORD rgb, UINT n, UINT count) { UINT i; for (i=0; ihbmImage, sizeof(bm), &bm); // if hbmImage is a DIBSection and we are on a HiColor device // the do a "real" blend if (bm.bmBits && bm.bmBitsPixel <= 8 && (GetDeviceCaps(hdcDst, BITSPIXEL) > 8 || piml->hpal)) { HPALETTE hpalT; if (rgb == CLR_DEFAULT) rgb = GetSysColor(COLOR_HIGHLIGHT); Assert(rgb != CLR_NONE); // get the DIB color table and blend it, only do this when the // blend color changes if (piml->clrBlend != rgb) { int n,cnt; piml->clrBlend = rgb; GetObject(piml->hbmImage, sizeof(piml->dib), &piml->dib.bm); cnt = GetDIBColorTable(piml->hdcImage, 0, 256, (LPRGBQUAD)&piml->dib.ct); if ((fStyle & ILD_BLENDMASK) == ILD_BLEND50) n = 50; else n = 25; BlendCT(piml->dib.ct, rgb, n, cnt); } if (piml->hpal) { hpalT = SelectPalette(hdcDst, piml->hpal, TRUE); RealizePalette(hdcDst); } // draw the image with a different color table StretchDIBits(hdcDst, xDst, yDst, cx, cy, x, piml->dib.bi.biHeight-(y+cy), cx, cy, bm.bmBits, (LPBITMAPINFO)&piml->dib.bi, DIB_RGB_COLORS, SRCCOPY); if (piml->hpal) { SelectPalette(hdcDst, hpalT, TRUE); RealizePalette(hdcDst); } } // simulate a blend with a dither pattern. else #endif // _WIN32 { HBRUSH hbr; HBRUSH hbrT; HBRUSH hbrMask; HBRUSH hbrFree = NULL; // free if non-null Assert(GetTextColor(hdcDst) == CLR_BLACK); Assert(GetBkColor(hdcDst) == CLR_WHITE); // choose a dither/blend brush switch (fStyle & ILD_BLENDMASK) { default: case ILD_BLEND50: hbrMask = g_hbrMonoDither; break; case ILD_BLEND25: hbrMask = g_hbrStripe; break; } // create (or use a existing) brush for the blend color switch (rgb) { case CLR_DEFAULT: hbr = g_hbrHighlight; break; case CLR_NONE: hbr = piml->hbrBk; break; default: if (rgb == piml->clrBk) hbr = piml->hbrBk; else hbr = hbrFree = CreateSolidBrush(rgb); break; } hbrT = SelectObject(hdcDst, hbr); PatBlt(hdcDst, xDst, yDst, cx, cy, PATCOPY); SelectObject(hdcDst, hbrT); hbrT = SelectObject(hdcDst, hbrMask); BitBlt(hdcDst, xDst, yDst, cx, cy, piml->hdcImage, x, y, ROP_MaskPat); SelectObject(hdcDst, hbrT); if (hbrFree) DeleteBrush(hbrFree); } } #ifdef IEWIN31_25 /* ** Draw the image, either selected, transparent, or just a blt ** For the selected case, a new highlighted image is generated ** and used for the final output. ** piml ImageList to get image from. ** i the image to get. ** hdc DC to draw image to ** x,y where to draw image (upper left corner) ** cx,cy size of image to draw (0,0 means normal size) ** rgbBk background color ** CLR_NONE - draw tansparent ** CLR_DEFAULT - use bk color of the image list ** rgbFg foreground (blend) color (only used if ILD_BLENDMASK set) ** CLR_NONE - blend with destination (transparent) ** CLR_DEFAULT - use windows hilight color ** if blend ** if blend with color ** copy image, and blend it with color. ** else if blend with dst ** copy image, copy mask, blend mask 50% ## ** if ILD_TRANSPARENT ** draw transparent (two blts) special case black or white background ** unless we copied the mask or image ** else if (rgbBk == piml->rgbBk && fSolidBk) ** just blt it ** else if mask ** copy image ** replace bk color ** blt it. ** else ** just blt it */ BOOL WINAPI ImageList_DrawIndirect(IMAGELISTDRAWPARAMS FAR * pimldp) { RECT rcImage; RECT rc; HBRUSH hbrT; BOOL fImage; HDC hdcMask; HDC hdcImage; int xMask, yMask; int xImage, yImage; V_HIMAGELIST(pimldp->himl); if (pimldp->cbSize != sizeof(IMAGELISTDRAWPARAMS)) return FALSE; #ifdef TODO if (ImageList_Filter(&pimldp->himl, &pimldp->i, FALSE)) return FALSE; #endif //TODO if (!IsImageListIndex(pimldp->himl, pimldp->i)) return FALSE; ENTERCRITICAL; ImageList_GetImageRect(pimldp->himl, pimldp->i, &rcImage); rcImage.left += pimldp->xBitmap; rcImage.top += pimldp->yBitmap; if (pimldp->rgbBk == CLR_DEFAULT) pimldp->rgbBk = pimldp->himl->clrBk; if (pimldp->rgbBk == CLR_NONE) pimldp->fStyle |= ILD_TRANSPARENT; if (pimldp->cx == 0) pimldp->cx = rcImage.right - rcImage.left; if (pimldp->cy == 0) pimldp->cy = rcImage.bottom - rcImage.top; again: hdcMask = pimldp->himl->hdcMask; xMask = rcImage.left; yMask = rcImage.top; hdcImage = pimldp->himl->hdcImage; xImage = rcImage.left; yImage = rcImage.top; if (pimldp->fStyle & ILD_BLENDMASK) { // make a copy of the image, because we will have to modify it hdcImage = ImageList_GetWorkDC(pimldp->hdcDst, pimldp->cx, pimldp->cy); xImage = 0; yImage = 0; // blend with the destination // by "oring" the mask with a 50% dither mask if (pimldp->rgbFg == CLR_NONE && hdcMask) { ImageList_GetSpareImageRect(pimldp->himl, &rc); xMask = rc.left; yMask = rc.top; // copy the source image BitBlt(hdcImage, 0, 0, pimldp->cx, pimldp->cy, pimldp->himl->hdcImage, rcImage.left, rcImage.top, SRCCOPY); // make a dithered copy of the mask hbrT = SelectObject(hdcMask, g_hbrMonoDither); BitBlt(hdcMask, rc.left, rc.top, pimldp->cx, pimldp->cy, hdcMask, rcImage.left, rcImage.top, ROP_PSo); SelectObject(hdcMask, hbrT); pimldp->fStyle |= ILD_TRANSPARENT; } else { // blend source into our work buffer ImageList_Blend(hdcImage, 0, 0, pimldp->himl, rcImage.left, rcImage.top, pimldp->cx, pimldp->cy, pimldp->rgbFg, pimldp->fStyle); } } // is the source image from the image list (not hdcWork) fImage = hdcImage == pimldp->himl->hdcImage; // ILD_MASK means draw the mask only if ((pimldp->fStyle & ILD_MASK) && hdcMask) { DWORD dwRop; Assert(GetTextColor(pimldp->hdcDst) == CLR_BLACK); Assert(GetBkColor(pimldp->hdcDst) == CLR_WHITE); if (pimldp->fStyle & ILD_ROP) dwRop = pimldp->dwRop; else if (pimldp->fStyle & ILD_TRANSPARENT) dwRop = SRCAND; else dwRop = SRCCOPY; BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcMask, xMask, yMask, dwRop); } else if (pimldp->fStyle & ILD_IMAGE) { COLORREF clrBk = GetBkColor(hdcImage); DWORD dwRop; if (pimldp->rgbBk != CLR_DEFAULT) { SetBkColor(hdcImage, pimldp->rgbBk); } if (pimldp->fStyle & ILD_ROP) dwRop = pimldp->dwRop; else dwRop = SRCCOPY; BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, dwRop); SetBkColor(hdcImage, clrBk); } // if there is a mask and the drawing is to be transparent, // use the mask for the drawing. else if ((pimldp->fStyle & ILD_TRANSPARENT) && hdcMask) { // on NT dont dork around, just call MaskBlt #ifdef USE_MASKBLT MaskBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, hdcMask, xMask, yMask, 0xCCAA0000); #else COLORREF clrTextSave; COLORREF clrBkSave; // we have some special cases: // if the background color is black, we just do a AND then OR // if the background color is white, we just do a OR then AND // otherwise change source, then AND then OR clrTextSave = SetTextColor(pimldp->hdcDst, CLR_BLACK); clrBkSave = SetBkColor(pimldp->hdcDst, CLR_WHITE); // we cant do white/black special cases if we munged the mask or image if (fImage && (pimldp->himl->clrBk == CLR_WHITE)) { BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcMask, xMask, yMask, ROP_DSno); BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, ROP_DSa); } else if (fImage && ((pimldp->himl->clrBk == CLR_BLACK) || (pimldp->himl->clrBk == CLR_NONE))) { BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcMask, xMask, yMask, ROP_DSa); BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, ROP_DSo); } else { Assert(GetTextColor(hdcImage) == CLR_BLACK); Assert(GetBkColor(hdcImage) == CLR_WHITE); // black out the source image. BitBlt(hdcImage, xImage, yImage, pimldp->cx, pimldp->cy, hdcMask, xMask, yMask, ROP_DSna); BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcMask, xMask, yMask, ROP_DSa); BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, ROP_DSo); // restore the bkcolor, if it came from the image list if (fImage) ImageList_ResetBkColor(pimldp->himl, pimldp->i, pimldp->i, pimldp->himl->clrBk); } SetTextColor(pimldp->hdcDst, clrTextSave); SetBkColor(pimldp->hdcDst, clrBkSave); #endif } else if (fImage && pimldp->rgbBk == pimldp->himl->clrBk && pimldp->himl->fSolidBk) { BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, SRCCOPY); } else if (hdcMask) { if (fImage && GetNearestColor(hdcImage, pimldp->rgbBk) != pimldp->rgbBk) { // make a copy of the image, because we will have to modify it hdcImage = ImageList_GetWorkDC(pimldp->hdcDst, pimldp->cx, pimldp->cy); xImage = 0; yImage = 0; fImage = FALSE; BitBlt(hdcImage, 0, 0, pimldp->cx, pimldp->cy, pimldp->himl->hdcImage, rcImage.left, rcImage.top, SRCCOPY); } SetBrushOrg(hdcImage, xImage-pimldp->x, yImage-pimldp->y); hbrT = SelectBrush(hdcImage, CreateSolidBrush(pimldp->rgbBk)); BitBlt(hdcImage, xImage, yImage, pimldp->cx, pimldp->cy, hdcMask, xMask, yMask, ROP_PatMask); DeleteObject(SelectBrush(hdcImage, hbrT)); SetBrushOrg(hdcImage, 0, 0); BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, SRCCOPY); if (fImage) ImageList_ResetBkColor(pimldp->himl, pimldp->i, pimldp->i, pimldp->himl->clrBk); } else { BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, pimldp->cx, pimldp->cy, hdcImage, xImage, yImage, SRCCOPY); } // now deal with a overlay image, use the minimal bounding rect (and flags) // we computed in ImageList_SetOverlayImage() if (pimldp->fStyle & ILD_OVERLAYMASK) { int n = OVERLAYMASKTOINDEX(pimldp->fStyle); if (n < NUM_OVERLAY_IMAGES) { pimldp->i = pimldp->himl->aOverlayIndexes[n]; ImageList_GetImageRect(pimldp->himl, pimldp->i, &rcImage); pimldp->cx = pimldp->himl->aOverlayDX[n]; pimldp->cy = pimldp->himl->aOverlayDY[n]; pimldp->x += pimldp->himl->aOverlayX[n]; pimldp->y += pimldp->himl->aOverlayY[n]; rcImage.left += pimldp->himl->aOverlayX[n]+pimldp->xBitmap; rcImage.top += pimldp->himl->aOverlayY[n]+pimldp->yBitmap; pimldp->fStyle &= ILD_MASK; pimldp->fStyle |= ILD_TRANSPARENT; pimldp->fStyle |= pimldp->himl->aOverlayF[n]; if (pimldp->cx > 0 && pimldp->cy > 0) goto again; // ImageList_DrawEx(piml, i, hdcDst, x, y, 0, 0, CLR_DEFAULT, CLR_NONE, fStyle); } } if (!fImage) { ImageList_ReleaseWorkDC(hdcImage); } LEAVECRITICAL; return TRUE; } #endif //IEWIN31_25 /* ** Draw the image, either selected, transparent, or just a blt ** For the selected case, a new highlighted image is generated ** and used for the final output. ** piml ImageList to get image from. ** i the image to get. ** hdc DC to draw image to ** x,y where to draw image (upper left corner) ** cx,cy size of image to draw (0,0 means normal size) ** rgbBk background color ** CLR_NONE - draw tansparent ** CLR_DEFAULT - use bk color of the image list ** rgbFg foreground (blend) color (only used if ILD_BLENDMASK set) ** CLR_NONE - blend with destination (transparent) ** CLR_DEFAULT - use windows hilight color ** if blend ** if blend with color ** copy image, and blend it with color. ** else if blend with dst ** copy image, copy mask, blend mask 50% ## ** if ILD_TRANSPARENT ** draw transparent (two blts) special case black or white background ** unless we copied the mask or image ** else if (rgbBk == piml->rgbBk && fSolidBk) ** just blt it ** else if mask ** copy image ** replace bk color ** blt it. ** else ** just blt it */ BOOL WINAPI ImageList_DrawEx(IMAGELIST* piml, int i, HDC hdcDst, int x, int y, int cx, int cy, COLORREF rgbBk, COLORREF rgbFg, UINT fStyle) { RECT rcImage; RECT rc; HBRUSH hbrT; BOOL fImage; HDC hdcMask; HDC hdcImage; int xMask, yMask; int xImage, yImage; HPALETTE hpalT; V_HIMAGELIST(piml); if (!IsImageListIndex(piml,i)) return FALSE; if (piml->hpal) { hpalT = SelectPalette(hdcDst, piml->hpal, TRUE); RealizePalette(hdcDst); } ENTERCRITICAL; ImageList_GetImageRect(piml, i, &rcImage); if (rgbBk == CLR_DEFAULT) rgbBk = piml->clrBk; if (rgbBk == CLR_NONE) fStyle |= ILD_TRANSPARENT; again: if (cx == 0) cx = rcImage.right - rcImage.left; if (cy == 0) cy = rcImage.bottom - rcImage.top; hdcMask = piml->hdcMask; xMask = rcImage.left; yMask = rcImage.top; hdcImage = piml->hdcImage; xImage = rcImage.left; yImage = rcImage.top; if (fStyle & ILD_BLENDMASK) { // make a copy of the image, because we will have to modify it hdcImage = ImageList_GetWorkDC(hdcDst, cx, cy); xImage = 0; yImage = 0; // blend with the destination // by "oring" the mask with a 50% dither mask if (rgbFg == CLR_NONE && hdcMask) { // special hacking to use the one scratch image at tail of list piml->cImage++; ImageList_GetImageRect(piml, piml->cImage-1, &rc); piml->cImage--; xMask = rc.left; yMask = rc.top; // copy the source image BitBlt(hdcImage, 0, 0, cx, cy, piml->hdcImage, rcImage.left, rcImage.top, SRCCOPY); // make a dithered copy of the mask hbrT = SelectObject(hdcMask, g_hbrMonoDither); BitBlt(hdcMask, rc.left, rc.top, cx, cy, hdcMask, rcImage.left, rcImage.top, ROP_PSo); SelectObject(hdcMask, hbrT); fStyle |= ILD_TRANSPARENT; } else { // blend source into our work buffer ImageList_Blend(hdcImage, 0, 0, piml, rcImage.left, rcImage.top, cx, cy, rgbFg, fStyle); } } // is the source image from the image list (not hdcWork) fImage = hdcImage == piml->hdcImage; // ILD_MASK means draw the mask only if ((fStyle & ILD_MASK) && hdcMask) { Assert(GetTextColor(hdcDst) == CLR_BLACK); Assert(GetBkColor(hdcDst) == CLR_WHITE); if (fStyle & ILD_TRANSPARENT) BitBlt(hdcDst, x, y, cx, cy, hdcMask, xMask, yMask, SRCAND); else BitBlt(hdcDst, x, y, cx, cy, hdcMask, xMask, yMask, SRCCOPY); } else if (fStyle & ILD_IMAGE) { BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, SRCCOPY); } // if there is a mask and the drawing is to be transparent, // use the mask for the drawing. else if ((fStyle & ILD_TRANSPARENT) && hdcMask) { // on NT dont dork around, just call MaskBlt #ifdef USE_MASKBLT MaskBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, hdcMask, xMask, yMask, 0xCCAA0000); #else COLORREF clrTextSave; COLORREF clrBkSave; // we have some special cases: // if the background color is black, we just do a AND then OR // if the background color is white, we just do a OR then AND // otherwise change source, then AND then OR clrTextSave = SetTextColor(hdcDst, CLR_BLACK); clrBkSave = SetBkColor(hdcDst, CLR_WHITE); // we cant do white/black special cases if we munged the mask or image if (fImage && piml->clrBk == CLR_WHITE) { BitBlt(hdcDst, x, y, cx, cy, hdcMask, xMask, yMask, ROP_DSno); BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, ROP_DSa); } else if (fImage && piml->clrBk == CLR_BLACK || piml->clrBk == CLR_NONE) { BitBlt(hdcDst, x, y, cx, cy, hdcMask, xMask, yMask, ROP_DSa); BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, ROP_DSo); } else { Assert(GetTextColor(hdcImage) == CLR_BLACK); Assert(GetBkColor(hdcImage) == CLR_WHITE); // black out the source image. BitBlt(hdcImage, xImage, yImage, cx, cy, hdcMask, xMask, yMask, ROP_DSna); BitBlt(hdcDst, x, y, cx, cy, hdcMask, xMask, yMask, ROP_DSa); BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, ROP_DSo); // restore the bkcolor, if it came from the image list if (fImage) ImageList_ResetBkColor(piml, i, i, piml->clrBk); } SetTextColor(hdcDst, clrTextSave); SetBkColor(hdcDst, clrBkSave); #endif } else if (fImage && rgbBk == piml->clrBk && piml->fSolidBk) { BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, SRCCOPY); } else if (hdcMask) { if (fImage && GetNearestColor(hdcImage, rgbBk) != rgbBk) { // make a copy of the image, because we will have to modify it hdcImage = ImageList_GetWorkDC(hdcDst, cx, cy); xImage = 0; yImage = 0; fImage = FALSE; BitBlt(hdcImage, 0, 0, cx, cy, piml->hdcImage, rcImage.left, rcImage.top, SRCCOPY); } SetBrushOrg(hdcImage, xImage-x, yImage-y); hbrT = SelectBrush(hdcImage, CreateSolidBrush(rgbBk)); BitBlt(hdcImage, xImage, yImage, cx, cy, hdcMask, xMask, yMask, ROP_PatMask); DeleteObject(SelectBrush(hdcImage, hbrT)); SetBrushOrg(hdcImage, 0, 0); BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, SRCCOPY); if (fImage) ImageList_ResetBkColor(piml, i, i, piml->clrBk); } else { BitBlt(hdcDst, x, y, cx, cy, hdcImage, xImage, yImage, SRCCOPY); } // now deal with a overlay image, use the minimal bounding rect (and flags) // we computed in ImageList_SetOverlayImage() if (fStyle & ILD_OVERLAYMASK) { int n = OVERLAYMASKTOINDEX(fStyle); i = piml->aOverlayIndexes[n]; ImageList_GetImageRect(piml, i, &rcImage); cx = piml->aOverlayDX[n]; cy = piml->aOverlayDY[n]; x += piml->aOverlayX[n]; y += piml->aOverlayY[n]; rcImage.left += piml->aOverlayX[n]; rcImage.top += piml->aOverlayY[n]; fStyle &= ILD_MASK; fStyle |= ILD_TRANSPARENT; fStyle |= piml->aOverlayF[n]; goto again; // ImageList_DrawEx(piml, i, hdcDst, x, y, 0, 0, CLR_DEFAULT, CLR_NONE, fStyle); } LEAVECRITICAL; if (piml->hpal) { SelectPalette(hdcDst, hpalT, TRUE); RealizePalette(hdcDst); } return TRUE; } BOOL WINAPI ImageList_Draw(IMAGELIST* piml, int i, HDC hdcDst, int x, int y, UINT fStyle) { return ImageList_DrawEx(piml, i, hdcDst, x, y, 0, 0, CLR_DEFAULT, CLR_DEFAULT, fStyle); } BOOL WINAPI ImageList_GetImageRect(IMAGELIST* piml, int i, RECT FAR* prcImage) { int x, y; Assert(prcImage); V_HIMAGELIST(piml); if (!piml || !prcImage || !IsImageListIndex(piml, i)) return FALSE; x = piml->cx * (i % piml->cImages); y = piml->cy * (i / piml->cImages); SetRect(prcImage, x, y, x + piml->cx, y + piml->cy); return TRUE; } #ifdef _WIN32 BOOL WINAPI ImageList_GetImageInfo(IMAGELIST* piml, int i, IMAGEINFO FAR* pImageInfo) { V_HIMAGELIST(piml); Assert(pImageInfo); if (!piml || !pImageInfo || i < 0 || i >= piml->cImage) return FALSE; pImageInfo->hbmImage = piml->hbmImage; pImageInfo->hbmMask = piml->hbmMask; return ImageList_GetImageRect(piml, i, &pImageInfo->rcImage); } #endif // Parameter: // i -- -1 to add int WINAPI ImageList_ReplaceIcon(IMAGELIST* piml, int i, HICON hIcon) { HICON hIconT = hIcon; RECT rc; V_HIMAGELIST(piml); Assert(hIcon); DM(DM_TRACE, "ImageList_ReplaceIcon"); // re-size the icon (iff needed) by calling CopyImage #ifdef _WIN32 hIcon = CopyImage(hIconT, IMAGE_ICON, piml->cx, piml->cy,LR_COPYFROMRESOURCE | LR_COPYRETURNORG); #else #ifdef IEWIN31_25 hIcon = NULL; // TBD - Temporary Hack... #else hIcon = CopyImage(HINST_THISDLL,hIconT, IMAGE_ICON, piml->cx, piml->cy,LR_COPYFROMRESOURCE | LR_COPYRETURNORG); #endif #endif if (hIcon == NULL) return -1; // alocate a slot for the icon if (i == -1) i = ImageList_Add2(piml,NULL,NULL,1,0,0); if (i == -1) return -1; // now draw it into the image bitmaps ImageList_GetImageRect(piml, i, &rc); FillRect(piml->hdcImage, &rc, piml->hbrBk); #ifdef IEWIN31_25 DrawIcon( piml->hdcImage, rc.left, rc.top, hIcon ); #else DrawIconEx(piml->hdcImage, rc.left, rc.top, hIcon, 0, 0, 0, NULL, DI_NORMAL); #endif if (piml->hdcMask) #ifdef IEWIN31_25 DrawIcon( piml->hdcMask, rc.left, rc.top, hIcon ); #else DrawIconEx(piml->hdcMask, rc.left, rc.top, hIcon, 0, 0, 0, NULL, DI_MASK); #endif // if we had user size a new icon, delete it. if (hIcon != hIconT) DestroyIcon(hIcon); return i; } #undef ImageList_AddIcon int WINAPI ImageList_AddIcon(IMAGELIST* piml, HICON hIcon) { return ImageList_ReplaceIcon(piml, -1, hIcon); } /* ** make a dithered copy of the source image in the destination image. ** allows placing of the final image in the destination. **-----------*/ void WINAPI ImageList_CopyDitherImage(IMAGELIST *pimlDst, WORD iDst, int xDst, int yDst, IMAGELIST *pimlSrc, int iSrc, UINT fStyle) { RECT rc; int x, y; ImageList_GetImageRect(pimlDst, iDst, &rc); // coordinates in destination image list x = xDst + rc.left; y = yDst + rc.top; fStyle &= ILD_OVERLAYMASK; ImageList_DrawEx(pimlSrc, iSrc, pimlDst->hdcImage, x, y, 0, 0, CLR_DEFAULT, CLR_NONE, ILD_IMAGE | fStyle); if (pimlDst->hdcMask) ImageList_DrawEx(pimlSrc, iSrc, pimlDst->hdcMask, x, y, 0, 0, CLR_NONE, CLR_NONE, ILD_BLEND50|ILD_MASK | fStyle); ImageList_ResetBkColor(pimlDst, iDst, iDst+1, pimlDst->clrBk); } // drag stuff is only WIN32 #ifdef _WIN32 // Cached bitmaps that we use during drag&drop. We re-use those bitmaps // across multiple drag session as far as the image size is the same. struct DRAGRESTOREBMP { HBITMAP hbmOffScreen; HBITMAP hbmRestore; SIZE sizeRestore; } g_drb = { NULL, NULL, {-1,-1} }; BOOL NEAR PASCAL ImageList_CreateDragBitmaps(IMAGELIST* piml) { V_HIMAGELIST(piml); if (piml->cx != g_drb.sizeRestore.cx || piml->cy != g_drb.sizeRestore.cy) { ImageList_DeleteDragBitmaps(); g_drb.sizeRestore.cx = piml->cx; g_drb.sizeRestore.cy = piml->cy; g_drb.hbmRestore = CreateColorBitmap(g_drb.sizeRestore.cx, g_drb.sizeRestore.cy); g_drb.hbmOffScreen = CreateColorBitmap(g_drb.sizeRestore.cx * 2 - 1, g_drb.sizeRestore.cy * 2 - 1); if (!g_drb.hbmRestore || !g_drb.hbmOffScreen) { ImageList_DeleteDragBitmaps(); return FALSE; } SetObjectOwner(g_drb.hbmRestore, HINST_THISDLL); SetObjectOwner(g_drb.hbmOffScreen, HINST_THISDLL); } return TRUE; } void NEAR PASCAL ImageList_DeleteDragBitmaps() { if (g_drb.hbmRestore) { ImageList_DeleteBitmap(g_drb.hbmRestore); g_drb.hbmRestore = NULL; } if (g_drb.hbmOffScreen) { ImageList_DeleteBitmap(g_drb.hbmOffScreen); g_drb.hbmOffScreen = NULL; } g_drb.sizeRestore.cx = -1; g_drb.sizeRestore.cy = -1; } // Drag context. We don't reuse none of them across two different // drag sessions. I'm planning to allocate it for each session // to minimize critical sections. struct DRAGCONTEXT { IMAGELIST* pimlDrag; // Image to be drawin while dragging IMAGELIST* pimlCursor; // Overlap cursor image IMAGELIST* pimlDither; // Dithered image int iCursor; // Image index of the cursor POINT ptDrag; // current drag position (hwndDC coords) POINT ptDragHotspot; BOOL fDragShow; HWND hwndDC; } g_dctx = { (IMAGELIST*)NULL, (IMAGELIST*)NULL, (IMAGELIST*)NULL, -1, {0, 0}, {0, 0}, FALSE, (HWND)NULL }; #define ImageList_GetDragDC() GetDCEx(g_dctx.hwndDC, NULL, DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE) #define ImageList_ReleaseDragDC(hdc) ReleaseDC(g_dctx.hwndDC, hdc) // x, y -- Specifies the initial cursor position in the coords of hwndLock, // which is specified by the previous ImageList_StartDrag call. BOOL WINAPI ImageList_DragMove(int x, int y) { ENTERCRITICAL; if (g_dctx.fDragShow) { RECT rcOld, rcNew, rcBounds; int dx, dy; dx = x - g_dctx.ptDrag.x; dy = y - g_dctx.ptDrag.y; rcOld.left = g_dctx.ptDrag.x - g_dctx.ptDragHotspot.x; rcOld.top = g_dctx.ptDrag.y - g_dctx.ptDragHotspot.y; rcOld.right = rcOld.left + g_drb.sizeRestore.cx; rcOld.bottom = rcOld.top + g_drb.sizeRestore.cy; rcNew = rcOld; OffsetRect(&rcNew, dx, dy); if (!IntersectRect(&rcBounds, &rcOld, &rcNew)) { // No intersection. Simply hide the old one and show the new one. ImageList_DragShowNolock(FALSE); g_dctx.ptDrag.x = x; g_dctx.ptDrag.y = y; ImageList_DragShowNolock(TRUE); } else { // Some intersection. HDC hdcScreen; int cx, cy; UnionRect(&rcBounds, &rcOld, &rcNew); hdcScreen = ImageList_GetDragDC(); cx = rcBounds.right - rcBounds.left; cy = rcBounds.bottom - rcBounds.top; // Copy the union rect from the screen to hbmOffScreen. ImageList_SelectDstBitmap(g_drb.hbmOffScreen); BitBlt(g_hdcDst, 0, 0, cx, cy, hdcScreen, rcBounds.left, rcBounds.top, SRCCOPY); // Hide the cursor on the hbmOffScreen by copying hbmRestore. ImageList_SelectSrcBitmap(g_drb.hbmRestore); BitBlt(g_hdcDst, rcOld.left - rcBounds.left, rcOld.top - rcBounds.top, g_drb.sizeRestore.cx, g_drb.sizeRestore.cy, g_hdcSrc, 0, 0, SRCCOPY); // Copy the original screen bits to hbmRestore BitBlt(g_hdcSrc, 0, 0, g_drb.sizeRestore.cx, g_drb.sizeRestore.cy, g_hdcDst, rcNew.left - rcBounds.left, rcNew.top - rcBounds.top, SRCCOPY); // Draw the image on hbmOffScreen ImageList_Draw(g_dctx.pimlDrag, 0, g_hdcDst, rcNew.left - rcBounds.left, rcNew.top - rcBounds.top, ILD_NORMAL); // Copy the hbmOffScreen back to the screen. BitBlt(hdcScreen, rcBounds.left, rcBounds.top, cx, cy, g_hdcDst, 0, 0, SRCCOPY); ImageList_ReleaseDragDC(hdcScreen); g_dctx.ptDrag.x = x; g_dctx.ptDrag.y = y; } } LEAVECRITICAL; return TRUE; } BOOL WINAPI ImageList_BeginDrag(IMAGELIST* pimlTrack, int iTrack, int dxHotspot, int dyHotspot) { BOOL fRet = FALSE;; V_HIMAGELIST(pimlTrack); ENTERCRITICAL; if (!g_dctx.pimlDrag) { g_dctx.fDragShow = FALSE; g_dctx.hwndDC = NULL; /* ** make a copy of the drag image */ g_dctx.pimlDither = ImageList_Create( pimlTrack->cx, pimlTrack->cy, pimlTrack->flags|ILC_SHARED, 1,0); if (g_dctx.pimlDither) { g_dctx.pimlDither->cImage++; g_dctx.ptDragHotspot.x = dxHotspot; g_dctx.ptDragHotspot.y = dyHotspot; ImageList_CopyOneImage(g_dctx.pimlDither, 0, 0, 0, pimlTrack, iTrack); fRet = ImageList_SetDragImage(g_dctx.pimlDither, 0, dxHotspot, dyHotspot); } } LEAVECRITICAL; return fRet; } BOOL WINAPI ImageList_DragEnter(HWND hwndLock, int x, int y) { BOOL fRet = FALSE; hwndLock = hwndLock ? hwndLock : GetDesktopWindow(); ENTERCRITICAL; if (!g_dctx.hwndDC) { g_dctx.hwndDC = hwndLock; g_dctx.ptDrag.x = x; g_dctx.ptDrag.y = y; ImageList_DragShowNolock(TRUE); fRet = TRUE; } LEAVECRITICAL; return fRet; } BOOL WINAPI ImageList_DragLeave(HWND hwndLock) { BOOL fRet = FALSE; hwndLock = hwndLock ? hwndLock : GetDesktopWindow(); ENTERCRITICAL; if (g_dctx.hwndDC == hwndLock) { ImageList_DragShowNolock(FALSE); g_dctx.hwndDC = NULL; fRet = TRUE; } LEAVECRITICAL; return fRet; } #if 0 // hwndLock -- Specifies the window to be used to draw destination feedback. // NULL indicates the whole screen. // x, y -- Specifies the initial cursor position in hwndLock coords. BOOL WINAPI ImageList_StartDrag(IMAGELIST* pimlTrack, HWND hwndLock, int iTrack, int x, int y, int dxHotspot, int dyHotspot) { BOOL fRet = FALSE; V_HIMAGELIST(pimlTrack); if (fRet = ImageList_BeginDrag(pimlTrack, iTrack, dxHotspot, dyHotspot)) { fRet = ImageList_DragEnter(hwndLock, x, y); } return fRet; } #endif BOOL WINAPI ImageList_DragShowNolock(BOOL fShow) { HDC hdcScreen; int x, y; x = g_dctx.ptDrag.x - g_dctx.ptDragHotspot.x; y = g_dctx.ptDrag.y - g_dctx.ptDragHotspot.y; if (!g_dctx.pimlDrag) return FALSE; // REVIEW: Why this block is in the critical section? We are supposed // to have only one dragging at a time, aren't we? ENTERCRITICAL; if (fShow && !g_dctx.fDragShow) { hdcScreen = ImageList_GetDragDC(); ImageList_SelectSrcBitmap(g_drb.hbmRestore); BitBlt(g_hdcSrc, 0, 0, g_drb.sizeRestore.cx, g_drb.sizeRestore.cy, hdcScreen, x, y, SRCCOPY); ImageList_Draw(g_dctx.pimlDrag, 0, hdcScreen, x, y, ILD_NORMAL); ImageList_ReleaseDragDC(hdcScreen); } else if (!fShow && g_dctx.fDragShow) { hdcScreen = ImageList_GetDragDC(); ImageList_SelectSrcBitmap(g_drb.hbmRestore); BitBlt(hdcScreen, x, y, g_drb.sizeRestore.cx, g_drb.sizeRestore.cy, g_hdcSrc, 0, 0, SRCCOPY); ImageList_ReleaseDragDC(hdcScreen); } g_dctx.fDragShow = fShow; LEAVECRITICAL; return TRUE; } IMAGELIST* WINAPI ImageList_GetDragImage(POINT FAR* ppt, POINT FAR* pptHotspot) { if (ppt) { ppt->x = g_dctx.ptDrag.x; ppt->y = g_dctx.ptDrag.y; } if (pptHotspot) { pptHotspot->x = g_dctx.ptDragHotspot.x; pptHotspot->y = g_dctx.ptDragHotspot.y; } return g_dctx.pimlDrag; } // BUGBUG: this hotspot stuff is broken in design BOOL ImageList_MergeDragImages(int dxHotspot, int dyHotspot) { IMAGELIST* pimlNew; if (g_dctx.pimlDither) { if (g_dctx.pimlCursor) { pimlNew = ImageList_Merge(g_dctx.pimlDither, 0, g_dctx.pimlCursor, g_dctx.iCursor, dxHotspot, dyHotspot); if (pimlNew && ImageList_CreateDragBitmaps(pimlNew)) { // WARNING: Don't destroy pimlDrag if it is pimlDither. if (g_dctx.pimlDrag && (g_dctx.pimlDrag != g_dctx.pimlDither)) { ImageList_Destroy(g_dctx.pimlDrag); } g_dctx.pimlDrag = pimlNew; return TRUE; } return FALSE; } else { if (ImageList_CreateDragBitmaps(g_dctx.pimlDither)) { g_dctx.pimlDrag = g_dctx.pimlDither; return TRUE; } return FALSE; } } else { // not an error case if both aren't set yet // only an error if we actually tried the merge and failed return TRUE; } } BOOL WINAPI ImageList_SetDragImage(IMAGELIST* piml, int i, int dxHotspot, int dyHotspot) { BOOL fVisible = g_dctx.fDragShow; BOOL fRet; V_HIMAGELIST(piml); ENTERCRITICAL; if (fVisible) ImageList_DragShowNolock(FALSE); // only do this last step if everything is there. fRet = ImageList_MergeDragImages(dxHotspot, dyHotspot); if (fVisible) ImageList_DragShowNolock(TRUE); LEAVECRITICAL; return fRet; } BOOL WINAPI ImageList_SetDragCursorImage(IMAGELIST * piml, int i, int dxHotspot, int dyHotspot) { BOOL fVisible = g_dctx.fDragShow; BOOL fRet = TRUE; V_HIMAGELIST(piml); ENTERCRITICAL; // do work only if something has changed if ((g_dctx.pimlCursor != piml) || (g_dctx.iCursor != i)) { if (fVisible) ImageList_DragShowNolock(FALSE); g_dctx.pimlCursor = piml; g_dctx.iCursor = i; fRet = ImageList_MergeDragImages(dxHotspot, dyHotspot); if (fVisible) ImageList_DragShowNolock(TRUE); } LEAVECRITICAL; return fRet; } void WINAPI ImageList_EndDrag() { IMAGELIST* piml = g_dctx.pimlDrag; ENTERCRITICAL; if (IsImageList(piml)) { ImageList_DragShowNolock(FALSE); // WARNING: Don't destroy pimlDrag if it is pimlDither. if (g_dctx.pimlDrag && (g_dctx.pimlDrag != g_dctx.pimlDither)) { ImageList_Destroy(g_dctx.pimlDrag); } if (g_dctx.pimlDither) { ImageList_Destroy(g_dctx.pimlDither); g_dctx.pimlDither = NULL; } g_dctx.pimlCursor = NULL; g_dctx.iCursor = -1; g_dctx.pimlDrag = NULL; g_dctx.hwndDC = NULL; } LEAVECRITICAL; } #endif // _WIN32 #ifdef DISABLE IMAGELIST* WINAPI ImageList_CopyImage(IMAGELIST* piml) { IMAGELIST* pimlCopy; HBITMAP hbmImage; HBITMAP hbmMask; Assert(piml); hbmImage = ImageList_CopyBitmap(piml->hbmImage); if (!hbmImage) goto Error; hbmMask = NULL; if (piml->hdcMask) { hbmMask = ImageList_CopyBitmap(piml->hbmMask); if (!hbmMask) goto Error; } pimlCopy = ImageList_Create(hbmImage, hbmMask, piml->flags|ILC_MASK, piml->cImage, piml->cGrow); if (!pimlCopy) { Error: if (hbmImage) ImageList_DeleteBitmap(hbmImage); if (hbmMask) ImageList_DeleteBitmap(hbmMask); } return pimlCopy; } HBITMAP WINAPI ImageList_CopyBitmap(HBITMAP hbm) { HBITMAP hbmCopy; BITMAP bm; Assert(hbm); hbmCopy = NULL; if (GetObject(hbm, sizeof(bm), &bm) == sizeof(bm)) { ENTERCIRITICAL; hbmCopy = CreateColorBitmap(bm.bmWidth, bm.bmHeight); ImageList_SelectDstBitmap(hbmCopy); ImageList_SelectSrcBitmap(hbm); BitBlt(g_hdcDst, 0, 0, bm.bmWidth, bm.bmHeight, g_hdcSrc, 0, 0, SRCCOPY); ImageList_SelectDstBitmap(NULL); LEAVECRITICAL; } return hbmCopy; } #endif #ifdef _WIN32 // REVIEW, make this public, this is useful. // copy an image from one imagelist to another at x,y within iDst in pimlDst. // pimlDst's image size should be larger than pimlSrc void NEAR PASCAL ImageList_CopyOneImage(IMAGELIST* pimlDst, int iDst, int x, int y, IMAGELIST* pimlSrc, int iSrc) { RECT rcSrc, rcDst; ImageList_GetImageRect(pimlSrc, iSrc, &rcSrc); ImageList_GetImageRect(pimlDst, iDst, &rcDst); if (pimlSrc->hdcMask && pimlDst->hdcMask) { BitBlt(pimlDst->hdcMask, rcDst.left + x, rcDst.top + y, pimlSrc->cx, pimlSrc->cy, pimlSrc->hdcMask, rcSrc.left, rcSrc.top, SRCCOPY); } BitBlt(pimlDst->hdcImage, rcDst.left + x, rcDst.top + y, pimlSrc->cx, pimlSrc->cy, pimlSrc->hdcImage, rcSrc.left, rcSrc.top, SRCCOPY); } void NEAR PASCAL ImageList_Merge2(IMAGELIST* piml, IMAGELIST* pimlMerge, int i, int dx, int dy) { if (piml->hdcMask && pimlMerge->hdcMask) { RECT rcMerge; ImageList_GetImageRect(pimlMerge, i, &rcMerge); BitBlt(piml->hdcMask, dx, dy, pimlMerge->cx, pimlMerge->cy, pimlMerge->hdcMask, rcMerge.left, rcMerge.top, SRCAND); } ImageList_Draw(pimlMerge, i, piml->hdcImage, dx, dy, ILD_TRANSPARENT); } IMAGELIST* WINAPI ImageList_Merge(IMAGELIST* piml1, int i1, IMAGELIST* piml2, int i2, int dx, int dy) { IMAGELIST* pimlNew; RECT rcNew; RECT rc1; RECT rc2; int cx, cy; UINT wFlags; V_HIMAGELIST(piml1); V_HIMAGELIST(piml2); ENTERCRITICAL; SetRect(&rc1, 0, 0, piml1->cx, piml1->cy); SetRect(&rc2, dx, dy, piml2->cx + dx, piml2->cy + dy); UnionRect(&rcNew, &rc1, &rc2); cx = rcNew.right - rcNew.left; cy = rcNew.bottom - rcNew.top; // If one of images are shared, create a shared image. wFlags = (piml1->flags|piml2->flags) & ~ILC_COLORMASK; wFlags |= max(piml1->flags&ILC_COLORMASK,piml2->flags&ILC_COLORMASK); pimlNew = ImageList_Create(cx, cy, ILC_MASK|wFlags, 1, 0); if (pimlNew) { pimlNew->cImage++; if (pimlNew->hdcMask) PatBlt(pimlNew->hdcMask, 0, 0, cx, cy, WHITENESS); PatBlt(pimlNew->hdcImage, 0, 0, cx, cy, BLACKNESS); ImageList_Merge2(pimlNew, piml1, i1, rc1.left - rcNew.left, rc1.top - rcNew.top); ImageList_Merge2(pimlNew, piml2, i2, rc2.left - rcNew.left, rc2.top - rcNew.top); } LEAVECRITICAL; return pimlNew; } #endif // WIN32 #ifdef _WIN32 // Only support persistence in 32 bits // helper macros for using a IStream* from "C" #define Stream_Read(ps, pv, cb) SUCCEEDED((ps)->lpVtbl->Read(ps, pv, cb, NULL)) #define Stream_Write(ps, pv, cb) SUCCEEDED((ps)->lpVtbl->Write(ps, pv, cb, NULL)) #define Stream_Flush(ps) SUCCEEDED((ps)->lpVtbl->Commit(ps, 0)) #define Stream_Seek(ps, li, d, p) SUCCEEDED((ps)->lpVtbl->Seek(ps, li, d, p)) #define Stream_Close(ps) (void)(ps)->lpVtbl->Release(ps) // BUGBUG should these be public? BOOL WINAPI Stream_WriteBitmap(LPSTREAM pstm, HBITMAP hbm, int cBitsPerPixel); HBITMAP WINAPI Stream_ReadBitmap(LPSTREAM pstm, BOOL f); BOOL WINAPI ImageList_Write(IMAGELIST* piml, LPSTREAM pstm) { int i; ILFILEHEADER ilfh; V_HIMAGELIST(piml); ilfh.magic = IMAGELIST_MAGIC; ilfh.version = IMAGELIST_VER; ilfh.cImage = piml->cImage; ilfh.cAlloc = piml->cAlloc; ilfh.cGrow = piml->cGrow; ilfh.cx = piml->cx; ilfh.cy = piml->cy; ilfh.clrBk = piml->clrBk; ilfh.flags = piml->flags; for (i=0; iaOverlayIndexes[i]; Stream_Write(pstm, &ilfh, sizeof(ilfh)); if (!Stream_WriteBitmap(pstm, piml->hbmImage, 0)) return FALSE; if (piml->hdcMask) { if (!Stream_WriteBitmap(pstm, piml->hbmMask, 1)) return FALSE; } return TRUE; } IMAGELIST* WINAPI ImageList_Read(LPSTREAM pstm) { IMAGELIST* piml; ILFILEHEADER ilfh; int i; HBITMAP hbmImage; HBITMAP hbmMask; piml = NULL; if (!Stream_Read(pstm, &ilfh, sizeof(ilfh))) return piml; if (ilfh.magic != IMAGELIST_MAGIC) return piml; if (ilfh.version != IMAGELIST_VER) return piml; hbmMask = NULL; hbmImage = Stream_ReadBitmap(pstm, (ilfh.flags&ILC_COLORMASK)); if (!hbmImage) return piml; if (hbmImage && (ilfh.flags & ILC_MASK)) { hbmMask = Stream_ReadBitmap(pstm, FALSE); if (!hbmMask) { DeleteBitmap(hbmImage); return piml; } } piml = ImageList_Create(ilfh.cx, ilfh.cy, ilfh.flags, 1, ilfh.cGrow); if (piml) { // select into DC's before deleting existing bitmaps // patch in the bitmaps we loaded SelectObject(piml->hdcImage, hbmImage); DeleteObject(piml->hbmImage); piml->hbmImage = hbmImage; piml->clrBlend = CLR_NONE; // Same for the mask (if necessary) if (piml->hdcMask) { SelectObject(piml->hdcMask, hbmMask); DeleteObject(piml->hbmMask); piml->hbmMask = hbmMask; } piml->cImage = ilfh.cImage; piml->cAlloc = ilfh.cAlloc; ImageList_SetBkColor(piml, ilfh.clrBk); for (i=0; ibiSizeImage = WIDTHBYTES(cx, cBitsPerPixel) * cy; if (!Stream_Write(pstm, &bf, sizeof(bf))) goto Error; if (!Stream_Write(pstm, pbi, sizeof(bi) + cbColorTable)) goto Error; // if we have a DIBSection just write the bits out if (bm.bmBits != NULL) { if (!Stream_Write(pstm, bm.bmBits, pbi->biSizeImage)) goto Error; goto Done; } // Calculate number of horizontal lines that'll fit into our buffer... cLines = CBDIBBUF / WIDTHBYTES(cx, cBitsPerPixel); pbuf = LocalAlloc(LPTR, CBDIBBUF); if (!pbuf) goto Error; for (cLinesWritten = 0; cLinesWritten < cy; cLinesWritten += cLines) { if (cLines > cy - cLinesWritten) cLines = cy - cLinesWritten; if (GetDIBits(hdc, hbm, cLinesWritten, cLines, pbuf, (BITMAPINFO FAR*)pbi, DIB_RGB_COLORS) == 0) goto Error; if (!Stream_Write(pstm, pbuf, WIDTHBYTES(cx, cBitsPerPixel) * cLines)) goto Error; } // if (!Stream_Flush(pstm)) // goto Error; Done: fSuccess = TRUE; Error: if (hdc) ReleaseDC(HWND_DESKTOP, hdc); if (pbi) LocalFree((HLOCAL)pbi); if (pbuf) LocalFree((HLOCAL)pbuf); return fSuccess; } HBITMAP WINAPI Stream_ReadBitmap(LPSTREAM pstm, BOOL fDS) { BOOL fSuccess; HDC hdc; HBITMAP hbm; BITMAPFILEHEADER bf; BITMAPINFOHEADER bi; BITMAPINFOHEADER FAR* pbi; BYTE FAR* pbuf=NULL; int cBitsPerPixel; UINT cbColorTable; int cx, cy; int cLines, cLinesRead; Assert(pstm); fSuccess = FALSE; hdc = NULL; hbm = NULL; pbi = NULL; if (!Stream_Read(pstm, &bf, sizeof(bf))) goto Error; if (bf.bfType != BFTYPE_BITMAP) goto Error; if (!Stream_Read(pstm, &bi, sizeof(bi))) goto Error; if (bi.biSize != sizeof(bi)) goto Error; cx = (int)bi.biWidth; cy = (int)bi.biHeight; cBitsPerPixel = (int)bi.biBitCount * (int)bi.biPlanes; if (cBitsPerPixel <= 8) cbColorTable = (1 << cBitsPerPixel) * sizeof(RGBQUAD); else cbColorTable = 0; pbi = (BITMAPINFOHEADER*)LocalAlloc(LPTR, sizeof(bi) + cbColorTable); if (!pbi) goto Error; *pbi = bi; pbi->biSizeImage = WIDTHBYTES(cx, cBitsPerPixel) * cy; if (cbColorTable) { if (!Stream_Read(pstm, pbi + 1, cbColorTable)) goto Error; } hdc = GetDC(HWND_DESKTOP); // see if we can make a DIBSection if ((cBitsPerPixel > 1) && (fDS != ILC_COLORDDB) && (fDS || UseDS(hdc))) { // create DIBSection and read the bits directly into it! hbm = CreateDIBSection(hdc, (LPBITMAPINFO)pbi, DIB_RGB_COLORS, &pbuf, NULL, 0); if (hbm == NULL) goto Error; if (!Stream_Read(pstm, pbuf, pbi->biSizeImage)) goto Error; pbuf = NULL; // dont free this goto Done; } // cant make a DIBSection make a mono or color bitmap. else if (cBitsPerPixel > 1) hbm = CreateColorBitmap(cx, cy); else hbm = CreateMonoBitmap(cx, cy); if (!hbm) return NULL; // Calculate number of horizontal lines that'll fit into our buffer... cLines = CBDIBBUF / WIDTHBYTES(cx, cBitsPerPixel); pbuf = LocalAlloc(LPTR, CBDIBBUF); if (!pbuf) goto Error; for (cLinesRead = 0; cLinesRead < cy; cLinesRead += cLines) { if (cLines > cy - cLinesRead) cLines = cy - cLinesRead; if (!Stream_Read(pstm, pbuf, WIDTHBYTES(cx, cBitsPerPixel) * cLines)) goto Error; if (!SetDIBits(hdc, hbm, cLinesRead, cLines, pbuf, (BITMAPINFO FAR*)pbi, DIB_RGB_COLORS)) goto Error; } Done: fSuccess = TRUE; Error: if (hdc) ReleaseDC(HWND_DESKTOP, hdc); if (pbi) LocalFree((HLOCAL)pbi); if (pbuf) LocalFree((HLOCAL)pbuf); if (!fSuccess && hbm) { DeleteBitmap(hbm); hbm = NULL; } return hbm; } #endif // WIN32 #ifdef IEWIN31_25 // This table has been brought from Win95 GDI. DWORD logPalHT[] = { 0x01000300, // version (0x0300), 256 entries 0x00000000,0x00000080,0x00008000,0x00008080,0x00800000,0x00800080,0x00808000,0x00c0c0c0, 0x00c0dcc0,0x00f0caa6, 0x04040404,0x04080808,0x040c0c0c,0x04111111,0x04161616,0x041c1c1c, 0x04222222,0x04292929,0x04555555,0x044d4d4d,0x04424242,0x04393939,0x04807CFF,0x045050FF, 0x049300D6,0x04FFECCC,0x04C6D6EF,0x04D6E7E7,0x0490A9AD,0x04000033,0x04000066,0x04000099, 0x040000cc,0x04003300,0x04003333,0x04003366,0x04003399,0x040033cc,0x040033ff,0x04006600, 0x04006633,0x04006666,0x04006699,0x040066cc,0x040066ff,0x04009900,0x04009933,0x04009966, 0x04009999,0x040099cc,0x040099ff,0x0400cc00,0x0400cc33,0x0400cc66,0x0400cc99,0x0400cccc, 0x0400ccff,0x0400ff66,0x0400ff99,0x0400ffcc,0x04330000,0x04330033,0x04330066,0x04330099, 0x043300cc,0x043300ff,0x04333300,0x04333333,0x04333366,0x04333399,0x043333cc,0x043333ff, 0x04336600,0x04336633,0x04336666,0x04336699,0x043366cc,0x043366ff,0x04339900,0x04339933, 0x04339966,0x04339999,0x043399cc,0x043399ff,0x0433cc00,0x0433cc33,0x0433cc66,0x0433cc99, 0x0433cccc,0x0433ccff,0x0433ff33,0x0433ff66,0x0433ff99,0x0433ffcc,0x0433ffff,0x04660000, 0x04660033,0x04660066,0x04660099,0x046600cc,0x046600ff,0x04663300,0x04663333,0x04663366, 0x04663399,0x046633cc,0x046633ff,0x04666600,0x04666633,0x04666666,0x04666699,0x046666cc, 0x04669900,0x04669933,0x04669966,0x04669999,0x046699cc,0x046699ff,0x0466cc00,0x0466cc33, 0x0466cc99,0x0466cccc,0x0466ccff,0x0466ff00,0x0466ff33,0x0466ff99,0x0466ffcc,0x04cc00ff, 0x04ff00cc,0x04999900,0x04993399,0x04990099,0x049900cc,0x04990000,0x04993333,0x04990066, 0x049933cc,0x049900ff,0x04996600,0x04996633,0x04993366,0x04996699,0x049966cc,0x049933ff, 0x04999933,0x04999966,0x04999999,0x049999cc,0x049999ff,0x0499cc00,0x0499cc33,0x0466cc66, 0x0499cc99,0x0499cccc,0x0499ccff,0x0499ff00,0x0499ff33,0x0499cc66,0x0499ff99,0x0499ffcc, 0x0499ffff,0x04cc0000,0x04990033,0x04cc0066,0x04cc0099,0x04cc00cc,0x04993300,0x04cc3333, 0x04cc3366,0x04cc3399,0x04cc33cc,0x04cc33ff,0x04cc6600,0x04cc6633,0x04996666,0x04cc6699, 0x04cc66cc,0x049966ff,0x04cc9900,0x04cc9933,0x04cc9966,0x04cc9999,0x04cc99cc,0x04cc99ff, 0x04cccc00,0x04cccc33,0x04cccc66,0x04cccc99,0x04cccccc,0x04ccccff,0x04ccff00,0x04ccff33, 0x0499ff66,0x04ccff99,0x04ccffcc,0x04ccffff,0x04cc0033,0x04ff0066,0x04ff0099,0x04cc3300, 0x04ff3333,0x04ff3366,0x04ff3399,0x04ff33cc,0x04ff33ff,0x04ff6600,0x04ff6633,0x04cc6666, 0x04ff6699,0x04ff66cc,0x04cc66ff,0x04ff9900,0x04ff9933,0x04ff9966,0x04ff9999,0x04ff99cc, 0x04ff99ff,0x04ffcc00,0x04ffcc33,0x04ffcc66,0x04ffcc99,0x04ffcccc,0x04ffccff,0x04ffff33, 0x04ccff66,0x04ffff99,0x04ffffcc,0x046666ff,0x0466ff66,0x0466ffff,0x04ff6666,0x04ff66ff, 0x04ffff66,0x042100A5,0x045f5f5f,0x04777777,0x04868686,0x04969696,0x04cbcbcb,0x04b2b2b2, 0x04d7d7d7,0x04dddddd,0x04e3e3e3,0x04eaeaea,0x04f1f1f1,0x04f8f8f8, 0x00f0fbff,0x00a4a0a0, 0x00808080,0x000000ff,0x0000ff00,0x0000ffff,0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff }; HPALETTE CreateHalftonePalette( HDC hdc ) { HPALETTE hPal, hPal2; int nRsvr; hPal = (HPALETTE) GetStockObject( DEFAULT_PALETTE ); nRsvr = 0; if ( hdc ) { if ( GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE == 0 ) return( hPal ); nRsvr = GetDeviceCaps( hdc, NUMRESERVED ); } if ( hPal2 = CreatePalette( (LOGPALETTE *) logPalHT ) ) { hPal = hPal2; if ( nRsvr == 20 ) { PALETTEENTRY pe[10]; GetSystemPaletteEntries( hdc, 0, 10, pe ); SetPaletteEntries( hPal, 0, 10, pe ); GetSystemPaletteEntries( hdc, 246, 10, pe ); SetPaletteEntries( hPal, 246, 10, pe ); } } return( hPal ); } // keep this block at the end of the file BOOL NEAR PASCAL ImageList_GetSpareImageRect(IMAGELIST* piml, RECT FAR* prcImage) { BOOL fRet; // special hacking to use the one scratch image at tail of list :) piml->cImage++; #ifdef TODO fRet = ImageList_IGetImageRect(piml, piml->cImage-1, prcImage); #else fRet = ImageList_GetImageRect(piml, piml->cImage-1, prcImage); #endif piml->cImage--; return fRet; } // keep this block at the end of the file #endif //IEWIN31_25