user32: Copy icon bits by hand in CreateIconIndirect if the bitmaps can't be selected into a DC.

This commit is contained in:
Alexandre Julliard 2010-05-26 15:57:41 +02:00
parent f90b6d5af6
commit e2cb88ec2d
1 changed files with 45 additions and 14 deletions

View File

@ -1830,6 +1830,43 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
return TRUE; return TRUE;
} }
/* copy an icon bitmap, even when it can't be selected into a DC */
/* helper for CreateIconIndirect */
static void stretch_blt_icon( HDC hdc_dst, int dst_x, int dst_y, int dst_width, int dst_height,
HBITMAP src, int width, int height )
{
HDC hdc = CreateCompatibleDC( 0 );
if (!SelectObject( hdc, src ) || 1) /* do it the hard way */
{
BITMAPINFO *info;
void *bits;
if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return;
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info->bmiHeader.biWidth = width;
info->bmiHeader.biHeight = height;
info->bmiHeader.biPlanes = GetDeviceCaps( hdc_dst, PLANES );
info->bmiHeader.biBitCount = GetDeviceCaps( hdc_dst, BITSPIXEL );
info->bmiHeader.biCompression = BI_RGB;
info->bmiHeader.biSizeImage = height * get_dib_width_bytes( width, info->bmiHeader.biBitCount );
info->bmiHeader.biXPelsPerMeter = 0;
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrUsed = 0;
info->bmiHeader.biClrImportant = 0;
bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
if (bits && GetDIBits( hdc, src, 0, height, bits, info, DIB_RGB_COLORS ))
StretchDIBits( hdc_dst, dst_x, dst_y, dst_width, dst_height,
0, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY );
HeapFree( GetProcessHeap(), 0, bits );
HeapFree( GetProcessHeap(), 0, info );
}
else StretchBlt( hdc_dst, dst_x, dst_y, dst_width, dst_height, hdc, 0, 0, width, height, SRCCOPY );
DeleteDC( hdc );
}
/********************************************************************** /**********************************************************************
* CreateIconIndirect (USER32.@) * CreateIconIndirect (USER32.@)
*/ */
@ -1839,7 +1876,7 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
HICON hObj; HICON hObj;
HBITMAP color = 0, mask; HBITMAP color = 0, mask;
int width, height; int width, height;
HDC src, dst; HDC hdc;
TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n", TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n",
iconinfo->hbmColor, iconinfo->hbmMask, iconinfo->hbmColor, iconinfo->hbmMask,
@ -1875,28 +1912,22 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
mask = CreateBitmap( width, height, 1, 1, NULL ); mask = CreateBitmap( width, height, 1, 1, NULL );
} }
src = CreateCompatibleDC( 0 ); hdc = CreateCompatibleDC( 0 );
dst = CreateCompatibleDC( 0 ); SelectObject( hdc, mask );
stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmMask, bmpAnd.bmWidth, bmpAnd.bmHeight );
SelectObject( src, iconinfo->hbmMask );
SelectObject( dst, mask );
StretchBlt( dst, 0, 0, width, height, src, 0, 0, bmpAnd.bmWidth, bmpAnd.bmHeight, SRCCOPY );
if (color) if (color)
{ {
SelectObject( src, iconinfo->hbmColor ); SelectObject( hdc, color );
SelectObject( dst, color ); stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmColor, width, height );
BitBlt( dst, 0, 0, width, height, src, 0, 0, SRCCOPY );
} }
else if (iconinfo->hbmColor) else if (iconinfo->hbmColor)
{ {
SelectObject( src, iconinfo->hbmColor ); stretch_blt_icon( hdc, 0, height, width, height, iconinfo->hbmColor, width, height );
BitBlt( dst, 0, height, width, height, src, 0, 0, SRCCOPY );
} }
else height /= 2; else height /= 2;
DeleteDC( src ); DeleteDC( hdc );
DeleteDC( dst );
hObj = alloc_icon_handle(); hObj = alloc_icon_handle();
if (hObj) if (hObj)