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
));
138 hResource
= LoadResource(hinst
, h2Resource
);
139 if (hResource
== NULL
)
142 ResIcon
= LockResource(hResource
);
146 hIcon
= CreateIconFromResourceEx((PBYTE
)ResIcon
,
147 SizeofResource(hinst
, h2Resource
),
148 Icon
, 0x00030000, width
, height
,
149 fuLoad
& (LR_DEFAULTCOLOR
| LR_MONOCHROME
));
150 if (hIcon
&& 0 != (fuLoad
& LR_SHARED
))
152 NtUserSetCursorIconData((HICON
)hIcon
, NULL
, NULL
, hinst
, (HRSRC
)hfRes
,
160 * FIXME: This code is incorrect and is likely to crash in many cases.
161 * In the file the cursor/icon directory records are stored like
162 * CURSORICONFILEDIR, but we treat them like CURSORICONDIR. In Wine
163 * this is solved by creating a fake cursor/icon directory in memory
164 * and passing that to CURSORICON_FindBestIcon.
167 if (fuLoad
& LR_SHARED
)
169 DbgPrint("FIXME: need LR_SHARED support for loading icon images from files\n");
172 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
173 OPEN_EXISTING
, 0, NULL
);
174 if (hFile
== INVALID_HANDLE_VALUE
)
177 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
179 if (hSection
== NULL
)
182 IconDIR
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
183 CloseHandle(hSection
);
187 if (0 != IconDIR
->idReserved
||
188 (IMAGE_ICON
!= IconDIR
->idType
&& IMAGE_CURSOR
!= IconDIR
->idType
))
190 UnmapViewOfFile(IconDIR
);
194 /* Get a handle to the screen dc, the icon we create is going to be
195 * compatable with this. */
196 hScreenDc
= CreateDCW(NULL
, NULL
, NULL
, NULL
);
197 if (hScreenDc
== NULL
)
199 UnmapViewOfFile(IconDIR
);
200 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
204 if (fuLoad
& LR_MONOCHROME
)
210 ColorBits
= GetDeviceCaps(hScreenDc
, BITSPIXEL
);
213 * Remove this after proper support for alpha icons will be finished.
219 /* Pick the best size. */
220 dirEntry
= (CURSORICONDIRENTRY
*)CURSORICON_FindBestIcon(IconDIR
, width
, height
, ColorBits
);
224 UnmapViewOfFile(IconDIR
);
228 SafeIconImage
= RtlAllocateHeap(GetProcessHeap(), 0, dirEntry
->dwBytesInRes
);
229 if (SafeIconImage
== NULL
)
232 UnmapViewOfFile(IconDIR
);
236 memcpy(SafeIconImage
, ((PBYTE
)IconDIR
) + dirEntry
->dwImageOffset
, dirEntry
->dwBytesInRes
);
237 UnmapViewOfFile(IconDIR
);
239 /* At this point we have a copy of the icon image to play with. */
241 SafeIconImage
->icHeader
.biHeight
= SafeIconImage
->icHeader
.biHeight
/2;
243 if (SafeIconImage
->icHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
245 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)SafeIconImage
;
246 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
247 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
251 ColorCount
= SafeIconImage
->icHeader
.biClrUsed
;
252 if (ColorCount
== 0 && SafeIconImage
->icHeader
.biBitCount
<= 8)
253 ColorCount
= 1 << SafeIconImage
->icHeader
.biBitCount
;
254 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
257 /* Make data point to the start of the XOR image data. */
258 Data
= (PBYTE
)SafeIconImage
+ HeaderSize
;
260 hIcon
= ICON_CreateIconFromData(hScreenDc
, Data
, SafeIconImage
, width
, height
, width
/2, height
/2);
261 RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage
);
269 LoadBitmapImage(HINSTANCE hInstance
, LPCWSTR lpszName
, UINT fuLoad
)
274 LPBITMAPINFO BitmapInfo
;
275 LPBITMAPINFO PrivateInfo
;
282 if (!(fuLoad
& LR_LOADFROMFILE
))
284 if (hInstance
== NULL
)
285 hInstance
= User32Instance
;
287 hResource
= FindResourceW(hInstance
, lpszName
, RT_BITMAP
);
288 if (hResource
== NULL
)
290 hResource
= LoadResource(hInstance
, hResource
);
291 if (hResource
== NULL
)
293 BitmapInfo
= LockResource(hResource
);
294 if (BitmapInfo
== NULL
)
299 hFile
= CreateFileW(lpszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
300 OPEN_EXISTING
, 0, NULL
);
301 if (hFile
== INVALID_HANDLE_VALUE
)
304 hSection
= CreateFileMappingW(hFile
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
306 if (hSection
== NULL
)
309 BitmapInfo
= MapViewOfFile(hSection
, FILE_MAP_READ
, 0, 0, 0);
310 CloseHandle(hSection
);
311 if (BitmapInfo
== NULL
)
314 BitmapInfo
= (LPBITMAPINFO
)((ULONG_PTR
)BitmapInfo
+ sizeof(BITMAPFILEHEADER
));
317 if (BitmapInfo
->bmiHeader
.biSize
== sizeof(BITMAPCOREHEADER
))
319 BITMAPCOREHEADER
* Core
= (BITMAPCOREHEADER
*)BitmapInfo
;
320 ColorCount
= (Core
->bcBitCount
<= 8) ? (1 << Core
->bcBitCount
) : 0;
321 HeaderSize
= sizeof(BITMAPCOREHEADER
) + ColorCount
* sizeof(RGBTRIPLE
);
325 ColorCount
= BitmapInfo
->bmiHeader
.biClrUsed
;
326 if (ColorCount
== 0 && BitmapInfo
->bmiHeader
.biBitCount
<= 8)
327 ColorCount
= 1 << BitmapInfo
->bmiHeader
.biBitCount
;
328 HeaderSize
= sizeof(BITMAPINFOHEADER
) + ColorCount
* sizeof(RGBQUAD
);
330 Data
= (PVOID
)((ULONG_PTR
)BitmapInfo
+ HeaderSize
);
332 PrivateInfo
= RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize
);
333 if (PrivateInfo
== NULL
)
335 if (fuLoad
& LR_LOADFROMFILE
)
336 UnmapViewOfFile(BitmapInfo
);
339 memcpy(PrivateInfo
, BitmapInfo
, HeaderSize
);
341 /* FIXME: Handle color conversion and transparency. */
343 hScreenDc
= CreateCompatibleDC(NULL
);
344 if (hScreenDc
== NULL
)
346 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
347 if (fuLoad
& LR_LOADFROMFILE
)
348 UnmapViewOfFile(BitmapInfo
);
352 if (fuLoad
& LR_CREATEDIBSECTION
)
356 hBitmap
= CreateDIBSection(hScreenDc
, PrivateInfo
, DIB_RGB_COLORS
, NULL
,
358 GetObjectA(hBitmap
, sizeof(DIBSECTION
), &Dib
);
359 SetDIBits(hScreenDc
, hBitmap
, 0, Dib
.dsBm
.bmHeight
, Data
, BitmapInfo
,
364 hBitmap
= CreateDIBitmap(hScreenDc
, &PrivateInfo
->bmiHeader
, CBM_INIT
,
365 Data
, PrivateInfo
, DIB_RGB_COLORS
);
368 RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo
);
370 if (fuLoad
& LR_LOADFROMFILE
)
371 UnmapViewOfFile(BitmapInfo
);
385 if (fuLoad
& LR_DEFAULTSIZE
)
387 if (uType
== IMAGE_ICON
)
390 cxDesired
= GetSystemMetrics(SM_CXICON
);
392 cyDesired
= GetSystemMetrics(SM_CYICON
);
394 else if (uType
== IMAGE_CURSOR
)
397 cxDesired
= GetSystemMetrics(SM_CXCURSOR
);
399 cyDesired
= GetSystemMetrics(SM_CYCURSOR
);
406 return LoadBitmapImage(hinst
, lpszName
, fuLoad
);
409 return LoadCursorIconImage(hinst
, lpszName
, cxDesired
, cyDesired
,
423 LoadBitmapA(HINSTANCE hInstance
, LPCSTR lpBitmapName
)
425 return LoadImageA(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
433 LoadBitmapW(HINSTANCE hInstance
, LPCWSTR lpBitmapName
)
435 return LoadImageW(hInstance
, lpBitmapName
, IMAGE_BITMAP
, 0, 0, 0);
457 DbgPrint("WARNING: Incomplete implementation of CopyImage!\n");
459 * FIXME: Support flags LR_COPYDELETEORG, LR_COPYFROMRESOURCE,
460 * LR_COPYRETURNORG, LR_CREATEDIBSECTION and LR_MONOCHROME.
462 if (!GetObjectW(hnd
, sizeof(bm
), &bm
))
465 if ((res
= CreateBitmapIndirect(&bm
)))
467 char *buf
= HeapAlloc(GetProcessHeap(), 0, bm
.bmWidthBytes
* bm
.bmHeight
);
473 GetBitmapBits(hnd
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
474 SetBitmapBits(res
, bm
.bmWidthBytes
* bm
.bmHeight
, buf
);
475 HeapFree(GetProcessHeap(), 0, buf
);
482 static BOOL IconMsgDisplayed
= FALSE
;
483 /* FIXME: support loading the image as shared from an instance */
484 if (!IconMsgDisplayed
)
486 DbgPrint("FIXME: CopyImage doesn't support IMAGE_ICON correctly!\n");
487 IconMsgDisplayed
= TRUE
;
489 return CopyIcon(hnd
);
494 static BOOL IconMsgDisplayed
= FALSE
;
495 /* FIXME: support loading the image as shared from an instance */
496 if (!IconMsgDisplayed
)
498 DbgPrint("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
499 IconMsgDisplayed
= TRUE
;
501 return CopyCursor(hnd
);