Overlay indices are signed shorts (-1 means no overlay) (ImageList_SetOverlayIndex) should accept -1 as overlayindex. (ImageList_Read) We can read a NxM bitmap from the stream and have to convert it into a 1x(M*N) bitmap, set cCurImage,cMaxImage. Added documentation. (others) removed some potential operator precendence problems.
diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c index a1c3afa..b97145c 100644 --- a/dlls/comctl32/imagelist.c +++ b/dlls/comctl32/imagelist.c
@@ -7,7 +7,7 @@ * - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop). * - Fix ImageList_GetIcon. * - Fix drag functions. - * - Fix ImageList_Read and ImageList_Write. + * - Fix ImageList_Write. * - Fix ImageList_SetFilter (undocumented). * BTW does anybody know anything about this function??? * - It removes 12 Bytes from the stack (3 Parameters). @@ -149,6 +149,7 @@ { HDC hImageDC; HBITMAP hOldBitmap; + hImageDC = CreateCompatibleDC(0); hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage); BitBlt(pimldp->hdcDst, @@ -203,7 +204,7 @@ /* Draw the Background for the appropriate Styles */ if( bUseCustomBackground && (pimldp->fStyle == ILD_NORMAL - || pimldp->fStyle & ILD_IMAGE + || (pimldp->fStyle & ILD_IMAGE) || bBlendFlag)) { hBrush = CreateSolidBrush (himlLocal->clrBk); @@ -218,7 +219,7 @@ /* Draw Image Transparently over the current background */ if(pimldp->fStyle == ILD_NORMAL - || pimldp->fStyle & ILD_TRANSPARENT + || (pimldp->fStyle & ILD_TRANSPARENT) || ((pimldp->fStyle & ILD_IMAGE) && bUseCustomBackground) || bBlendFlag) { @@ -245,7 +246,7 @@ } /* Draw the image when no Background is specified */ - else if(pimldp->fStyle & ILD_IMAGE && !bUseCustomBackground) + else if((pimldp->fStyle & ILD_IMAGE) && !bUseCustomBackground) { BitBlt(pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, @@ -1252,8 +1253,10 @@ return FALSE; if (pimldp->himl == NULL) return FALSE; - if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) + if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) { + ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage); return FALSE; + } /* Get the Height and Width to display */ @@ -1334,8 +1337,10 @@ DeleteDC (hdcDst); DeleteDC (hdcSrc); - } + himlDst->cCurImage = himlSrc->cCurImage; + himlDst->cMaxImage = himlSrc->cMaxImage; + } return himlDst; } @@ -1451,8 +1456,10 @@ HBITMAP hOldSrcBitmap,hOldDstBitmap; HDC hdcSrc, hdcDst; - if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) + if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) { + FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle); return 0; + } hdcSrc = CreateCompatibleDC(0); hdcDst = CreateCompatibleDC(0); @@ -1883,6 +1890,7 @@ } +/* helper for _read_bitmap currently unused */ static int may_use_dibsection(HDC hdc) { int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); if (bitspixel>8) @@ -1892,7 +1900,8 @@ return GetDeviceCaps(hdc,94) & 0x10; } -static HBITMAP _read_bitmap(LPSTREAM pstm,int x) { +/* helper for ImageList_Read, see comments below */ +static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) { HDC xdc = 0; BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih; @@ -1900,7 +1909,8 @@ LPBITMAPINFOHEADER bmihc = NULL; int result = 0; HBITMAP hbitmap = 0; - LPBYTE bits = NULL; + LPBYTE bits = NULL,nbits = NULL; + int nbytesperline,bytesperline; if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) || (bmfh.bfType != (('M'<<8)|'B')) || @@ -1922,38 +1932,62 @@ bmihc->biSizeImage = (longsperline*height)<<2; /* read the palette right after the end of the bitmapinfoheader */ - if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL))) - goto ret1; + if (palspace) + if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL))) + goto ret1; xdc = GetDC(0); +#if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */ if ((bitsperpixel>1) && - ((x!=0xfe) && (!x || may_use_dibsection(xdc))) + ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc))) ) { hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0); if (!hbitmap) goto ret1; if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL))) goto ret1; - bits = NULL; result = 1; - } else { + } else +#endif + { + int i,nwidth,nheight; + + nwidth = width*(height/cy); + nheight = cy; + if (bitsperpixel==1) - hbitmap = CreateBitmap(width,height,1,1,NULL); + hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL); else - hbitmap = CreateCompatibleBitmap(xdc,width,height); + hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight); /* Might be a bit excessive memory use here */ - bits = (LPBYTE)LocalAlloc(0,longsperline*4*height); - if (!SUCCEEDED(IStream_Read ( pstm, bits, longsperline*4*height, NULL))) + bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage); + nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage); + if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL))) goto ret1; - if (!SetDIBits(xdc,hbitmap,0,height,bits,(BITMAPINFO*)bmihc,0)) + + /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */ + /* Do not forget that windows bitmaps are bottom->top */ + bytesperline = longsperline*4; + nbytesperline = (height/cy)*bytesperline; + for (i=0;i<height;i++) { + memcpy( + nbits+((height-i)%cy)*nbytesperline+(i/cy)*bytesperline, + bits+bytesperline*(height-i), + bytesperline + ); + } + bmihc->biWidth = nwidth; + bmihc->biHeight = nheight; + if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0)) goto ret1; + LocalFree((HLOCAL)nbits); + LocalFree((HLOCAL)bits); result = 1; } ret1: if (xdc) ReleaseDC(0,xdc); if (bmihc) LocalFree((HLOCAL)bmihc); - if (bits) LocalFree((HLOCAL)bits); if (!result) { if (hbitmap) { DeleteObject(hbitmap); @@ -1975,8 +2009,27 @@ * Success: handle to image list * Failure: NULL * - * BUGS - * still not complete functional + * The format is like this: + * ILHEAD ilheadstruct; + * + * for the color image part: + * BITMAPFILEHEADER bmfh; + * BITMAPINFOHEADER bmih; + * only if it has a palette: + * RGBQUAD rgbs[nr_of_paletted_colors]; + * + * BYTE colorbits[imagesize]; + * + * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags: + * BITMAPFILEHEADER bmfh_mask; + * BITMAPINFOHEADER bmih_mask; + * only if it has a palette (it usually does not): + * RGBQUAD rgbs[nr_of_paletted_colors]; + * + * BYTE maskbits[imagesize]; + * + * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect. + * _read_bitmap needs to convert them. */ HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) { @@ -1995,7 +2048,7 @@ #if 0 FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage); FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage); - FIXME(" ilHead.grow = %d\n",ilHead.grow); + FIXME(" ilHead.cGrow = %d\n",ilHead.cGrow); FIXME(" ilHead.cx = %d\n",ilHead.cx); FIXME(" ilHead.cy = %d\n",ilHead.cy); FIXME(" ilHead.flags = %x\n",ilHead.flags); @@ -2005,11 +2058,11 @@ FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]); #endif - hbmColor = _read_bitmap(pstm,ilHead.flags & 0xfe); + hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy); if (!hbmColor) return NULL; - if (ilHead.flags & 1) { - hbmMask = _read_bitmap(pstm,0); + if (ilHead.flags & ILC_MASK) { + hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy); if (!hbmMask) { DeleteObject(hbmColor); return NULL; @@ -2021,22 +2074,21 @@ ilHead.cy, ilHead.flags, 1, /* initial */ - ilHead.grow + ilHead.cGrow ); if (!himl) { DeleteObject(hbmColor); DeleteObject(hbmMask); return NULL; - } - + } himl->hbmImage = hbmColor; himl->hbmMask = hbmMask; + himl->cCurImage = ilHead.cCurImage; + himl->cMaxImage = ilHead.cMaxImage; ImageList_SetBkColor(himl,ilHead.bkcolor); - for (i=0;i<4;i++) ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1); - return himl; } @@ -2593,9 +2645,8 @@ return FALSE; if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) return FALSE; - if ((iImage < 0) || (iImage > himl->cCurImage)) + if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage))) return FALSE; - himl->nOvlIdx[iOverlay - 1] = iImage; return TRUE; }
diff --git a/include/imagelist.h b/include/imagelist.h index 2e2bb56..9c45222 100644 --- a/include/imagelist.h +++ b/include/imagelist.h
@@ -48,12 +48,12 @@ USHORT usVersion; WORD cCurImage; WORD cMaxImage; - WORD grow; /* unclear */ + WORD cGrow; WORD cx; WORD cy; COLORREF bkcolor; WORD flags; - WORD ovls[4]; + SHORT ovls[4]; } ILHEAD; #include "poppack.h"