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 ******************************************************************/
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
));
152 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
154 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
161 if (fuLoad
& LR_SHARED
)
163 DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
166 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
167 OPEN_EXISTING
, 0, NULL
);
173 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
175 if (hSection
== NULL
)
180 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
181 CloseHandle(hSection
);
182 if (IconDIR
== NULL
|| 0 != IconDIR
->idReserved
183 || (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
189 * Get a handle to the screen dc, the icon we create is going to be
190 * compatable with it.
192 hScreenDc
= CreateCompatibleDC(0);
193 if (hScreenDc
== NULL
)
195 UnmapViewOfFile(IconDIR
);
199 if (fuLoad
& LR_MONOCHROME
)
205 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
208 * Remove this after proper support for alpha icons will be finished.
214 /* Pick the best size. */
215 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, 32, 32, ColorBits
);
218 UnmapViewOfFile(IconDIR
);
222 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
223 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
225 /* at this point we have a copy of the icon image to play with */
227 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
229 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
231 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
232 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
233 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
237 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
238 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
240 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
242 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
245 /* make data point to the start of the XOR image data */
246 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
248 hIcon
= ICON_CreateCursorFromData(hScreenDc
, Data
, SafeIconImage
, 32, 32, dirEntry
->Info
.cursor
.wXHotspot
, dirEntry
->Info
.cursor
.wYHotspot
);
250 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
256 LoadIconImage(HINSTANCE hinst
, LPCWSTR lpszName
, INT width
, INT height
, UINT fuLoad
)
263 CURSORICONDIR
* IconDIR
;
269 CURSORICONDIRENTRY
* dirEntry
;
270 ICONIMAGE
* SafeIconImage
;
271 GRPCURSORICONDIR
* IconResDir
;
275 if (!(fuLoad
& LR_LOADFROMFILE
))
279 hinst
= GetModuleHandleW(L
"USER32");
281 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_ICON
);
282 if (hResource
== NULL
)
287 if (fuLoad
& LR_SHARED
)
289 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, width
, height
);
294 hResource
= LoadResource(hinst
, hResource
);
295 if (hResource
== NULL
)
299 IconResDir
= LockResource(hResource
);
300 if (IconResDir
== NULL
)
305 //find the best fitting in the IconResDir for this resolution
306 id
= LookupIconIdFromDirectoryEx((PBYTE
) IconResDir
, TRUE
,
307 width
, height
, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
309 h2Resource
= FindResourceW(hinst
,
310 MAKEINTRESOURCEW(id
),
311 MAKEINTRESOURCEW(RT_ICON
));
313 hResource
= LoadResource(hinst
, h2Resource
);
314 if (hResource
== NULL
)
319 ResIcon
= LockResource(hResource
);
324 hIcon
= (HANDLE
)CreateIconFromResourceEx((PBYTE
) ResIcon
,
325 SizeofResource(hinst
, h2Resource
), TRUE
, 0x00030000,
326 width
, height
, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
327 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
329 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
337 * FIXME: This code is incorrect and is likely to crash in many cases.
338 * In the file the cursor/icon directory records are stored like
339 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
340 * this is solved by creating a fake cursor/icon directory in memory
341 * and passing that to CURSORICON_FindBestIcon.
344 if (fuLoad
& LR_SHARED
)
346 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
349 hFile
= CreateFileW(lpszName
,
361 hSection
= CreateFileMappingW(hFile
,
368 if (hSection
== NULL
)
373 IconDIR
= MapViewOfFile(hSection
,
379 if (IconDIR
== NULL
|| 0 != IconDIR
->idReserved
380 || (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
383 CloseHandle(hSection
);
387 //pick the best size.
388 dirEntry
= (CURSORICONDIRENTRY
*) CURSORICON_FindBestIcon( IconDIR
, width
, height
, 1);
394 CloseHandle(hSection
);
395 UnmapViewOfFile(IconDIR
);
399 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
401 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
404 CloseHandle(hSection
);
407 //at this point we have a copy of the icon image to play with
409 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
411 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
413 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
414 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
415 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
419 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
420 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
422 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
424 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
427 //make data point to the start of the XOR image data
428 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
431 //get a handle to the screen dc, the icon we create is going to be compatable with this
432 hScreenDc
= CreateDCW(L
"DISPLAY", NULL
, NULL
, NULL
);
433 if (hScreenDc
== NULL
)
435 if (fuLoad
& LR_LOADFROMFILE
)
437 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
438 UnmapViewOfFile(IconDIR
);
443 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
444 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
450 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
455 BITMAPINFO
* BitmapInfo
;
456 BITMAPINFO
* PrivateInfo
;
463 if (!(fuLoad
& LR_LOADFROMFILE
))
465 if (hInstance
== NULL
)
467 hInstance
= GetModuleHandleW(L
"USER32");
469 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
470 if (hResource
== NULL
)
474 hResource
= LoadResource(hInstance
, hResource
);
475 if (hResource
== NULL
)
479 BitmapInfo
= LockResource(hResource
);
480 if (BitmapInfo
== NULL
)
487 hFile
= CreateFileW(lpszName
,
498 hSection
= CreateFileMappingW(hFile
,
505 if (hSection
== NULL
)
509 BitmapInfo
= MapViewOfFile(hSection
,
514 CloseHandle(hSection
);
515 if (BitmapInfo
== NULL
)
519 /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
520 unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
522 BitmapInfo
= (BITMAPINFO
*)(((PBYTE
)BitmapInfo
) + 14);
525 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
527 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
528 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
529 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
533 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
534 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
536 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
538 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
540 Data
= (PVOID
)BitmapInfo
+ HeaderSize
;
542 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
543 if (PrivateInfo
== NULL
)
545 if (fuLoad
& LR_LOADFROMFILE
)
547 UnmapViewOfFile(BitmapInfo
);
551 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
553 /* FIXME: Handle color conversion and transparency. */
555 hScreenDc
= CreateCompatibleDC(NULL
);
556 if (hScreenDc
== NULL
)
558 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
559 if (fuLoad
& LR_LOADFROMFILE
)
561 UnmapViewOfFile(BitmapInfo
);
566 if (fuLoad
& LR_CREATEDIBSECTION
)
570 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
572 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
573 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
578 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
579 Data
, PrivateInfo
, DIB_RGB_COLORS
);
582 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
584 if (fuLoad
& LR_LOADFROMFILE
)
586 UnmapViewOfFile(BitmapInfo
);
592 LoadImageW(HINSTANCE hinst
,
599 if (fuLoad
& LR_DEFAULTSIZE
)
601 if (uType
== IMAGE_ICON
)
605 cxDesired
= GetSystemMetrics(SM_CXICON
);
609 cyDesired
= GetSystemMetrics(SM_CYICON
);
612 else if (uType
== IMAGE_CURSOR
)
616 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
620 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
629 return(LoadBitmapImage(hinst
, lpszName
, fuLoad
));
633 return(LoadCursorImage(hinst
, lpszName
, fuLoad
));
637 return(LoadIconImage(hinst
, lpszName
, cxDesired
, cyDesired
, fuLoad
));
651 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
653 return(LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0));
661 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
663 return(LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0));
671 CopyImage(HANDLE hnd
, UINT type
, INT desiredx
, INT desiredy
, UINT flags
)
677 DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
678 /* FIXME: support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
679 LR_COPYRETURNORG, LR_CREATEDIBSECTION,
680 and LR_MONOCHROME; */
684 if (!GetObjectW(hnd
, sizeof(bm
), &bm
)) return 0;
686 if ((res
= CreateBitmapIndirect(&bm
)))
688 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
689 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
690 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
691 HeapFree(GetProcessHeap(), 0, buf
);
697 static BOOL IconMsgDisplayed
= FALSE
;
698 /* FIXME: support loading the image as shared from an instance */
699 if (!IconMsgDisplayed
) {
700 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
701 IconMsgDisplayed
= TRUE
;
703 return CopyIcon(hnd
);
707 static BOOL IconMsgDisplayed
= FALSE
;
708 /* FIXME: support loading the image as shared from an instance */
709 if (!IconMsgDisplayed
) {
710 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
711 IconMsgDisplayed
= TRUE
;
713 return CopyCursor(hnd
);