📄 imagelist.c
字号:
yOff1 = 0;
yOff2 = dy;
}
else if (dy < 0) {
cyDst = max (himl2->cy, himl1->cy - dy);
yOff1 = -dy;
yOff2 = 0;
}
else {
cyDst = max (himl1->cy, himl2->cy);
yOff1 = 0;
yOff2 = 0;
}
himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
if (himlDst)
{
imagelist_point_from_index( himl1, i1, &pt1 );
imagelist_point_from_index( himl1, i2, &pt2 );
/* copy image */
BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS);
if (i1 >= 0 && i1 < himl1->cCurImage)
BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, pt1.x, pt1.y, SRCCOPY);
if (i2 >= 0 && i2 < himl2->cCurImage)
{
BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
}
/* copy mask */
BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS);
if (i1 >= 0 && i1 < himl1->cCurImage)
BitBlt (himlDst->hdcMask, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask, pt1.x, pt1.y, SRCCOPY);
if (i2 >= 0 && i2 < himl2->cCurImage)
BitBlt (himlDst->hdcMask, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask, pt2.x, pt2.y, SRCAND);
himlDst->cCurImage = 1;
}
return himlDst;
}
/***********************************************************************
* DIB_GetDIBWidthBytes
*
* Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
*/
static int DIB_GetDIBWidthBytes( int width, int depth )
{
int words;
switch(depth)
{
case 1: words = (width + 31) / 32; break;
case 4: words = (width + 7) / 8; break;
case 8: words = (width + 3) / 4; break;
case 15:
case 16: words = (width + 1) / 2; break;
case 24: words = (width * 3 + 3)/4; break;
default:
WARN("(%d): Unsupported depth\n", depth );
/* fall through */
case 32:
words = width;
break;
}
return 4 * words;
}
/***********************************************************************
* DIB_GetDIBImageBytes
*
* Return the number of bytes used to hold the image in a DIB bitmap.
*/
static int DIB_GetDIBImageBytes( int width, int height, int depth )
{
return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
}
/* helper for ImageList_Read, see comments below */
static BOOL _read_bitmap(HIMAGELIST himl, HDC hdcIml, LPSTREAM pstm)
{
BITMAPFILEHEADER bmfh;
int bitsperpixel, palspace;
char bmi_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
LPBITMAPINFO bmi = (LPBITMAPINFO)bmi_buf;
int result = FALSE;
LPBYTE bits = NULL;
if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)))
return FALSE;
if (bmfh.bfType != (('M'<<8)|'B'))
return FALSE;
if (!SUCCEEDED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL)))
return FALSE;
if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader)))
return FALSE;
TRACE("width %u, height %u, planes %u, bpp %u\n",
bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount);
bitsperpixel = bmi->bmiHeader.biPlanes * bmi->bmiHeader.biBitCount;
if (bitsperpixel<=8)
palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
else
palspace = 0;
bmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bitsperpixel);
/* read the palette right after the end of the bitmapinfoheader */
if (palspace && !SUCCEEDED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL)))
goto error;
bits = Alloc(bmi->bmiHeader.biSizeImage);
if (!bits)
goto error;
if (!SUCCEEDED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
goto error;
if (!StretchDIBits(hdcIml, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
bits, bmi, DIB_RGB_COLORS, SRCCOPY))
goto error;
result = TRUE;
error:
Free(bits);
return result;
}
/*************************************************************************
* ImageList_Read [COMCTL32.@]
*
* Reads an image list from a stream.
*
* PARAMS
* pstm [I] pointer to a stream
*
* RETURNS
* Success: handle to image list
* Failure: NULL
*
* 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];
*/
HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
{
ILHEAD ilHead;
HIMAGELIST himl;
int i;
TRACE("%p\n", pstm);
if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
return NULL;
if (ilHead.usMagic != (('L' << 8) | 'I'))
return NULL;
if (ilHead.usVersion != 0x101) /* probably version? */
return NULL;
TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
if (!himl)
return NULL;
if (!_read_bitmap(himl, himl->hdcImage, pstm))
{
WARN("failed to read bitmap from stream\n");
return NULL;
}
if (ilHead.flags & ILC_MASK)
{
if (!_read_bitmap(himl, himl->hdcMask, pstm))
{
WARN("failed to read mask bitmap from stream\n");
return NULL;
}
}
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;
}
/*************************************************************************
* ImageList_Remove [COMCTL32.@]
*
* Removes an image from an image list
*
* PARAMS
* himl [I] image list handle
* i [I] image index
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
* FIXME: as the image list storage test shows, native comctl32 simply shifts
* images without creating a new bitmap.
*/
BOOL WINAPI
ImageList_Remove (HIMAGELIST himl, INT i)
{
HBITMAP hbmNewImage, hbmNewMask;
HDC hdcBmp;
SIZE sz;
TRACE("(himl=%p i=%d)\n", himl, i);
if (!is_valid(himl)) {
ERR("Invalid image list handle!\n");
return FALSE;
}
if ((i < -1) || (i >= himl->cCurImage)) {
TRACE("index out of range! %d\n", i);
return FALSE;
}
if (i == -1) {
INT nCount;
/* remove all */
if (himl->cCurImage == 0) {
/* remove all on empty ImageList is allowed */
TRACE("remove all on empty ImageList!\n");
return TRUE;
}
himl->cMaxImage = himl->cInitial + himl->cGrow - 1;
himl->cCurImage = 0;
for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
himl->nOvlIdx[nCount] = -1;
hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage, himl->cx);
SelectObject (himl->hdcImage, hbmNewImage);
DeleteObject (himl->hbmImage);
himl->hbmImage = hbmNewImage;
if (himl->hbmMask) {
imagelist_get_bitmap_size(himl, himl->cMaxImage, himl->cx, &sz);
hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
SelectObject (himl->hdcMask, hbmNewMask);
DeleteObject (himl->hbmMask);
himl->hbmMask = hbmNewMask;
}
}
else {
/* delete one image */
TRACE("Remove single image! %d\n", i);
/* create new bitmap(s) */
TRACE(" - Number of images: %d / %d (Old/New)\n",
himl->cCurImage, himl->cCurImage - 1);
hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage, himl->cx);
imagelist_get_bitmap_size(himl, himl->cMaxImage, himl->cx, &sz );
if (himl->hbmMask)
hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
else
hbmNewMask = 0; /* Just to keep compiler happy! */
hdcBmp = CreateCompatibleDC (0);
/* copy all images and masks prior to the "removed" image */
if (i > 0) {
TRACE("Pre image copy: Copy %d images\n", i);
SelectObject (hdcBmp, hbmNewImage);
imagelist_copy_images( himl, himl->hdcImage, hdcBmp, 0, i, 0 );
if (himl->hbmMask) {
SelectObject (hdcBmp, hbmNewMask);
imagelist_copy_images( himl, himl->hdcMask, hdcBmp, 0, i, 0 );
}
}
/* copy all images and masks behind the removed image */
if (i < himl->cCurImage - 1) {
TRACE("Post image copy!\n");
SelectObject (hdcBmp, hbmNewImage);
imagelist_copy_images( himl, himl->hdcImage, hdcBmp, i + 1,
(himl->cCurImage - i), i );
if (himl->hbmMask) {
SelectObject (hdcBmp, hbmNewMask);
imagelist_copy_images( himl, himl->hdcMask, hdcBmp, i + 1,
(himl->cCurImage - i), i );
}
}
DeleteDC (hdcBmp);
/* delete old images and insert new ones */
SelectObject (himl->hdcImage, hbmNewImage);
DeleteObject (himl->hbmImage);
himl->hbmImage = hbmNewImage;
if (himl->hbmMask) {
SelectObject (himl->hdcMask, hbmNewMask);
DeleteObject (himl->hbmMask);
himl->hbmMask = hbmNewMask;
}
himl->cCurImage--;
}
return TRUE;
}
/*************************************************************************
* ImageList_Replace [COMCTL32.@]
*
* Replaces an image in an image list with a new image.
*
* PARAMS
* himl [I] handle to image list
* i [I] image index
* hbmImage [I] handle to image bitmap
* hbmMask [I] handle to mask bitmap. Can be NULL.
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI
ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
HBITMAP hbmMask)
{
HDC hdcImage;
BITMAP bmp;
HBITMAP hOldBitmap;
POINT pt;
TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask);
if (!is_valid(himl)) {
ERR("Invalid image list handle!\n");
return FALSE;
}
if ((i >= himl->cMaxImage) || (i < 0)) {
ERR("Invalid image index!\n");
return FALSE;
}
if (!GetObjectW(hbmImage, sizeof(BITMAP), (LPVOID)&bmp))
return FALSE;
hdcImage = CreateCompatibleDC (0);
/* Replace Image */
hOldBitmap = SelectObject (hdcImage, hbmImage);
imagelist_point_from_index(himl, i, &pt);
StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
if (himl->hbmMask)
{
HDC hdcTemp;
HBITMAP hOldBitmapTemp;
hdcTemp = CreateCompatibleDC(0);
hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
hdcTemp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
SelectObject(hdcTemp, hOldBitmapTemp);
DeleteDC(hdcTemp);
/* Remove the background from the image
*/
BitBlt (himl->hdcImage, pt.x, pt.y, bmp.bmWidth, bmp.bmHeight,
himl->hdcMask, pt.x, pt.y, 0x220326); /* NOTSRCAND */
}
SelectObject (hdcImage, hOldBitmap);
DeleteDC (hdcImage);
return TRUE;
}
/*************************************************************************
* ImageList_ReplaceIcon [COMCTL32.@]
*
* Replaces an image in an image list using an icon.
*
* PARAMS
* himl [I] handle to image list
* i [I] image index
* hIcon [I] handle to icon
*
* RETURNS
* Success: index of the replaced image
* Failure: -1
*/
INT WINAPI
ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
{
HDC hdcImage;
HICON hBestFitIcon;
HBITMAP hbmOldSrc;
ICONINFO ii;
BITMAP bmp;
BOOL ret;
POINT pt;
TRACE("(%p %d %p)\n", himl, nIndex, hIcon);
if (!is_valid(himl)) {
ERR("invalid image list\n");
return -1;
}
if ((nIndex >= himl->cMaxImage) || (nIndex < -1)) {
ERR("invalid image index %d / %d\n", nIndex, himl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -