3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: bitmap.c,v 1.33 2004/10/05 22:08:56 gvg Exp $
21 * PROJECT: ReactOS user32.dll
22 * FILE: lib/user32/windows/input.c
24 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 09-05-2001 CSH Created
29 /* INCLUDES ******************************************************************/
36 /*forward declerations... actualy in user32\windows\icon.c but usful here****/
37 HICON
ICON_CreateCursorFromData(HDC hDC
, PVOID ImageData
, ICONIMAGE
* IconImage
, int cxDesired
, int cyDesired
, int xHotspot
, int yHotspot
);
38 HICON
ICON_CreateIconFromData(HDC hDC
, PVOID ImageData
, ICONIMAGE
* IconImage
, int cxDesired
, int cyDesired
, int xHotspot
, int yHotspot
);
39 CURSORICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
, int height
, int colors
);
40 CURSORICONDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
, int width
, int height
, int colors
);
42 /* FUNCTIONS *****************************************************************/
48 LoadImageA(HINSTANCE hinst
,
57 UNICODE_STRING NameString
;
61 RtlCreateUnicodeStringFromAsciiz(&NameString
, (LPSTR
)lpszName
);
62 lpszWName
= NameString
.Buffer
;
63 Handle
= LoadImageW(hinst
, lpszWName
, uType
, cxDesired
,
65 RtlFreeUnicodeString(&NameString
);
69 Handle
= LoadImageW(hinst
, (LPCWSTR
)lpszName
, uType
, cxDesired
,
77 LoadCursorImage(HINSTANCE hinst
, LPCWSTR lpszName
, UINT fuLoad
)
84 CURSORICONDIR
*IconDIR
;
90 CURSORICONDIRENTRY
* dirEntry
;
91 ICONIMAGE
* SafeIconImage
;
92 GRPCURSORICONDIR
* IconResDir
;
97 if (!(fuLoad
& LR_LOADFROMFILE
))
101 hinst
= GetModuleHandleW(L
"USER32");
103 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_CURSOR
);
104 if (hResource
== NULL
)
109 if (fuLoad
& LR_SHARED
)
111 /* FIXME - pass size! */
112 hIcon
= (HANDLE
)NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, 0, 0);
119 hResource
= LoadResource(hinst
, hResource
);
120 if (hResource
== NULL
)
124 IconResDir
= LockResource(hResource
);
125 if (IconResDir
== NULL
)
130 /* Find the best fitting in the IconResDir for this resolution. */
131 id
= LookupIconIdFromDirectoryEx((PBYTE
)IconResDir
, TRUE
,
132 32, 32, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
134 h2Resource
= FindResourceW(hinst
, MAKEINTRESOURCEW(id
),
135 MAKEINTRESOURCEW(RT_CURSOR
));
137 hResource
= LoadResource(hinst
, h2Resource
);
138 if (hResource
== NULL
)
143 ResIcon
= LockResource(hResource
);
149 hIcon
= (HANDLE
)CreateIconFromResourceEx((PBYTE
)ResIcon
,
150 SizeofResource(hinst
, h2Resource
), FALSE
, 0x00030000,
151 32, 32, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
154 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
162 if (fuLoad
& LR_SHARED
)
164 DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
167 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
168 OPEN_EXISTING
, 0, NULL
);
174 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
176 if (hSection
== NULL
)
181 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
182 CloseHandle(hSection
);
183 if (IconDIR
== NULL
|| 0 != IconDIR
->idReserved
184 || (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
190 * Get a handle to the screen dc, the icon we create is going to be
191 * compatable with it.
193 hScreenDc
= CreateCompatibleDC(0);
194 if (hScreenDc
== NULL
)
196 UnmapViewOfFile(IconDIR
);
200 if (fuLoad
& LR_MONOCHROME
)
206 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
209 * Remove this after proper support for alpha icons will be finished.
215 /* Pick the best size. */
216 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, 32, 32, ColorBits
);
219 UnmapViewOfFile(IconDIR
);
223 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
224 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
227 //at this point we have a copy of the icon image to play with
229 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
231 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
233 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
234 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
235 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
239 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
240 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
242 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
244 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
247 //make data point to the start of the XOR image data
248 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
250 hIcon
= ICON_CreateCursorFromData(hScreenDc
, Data
, SafeIconImage
, 32, 32, dirEntry
->Info
.cursor
.wXHotspot
, dirEntry
->Info
.cursor
.wYHotspot
);
252 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
258 LoadIconImage(HINSTANCE hinst
, LPCWSTR lpszName
, INT width
, INT height
, UINT fuLoad
)
265 CURSORICONDIR
* IconDIR
;
271 CURSORICONDIRENTRY
* dirEntry
;
272 ICONIMAGE
* SafeIconImage
;
273 GRPCURSORICONDIR
* IconResDir
;
277 if (!(fuLoad
& LR_LOADFROMFILE
))
281 hinst
= GetModuleHandleW(L
"USER32");
283 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_ICON
);
284 if (hResource
== NULL
)
289 if (fuLoad
& LR_SHARED
)
291 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, width
, height
);
296 hResource
= LoadResource(hinst
, hResource
);
297 if (hResource
== NULL
)
301 IconResDir
= LockResource(hResource
);
302 if (IconResDir
== NULL
)
307 //find the best fitting in the IconResDir for this resolution
308 id
= LookupIconIdFromDirectoryEx((PBYTE
) IconResDir
, TRUE
,
309 width
, height
, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
311 h2Resource
= FindResourceW(hinst
,
312 MAKEINTRESOURCEW(id
),
313 MAKEINTRESOURCEW(RT_ICON
));
315 hResource
= LoadResource(hinst
, h2Resource
);
316 if (hResource
== NULL
)
321 ResIcon
= LockResource(hResource
);
326 hIcon
= (HANDLE
)CreateIconFromResourceEx((PBYTE
) ResIcon
,
327 SizeofResource(hinst
, h2Resource
), TRUE
, 0x00030000,
328 width
, height
, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
331 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
339 * FIXME: This code is incorrect and is likely to crash in many cases.
340 * In the file the cursor/icon directory records are stored like
341 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
342 * this is solved by creating a fake cursor/icon directory in memory
343 * and passing that to CURSORICON_FindBestIcon.
346 if (fuLoad
& LR_SHARED
)
348 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
351 hFile
= CreateFileW(lpszName
,
363 hSection
= CreateFileMappingW(hFile
,
370 if (hSection
== NULL
)
375 IconDIR
= MapViewOfFile(hSection
,
381 if (IconDIR
== NULL
|| 0 != IconDIR
->idReserved
382 || (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
385 CloseHandle(hSection
);
389 //pick the best size.
390 dirEntry
= (CURSORICONDIRENTRY
*) CURSORICON_FindBestIcon( IconDIR
, width
, height
, 1);
396 CloseHandle(hSection
);
397 UnmapViewOfFile(IconDIR
);
401 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
403 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
406 CloseHandle(hSection
);
409 //at this point we have a copy of the icon image to play with
411 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
413 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
415 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
416 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
417 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
421 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
422 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
424 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
426 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
429 //make data point to the start of the XOR image data
430 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
433 //get a handle to the screen dc, the icon we create is going to be compatable with this
434 hScreenDc
= CreateDCW(L
"DISPLAY", NULL
, NULL
, NULL
);
435 if (hScreenDc
== NULL
)
437 if (fuLoad
& LR_LOADFROMFILE
)
439 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
440 UnmapViewOfFile(IconDIR
);
445 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
446 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
452 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
457 BITMAPINFO
* BitmapInfo
;
458 BITMAPINFO
* PrivateInfo
;
465 if (!(fuLoad
& LR_LOADFROMFILE
))
467 if (hInstance
== NULL
)
469 hInstance
= GetModuleHandleW(L
"USER32");
471 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
472 if (hResource
== NULL
)
476 hResource
= LoadResource(hInstance
, hResource
);
477 if (hResource
== NULL
)
481 BitmapInfo
= LockResource(hResource
);
482 if (BitmapInfo
== NULL
)
489 hFile
= CreateFileW(lpszName
,
500 hSection
= CreateFileMappingW(hFile
,
507 if (hSection
== NULL
)
511 BitmapInfo
= MapViewOfFile(hSection
,
516 CloseHandle(hSection
);
517 if (BitmapInfo
== NULL
)
521 /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
522 unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
524 BitmapInfo
= (BITMAPINFO
*)(((PBYTE
)BitmapInfo
) + 14);
527 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
529 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
530 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
531 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
535 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
536 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
538 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
540 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
542 Data
= (PVOID
)BitmapInfo
+ HeaderSize
;
544 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
545 if (PrivateInfo
== NULL
)
547 if (fuLoad
& LR_LOADFROMFILE
)
549 UnmapViewOfFile(BitmapInfo
);
553 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
555 /* FIXME: Handle color conversion and transparency. */
557 hScreenDc
= CreateDCW(L
"DISPLAY", NULL
, NULL
, NULL
);
558 if (hScreenDc
== NULL
)
560 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
561 if (fuLoad
& LR_LOADFROMFILE
)
563 UnmapViewOfFile(BitmapInfo
);
568 if (fuLoad
& LR_CREATEDIBSECTION
)
572 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
574 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
575 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
580 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
581 Data
, PrivateInfo
, DIB_RGB_COLORS
);
584 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
585 /*DeleteDC(hScreenDc);*/
586 if (fuLoad
& LR_LOADFROMFILE
)
588 UnmapViewOfFile(BitmapInfo
);
594 LoadImageW(HINSTANCE hinst
,
601 if (fuLoad
& LR_DEFAULTSIZE
)
603 if (uType
== IMAGE_ICON
)
607 cxDesired
= GetSystemMetrics(SM_CXICON
);
611 cyDesired
= GetSystemMetrics(SM_CYICON
);
614 else if (uType
== IMAGE_CURSOR
)
618 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
622 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
631 return(LoadBitmapImage(hinst
, lpszName
, fuLoad
));
635 return(LoadCursorImage(hinst
, lpszName
, fuLoad
));
639 return(LoadIconImage(hinst
, lpszName
, cxDesired
, cyDesired
, fuLoad
));
653 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
655 return(LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0));
663 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
665 return(LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0));
673 CopyImage(HANDLE hnd
, UINT type
, INT desiredx
, INT desiredy
, UINT flags
)
679 DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
680 /* FIXME: support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
681 LR_COPYRETURNORG, LR_CREATEDIBSECTION,
682 and LR_MONOCHROME; */
686 if (!GetObjectW(hnd
, sizeof(bm
), &bm
)) return 0;
688 if ((res
= CreateBitmapIndirect(&bm
)))
690 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
691 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
692 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
693 HeapFree(GetProcessHeap(), 0, buf
);
699 static BOOL IconMsgDisplayed
= FALSE
;
700 /* FIXME: support loading the image as shared from an instance */
701 if (!IconMsgDisplayed
) {
702 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
703 IconMsgDisplayed
= TRUE
;
705 return CopyIcon(hnd
);
709 static BOOL IconMsgDisplayed
= FALSE
;
710 /* FIXME: support loading the image as shared from an instance */
711 if (!IconMsgDisplayed
) {
712 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
713 IconMsgDisplayed
= TRUE
;
715 return CopyCursor(hnd
);