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
,
74 LoadCursorImage(HINSTANCE hinst
, LPCWSTR lpszName
, UINT fuLoad
)
81 CURSORICONDIR
*IconDIR
;
87 CURSORICONDIRENTRY
* dirEntry
;
88 ICONIMAGE
* SafeIconImage
;
89 GRPCURSORICONDIR
* IconResDir
;
94 if (!(fuLoad
& LR_LOADFROMFILE
))
98 hinst
= GetModuleHandleW(L
"USER32");
100 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_CURSOR
);
101 if (hResource
== NULL
)
106 if (fuLoad
& LR_SHARED
)
108 /* FIXME - pass size! */
109 hIcon
= (HANDLE
)NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, 0, 0);
116 hResource
= LoadResource(hinst
, hResource
);
117 if (hResource
== NULL
)
121 IconResDir
= LockResource(hResource
);
122 if (IconResDir
== NULL
)
127 /* Find the best fitting in the IconResDir for this resolution. */
128 id
= LookupIconIdFromDirectoryEx((PBYTE
)IconResDir
, TRUE
,
129 32, 32, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
131 h2Resource
= FindResourceW(hinst
, MAKEINTRESOURCEW(id
),
132 MAKEINTRESOURCEW(RT_CURSOR
));
134 hResource
= LoadResource(hinst
, h2Resource
);
135 if (hResource
== NULL
)
140 ResIcon
= LockResource(hResource
);
146 hIcon
= (HANDLE
)CreateIconFromResourceEx((PBYTE
)ResIcon
,
147 SizeofResource(hinst
, h2Resource
), FALSE
, 0x00030000,
148 32, 32, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
149 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
151 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
158 if (fuLoad
& LR_SHARED
)
160 DbgPrint("FIXME: need LR_SHARED support loading cursor images from files\n");
163 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
164 OPEN_EXISTING
, 0, NULL
);
170 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
172 if (hSection
== NULL
)
177 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
178 CloseHandle(hSection
);
179 if (IconDIR
== NULL
|| 0 != IconDIR
->idReserved
180 || (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
186 * Get a handle to the screen dc, the icon we create is going to be
187 * compatable with it.
189 hScreenDc
= CreateCompatibleDC(0);
190 if (hScreenDc
== NULL
)
192 UnmapViewOfFile(IconDIR
);
196 if (fuLoad
& LR_MONOCHROME
)
202 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
205 * Remove this after proper support for alpha icons will be finished.
211 /* Pick the best size. */
212 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, 32, 32, ColorBits
);
215 UnmapViewOfFile(IconDIR
);
219 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
220 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
222 /* at this point we have a copy of the icon image to play with */
224 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
226 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
228 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
229 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
230 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
234 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
235 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
237 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
239 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
242 /* make data point to the start of the XOR image data */
243 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
245 hIcon
= ICON_CreateCursorFromData(hScreenDc
, Data
, SafeIconImage
, 32, 32, dirEntry
->Info
.cursor
.wXHotspot
, dirEntry
->Info
.cursor
.wYHotspot
);
247 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
253 LoadIconImage(HINSTANCE hinst
, LPCWSTR lpszName
, INT width
, INT height
, UINT fuLoad
)
260 CURSORICONDIR
* IconDIR
;
266 CURSORICONDIRENTRY
* dirEntry
;
267 ICONIMAGE
* SafeIconImage
;
268 GRPCURSORICONDIR
* IconResDir
;
272 if (!(fuLoad
& LR_LOADFROMFILE
))
276 hinst
= GetModuleHandleW(L
"USER32");
278 hResource
= hfRes
= FindResourceW(hinst
, lpszName
, RT_GROUP_ICON
);
279 if (hResource
== NULL
)
284 if (fuLoad
& LR_SHARED
)
286 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, width
, height
);
291 hResource
= LoadResource(hinst
, hResource
);
292 if (hResource
== NULL
)
296 IconResDir
= LockResource(hResource
);
297 if (IconResDir
== NULL
)
302 //find the best fitting in the IconResDir for this resolution
303 id
= LookupIconIdFromDirectoryEx((PBYTE
) IconResDir
, TRUE
,
304 width
, height
, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
306 h2Resource
= FindResourceW(hinst
,
307 MAKEINTRESOURCEW(id
),
308 MAKEINTRESOURCEW(RT_ICON
));
310 hResource
= LoadResource(hinst
, h2Resource
);
311 if (hResource
== NULL
)
316 ResIcon
= LockResource(hResource
);
321 hIcon
= (HANDLE
)CreateIconFromResourceEx((PBYTE
) ResIcon
,
322 SizeofResource(hinst
, h2Resource
), TRUE
, 0x00030000,
323 width
, height
, fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
324 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
326 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
334 * FIXME: This code is incorrect and is likely to crash in many cases.
335 * In the file the cursor/icon directory records are stored like
336 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
337 * this is solved by creating a fake cursor/icon directory in memory
338 * and passing that to CURSORICON_FindBestIcon.
341 if (fuLoad
& LR_SHARED
)
343 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
346 hFile
= CreateFileW(lpszName
,
358 hSection
= CreateFileMappingW(hFile
,
365 if (hSection
== NULL
)
370 IconDIR
= MapViewOfFile(hSection
,
376 if (IconDIR
== NULL
|| 0 != IconDIR
->idReserved
377 || (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
380 CloseHandle(hSection
);
384 //pick the best size.
385 dirEntry
= (CURSORICONDIRENTRY
*) CURSORICON_FindBestIcon( IconDIR
, width
, height
, 1);
391 CloseHandle(hSection
);
392 UnmapViewOfFile(IconDIR
);
396 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
398 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
401 CloseHandle(hSection
);
404 //at this point we have a copy of the icon image to play with
406 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
408 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
410 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
411 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
412 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
416 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
417 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
419 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
421 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
424 //make data point to the start of the XOR image data
425 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
428 //get a handle to the screen dc, the icon we create is going to be compatable with this
429 hScreenDc
= CreateDCW(L
"DISPLAY", NULL
, NULL
, NULL
);
430 if (hScreenDc
== NULL
)
432 if (fuLoad
& LR_LOADFROMFILE
)
434 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
435 UnmapViewOfFile(IconDIR
);
440 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
441 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
447 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
452 BITMAPINFO
* BitmapInfo
;
453 BITMAPINFO
* PrivateInfo
;
460 if (!(fuLoad
& LR_LOADFROMFILE
))
462 if (hInstance
== NULL
)
464 hInstance
= GetModuleHandleW(L
"USER32");
466 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
467 if (hResource
== NULL
)
471 hResource
= LoadResource(hInstance
, hResource
);
472 if (hResource
== NULL
)
476 BitmapInfo
= LockResource(hResource
);
477 if (BitmapInfo
== NULL
)
484 hFile
= CreateFileW(lpszName
,
495 hSection
= CreateFileMappingW(hFile
,
502 if (hSection
== NULL
)
506 BitmapInfo
= MapViewOfFile(hSection
,
511 CloseHandle(hSection
);
512 if (BitmapInfo
== NULL
)
516 /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
517 unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
519 BitmapInfo
= (BITMAPINFO
*)(((PBYTE
)BitmapInfo
) + 14);
522 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
524 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
525 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
526 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
530 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
531 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
533 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
535 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
537 Data
= (PVOID
)((ULONG_PTR
)BitmapInfo
+ HeaderSize
);
539 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
540 if (PrivateInfo
== NULL
)
542 if (fuLoad
& LR_LOADFROMFILE
)
544 UnmapViewOfFile(BitmapInfo
);
548 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
550 /* FIXME: Handle color conversion and transparency. */
552 hScreenDc
= CreateCompatibleDC(NULL
);
553 if (hScreenDc
== NULL
)
555 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
556 if (fuLoad
& LR_LOADFROMFILE
)
558 UnmapViewOfFile(BitmapInfo
);
563 if (fuLoad
& LR_CREATEDIBSECTION
)
567 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
569 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
570 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
575 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
576 Data
, PrivateInfo
, DIB_RGB_COLORS
);
579 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
581 if (fuLoad
& LR_LOADFROMFILE
)
583 UnmapViewOfFile(BitmapInfo
);
589 LoadImageW(HINSTANCE hinst
,
596 if (fuLoad
& LR_DEFAULTSIZE
)
598 if (uType
== IMAGE_ICON
)
602 cxDesired
= GetSystemMetrics(SM_CXICON
);
606 cyDesired
= GetSystemMetrics(SM_CYICON
);
609 else if (uType
== IMAGE_CURSOR
)
613 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
617 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
626 return(LoadBitmapImage(hinst
, lpszName
, fuLoad
));
630 return(LoadCursorImage(hinst
, lpszName
, fuLoad
));
634 return(LoadIconImage(hinst
, lpszName
, cxDesired
, cyDesired
, fuLoad
));
648 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
650 return(LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0));
658 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
660 return(LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0));
668 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; */
682 if (!GetObjectW(hnd
, sizeof(bm
), &bm
)) return 0;
684 if ((res
= CreateBitmapIndirect(&bm
)))
686 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
687 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
688 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
689 HeapFree(GetProcessHeap(), 0, buf
);
695 static BOOL IconMsgDisplayed
= FALSE
;
696 /* FIXME: support loading the image as shared from an instance */
697 if (!IconMsgDisplayed
) {
698 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
699 IconMsgDisplayed
= TRUE
;
701 return CopyIcon(hnd
);
705 static BOOL IconMsgDisplayed
= FALSE
;
706 /* FIXME: support loading the image as shared from an instance */
707 if (!IconMsgDisplayed
) {
708 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
709 IconMsgDisplayed
= TRUE
;
711 return CopyCursor(hnd
);