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 ******************************************************************/
44 } CURSORICONFILEDIRENTRY
;
51 CURSORICONFILEDIRENTRY idEntries
[1];
56 /*forward declerations... actualy in user32\windows\icon.c but usful here****/
57 HICON
ICON_CreateCursorFromData(HDC hDC
, PVOID ImageData
, ICONIMAGE
* IconImage
, int cxDesired
, int cyDesired
, int xHotspot
, int yHotspot
);
58 HICON
ICON_CreateIconFromData(HDC hDC
, PVOID ImageData
, ICONIMAGE
* IconImage
, int cxDesired
, int cyDesired
, int xHotspot
, int yHotspot
);
59 CURSORICONDIRENTRY
*CURSORICON_FindBestIcon( CURSORICONDIR
*dir
, int width
, int height
, int colors
);
60 CURSORICONDIRENTRY
*CURSORICON_FindBestCursor( CURSORICONDIR
*dir
, int width
, int height
, int colors
);
62 /* FUNCTIONS *****************************************************************/
68 LoadImageA(HINSTANCE hinst
,
77 UNICODE_STRING NameString
;
81 RtlCreateUnicodeStringFromAsciiz(&NameString
, (LPSTR
)lpszName
);
82 lpszWName
= NameString
.Buffer
;
83 Handle
= LoadImageW(hinst
, lpszWName
, uType
, cxDesired
,
85 RtlFreeUnicodeString(&NameString
);
89 Handle
= LoadImageW(hinst
, (LPCWSTR
)lpszName
, uType
, cxDesired
,
98 * The following macro functions account for the irregularities of
99 * accessing cursor and icon resources in files and resource entries.
101 typedef BOOL (*fnGetCIEntry
)( LPVOID dir
, int n
,
102 int *width
, int *height
, int *bits
);
104 /**********************************************************************
105 * CURSORICON_FindBestCursor2
107 * Find the cursor closest to the requested size.
108 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
111 static int CURSORICON_FindBestCursor2( LPVOID dir
, fnGetCIEntry get_entry
,
112 int width
, int height
, int color
)
114 int i
, maxwidth
, maxheight
, cx
, cy
, bits
, bestEntry
= -1;
116 /* Double height to account for AND and XOR masks */
120 /* First find the largest one smaller than or equal to the requested size*/
122 maxwidth
= maxheight
= 0;
123 for ( i
= 0; get_entry( dir
, i
, &cx
, &cy
, &bits
); i
++ )
125 if ((cx
<= width
) && (cy
<= height
) &&
126 (cx
> maxwidth
) && (cy
> maxheight
) &&
134 if (bestEntry
!= -1) return bestEntry
;
136 /* Now find the smallest one larger than the requested size */
138 maxwidth
= maxheight
= 255;
139 for ( i
= 0; get_entry( dir
, i
, &cx
, &cy
, &bits
); i
++ )
141 if (((cx
< maxwidth
) && (cy
< maxheight
) && (bits
== 1)) ||
153 static BOOL
CURSORICON_GetFileEntry( LPVOID dir
, int n
,
154 int *width
, int *height
, int *bits
)
156 CURSORICONFILEDIR
*filedir
= dir
;
157 CURSORICONFILEDIRENTRY
*entry
;
159 if ( filedir
->idCount
<= n
)
161 entry
= &filedir
->idEntries
[n
];
162 *width
= entry
->bWidth
;
163 *height
= entry
->bHeight
;
164 *bits
= entry
->bColorCount
;
168 static CURSORICONFILEDIRENTRY
*CURSORICON_FindBestCursorFile( CURSORICONFILEDIR
*dir
,
169 int width
, int height
, int color
)
171 int n
= CURSORICON_FindBestCursor2( dir
, CURSORICON_GetFileEntry
,
172 width
, height
, color
);
175 return &dir
->idEntries
[n
];
192 CURSORICONFILEDIR
*IconDIR
;
199 CURSORICONFILEDIRENTRY
* dirEntry
;
200 ICONIMAGE
* SafeIconImage
= NULL
;
201 GRPCURSORICONDIR
* IconResDir
;
204 BOOL Icon
= (uType
== IMAGE_ICON
);
207 if (!(fuLoad
& LR_LOADFROMFILE
))
210 hinst
= User32Instance
;
212 hResource
= hfRes
= FindResourceW(hinst
, lpszName
,
213 Icon
? RT_GROUP_ICON
: RT_GROUP_CURSOR
);
214 if (hResource
== NULL
)
217 if (fuLoad
& LR_SHARED
)
219 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, width
, height
);
224 hResource
= LoadResource(hinst
, hResource
);
225 if (hResource
== NULL
)
228 IconResDir
= LockResource(hResource
);
229 if (IconResDir
== NULL
)
233 * Find the best fitting in the IconResDir for this resolution
236 id
= LookupIconIdFromDirectoryEx((PBYTE
)IconResDir
, Icon
, width
, height
,
237 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
239 h2Resource
= FindResourceW(hinst
, MAKEINTRESOURCEW(id
),
240 Icon
? MAKEINTRESOURCEW(RT_ICON
) :
241 MAKEINTRESOURCEW(RT_CURSOR
));
242 if (h2Resource
== NULL
)
245 hResource
= LoadResource(hinst
, h2Resource
);
246 if (hResource
== NULL
)
249 ResIcon
= LockResource(hResource
);
253 hIcon
= CreateIconFromResourceEx((PBYTE
)ResIcon
,
254 SizeofResource(hinst
, h2Resource
),
255 Icon
, 0x00030000, width
, height
,
256 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
257 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
259 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
266 if (fuLoad
& LR_SHARED
)
268 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
271 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
272 OPEN_EXISTING
, 0, NULL
);
273 if (hFile
== INVALID_HANDLE_VALUE
)
276 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
277 filesize
= GetFileSize( hFile
, NULL
);
279 if (hSection
== NULL
)
282 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
283 CloseHandle(hSection
);
287 if (0 != IconDIR
->idReserved
||
288 (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
290 UnmapViewOfFile(IconDIR
);
294 /* Get a handle to the screen dc, the icon we create is going to be
295 * compatable with this. */
296 hScreenDc
= CreateDCW(NULL
, NULL
, NULL
, NULL
);
297 if (hScreenDc
== NULL
)
299 UnmapViewOfFile(IconDIR
);
300 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
304 if (fuLoad
& LR_MONOCHROME
)
310 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
313 * Remove this after proper support for alpha icons will be finished.
319 /* Pick the best size. */
320 dirEntry
= CURSORICON_FindBestCursorFile( IconDIR
, width
, height
, ColorBits
);
324 UnmapViewOfFile(IconDIR
);
328 if ( dirEntry
->dwDIBOffset
> filesize
)
331 UnmapViewOfFile(IconDIR
);
335 if ( dirEntry
->dwDIBOffset
+ dirEntry
->dwDIBSize
> filesize
){
337 UnmapViewOfFile(IconDIR
);
341 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwDIBSize
);
342 if (SafeIconImage
== NULL
)
345 UnmapViewOfFile(IconDIR
);
349 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwDIBOffset
, dirEntry
->dwDIBSize
);
350 UnmapViewOfFile(IconDIR
);
352 /* At this point we have a copy of the icon image to play with. */
354 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
356 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
358 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
359 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
360 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
364 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
365 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
366 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
367 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
370 /* Make data point to the start of the XOR image data. */
371 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
373 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
374 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
382 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
387 LPBITMAPINFO BitmapInfo
;
388 LPBITMAPINFO PrivateInfo
;
395 if (!(fuLoad
& LR_LOADFROMFILE
))
397 if (hInstance
== NULL
)
398 hInstance
= User32Instance
;
400 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
401 if (hResource
== NULL
)
403 hResource
= LoadResource(hInstance
, hResource
);
404 if (hResource
== NULL
)
406 BitmapInfo
= LockResource(hResource
);
407 if (BitmapInfo
== NULL
)
412 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
413 OPEN_EXISTING
, 0, NULL
);
414 if (hFile
== INVALID_HANDLE_VALUE
)
417 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
419 if (hSection
== NULL
)
422 BitmapInfo
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
423 CloseHandle(hSection
);
424 if (BitmapInfo
== NULL
)
427 BitmapInfo
= (LPBITMAPINFO
)((ULONG_PTR
)BitmapInfo
+ sizeof(BITMAPFILEHEADER
));
430 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
432 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
433 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
434 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
438 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
439 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
440 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
441 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
443 Data
= (PVOID
)((ULONG_PTR
)BitmapInfo
+ HeaderSize
);
445 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
446 if (PrivateInfo
== NULL
)
448 if (fuLoad
& LR_LOADFROMFILE
)
449 UnmapViewOfFile(BitmapInfo
);
452 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
454 /* FIXME: Handle color conversion and transparency. */
456 hScreenDc
= CreateCompatibleDC(NULL
);
457 if (hScreenDc
== NULL
)
459 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
460 if (fuLoad
& LR_LOADFROMFILE
)
461 UnmapViewOfFile(BitmapInfo
);
465 if (fuLoad
& LR_CREATEDIBSECTION
)
469 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
471 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
472 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
477 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
478 Data
, PrivateInfo
, DIB_RGB_COLORS
);
481 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
483 if (fuLoad
& LR_LOADFROMFILE
)
484 UnmapViewOfFile(BitmapInfo
);
498 if (fuLoad
& LR_DEFAULTSIZE
)
500 if (uType
== IMAGE_ICON
)
503 cxDesired
= GetSystemMetrics(SM_CXICON
);
505 cyDesired
= GetSystemMetrics(SM_CYICON
);
507 else if (uType
== IMAGE_CURSOR
)
510 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
512 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
519 return LoadBitmapImage(hinst
, lpszName
, fuLoad
);
522 return LoadCursorIconImage(hinst
, lpszName
, cxDesired
, cyDesired
,
536 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
538 return LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
546 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
548 return LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
570 DPRINT("WARNING: Incomplete implementation of CopyImage!\n");
572 * FIXME: Support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
573 * LR_COPYRETURNORG, LR_CREATEDIBSECTION and LR_MONOCHROME.
575 if (!GetObjectW(hnd
, sizeof(bm
), &bm
))
578 if ((res
= CreateBitmapIndirect(&bm
)))
580 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
586 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
587 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
588 HeapFree(GetProcessHeap(), 0, buf
);
595 static BOOL IconMsgDisplayed
= FALSE
;
596 /* FIXME: support loading the image as shared from an instance */
597 if (!IconMsgDisplayed
)
599 DPRINT("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
600 IconMsgDisplayed
= TRUE
;
602 return CopyIcon(hnd
);
607 static BOOL IconMsgDisplayed
= FALSE
;
608 /* FIXME: support loading the image as shared from an instance */
609 if (!IconMsgDisplayed
)
611 DPRINT("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
612 IconMsgDisplayed
= TRUE
;
614 return CopyCursor(hnd
);