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
,
88 CURSORICONDIR
*IconDIR
;
95 CURSORICONDIRENTRY
* dirEntry
;
96 ICONIMAGE
* SafeIconImage
;
97 GRPCURSORICONDIR
* IconResDir
;
100 BOOL Icon
= (uType
== IMAGE_ICON
);
102 if (!(fuLoad
& LR_LOADFROMFILE
))
105 hinst
= User32Instance
;
107 hResource
= hfRes
= FindResourceW(hinst
, lpszName
,
108 Icon
? RT_GROUP_ICON
: RT_GROUP_CURSOR
);
109 if (hResource
== NULL
)
112 if (fuLoad
& LR_SHARED
)
114 hIcon
= NtUserFindExistingCursorIcon(hinst
, (HRSRC
)hfRes
, width
, height
);
119 hResource
= LoadResource(hinst
, hResource
);
120 if (hResource
== NULL
)
123 IconResDir
= LockResource(hResource
);
124 if (IconResDir
== NULL
)
128 * Find the best fitting in the IconResDir for this resolution
131 id
= LookupIconIdFromDirectoryEx((PBYTE
)IconResDir
, Icon
, width
, height
,
132 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
134 h2Resource
= FindResourceW(hinst
, MAKEINTRESOURCEW(id
),
135 Icon
? MAKEINTRESOURCEW(RT_ICON
) :
136 MAKEINTRESOURCEW(RT_CURSOR
));
137 if (h2Resource
== NULL
)
140 hResource
= LoadResource(hinst
, h2Resource
);
141 if (hResource
== NULL
)
144 ResIcon
= LockResource(hResource
);
148 hIcon
= CreateIconFromResourceEx((PBYTE
)ResIcon
,
149 SizeofResource(hinst
, h2Resource
),
150 Icon
, 0x00030000, width
, height
,
151 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
152 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
154 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
162 * FIXME: This code is incorrect and is likely to crash in many cases.
163 * In the file the cursor/icon directory records are stored like
164 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
165 * this is solved by creating a fake cursor/icon directory in memory
166 * and passing that to CURSORICON_FindBestIcon.
169 if (fuLoad
& LR_SHARED
)
171 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
174 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
175 OPEN_EXISTING
, 0, NULL
);
176 if (hFile
== INVALID_HANDLE_VALUE
)
179 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
181 if (hSection
== NULL
)
184 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
185 CloseHandle(hSection
);
189 if (0 != IconDIR
->idReserved
||
190 (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
192 UnmapViewOfFile(IconDIR
);
196 /* Get a handle to the screen dc, the icon we create is going to be
197 * compatable with this. */
198 hScreenDc
= CreateDCW(NULL
, NULL
, NULL
, NULL
);
199 if (hScreenDc
== NULL
)
201 UnmapViewOfFile(IconDIR
);
202 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
206 if (fuLoad
& LR_MONOCHROME
)
212 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
215 * Remove this after proper support for alpha icons will be finished.
221 /* Pick the best size. */
222 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, width
, height
, ColorBits
);
226 UnmapViewOfFile(IconDIR
);
230 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
231 if (SafeIconImage
== NULL
)
234 UnmapViewOfFile(IconDIR
);
238 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
239 UnmapViewOfFile(IconDIR
);
241 /* At this point we have a copy of the icon image to play with. */
243 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
245 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
247 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
248 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
249 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
253 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
254 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
255 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
256 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
259 /* Make data point to the start of the XOR image data. */
260 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
262 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
263 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
271 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
276 LPBITMAPINFO BitmapInfo
;
277 LPBITMAPINFO PrivateInfo
;
284 if (!(fuLoad
& LR_LOADFROMFILE
))
286 if (hInstance
== NULL
)
287 hInstance
= User32Instance
;
289 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
290 if (hResource
== NULL
)
292 hResource
= LoadResource(hInstance
, hResource
);
293 if (hResource
== NULL
)
295 BitmapInfo
= LockResource(hResource
);
296 if (BitmapInfo
== NULL
)
301 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
302 OPEN_EXISTING
, 0, NULL
);
303 if (hFile
== INVALID_HANDLE_VALUE
)
306 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
308 if (hSection
== NULL
)
311 BitmapInfo
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
312 CloseHandle(hSection
);
313 if (BitmapInfo
== NULL
)
316 BitmapInfo
= (LPBITMAPINFO
)((ULONG_PTR
)BitmapInfo
+ sizeof(BITMAPFILEHEADER
));
319 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
321 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
322 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
323 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
327 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
328 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
329 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
330 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
332 Data
= (PVOID
)((ULONG_PTR
)BitmapInfo
+ HeaderSize
);
334 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
335 if (PrivateInfo
== NULL
)
337 if (fuLoad
& LR_LOADFROMFILE
)
338 UnmapViewOfFile(BitmapInfo
);
341 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
343 /* FIXME: Handle color conversion and transparency. */
345 hScreenDc
= CreateCompatibleDC(NULL
);
346 if (hScreenDc
== NULL
)
348 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
349 if (fuLoad
& LR_LOADFROMFILE
)
350 UnmapViewOfFile(BitmapInfo
);
354 if (fuLoad
& LR_CREATEDIBSECTION
)
358 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
360 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
361 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
366 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
367 Data
, PrivateInfo
, DIB_RGB_COLORS
);
370 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
372 if (fuLoad
& LR_LOADFROMFILE
)
373 UnmapViewOfFile(BitmapInfo
);
387 if (fuLoad
& LR_DEFAULTSIZE
)
389 if (uType
== IMAGE_ICON
)
392 cxDesired
= GetSystemMetrics(SM_CXICON
);
394 cyDesired
= GetSystemMetrics(SM_CYICON
);
396 else if (uType
== IMAGE_CURSOR
)
399 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
401 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
408 return LoadBitmapImage(hinst
, lpszName
, fuLoad
);
411 return LoadCursorIconImage(hinst
, lpszName
, cxDesired
, cyDesired
,
425 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
427 return LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
435 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
437 return LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
459 DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
461 * FIXME: Support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
462 * LR_COPYRETURNORG, LR_CREATEDIBSECTION and LR_MONOCHROME.
464 if (!GetObjectW(hnd
, sizeof(bm
), &bm
))
467 if ((res
= CreateBitmapIndirect(&bm
)))
469 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
475 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
476 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
477 HeapFree(GetProcessHeap(), 0, buf
);
484 static BOOL IconMsgDisplayed
= FALSE
;
485 /* FIXME: support loading the image as shared from an instance */
486 if (!IconMsgDisplayed
)
488 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
489 IconMsgDisplayed
= TRUE
;
491 return CopyIcon(hnd
);
496 static BOOL IconMsgDisplayed
= FALSE
;
497 /* FIXME: support loading the image as shared from an instance */
498 if (!IconMsgDisplayed
)
500 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
501 IconMsgDisplayed
= TRUE
;
503 return CopyCursor(hnd
);