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.
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 ******************************************************************/
33 /*forward declerations... actualy in user32\windows\icon.c but usful here****/
34 HICON
ICON_CreateCursorFromData(HDC hDC
, PVOID ImageData
, ICONIMAGE
* IconImage
, int cxDesired
, int cyDesired
, int xHotspot
, int yHotspot
);
35 HICON
ICON_CreateIconFromData(HDC hDC
, PVOID ImageData
, ICONIMAGE
* IconImage
, int cxDesired
, int cyDesired
, int xHotspot
, int yHotspot
);
36 CURSORICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
, int height
, int colors
);
37 CURSORICONDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
, int width
, int height
, int colors
);
39 /* FUNCTIONS *****************************************************************/
45 LoadImageA(HINSTANCE hinst
,
54 UNICODE_STRING NameString
;
58 RtlCreateUnicodeStringFromAsciiz(&NameString
, (LPSTR
)lpszName
);
59 lpszWName
= NameString
.Buffer
;
60 Handle
= LoadImageW(hinst
, lpszWName
, uType
, cxDesired
,
62 RtlFreeUnicodeString(&NameString
);
66 Handle
= LoadImageW(hinst
, (LPCWSTR
)lpszName
, uType
, cxDesired
,
75 LoadCursorImage(HINSTANCE hinst
, LPCWSTR lpszName
, UINT fuLoad
)
82 CURSORICONDIR
*IconDIR
;
88 CURSORICONDIRENTRY
* dirEntry
;
89 ICONIMAGE
* SafeIconImage
;
90 GRPCURSORICONDIR
* IconResDir
;
95 if (!(fuLoad
& LR_LOADFROMFILE
))
98 hinst
= User32Instance
;
100 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_CURSOR
);
101 if (hResource
== NULL
)
104 if (fuLoad
& LR_SHARED
)
106 /* FIXME - pass size! */
107 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, 0, 0);
112 hResource
= LoadResource(hinst
, hResource
);
113 if (hResource
== NULL
)
116 IconResDir
= LockResource(hResource
);
117 if (IconResDir
== NULL
)
121 * Find the best fitting in the IconResDir for this resolution
124 id
= LookupIconIdFromDirectoryEx((PBYTE
)IconResDir
, TRUE
, 32, 32,
125 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
127 h2Resource
= FindResourceW(hinst
, MAKEINTRESOURCEW(id
), MAKEINTRESOURCEW(RT_CURSOR
));
129 hResource
= LoadResource(hinst
, h2Resource
);
130 if (hResource
== NULL
)
133 ResIcon
= LockResource(hResource
);
137 hIcon
= CreateIconFromResourceEx((PBYTE
)ResIcon
,
138 SizeofResource(hinst
, h2Resource
),
139 FALSE
, 0x00030000, 32, 32,
140 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
141 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
143 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
150 if (fuLoad
& LR_SHARED
)
152 DbgPrint("FIXME: need LR_SHARED support for loading cursor images from files\n");
155 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
156 OPEN_EXISTING
, 0, NULL
);
160 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
162 if (hSection
== NULL
)
165 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
166 CloseHandle(hSection
);
170 if (0 != IconDIR
->idReserved
||
171 (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
173 UnmapViewOfFile(IconDIR
);
178 * Get a handle to the screen dc, the icon we create is going to be
179 * compatable with it.
181 hScreenDc
= CreateICW(NULL
, NULL
, NULL
, NULL
);
182 if (hScreenDc
== NULL
)
184 UnmapViewOfFile(IconDIR
);
188 if (fuLoad
& LR_MONOCHROME
)
194 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
197 * Remove this after proper support for alpha icons will be finished.
203 /* Pick the best size. */
204 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, 32, 32, ColorBits
);
207 UnmapViewOfFile(IconDIR
);
211 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
212 if (SafeIconImage
== NULL
)
214 UnmapViewOfFile(IconDIR
);
217 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
218 UnmapViewOfFile(IconDIR
);
220 /* At this point we have a copy of the icon image to play with. */
222 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
224 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
226 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
227 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
228 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
232 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
233 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
234 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
235 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
238 /* Make data point to the start of the XOR image data. */
239 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
241 hIcon
= ICON_CreateCursorFromData(hScreenDc
, Data
, SafeIconImage
, 32, 32, dirEntry
->Info
.cursor
.wXHotspot
, dirEntry
->Info
.cursor
.wYHotspot
);
243 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
250 LoadIconImage(HINSTANCE hinst
, LPCWSTR lpszName
, INT width
, INT height
, UINT fuLoad
)
257 CURSORICONDIR
*IconDIR
;
263 CURSORICONDIRENTRY
* dirEntry
;
264 ICONIMAGE
* SafeIconImage
;
265 GRPCURSORICONDIR
* IconResDir
;
269 if (!(fuLoad
& LR_LOADFROMFILE
))
272 hinst
= User32Instance
;
274 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_ICON
);
275 if (hResource
== NULL
)
278 if (fuLoad
& LR_SHARED
)
280 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, width
, height
);
285 hResource
= LoadResource(hinst
, hResource
);
286 if (hResource
== NULL
)
289 IconResDir
= LockResource(hResource
);
290 if (IconResDir
== NULL
)
294 * Find the best fitting in the IconResDir for this resolution
297 id
= LookupIconIdFromDirectoryEx((PBYTE
)IconResDir
, TRUE
, width
, height
,
298 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
300 h2Resource
= FindResourceW(hinst
, MAKEINTRESOURCEW(id
), MAKEINTRESOURCEW(RT_ICON
));
302 hResource
= LoadResource(hinst
, h2Resource
);
303 if (hResource
== NULL
)
306 ResIcon
= LockResource(hResource
);
310 hIcon
= CreateIconFromResourceEx((PBYTE
)ResIcon
,
311 SizeofResource(hinst
, h2Resource
),
312 TRUE
, 0x00030000, width
, height
,
313 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
314 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
316 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
324 * FIXME: This code is incorrect and is likely to crash in many cases.
325 * In the file the cursor/icon directory records are stored like
326 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
327 * this is solved by creating a fake cursor/icon directory in memory
328 * and passing that to CURSORICON_FindBestIcon.
331 if (fuLoad
& LR_SHARED
)
333 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
336 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
337 OPEN_EXISTING
, 0, NULL
);
341 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
343 if (hSection
== NULL
)
346 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
347 CloseHandle(hSection
);
351 if (0 != IconDIR
->idReserved
||
352 (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
354 UnmapViewOfFile(IconDIR
);
358 /* Pick the best size. */
359 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, width
, height
, 1);
362 UnmapViewOfFile(IconDIR
);
366 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
367 if (SafeIconImage
== NULL
)
369 UnmapViewOfFile(IconDIR
);
373 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
374 UnmapViewOfFile(IconDIR
);
376 /* At this point we have a copy of the icon image to play with. */
378 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
380 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
382 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
383 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
384 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
388 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
389 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
390 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
391 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
394 /* Make data point to the start of the XOR image data. */
395 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
397 /* Get a handle to the screen dc, the icon we create is going to be
398 * compatable with this. */
399 hScreenDc
= CreateICW(NULL
, NULL
, NULL
, NULL
);
400 if (hScreenDc
== NULL
)
402 if (fuLoad
& LR_LOADFROMFILE
)
403 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
407 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
408 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
416 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
421 LPBITMAPINFO BitmapInfo
;
422 LPBITMAPINFO PrivateInfo
;
429 if (!(fuLoad
& LR_LOADFROMFILE
))
431 if (hInstance
== NULL
)
432 hInstance
= User32Instance
;
434 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
435 if (hResource
== NULL
)
437 hResource
= LoadResource(hInstance
, hResource
);
438 if (hResource
== NULL
)
440 BitmapInfo
= LockResource(hResource
);
441 if (BitmapInfo
== NULL
)
446 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
447 OPEN_EXISTING
, 0, NULL
);
451 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
453 if (hSection
== NULL
)
456 BitmapInfo
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
457 CloseHandle(hSection
);
458 if (BitmapInfo
== NULL
)
461 BitmapInfo
= (LPBITMAPINFO
)((ULONG_PTR
)BitmapInfo
+ sizeof(BITMAPFILEHEADER
));
464 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
466 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
467 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
468 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
472 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
473 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
474 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
475 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
477 Data
= (PVOID
)((ULONG_PTR
)BitmapInfo
+ HeaderSize
);
479 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
480 if (PrivateInfo
== NULL
)
482 if (fuLoad
& LR_LOADFROMFILE
)
483 UnmapViewOfFile(BitmapInfo
);
486 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
488 /* FIXME: Handle color conversion and transparency. */
490 hScreenDc
= CreateCompatibleDC(NULL
);
491 if (hScreenDc
== NULL
)
493 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
494 if (fuLoad
& LR_LOADFROMFILE
)
495 UnmapViewOfFile(BitmapInfo
);
499 if (fuLoad
& LR_CREATEDIBSECTION
)
503 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
505 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
506 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
511 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
512 Data
, PrivateInfo
, DIB_RGB_COLORS
);
515 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
517 if (fuLoad
& LR_LOADFROMFILE
)
518 UnmapViewOfFile(BitmapInfo
);
532 if (fuLoad
& LR_DEFAULTSIZE
)
534 if (uType
== IMAGE_ICON
)
537 cxDesired
= GetSystemMetrics(SM_CXICON
);
539 cyDesired
= GetSystemMetrics(SM_CYICON
);
541 else if (uType
== IMAGE_CURSOR
)
544 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
546 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
553 return LoadBitmapImage(hinst
, lpszName
, fuLoad
);
555 return LoadCursorImage(hinst
, lpszName
, fuLoad
);
557 return LoadIconImage(hinst
, lpszName
, cxDesired
, cyDesired
, fuLoad
);
570 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
572 return LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
580 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
582 return LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
604 DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
606 * FIXME: Support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
607 * LR_COPYRETURNORG, LR_CREATEDIBSECTION and LR_MONOCHROME.
609 if (!GetObjectW(hnd
, sizeof(bm
), &bm
))
612 if ((res
= CreateBitmapIndirect(&bm
)))
614 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
620 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
621 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
622 HeapFree(GetProcessHeap(), 0, buf
);
629 static BOOL IconMsgDisplayed
= FALSE
;
630 /* FIXME: support loading the image as shared from an instance */
631 if (!IconMsgDisplayed
)
633 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
634 IconMsgDisplayed
= TRUE
;
636 return CopyIcon(hnd
);
641 static BOOL IconMsgDisplayed
= FALSE
;
642 /* FIXME: support loading the image as shared from an instance */
643 if (!IconMsgDisplayed
)
645 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
646 IconMsgDisplayed
= TRUE
;
648 return CopyCursor(hnd
);