imagelist.c
来自「一个类似windows」· C语言 代码 · 共 2,271 行 · 第 1/5 页
C
2,271 行
if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)) ||
(bmfh.bfType != (('M'<<8)|'B')) ||
!SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL)) ||
(bmih.biSize != sizeof(bmih))
)
return 0;
bitsperpixel = bmih.biPlanes * bmih.biBitCount;
if (bitsperpixel<=8)
palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
else
palspace = 0;
width = bmih.biWidth;
height = bmih.biHeight;
bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
memcpy(bmihc,&bmih,sizeof(bmih));
longsperline = ((width*bitsperpixel+31)&~0x1f)>>5;
bmihc->biSizeImage = (longsperline*height)<<2;
/* read the palette right after the end of the bitmapinfoheader */
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) &&
((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;
result = 1;
} else
#endif
{
int i,nwidth,nheight,nRows;
nwidth = width*(height/cy);
nheight = cy;
nRows = (height/cy);
if (bitsperpixel==1)
hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
else
hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
hDIB = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
if (!hDIB)
goto ret1;
if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
goto ret1;
hBitmapDC = CreateCompatibleDC(0);
SelectObject(hBitmapDC, hbitmap);
/* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
/* Do not forget that windows bitmaps are bottom->top */
TRACE("nRows=%d\n", nRows);
for (i=0; i < nRows; i++){
StretchDIBits(hBitmapDC, width*i, 0, width, cy, 0, cy*(nRows-1-i), width, cy, bits,
(BITMAPINFO*)bmihc, DIB_RGB_COLORS, SRCCOPY);
}
result = 1;
}
ret1:
if (xdc) ReleaseDC(0,xdc);
if (bmihc) LocalFree((HLOCAL)bmihc);
if (hDIB) DeleteObject(hDIB);
if (hBitmapDC) DeleteDC(hBitmapDC);
if (!result) {
if (hbitmap) {
DeleteObject(hbitmap);
hbitmap = 0;
}
}
return hbitmap;
}
/*************************************************************************
* 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];
*
* 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)
{
ILHEAD ilHead;
HIMAGELIST himl;
HBITMAP hbmColor=0,hbmMask=0;
int i;
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;
#if 0
FIXME(" ilHead.cCurImage = %d\n",ilHead.cCurImage);
FIXME(" ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
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);
FIXME(" ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
FIXME(" ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
FIXME(" ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
FIXME(" ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
#endif
hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
if (!hbmColor)
return NULL;
if (ilHead.flags & ILC_MASK) {
hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
if (!hbmMask) {
DeleteObject(hbmColor);
return NULL;
}
}
himl = ImageList_Create (
ilHead.cx,
ilHead.cy,
ilHead.flags,
1, /* initial */
ilHead.cGrow
);
if (!himl) {
DeleteObject(hbmColor);
DeleteObject(hbmMask);
return NULL;
}
SelectObject(himl->hdcImage, hbmColor);
DeleteObject(himl->hbmImage);
himl->hbmImage = hbmColor;
if (hbmMask){
SelectObject(himl->hdcMask, hbmMask);
DeleteObject(himl->hbmMask);
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;
}
/*************************************************************************
* 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
*/
BOOL WINAPI
ImageList_Remove (HIMAGELIST himl, INT i)
{
HBITMAP hbmNewImage, hbmNewMask;
HDC hdcBmp;
INT cxNew, nCount;
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) {
/* 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;
himl->cCurImage = 0;
for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
himl->nOvlIdx[nCount] = -1;
hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage * himl->cx, himl->cy);
SelectObject (himl->hdcImage, hbmNewImage);
DeleteObject (himl->hbmImage);
himl->hbmImage = hbmNewImage;
if (himl->hbmMask) {
hbmNewMask = CreateBitmap (himl->cMaxImage * himl->cx, himl->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) */
nCount = (himl->cCurImage + himl->cGrow - 1);
cxNew = nCount * himl->cx;
TRACE(" - Number of images: %d / %d (Old/New)\n",
himl->cCurImage, himl->cCurImage - 1);
TRACE(" - Max. number of images: %d / %d (Old/New)\n",
himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, cxNew, himl->cy);
if (himl->hbmMask)
hbmNewMask = CreateBitmap (cxNew, himl->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);
BitBlt (hdcBmp, 0, 0, i * himl->cx, himl->cy,
himl->hdcImage, 0, 0, SRCCOPY);
if (himl->hbmMask) {
SelectObject (hdcBmp, hbmNewMask);
BitBlt (hdcBmp, 0, 0, i * himl->cx, himl->cy,
himl->hdcMask, 0, 0, SRCCOPY);
}
}
/* copy all images and masks behind the removed image */
if (i < himl->cCurImage - 1) {
TRACE("Post image copy!\n");
SelectObject (hdcBmp, hbmNewImage);
BitBlt (hdcBmp, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
himl->cy, himl->hdcImage, (i + 1) * himl->cx, 0, SRCCOPY);
if (himl->hbmMask) {
SelectObject (hdcBmp, hbmNewMask);
BitBlt (hdcBmp, i * himl->cx, 0,
(himl->cCurImage - i - 1) * himl->cx,
himl->cy, himl->hdcMask, (i + 1) * himl->cx, 0, SRCCOPY);
}
}
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--;
himl->cMaxImage = himl->cCurImage + himl->cGrow;
}
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;
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;
}
hdcImage = CreateCompatibleDC (0);
GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
/* Replace Image */
SelectObject (hdcImage, hbmImage);
StretchBlt (himl->hdcImage, i * himl->cx, 0, himl->cx, himl->cy,
hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
if (himl->hbmMask)
{
/* Replace Mask */
SelectObject (hdcImage, hbmMask);
StretchBlt (himl->hdcMask, i * himl->cx, 0, himl->cx, himl->cy,
hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
/* Remove the background from the image
*/
StretchBlt (himl->hdcImage,
i*himl->cx, 0, himl->cx, himl->cy,
hdcImage,
0, 0, bmp.bmWidth, bmp.bmHeight,
0x220326); /* NOTSRCAND */
}
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 i, HICON hIcon)
{
HDC hdcImage;
INT nIndex;
HICON hBestFitIcon;
HBITMAP hbmOldSrc;
ICONINFO ii;
BITMAP bmp;
BOOL ret;
TRACE("(%p %d %p)\n", himl, i, hIcon);
if (!is_valid(himl)) {
ERR("invalid image list\n");
return -1;
}
if ((i >= himl->cMaxImage) || (i < -1)) {
ERR("invalid image index %d / %d\n", i, himl->cMaxImage);
return -1;
}
hBestFitIcon = CopyImage(
hIcon, IMAGE_ICON,
himl->cx, himl->cy,
LR_COPYFROMRESOURCE);
/* the above will fail if the icon wasn't loaded from a resource, so try
* again without LR_COPYFROMRESOURCE flag */
if (!hBestFitIcon)
hBestFitIcon = CopyImage(
hIcon, IMAGE_ICON,
himl->cx, himl->cy,
0);
if (!hBestFitIcon)
return -1;
ret = GetIconInfo (hBestFitIcon, &ii);
if (!ret) {
DestroyIcon(hBestFitIcon);
return -1;
}
if (ii.hbmColor == 0)
ERR("no color!\n");
ret = GetObjectW (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
if (!ret) {
ERR("couldn't get mask bitmap info\n");
if (ii.hbmColor)
DeleteObject (ii.hbmColor);
if (ii.hbmMask)
DeleteObject (ii.hbmMask);
DestroyIcon(hBestFitIcon);
return -
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?