mirror of
https://github.com/reactos/reactos.git
synced 2025-05-14 23:03:53 +00:00
[USER32]
- Rewrite support of cursors, icons and bitmaps in user32.dll, based from WINE implementation. One file to rule them all. Now user32::cursoricon winetests don't crash anymore. svn path=/trunk/; revision=48008
This commit is contained in:
parent
74cae57136
commit
0b5d0c20e8
6 changed files with 2089 additions and 1925 deletions
|
@ -48,18 +48,16 @@
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="windows">
|
<directory name="windows">
|
||||||
<file>accel.c</file>
|
<file>accel.c</file>
|
||||||
<file>bitmap.c</file>
|
|
||||||
<file>caret.c</file>
|
<file>caret.c</file>
|
||||||
<file>class.c</file>
|
<file>class.c</file>
|
||||||
<file>clipboard.c</file>
|
<file>clipboard.c</file>
|
||||||
<file>cursor.c</file>
|
<file>cursoricon.c</file>
|
||||||
<file>dc.c</file>
|
<file>dc.c</file>
|
||||||
<file>defwnd.c</file>
|
<file>defwnd.c</file>
|
||||||
<file>dialog.c</file>
|
<file>dialog.c</file>
|
||||||
<file>draw.c</file>
|
<file>draw.c</file>
|
||||||
<file>font.c</file>
|
<file>font.c</file>
|
||||||
<file>hook.c</file>
|
<file>hook.c</file>
|
||||||
<file>icon.c</file>
|
|
||||||
<file>input.c</file>
|
<file>input.c</file>
|
||||||
<file>mdi.c</file>
|
<file>mdi.c</file>
|
||||||
<file>menu.c</file>
|
<file>menu.c</file>
|
||||||
|
|
|
@ -1,921 +0,0 @@
|
||||||
/*
|
|
||||||
* ReactOS kernel
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
/* $Id$
|
|
||||||
*
|
|
||||||
* PROJECT: ReactOS user32.dll
|
|
||||||
* FILE: lib/user32/windows/input.c
|
|
||||||
* PURPOSE: Input
|
|
||||||
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 09-05-2001 CSH Created
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
|
||||||
|
|
||||||
#include <user32.h>
|
|
||||||
|
|
||||||
#include <wine/debug.h>
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
||||||
|
|
||||||
#include "pshpack1.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
BYTE bWidth;
|
|
||||||
BYTE bHeight;
|
|
||||||
BYTE bColorCount;
|
|
||||||
BYTE bReserved;
|
|
||||||
WORD xHotspot;
|
|
||||||
WORD yHotspot;
|
|
||||||
DWORD dwDIBSize;
|
|
||||||
DWORD dwDIBOffset;
|
|
||||||
} CURSORICONFILEDIRENTRY;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
WORD idReserved;
|
|
||||||
WORD idType;
|
|
||||||
WORD idCount;
|
|
||||||
CURSORICONFILEDIRENTRY idEntries[1];
|
|
||||||
} CURSORICONFILEDIR;
|
|
||||||
|
|
||||||
#include "poppack.h"
|
|
||||||
|
|
||||||
/* forward declarations... actually in user32\windows\icon.c but useful here */
|
|
||||||
HICON CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon);
|
|
||||||
CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
|
|
||||||
CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HANDLE WINAPI
|
|
||||||
LoadImageA(HINSTANCE hinst,
|
|
||||||
LPCSTR lpszName,
|
|
||||||
UINT uType,
|
|
||||||
int cxDesired,
|
|
||||||
int cyDesired,
|
|
||||||
UINT fuLoad)
|
|
||||||
{
|
|
||||||
LPWSTR lpszWName;
|
|
||||||
HANDLE Handle;
|
|
||||||
UNICODE_STRING NameString;
|
|
||||||
|
|
||||||
if (HIWORD(lpszName))
|
|
||||||
{
|
|
||||||
RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
|
|
||||||
lpszWName = NameString.Buffer;
|
|
||||||
Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
|
|
||||||
cyDesired, fuLoad);
|
|
||||||
RtlFreeUnicodeString(&NameString);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,
|
|
||||||
cyDesired, fuLoad);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following macro functions account for the irregularities of
|
|
||||||
* accessing cursor and icon resources in files and resource entries.
|
|
||||||
*/
|
|
||||||
typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n,
|
|
||||||
int *width, int *height, int *bits );
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* CURSORICON_FindBestCursor2
|
|
||||||
*
|
|
||||||
* Find the cursor closest to the requested size.
|
|
||||||
* FIXME: parameter 'color' ignored and entries with more than 1 bpp
|
|
||||||
* ignored too
|
|
||||||
*/
|
|
||||||
static int CURSORICON_FindBestCursor2( LPVOID dir, fnGetCIEntry get_entry,
|
|
||||||
int width, int height, int color )
|
|
||||||
{
|
|
||||||
int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1;
|
|
||||||
|
|
||||||
/* Double height to account for AND and XOR masks */
|
|
||||||
|
|
||||||
height *= 2;
|
|
||||||
|
|
||||||
/* First find the largest one smaller than or equal to the requested size*/
|
|
||||||
|
|
||||||
maxwidth = maxheight = 0;
|
|
||||||
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
|
|
||||||
{
|
|
||||||
if ((cx <= width) && (cy <= height) &&
|
|
||||||
(cx > maxwidth) && (cy > maxheight) &&
|
|
||||||
(bits == 1))
|
|
||||||
{
|
|
||||||
bestEntry = i;
|
|
||||||
maxwidth = cx;
|
|
||||||
maxheight = cy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bestEntry != -1) return bestEntry;
|
|
||||||
|
|
||||||
/* Now find the smallest one larger than the requested size */
|
|
||||||
|
|
||||||
maxwidth = maxheight = 255;
|
|
||||||
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
|
|
||||||
{
|
|
||||||
if (((cx < maxwidth) && (cy < maxheight) && (bits == 1)) ||
|
|
||||||
(bestEntry==-1))
|
|
||||||
{
|
|
||||||
bestEntry = i;
|
|
||||||
maxwidth = cx;
|
|
||||||
maxheight = cy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bestEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n,
|
|
||||||
int *width, int *height, int *bits )
|
|
||||||
{
|
|
||||||
CURSORICONFILEDIR *filedir = dir;
|
|
||||||
CURSORICONFILEDIRENTRY *entry;
|
|
||||||
|
|
||||||
if ( filedir->idCount <= n )
|
|
||||||
return FALSE;
|
|
||||||
entry = &filedir->idEntries[n];
|
|
||||||
*width = entry->bWidth;
|
|
||||||
*height = entry->bHeight;
|
|
||||||
*bits = entry->bColorCount;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir,
|
|
||||||
int width, int height, int color )
|
|
||||||
{
|
|
||||||
int n = CURSORICON_FindBestCursor2( dir, CURSORICON_GetFileEntry,
|
|
||||||
width, height, color );
|
|
||||||
if ( n < 0 )
|
|
||||||
return NULL;
|
|
||||||
return &dir->idEntries[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
static HANDLE
|
|
||||||
LoadCursorIconImage(
|
|
||||||
HINSTANCE hinst,
|
|
||||||
LPCWSTR lpszName,
|
|
||||||
INT width,
|
|
||||||
INT height,
|
|
||||||
UINT fuLoad,
|
|
||||||
ULONG uType)
|
|
||||||
{
|
|
||||||
HRSRC hResInfo;
|
|
||||||
HANDLE hResource;
|
|
||||||
HANDLE hFile;
|
|
||||||
HANDLE hSection;
|
|
||||||
CURSORICONFILEDIR *IconDIR;
|
|
||||||
HDC hScreenDc;
|
|
||||||
HICON hIcon;
|
|
||||||
ULONG HeaderSize;
|
|
||||||
ULONG ColorCount;
|
|
||||||
ULONG ColorBits;
|
|
||||||
PVOID Data;
|
|
||||||
CURSORICONFILEDIRENTRY* dirEntry;
|
|
||||||
ICONIMAGE* SafeIconImage = NULL;
|
|
||||||
GRPCURSORICONDIR* IconResDir;
|
|
||||||
INT id;
|
|
||||||
ICONIMAGE *ResIcon;
|
|
||||||
BOOL Icon = (uType == IMAGE_ICON);
|
|
||||||
DWORD filesize = 0;
|
|
||||||
|
|
||||||
if (!(fuLoad & LR_LOADFROMFILE))
|
|
||||||
{
|
|
||||||
if (hinst == NULL)
|
|
||||||
hinst = User32Instance;
|
|
||||||
|
|
||||||
hResInfo = FindResourceW(hinst, lpszName,
|
|
||||||
Icon ? RT_GROUP_ICON : RT_GROUP_CURSOR);
|
|
||||||
if (hResInfo == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
hResource = LoadResource(hinst, hResInfo);
|
|
||||||
if (hResource == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
IconResDir = LockResource(hResource);
|
|
||||||
if (IconResDir == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the best fitting in the IconResDir for this resolution */
|
|
||||||
id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, Icon, width, height,
|
|
||||||
fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
|
|
||||||
|
|
||||||
hResInfo = FindResourceW(hinst, MAKEINTRESOURCEW(id),
|
|
||||||
Icon ? (LPCWSTR) RT_ICON :
|
|
||||||
(LPCWSTR) RT_CURSOR);
|
|
||||||
if (hResInfo == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now we have found the icon we want to load.
|
|
||||||
* Let's see if we already loaded it */
|
|
||||||
if (fuLoad & LR_SHARED)
|
|
||||||
{
|
|
||||||
hIcon = NtUserFindExistingCursorIcon(hinst, hResInfo, 0, 0);
|
|
||||||
if (hIcon)
|
|
||||||
{
|
|
||||||
return hIcon;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
TRACE("Didn't find the shared icon!!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
hResource = LoadResource(hinst, hResInfo);
|
|
||||||
if (hResource == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResIcon = LockResource(hResource);
|
|
||||||
if (ResIcon == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hIcon = CreateIconFromResourceEx((PBYTE)ResIcon,
|
|
||||||
SizeofResource(hinst, hResInfo),
|
|
||||||
Icon, 0x00030000, width, height,
|
|
||||||
(fuLoad & (LR_DEFAULTSIZE | LR_SHARED)) | LR_DEFAULTCOLOR);
|
|
||||||
|
|
||||||
if (hIcon && 0 != (fuLoad & LR_SHARED))
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, hResInfo,
|
|
||||||
(HRSRC)NULL);
|
|
||||||
#else
|
|
||||||
ICONINFO iconInfo;
|
|
||||||
|
|
||||||
if(NtUserGetIconInfo(ResIcon, &iconInfo, NULL, NULL, NULL, FALSE))
|
|
||||||
NtUserSetCursorIconData((HICON)hIcon, hinst, NULL, &iconInfo);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return hIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fuLoad & LR_SHARED)
|
|
||||||
{
|
|
||||||
FIXME("Need LR_SHARED support for loading icon images from files\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
||||||
OPEN_EXISTING, 0, NULL);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
||||||
filesize = GetFileSize( hFile, NULL );
|
|
||||||
CloseHandle(hFile);
|
|
||||||
if (hSection == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
IconDIR = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
|
|
||||||
CloseHandle(hSection);
|
|
||||||
if (IconDIR == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (0 != IconDIR->idReserved ||
|
|
||||||
(IMAGE_ICON != IconDIR->idType && IMAGE_CURSOR != IconDIR->idType))
|
|
||||||
{
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a handle to the screen dc, the icon we create is going to be
|
|
||||||
* compatable with this. */
|
|
||||||
hScreenDc = CreateDCW(NULL, NULL, NULL, NULL);
|
|
||||||
if (hScreenDc == NULL)
|
|
||||||
{
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fuLoad & LR_MONOCHROME)
|
|
||||||
{
|
|
||||||
ColorBits = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ColorBits = GetDeviceCaps(hScreenDc, BITSPIXEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pick the best size. */
|
|
||||||
dirEntry = CURSORICON_FindBestCursorFile( IconDIR, width, height, ColorBits );
|
|
||||||
if (!dirEntry)
|
|
||||||
{
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( dirEntry->dwDIBOffset > filesize )
|
|
||||||
{
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( dirEntry->dwDIBOffset + dirEntry->dwDIBSize > filesize ){
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwDIBSize);
|
|
||||||
if (SafeIconImage == NULL)
|
|
||||||
{
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwDIBOffset, dirEntry->dwDIBSize);
|
|
||||||
UnmapViewOfFile(IconDIR);
|
|
||||||
|
|
||||||
/* At this point we have a copy of the icon image to play with. */
|
|
||||||
|
|
||||||
SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
|
|
||||||
|
|
||||||
if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
|
|
||||||
{
|
|
||||||
BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
|
|
||||||
ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
|
|
||||||
HeaderSize = sizeof(BITMAPCOREHEADER) + ColorCount * sizeof(RGBTRIPLE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ColorCount = SafeIconImage->icHeader.biClrUsed;
|
|
||||||
if (ColorCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
|
|
||||||
ColorCount = 1 << SafeIconImage->icHeader.biBitCount;
|
|
||||||
HeaderSize = sizeof(BITMAPINFOHEADER) + ColorCount * sizeof(RGBQUAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make data point to the start of the XOR image data. */
|
|
||||||
Data = (PBYTE)SafeIconImage + HeaderSize;
|
|
||||||
|
|
||||||
hIcon = CreateCursorIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2, Icon);
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
|
|
||||||
return hIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static HANDLE
|
|
||||||
LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
|
|
||||||
{
|
|
||||||
HANDLE hResource;
|
|
||||||
HANDLE hFile;
|
|
||||||
HANDLE hSection;
|
|
||||||
LPBITMAPINFO BitmapInfo;
|
|
||||||
LPBITMAPINFO PrivateInfo;
|
|
||||||
HDC hScreenDc;
|
|
||||||
HANDLE hBitmap;
|
|
||||||
ULONG HeaderSize;
|
|
||||||
ULONG ColorCount;
|
|
||||||
PVOID Data;
|
|
||||||
BOOL Hit = FALSE;
|
|
||||||
|
|
||||||
if (!(fuLoad & LR_LOADFROMFILE))
|
|
||||||
{
|
|
||||||
if (hInstance == NULL)
|
|
||||||
hInstance = User32Instance;
|
|
||||||
|
|
||||||
hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
|
|
||||||
if (hResource == NULL)
|
|
||||||
return NULL;
|
|
||||||
hResource = LoadResource(hInstance, hResource);
|
|
||||||
if (hResource == NULL)
|
|
||||||
return NULL;
|
|
||||||
BitmapInfo = LockResource(hResource);
|
|
||||||
if (BitmapInfo == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hFile = CreateFileW(lpszName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
||||||
OPEN_EXISTING, 0, NULL);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
hSection = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
if (hSection == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
BitmapInfo = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
|
|
||||||
CloseHandle(hSection);
|
|
||||||
if (BitmapInfo == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
BitmapInfo = (LPBITMAPINFO)((ULONG_PTR)BitmapInfo + sizeof(BITMAPFILEHEADER));
|
|
||||||
}
|
|
||||||
|
|
||||||
HeaderSize = BitmapInfo->bmiHeader.biSize;
|
|
||||||
if (HeaderSize == sizeof(BITMAPCOREHEADER))
|
|
||||||
{
|
|
||||||
BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
|
|
||||||
ColorCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
|
|
||||||
HeaderSize += ColorCount * sizeof(RGBTRIPLE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (BitmapInfo->bmiHeader.biCompression == BI_BITFIELDS)
|
|
||||||
{
|
|
||||||
HeaderSize += 3 * sizeof(RGBQUAD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ColorCount = BitmapInfo->bmiHeader.biClrUsed;
|
|
||||||
if (ColorCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
|
|
||||||
ColorCount = 1 << BitmapInfo->bmiHeader.biBitCount;
|
|
||||||
HeaderSize += ColorCount * sizeof(RGBQUAD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Data = (PVOID)((ULONG_PTR)BitmapInfo + HeaderSize);
|
|
||||||
|
|
||||||
PrivateInfo = RtlAllocateHeap(GetProcessHeap(), 0, HeaderSize);
|
|
||||||
if (PrivateInfo == NULL)
|
|
||||||
{
|
|
||||||
if (fuLoad & LR_LOADFROMFILE)
|
|
||||||
UnmapViewOfFile(BitmapInfo);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
memcpy(PrivateInfo, BitmapInfo, HeaderSize);
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
Hit = TRUE;
|
|
||||||
}
|
|
||||||
_SEH2_END;
|
|
||||||
|
|
||||||
if (Hit)
|
|
||||||
{
|
|
||||||
ERR("We have a thread overrun, these are already freed! pi -> %d, bi -> %d\n", PrivateInfo, BitmapInfo);
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
|
|
||||||
if (fuLoad & LR_LOADFROMFILE)
|
|
||||||
UnmapViewOfFile(BitmapInfo);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Handle color conversion and transparency. */
|
|
||||||
|
|
||||||
hScreenDc = CreateCompatibleDC(NULL);
|
|
||||||
if (hScreenDc == NULL)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
|
|
||||||
if (fuLoad & LR_LOADFROMFILE)
|
|
||||||
UnmapViewOfFile(BitmapInfo);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fuLoad & LR_CREATEDIBSECTION)
|
|
||||||
{
|
|
||||||
DIBSECTION Dib;
|
|
||||||
|
|
||||||
hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL,
|
|
||||||
0, 0);
|
|
||||||
GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
|
|
||||||
SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
|
|
||||||
DIB_RGB_COLORS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,
|
|
||||||
Data, PrivateInfo, DIB_RGB_COLORS);
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, PrivateInfo);
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
if (fuLoad & LR_LOADFROMFILE)
|
|
||||||
UnmapViewOfFile(BitmapInfo);
|
|
||||||
|
|
||||||
return hBitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE WINAPI
|
|
||||||
LoadImageW(
|
|
||||||
IN HINSTANCE hinst,
|
|
||||||
IN LPCWSTR lpszName,
|
|
||||||
IN UINT uType,
|
|
||||||
IN INT cxDesired,
|
|
||||||
IN INT cyDesired,
|
|
||||||
IN UINT fuLoad)
|
|
||||||
{
|
|
||||||
if (fuLoad & LR_DEFAULTSIZE)
|
|
||||||
{
|
|
||||||
if (uType == IMAGE_ICON)
|
|
||||||
{
|
|
||||||
if (cxDesired == 0)
|
|
||||||
cxDesired = GetSystemMetrics(SM_CXICON);
|
|
||||||
if (cyDesired == 0)
|
|
||||||
cyDesired = GetSystemMetrics(SM_CYICON);
|
|
||||||
}
|
|
||||||
else if (uType == IMAGE_CURSOR)
|
|
||||||
{
|
|
||||||
if (cxDesired == 0)
|
|
||||||
cxDesired = GetSystemMetrics(SM_CXCURSOR);
|
|
||||||
if (cyDesired == 0)
|
|
||||||
cyDesired = GetSystemMetrics(SM_CYCURSOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (uType)
|
|
||||||
{
|
|
||||||
case IMAGE_BITMAP:
|
|
||||||
return LoadBitmapImage(hinst, lpszName, fuLoad);
|
|
||||||
case IMAGE_CURSOR:
|
|
||||||
case IMAGE_ICON:
|
|
||||||
return LoadCursorIconImage(hinst, lpszName, cxDesired, cyDesired,
|
|
||||||
fuLoad, uType);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HBITMAP WINAPI
|
|
||||||
LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
|
|
||||||
{
|
|
||||||
return LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HBITMAP WINAPI
|
|
||||||
LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
|
|
||||||
{
|
|
||||||
return LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static HANDLE
|
|
||||||
CopyBmp(HANDLE hnd,
|
|
||||||
UINT type,
|
|
||||||
INT desiredx,
|
|
||||||
INT desiredy,
|
|
||||||
UINT flags)
|
|
||||||
{
|
|
||||||
HBITMAP res = NULL;
|
|
||||||
DIBSECTION ds;
|
|
||||||
int objSize;
|
|
||||||
BITMAPINFO * bi;
|
|
||||||
|
|
||||||
objSize = GetObjectW( hnd, sizeof(ds), &ds );
|
|
||||||
if (!objSize) return 0;
|
|
||||||
if ((desiredx < 0) || (desiredy < 0)) return 0;
|
|
||||||
|
|
||||||
if (flags & LR_COPYFROMRESOURCE)
|
|
||||||
{
|
|
||||||
FIXME("FIXME: The flag LR_COPYFROMRESOURCE is not implemented for bitmaps\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (desiredx == 0) desiredx = ds.dsBm.bmWidth;
|
|
||||||
if (desiredy == 0) desiredy = ds.dsBm.bmHeight;
|
|
||||||
|
|
||||||
/* Allocate memory for a BITMAPINFOHEADER structure and a
|
|
||||||
color table. The maximum number of colors in a color table
|
|
||||||
is 256 which corresponds to a bitmap with depth 8.
|
|
||||||
Bitmaps with higher depths don't have color tables. */
|
|
||||||
bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
|
||||||
if (!bi) return 0;
|
|
||||||
|
|
||||||
bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
|
|
||||||
bi->bmiHeader.biPlanes = ds.dsBm.bmPlanes;
|
|
||||||
bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
|
|
||||||
bi->bmiHeader.biCompression = BI_RGB;
|
|
||||||
|
|
||||||
if (flags & LR_CREATEDIBSECTION)
|
|
||||||
{
|
|
||||||
/* Create a DIB section. LR_MONOCHROME is ignored */
|
|
||||||
void * bits;
|
|
||||||
HDC dc = CreateCompatibleDC(NULL);
|
|
||||||
|
|
||||||
if (objSize == sizeof(DIBSECTION))
|
|
||||||
{
|
|
||||||
/* The source bitmap is a DIB.
|
|
||||||
Get its attributes to create an exact copy */
|
|
||||||
memcpy(bi, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the color table or the color masks */
|
|
||||||
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
|
|
||||||
|
|
||||||
bi->bmiHeader.biWidth = desiredx;
|
|
||||||
bi->bmiHeader.biHeight = desiredy;
|
|
||||||
bi->bmiHeader.biSizeImage = 0;
|
|
||||||
|
|
||||||
res = CreateDIBSection(dc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
|
|
||||||
DeleteDC(dc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Create a device-dependent bitmap */
|
|
||||||
|
|
||||||
BOOL monochrome = (flags & LR_MONOCHROME);
|
|
||||||
|
|
||||||
if (objSize == sizeof(DIBSECTION))
|
|
||||||
{
|
|
||||||
/* The source bitmap is a DIB section.
|
|
||||||
Get its attributes */
|
|
||||||
HDC dc = CreateCompatibleDC(NULL);
|
|
||||||
bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
|
|
||||||
bi->bmiHeader.biBitCount = ds.dsBm.bmBitsPixel;
|
|
||||||
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
|
|
||||||
DeleteDC(dc);
|
|
||||||
|
|
||||||
if (!monochrome && ds.dsBm.bmBitsPixel == 1)
|
|
||||||
{
|
|
||||||
/* Look if the colors of the DIB are black and white */
|
|
||||||
|
|
||||||
monochrome =
|
|
||||||
(bi->bmiColors[0].rgbRed == 0xff
|
|
||||||
&& bi->bmiColors[0].rgbGreen == 0xff
|
|
||||||
&& bi->bmiColors[0].rgbBlue == 0xff
|
|
||||||
&& bi->bmiColors[0].rgbReserved == 0
|
|
||||||
&& bi->bmiColors[1].rgbRed == 0
|
|
||||||
&& bi->bmiColors[1].rgbGreen == 0
|
|
||||||
&& bi->bmiColors[1].rgbBlue == 0
|
|
||||||
&& bi->bmiColors[1].rgbReserved == 0)
|
|
||||||
||
|
|
||||||
(bi->bmiColors[0].rgbRed == 0
|
|
||||||
&& bi->bmiColors[0].rgbGreen == 0
|
|
||||||
&& bi->bmiColors[0].rgbBlue == 0
|
|
||||||
&& bi->bmiColors[0].rgbReserved == 0
|
|
||||||
&& bi->bmiColors[1].rgbRed == 0xff
|
|
||||||
&& bi->bmiColors[1].rgbGreen == 0xff
|
|
||||||
&& bi->bmiColors[1].rgbBlue == 0xff
|
|
||||||
&& bi->bmiColors[1].rgbReserved == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!monochrome)
|
|
||||||
{
|
|
||||||
monochrome = ds.dsBm.bmBitsPixel == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monochrome)
|
|
||||||
{
|
|
||||||
res = CreateBitmap(desiredx, desiredy, 1, 1, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HDC screenDC = GetDC(NULL);
|
|
||||||
res = CreateCompatibleBitmap(screenDC, desiredx, desiredy);
|
|
||||||
ReleaseDC(NULL, screenDC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
/* Only copy the bitmap if it's a DIB section or if it's
|
|
||||||
compatible to the screen */
|
|
||||||
BOOL copyContents;
|
|
||||||
|
|
||||||
if (objSize == sizeof(DIBSECTION))
|
|
||||||
{
|
|
||||||
copyContents = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HDC screenDC = GetDC(NULL);
|
|
||||||
int screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
|
|
||||||
ReleaseDC(NULL, screenDC);
|
|
||||||
|
|
||||||
copyContents = (ds.dsBm.bmBitsPixel == 1 || ds.dsBm.bmBitsPixel == screen_depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copyContents)
|
|
||||||
{
|
|
||||||
/* The source bitmap may already be selected in a device context,
|
|
||||||
use GetDIBits/StretchDIBits and not StretchBlt */
|
|
||||||
|
|
||||||
HDC dc;
|
|
||||||
void * bits;
|
|
||||||
|
|
||||||
dc = CreateCompatibleDC(NULL);
|
|
||||||
|
|
||||||
bi->bmiHeader.biWidth = ds.dsBm.bmWidth;
|
|
||||||
bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
|
|
||||||
bi->bmiHeader.biSizeImage = 0;
|
|
||||||
bi->bmiHeader.biClrUsed = 0;
|
|
||||||
bi->bmiHeader.biClrImportant = 0;
|
|
||||||
|
|
||||||
/* Fill in biSizeImage */
|
|
||||||
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, NULL, bi, DIB_RGB_COLORS);
|
|
||||||
bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bi->bmiHeader.biSizeImage);
|
|
||||||
|
|
||||||
if (bits)
|
|
||||||
{
|
|
||||||
HBITMAP oldBmp;
|
|
||||||
|
|
||||||
/* Get the image bits of the source bitmap */
|
|
||||||
GetDIBits(dc, hnd, 0, ds.dsBm.bmHeight, bits, bi, DIB_RGB_COLORS);
|
|
||||||
|
|
||||||
/* Copy it to the destination bitmap */
|
|
||||||
oldBmp = SelectObject(dc, res);
|
|
||||||
StretchDIBits(dc, 0, 0, desiredx, desiredy,
|
|
||||||
0, 0, ds.dsBm.bmWidth, ds.dsBm.bmHeight,
|
|
||||||
bits, bi, DIB_RGB_COLORS, SRCCOPY);
|
|
||||||
SelectObject(dc, oldBmp);
|
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteDC(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & LR_COPYDELETEORG)
|
|
||||||
{
|
|
||||||
DeleteObject(hnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HeapFree(GetProcessHeap(), 0, bi);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
INT
|
|
||||||
GetIconCurBpp(PICONINFO pIconInfo)
|
|
||||||
{
|
|
||||||
PBITMAPINFO pbi;
|
|
||||||
|
|
||||||
pbi = (PBITMAPINFO)pIconInfo->hbmColor;
|
|
||||||
return pbi->bmiHeader.biBitCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static BOOL
|
|
||||||
SetCursorIconData(
|
|
||||||
HANDLE Handle,
|
|
||||||
HINSTANCE hMod,
|
|
||||||
LPWSTR lpResName,
|
|
||||||
PICONINFO pIconInfo)
|
|
||||||
{
|
|
||||||
|
|
||||||
UNICODE_STRING Res;
|
|
||||||
|
|
||||||
if (!Handle || !pIconInfo)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
RtlInitUnicodeString(&Res, lpResName);
|
|
||||||
|
|
||||||
return NtUserSetCursorIconData(Handle, hMod, &Res, pIconInfo);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* bare bones icon copy implementation */
|
|
||||||
static HANDLE
|
|
||||||
CopyIcoCur(HANDLE hIconCur,
|
|
||||||
UINT type,
|
|
||||||
INT desiredx,
|
|
||||||
INT desiredy,
|
|
||||||
UINT flags)
|
|
||||||
{
|
|
||||||
HANDLE hNewIcon = NULL;
|
|
||||||
ICONINFO origIconInfo, newIconInfo;
|
|
||||||
SIZE origSize;
|
|
||||||
DWORD origBpp;
|
|
||||||
|
|
||||||
if (!hIconCur)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (flags & LR_COPYFROMRESOURCE)
|
|
||||||
{
|
|
||||||
TRACE("FIXME: LR_COPYFROMRESOURCE is yet not implemented for icons\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NtUserGetIconSize(hIconCur, 0, &origSize.cx, &origSize.cy))
|
|
||||||
{
|
|
||||||
if (desiredx == 0) desiredx = origSize.cx;
|
|
||||||
if (desiredx == 0) desiredy = origSize.cy;
|
|
||||||
|
|
||||||
if (NtUserGetIconInfo(hIconCur, &origIconInfo, NULL, NULL, &origBpp, TRUE))
|
|
||||||
{
|
|
||||||
hNewIcon = (HANDLE)NtUserCallOneParam(0, ONEPARAM_ROUTINE_CREATECURICONHANDLE);
|
|
||||||
|
|
||||||
if (hNewIcon)
|
|
||||||
{
|
|
||||||
/* the bitmaps returned from the NtUserGetIconInfo are copies of the original,
|
|
||||||
* so we can use these directly to build up our icon/cursor copy */
|
|
||||||
RtlCopyMemory(&newIconInfo, &origIconInfo, sizeof(ICONINFO));
|
|
||||||
|
|
||||||
if (!SetCursorIconData(hNewIcon, NULL, NULL, &newIconInfo))
|
|
||||||
{
|
|
||||||
if (newIconInfo.fIcon)
|
|
||||||
DestroyIcon(hNewIcon);
|
|
||||||
else
|
|
||||||
DestroyCursor(hNewIcon);
|
|
||||||
|
|
||||||
hNewIcon = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteObject(origIconInfo.hbmMask);
|
|
||||||
DeleteObject(origIconInfo.hbmColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hNewIcon && (flags & LR_COPYDELETEORG))
|
|
||||||
{
|
|
||||||
DestroyCursor((HCURSOR)hIconCur);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hNewIcon;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
HANDLE WINAPI
|
|
||||||
CopyImage(
|
|
||||||
IN HANDLE hnd,
|
|
||||||
IN UINT type,
|
|
||||||
IN INT desiredx,
|
|
||||||
IN INT desiredy,
|
|
||||||
IN UINT flags)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* BUGS
|
|
||||||
* Only Windows NT 4.0 supports the LR_COPYRETURNORG flag for bitmaps,
|
|
||||||
* all other versions (95/2000/XP have been tested) ignore it.
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* If LR_CREATEDIBSECTION is absent, the copy will be monochrome for
|
|
||||||
* a monochrome source bitmap or if LR_MONOCHROME is present, otherwise
|
|
||||||
* the copy will have the same depth as the screen.
|
|
||||||
* The content of the image will only be copied if the bit depth of the
|
|
||||||
* original image is compatible with the bit depth of the screen, or
|
|
||||||
* if the source is a DIB section.
|
|
||||||
* The LR_MONOCHROME flag is ignored if LR_CREATEDIBSECTION is present.
|
|
||||||
*/
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case IMAGE_BITMAP:
|
|
||||||
return CopyBmp(hnd, type, desiredx, desiredy, flags);
|
|
||||||
|
|
||||||
case IMAGE_ICON:
|
|
||||||
//return CopyIcoCur(hnd, type, desiredx, desiredy, flags);
|
|
||||||
return CopyIcon(hnd);
|
|
||||||
|
|
||||||
case IMAGE_CURSOR:
|
|
||||||
{
|
|
||||||
static BOOL IconMsgDisplayed = FALSE;
|
|
||||||
/* FIXME: support loading the image as shared from an instance */
|
|
||||||
if (!IconMsgDisplayed)
|
|
||||||
{
|
|
||||||
FIXME("FIXME: CopyImage doesn't support IMAGE_CURSOR correctly!\n");
|
|
||||||
IconMsgDisplayed = TRUE;
|
|
||||||
}
|
|
||||||
/* Should call CURSORICON_ExtCopy but more testing
|
|
||||||
* needs to be done before we change this
|
|
||||||
*/
|
|
||||||
if (flags) FIXME("FIXME: Flags are ignored\n");
|
|
||||||
return CopyCursor(hnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
|
@ -1,316 +0,0 @@
|
||||||
/*
|
|
||||||
* ReactOS kernel
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
/* $Id$
|
|
||||||
*
|
|
||||||
* PROJECT: ReactOS user32.dll
|
|
||||||
* FILE: lib/user32/windows/cursor.c
|
|
||||||
* PURPOSE: Cursor
|
|
||||||
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 09-05-2001 CSH Created
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
|
||||||
|
|
||||||
#include <user32.h>
|
|
||||||
|
|
||||||
#include <wine/debug.h>
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
||||||
|
|
||||||
#undef CopyCursor
|
|
||||||
|
|
||||||
HBITMAP
|
|
||||||
CopyBitmap(HBITMAP bmp);
|
|
||||||
|
|
||||||
/* INTERNAL ******************************************************************/
|
|
||||||
|
|
||||||
/* This callback routine is called directly after switching to gui mode */
|
|
||||||
NTSTATUS
|
|
||||||
WINAPI
|
|
||||||
User32SetupDefaultCursors(PVOID Arguments,
|
|
||||||
ULONG ArgumentLength)
|
|
||||||
{
|
|
||||||
BOOL *DefaultCursor = (BOOL*)Arguments;
|
|
||||||
LRESULT Result = TRUE;
|
|
||||||
|
|
||||||
if(*DefaultCursor)
|
|
||||||
{
|
|
||||||
/* set default cursor */
|
|
||||||
SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME load system cursor scheme */
|
|
||||||
SetCursor(0);
|
|
||||||
SetCursor(LoadCursorW(0, (LPCWSTR)IDC_ARROW));
|
|
||||||
}
|
|
||||||
|
|
||||||
return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
CopyCursor(HCURSOR pcur)
|
|
||||||
{
|
|
||||||
ICONINFO IconInfo;
|
|
||||||
|
|
||||||
if(GetIconInfo((HANDLE)pcur, &IconInfo))
|
|
||||||
{
|
|
||||||
return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE);
|
|
||||||
}
|
|
||||||
return (HCURSOR)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
CreateCursor(HINSTANCE hInst,
|
|
||||||
int xHotSpot,
|
|
||||||
int yHotSpot,
|
|
||||||
int nWidth,
|
|
||||||
int nHeight,
|
|
||||||
CONST VOID *pvANDPlane,
|
|
||||||
CONST VOID *pvXORPlane)
|
|
||||||
{
|
|
||||||
ICONINFO IconInfo;
|
|
||||||
BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)];
|
|
||||||
BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer;
|
|
||||||
HDC hScreenDc;
|
|
||||||
|
|
||||||
hScreenDc = CreateCompatibleDC(NULL);
|
|
||||||
if (hScreenDc == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
bwBIH->bmiHeader.biBitCount = 1;
|
|
||||||
bwBIH->bmiHeader.biWidth = nWidth;
|
|
||||||
bwBIH->bmiHeader.biHeight = -nHeight * 2;
|
|
||||||
bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
||||||
bwBIH->bmiHeader.biPlanes = 1;
|
|
||||||
bwBIH->bmiHeader.biSizeImage = 0;
|
|
||||||
bwBIH->bmiHeader.biCompression = BI_RGB;
|
|
||||||
bwBIH->bmiHeader.biClrImportant = 0;
|
|
||||||
bwBIH->bmiHeader.biClrUsed = 0;
|
|
||||||
bwBIH->bmiHeader.biXPelsPerMeter = 0;
|
|
||||||
bwBIH->bmiHeader.biYPelsPerMeter = 0;
|
|
||||||
|
|
||||||
bwBIH->bmiColors[0].rgbBlue = 0;
|
|
||||||
bwBIH->bmiColors[0].rgbGreen = 0;
|
|
||||||
bwBIH->bmiColors[0].rgbRed = 0;
|
|
||||||
bwBIH->bmiColors[0].rgbReserved = 0;
|
|
||||||
|
|
||||||
bwBIH->bmiColors[1].rgbBlue = 0xff;
|
|
||||||
bwBIH->bmiColors[1].rgbGreen = 0xff;
|
|
||||||
bwBIH->bmiColors[1].rgbRed = 0xff;
|
|
||||||
bwBIH->bmiColors[1].rgbReserved = 0;
|
|
||||||
|
|
||||||
IconInfo.hbmMask = CreateDIBitmap(hScreenDc, &bwBIH->bmiHeader, 0,
|
|
||||||
NULL, bwBIH, DIB_RGB_COLORS);
|
|
||||||
if (IconInfo.hbmMask)
|
|
||||||
{
|
|
||||||
SetDIBits(hScreenDc, IconInfo.hbmMask, 0, nHeight,
|
|
||||||
pvXORPlane, bwBIH, DIB_RGB_COLORS);
|
|
||||||
SetDIBits(hScreenDc, IconInfo.hbmMask, nHeight, nHeight,
|
|
||||||
pvANDPlane, bwBIH, DIB_RGB_COLORS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
|
|
||||||
IconInfo.fIcon = FALSE;
|
|
||||||
IconInfo.xHotspot = xHotSpot;
|
|
||||||
IconInfo.yHotspot = yHotSpot;
|
|
||||||
IconInfo.hbmColor = 0;
|
|
||||||
|
|
||||||
return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
DestroyCursor(HCURSOR hCursor)
|
|
||||||
{
|
|
||||||
return (BOOL)NtUserDestroyCursor((HANDLE)hCursor, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
GetCursor(VOID)
|
|
||||||
{
|
|
||||||
CURSORINFO ci;
|
|
||||||
ci.cbSize = sizeof(CURSORINFO);
|
|
||||||
if(NtUserGetCursorInfo(&ci))
|
|
||||||
return ci.hCursor;
|
|
||||||
else
|
|
||||||
return (HCURSOR)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
GetCursorPos(LPPOINT lpPoint)
|
|
||||||
{
|
|
||||||
BOOL res;
|
|
||||||
/* Windows doesn't check if lpPoint == NULL, we do */
|
|
||||||
if(!lpPoint)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = NtUserGetCursorPos(lpPoint);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
LoadCursorA(HINSTANCE hInstance,
|
|
||||||
LPCSTR lpCursorName)
|
|
||||||
{
|
|
||||||
return(LoadImageA(hInstance,
|
|
||||||
lpCursorName,
|
|
||||||
IMAGE_CURSOR,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_SHARED | LR_DEFAULTSIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
LoadCursorFromFileA(LPCSTR lpFileName)
|
|
||||||
{
|
|
||||||
UNICODE_STRING FileName;
|
|
||||||
HCURSOR Result;
|
|
||||||
RtlCreateUnicodeStringFromAsciiz(&FileName, (LPSTR)lpFileName);
|
|
||||||
Result = LoadImageW(0,
|
|
||||||
FileName.Buffer,
|
|
||||||
IMAGE_CURSOR,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_LOADFROMFILE | LR_DEFAULTSIZE);
|
|
||||||
RtlFreeUnicodeString(&FileName);
|
|
||||||
return(Result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
LoadCursorFromFileW(LPCWSTR lpFileName)
|
|
||||||
{
|
|
||||||
return(LoadImageW(0,
|
|
||||||
lpFileName,
|
|
||||||
IMAGE_CURSOR,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_LOADFROMFILE | LR_DEFAULTSIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HCURSOR
|
|
||||||
WINAPI
|
|
||||||
LoadCursorW(HINSTANCE hInstance,
|
|
||||||
LPCWSTR lpCursorName)
|
|
||||||
{
|
|
||||||
return(LoadImageW(hInstance,
|
|
||||||
lpCursorName,
|
|
||||||
IMAGE_CURSOR,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_SHARED | LR_DEFAULTSIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
SetCursorPos(int X,
|
|
||||||
int Y)
|
|
||||||
{
|
|
||||||
return NtUserSetCursorPos(X,Y);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
SetSystemCursor(HCURSOR hcur,
|
|
||||||
DWORD id)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
WINAPI
|
|
||||||
ShowCursor(BOOL bShow)
|
|
||||||
{
|
|
||||||
return NtUserShowCursor(bShow);
|
|
||||||
}
|
|
||||||
|
|
||||||
HCURSOR
|
|
||||||
CursorIconToCursor(HICON hIcon,
|
|
||||||
BOOL SemiTransparent)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED;
|
|
||||||
return 0;
|
|
||||||
}
|
|
2074
reactos/dll/win32/user32/windows/cursoricon.c
Normal file
2074
reactos/dll/win32/user32/windows/cursoricon.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,667 +0,0 @@
|
||||||
/*
|
|
||||||
* ReactOS kernel
|
|
||||||
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* PROJECT: ReactOS user32.dll
|
|
||||||
* FILE: dll/win32/user32/windows/icon.c
|
|
||||||
* PURPOSE: Icon
|
|
||||||
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 09-05-2001 CSH Created
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
|
||||||
|
|
||||||
#include <user32.h>
|
|
||||||
|
|
||||||
#include <wine/debug.h>
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
HICON
|
|
||||||
CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon)
|
|
||||||
{
|
|
||||||
BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)];
|
|
||||||
BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer;
|
|
||||||
ICONINFO IconInfo;
|
|
||||||
|
|
||||||
IconInfo.fIcon = fIcon;
|
|
||||||
IconInfo.xHotspot = xHotspot;
|
|
||||||
IconInfo.yHotspot = yHotspot;
|
|
||||||
|
|
||||||
if (IconImage->icHeader.biBitCount == 1)
|
|
||||||
{
|
|
||||||
IconInfo.hbmColor = (HBITMAP)0;
|
|
||||||
IconImage->icHeader.biHeight *= 2;
|
|
||||||
IconInfo.hbmMask = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT,
|
|
||||||
ImageData, (BITMAPINFO*)IconImage,
|
|
||||||
DIB_RGB_COLORS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Create the XOR bitmap */
|
|
||||||
IconInfo.hbmColor = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT,
|
|
||||||
ImageData, (BITMAPINFO*)IconImage,
|
|
||||||
DIB_RGB_COLORS);
|
|
||||||
|
|
||||||
/* Make ImageData point to the start of the AND image data. */
|
|
||||||
ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth *
|
|
||||||
IconImage->icHeader.biBitCount + 31) & ~31) >> 3) *
|
|
||||||
(IconImage->icHeader.biHeight );
|
|
||||||
|
|
||||||
/* Create a BITMAPINFO header for the monochrome part of the icon. */
|
|
||||||
bwBIH->bmiHeader.biBitCount = 1;
|
|
||||||
bwBIH->bmiHeader.biWidth = IconImage->icHeader.biWidth;
|
|
||||||
bwBIH->bmiHeader.biHeight = IconImage->icHeader.biHeight;
|
|
||||||
bwBIH->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
||||||
bwBIH->bmiHeader.biPlanes = 1;
|
|
||||||
bwBIH->bmiHeader.biSizeImage = 0;
|
|
||||||
bwBIH->bmiHeader.biCompression = BI_RGB;
|
|
||||||
bwBIH->bmiHeader.biClrImportant = 2;
|
|
||||||
bwBIH->bmiHeader.biClrUsed = 2;
|
|
||||||
bwBIH->bmiHeader.biXPelsPerMeter = 0;
|
|
||||||
bwBIH->bmiHeader.biYPelsPerMeter = 0;
|
|
||||||
|
|
||||||
bwBIH->bmiColors[0].rgbBlue = 0;
|
|
||||||
bwBIH->bmiColors[0].rgbGreen = 0;
|
|
||||||
bwBIH->bmiColors[0].rgbRed = 0;
|
|
||||||
bwBIH->bmiColors[0].rgbReserved = 0;
|
|
||||||
|
|
||||||
bwBIH->bmiColors[1].rgbBlue = 0xff;
|
|
||||||
bwBIH->bmiColors[1].rgbGreen = 0xff;
|
|
||||||
bwBIH->bmiColors[1].rgbRed = 0xff;
|
|
||||||
bwBIH->bmiColors[1].rgbReserved = 0;
|
|
||||||
|
|
||||||
/* Create the AND bitmap. */
|
|
||||||
IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0,
|
|
||||||
ImageData, bwBIH, DIB_RGB_COLORS);
|
|
||||||
|
|
||||||
SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight,
|
|
||||||
ImageData, bwBIH, DIB_RGB_COLORS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the icon based on everything we have so far */
|
|
||||||
return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
CopyIcon(HICON hIcon)
|
|
||||||
{
|
|
||||||
HICON hRetIcon = NULL;
|
|
||||||
ICONINFO IconInfo;
|
|
||||||
|
|
||||||
if(GetIconInfo(hIcon, &IconInfo))
|
|
||||||
{
|
|
||||||
hRetIcon = CreateIconIndirect(&IconInfo);
|
|
||||||
DeleteObject(IconInfo.hbmColor);
|
|
||||||
DeleteObject(IconInfo.hbmMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hRetIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
CreateIcon(
|
|
||||||
HINSTANCE hInstance,
|
|
||||||
int nWidth,
|
|
||||||
int nHeight,
|
|
||||||
BYTE cPlanes,
|
|
||||||
BYTE cBitsPixel,
|
|
||||||
CONST BYTE *ANDbits,
|
|
||||||
CONST BYTE *XORbits)
|
|
||||||
{
|
|
||||||
ICONINFO IconInfo;
|
|
||||||
|
|
||||||
IconInfo.fIcon = TRUE;
|
|
||||||
|
|
||||||
if (cBitsPixel == 1)
|
|
||||||
{
|
|
||||||
nHeight <<= 1;
|
|
||||||
}
|
|
||||||
IconInfo.hbmMask = CreateBitmap(nWidth, nHeight, 1, 1, ANDbits);
|
|
||||||
if(!IconInfo.hbmMask)
|
|
||||||
{
|
|
||||||
return (HICON)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cBitsPixel == 1)
|
|
||||||
{
|
|
||||||
IconInfo.hbmColor = (HBITMAP)0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IconInfo.hbmColor = CreateBitmap(nWidth, nHeight, cPlanes, cBitsPixel, XORbits);
|
|
||||||
if(!IconInfo.hbmColor)
|
|
||||||
{
|
|
||||||
DeleteObject(IconInfo.hbmMask);
|
|
||||||
return (HICON)0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NtUserCreateCursorIconHandle(&IconInfo, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
CreateIconFromResource(
|
|
||||||
PBYTE presbits,
|
|
||||||
DWORD dwResSize,
|
|
||||||
BOOL fIcon,
|
|
||||||
DWORD dwVer)
|
|
||||||
{
|
|
||||||
return CreateIconFromResourceEx(presbits, dwResSize, fIcon, dwVer, 0, 0, LR_DEFAULTSIZE|LR_SHARED );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
CreateIconFromResourceEx(
|
|
||||||
PBYTE pbIconBits,
|
|
||||||
DWORD cbIconBits,
|
|
||||||
BOOL fIcon,
|
|
||||||
DWORD dwVersion,
|
|
||||||
int cxDesired,
|
|
||||||
int cyDesired,
|
|
||||||
UINT uFlags)
|
|
||||||
{
|
|
||||||
ICONIMAGE* SafeIconImage;
|
|
||||||
HICON hIcon;
|
|
||||||
ULONG HeaderSize;
|
|
||||||
ULONG ColourCount;
|
|
||||||
PVOID Data;
|
|
||||||
HDC hScreenDc;
|
|
||||||
WORD wXHotspot;
|
|
||||||
WORD wYHotspot;
|
|
||||||
|
|
||||||
/*
|
|
||||||
FIXME - does win support LR_SHARED? According to msdn it does but we don't
|
|
||||||
have useful information to identify the icon
|
|
||||||
if (uFlags & LR_SHARED)
|
|
||||||
{
|
|
||||||
DbgPrint("FIXME: need LR_SHARED support in CreateIconFromResourceEx()\n");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
TRACE("dwVersion, cxDesired, cyDesired are all ignored in this implementation!\n");
|
|
||||||
|
|
||||||
if (! fIcon)
|
|
||||||
{
|
|
||||||
wXHotspot = *(WORD*)pbIconBits;
|
|
||||||
pbIconBits += sizeof(WORD);
|
|
||||||
wYHotspot = *(WORD*)pbIconBits;
|
|
||||||
pbIconBits += sizeof(WORD);
|
|
||||||
cbIconBits -= 2 * sizeof(WORD);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wXHotspot = cxDesired / 2;
|
|
||||||
wYHotspot = cyDesired / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get an safe copy of the icon data */
|
|
||||||
SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, cbIconBits);
|
|
||||||
if (SafeIconImage == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(SafeIconImage, pbIconBits, cbIconBits);
|
|
||||||
|
|
||||||
/* Take into acount the original height was for both the AND and XOR images */
|
|
||||||
SafeIconImage->icHeader.biHeight /= 2;
|
|
||||||
|
|
||||||
if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
|
|
||||||
{
|
|
||||||
BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
|
|
||||||
ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
|
|
||||||
HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ColourCount = (SafeIconImage->icHeader.biBitCount <= 8) ?
|
|
||||||
(1 << SafeIconImage->icHeader.biBitCount) : 0;
|
|
||||||
HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make data point to the start of the XOR image data */
|
|
||||||
Data = (PBYTE)SafeIconImage + HeaderSize;
|
|
||||||
|
|
||||||
/* get a handle to the screen dc, the icon we create is going to be compatable with this */
|
|
||||||
// FIXME!!! This is a victim of the Win32k Initialization BUG!!!!!
|
|
||||||
//hScreenDc = CreateDCW(NULL, NULL, NULL, NULL);
|
|
||||||
hScreenDc = CreateCompatibleDC(NULL);
|
|
||||||
if (hScreenDc == NULL)
|
|
||||||
{
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
hIcon = CreateCursorIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot, fIcon);
|
|
||||||
RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage);
|
|
||||||
DeleteDC(hScreenDc);
|
|
||||||
|
|
||||||
return hIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
CreateIconIndirect(PICONINFO IconInfo)
|
|
||||||
{
|
|
||||||
BITMAP ColorBitmap;
|
|
||||||
BITMAP MaskBitmap;
|
|
||||||
HBITMAP hbmTemp;
|
|
||||||
|
|
||||||
if(!IconInfo)
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return (HICON)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!GetObjectW(IconInfo->hbmMask, sizeof(BITMAP), &MaskBitmap))
|
|
||||||
{
|
|
||||||
return (HICON)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to get color bitmap */
|
|
||||||
if (GetObjectW(IconInfo->hbmColor, sizeof(BITMAP), &ColorBitmap))
|
|
||||||
{
|
|
||||||
/* Compare size of color and mask bitmap*/
|
|
||||||
if (ColorBitmap.bmWidth != MaskBitmap.bmWidth ||
|
|
||||||
ColorBitmap.bmHeight != MaskBitmap.bmHeight)
|
|
||||||
{
|
|
||||||
ERR("Color and mask size are different!");
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return (HICON)0;
|
|
||||||
}
|
|
||||||
/* Check if color and mask are switched and switch them back */
|
|
||||||
if (MaskBitmap.bmBitsPixel != 1 && ColorBitmap.bmBitsPixel == 1)
|
|
||||||
{
|
|
||||||
hbmTemp = IconInfo->hbmMask;
|
|
||||||
IconInfo->hbmMask = IconInfo->hbmColor;
|
|
||||||
IconInfo->hbmColor = hbmTemp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (HICON)NtUserCreateCursorIconHandle(IconInfo, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
DestroyIcon(
|
|
||||||
HICON hIcon)
|
|
||||||
{
|
|
||||||
return (BOOL)NtUserDestroyCursor((HANDLE)hIcon, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
DrawIcon(
|
|
||||||
HDC hDC,
|
|
||||||
int X,
|
|
||||||
int Y,
|
|
||||||
HICON hIcon)
|
|
||||||
{
|
|
||||||
return DrawIconEx(hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL|DI_DEFAULTSIZE|DI_COMPAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
DrawIconEx(
|
|
||||||
HDC hdc,
|
|
||||||
int xLeft,
|
|
||||||
int yTop,
|
|
||||||
HICON hIcon,
|
|
||||||
int cxWidth,
|
|
||||||
int cyWidth,
|
|
||||||
UINT istepIfAniCur,
|
|
||||||
HBRUSH hbrFlickerFreeDraw,
|
|
||||||
UINT diFlags)
|
|
||||||
{
|
|
||||||
return (BOOL)NtUserDrawIconEx(hdc, xLeft, yTop, hIcon, cxWidth, cyWidth,
|
|
||||||
istepIfAniCur, hbrFlickerFreeDraw, diFlags,
|
|
||||||
0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
BOOL
|
|
||||||
WINAPI
|
|
||||||
GetIconInfo(
|
|
||||||
HICON hIcon,
|
|
||||||
PICONINFO IconInfo)
|
|
||||||
{
|
|
||||||
return NtUserGetIconInfo((HANDLE)hIcon, IconInfo, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
LoadIconA(
|
|
||||||
HINSTANCE hInstance,
|
|
||||||
LPCSTR lpIconName)
|
|
||||||
{
|
|
||||||
return(LoadImageA(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
HICON
|
|
||||||
WINAPI
|
|
||||||
LoadIconW(
|
|
||||||
HINSTANCE hInstance,
|
|
||||||
LPCWSTR lpIconName)
|
|
||||||
{
|
|
||||||
return(LoadImageW(hInstance, lpIconName, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
WINAPI
|
|
||||||
LookupIconIdFromDirectory(
|
|
||||||
PBYTE presbits,
|
|
||||||
BOOL fIcon)
|
|
||||||
{
|
|
||||||
return LookupIconIdFromDirectoryEx(presbits,
|
|
||||||
fIcon,
|
|
||||||
fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
|
|
||||||
fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR),
|
|
||||||
LR_DEFAULTCOLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following macro function accounts for the irregularities of
|
|
||||||
* accessing cursor and icon resources in files and resource entries.
|
|
||||||
*/
|
|
||||||
typedef BOOL
|
|
||||||
(*fnGetCIEntry)(LPVOID dir, int n, int *width, int *height, int *bits );
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* CURSORICON_FindBestIcon
|
|
||||||
*
|
|
||||||
* Find the icon closest to the requested size and number of colors.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
CURSORICON_FindBestIcon(LPVOID dir,
|
|
||||||
fnGetCIEntry get_entry,
|
|
||||||
int Width,
|
|
||||||
int Height,
|
|
||||||
int ColorBits)
|
|
||||||
{
|
|
||||||
int i, cx, cy, Bits, BestBits = 0, BestEntry = -1;
|
|
||||||
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
|
|
||||||
UINT iTempXDiff, iTempYDiff, iTempColorDiff;
|
|
||||||
|
|
||||||
/* Find Best Fit */
|
|
||||||
iTotalDiff = 0xFFFFFFFF;
|
|
||||||
iColorDiff = 0xFFFFFFFF;
|
|
||||||
for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ )
|
|
||||||
{
|
|
||||||
iTempXDiff = abs(Width - cx);
|
|
||||||
iTempYDiff = abs(Height - cy);
|
|
||||||
|
|
||||||
if(iTotalDiff > (iTempXDiff + iTempYDiff))
|
|
||||||
{
|
|
||||||
iXDiff = iTempXDiff;
|
|
||||||
iYDiff = iTempYDiff;
|
|
||||||
iTotalDiff = iXDiff + iYDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find Best Colors for Best Fit */
|
|
||||||
for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ )
|
|
||||||
{
|
|
||||||
if(abs(Width - cx) == iXDiff && abs(Height - cy) == iYDiff)
|
|
||||||
{
|
|
||||||
iTempColorDiff = abs(ColorBits - Bits);
|
|
||||||
if(iColorDiff > iTempColorDiff)
|
|
||||||
{
|
|
||||||
BestEntry = i;
|
|
||||||
BestBits = Bits;
|
|
||||||
iColorDiff = iTempColorDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("Best Icon: ResId: %d, bits : %d\n", BestEntry, BestBits);
|
|
||||||
|
|
||||||
return BestEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
* CURSORICON_FindBestCursor
|
|
||||||
*
|
|
||||||
* Find the cursor closest to the requested size.
|
|
||||||
* FIXME: parameter 'color' ignored and entries with more than 1 bpp
|
|
||||||
* ignored too
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
CURSORICON_FindBestCursor(LPVOID dir,
|
|
||||||
fnGetCIEntry get_entry,
|
|
||||||
int Width,
|
|
||||||
int Height,
|
|
||||||
int ColorBits)
|
|
||||||
{
|
|
||||||
int i, cx, cy, Bits, BestBits = 0, BestEntry = -1;
|
|
||||||
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
|
|
||||||
UINT iTempXDiff, iTempYDiff, iTempColorDiff;
|
|
||||||
|
|
||||||
/* Find Best Fit */
|
|
||||||
iTotalDiff = 0xFFFFFFFF;
|
|
||||||
iColorDiff = 0xFFFFFFFF;
|
|
||||||
for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ )
|
|
||||||
{
|
|
||||||
iTempXDiff = abs(Width - cx);
|
|
||||||
iTempYDiff = abs(Height - cy);
|
|
||||||
|
|
||||||
if(iTotalDiff > (iTempXDiff + iTempYDiff))
|
|
||||||
{
|
|
||||||
iXDiff = iTempXDiff;
|
|
||||||
iYDiff = iTempYDiff;
|
|
||||||
iTotalDiff = iXDiff + iYDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find Best Colors for Best Fit */
|
|
||||||
for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ )
|
|
||||||
{
|
|
||||||
if(abs(Width - cx) == iXDiff && abs(Height - cy) == iYDiff)
|
|
||||||
{
|
|
||||||
iTempColorDiff = abs(ColorBits - Bits);
|
|
||||||
if(iColorDiff > iTempColorDiff)
|
|
||||||
{
|
|
||||||
BestEntry = i;
|
|
||||||
BestBits = Bits;
|
|
||||||
iColorDiff = iTempColorDiff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("Best Cursor: ResId: %d, bits : %d\n", BestEntry, BestBits);
|
|
||||||
|
|
||||||
return BestEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
CURSORICON_GetResIconEntry(LPVOID dir,
|
|
||||||
int n,
|
|
||||||
int *Width,
|
|
||||||
int *Height,
|
|
||||||
int *Bits)
|
|
||||||
{
|
|
||||||
GRPCURSORICONDIR *ResDir = dir;
|
|
||||||
ICONRESDIR *Icon;
|
|
||||||
|
|
||||||
if (ResDir->idCount <= n)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
Icon = &ResDir->idEntries[n].ResInfo.icon;
|
|
||||||
*Width = Icon->bWidth;
|
|
||||||
*Height = Icon->bHeight;
|
|
||||||
*Bits = ResDir->idEntries[n].wBitCount;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL
|
|
||||||
CURSORICON_GetResCursorEntry(LPVOID dir,
|
|
||||||
int n,
|
|
||||||
int *Width,
|
|
||||||
int *Height,
|
|
||||||
int *Bits)
|
|
||||||
{
|
|
||||||
GRPCURSORICONDIR *ResDir = dir;
|
|
||||||
CURSORRESDIR *Cursor;
|
|
||||||
|
|
||||||
if (ResDir->idCount <= n)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
Cursor = &ResDir->idEntries[n].ResInfo.cursor;
|
|
||||||
*Width = Cursor->wWidth;
|
|
||||||
*Height = Cursor->wHeight;
|
|
||||||
*Bits = ResDir->idEntries[n].wBitCount;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GRPCURSORICONDIRENTRY *
|
|
||||||
CURSORICON_FindBestIconRes(GRPCURSORICONDIR * dir,
|
|
||||||
int Width,
|
|
||||||
int Height,
|
|
||||||
int ColorBits)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
n = CURSORICON_FindBestIcon(dir,
|
|
||||||
CURSORICON_GetResIconEntry,
|
|
||||||
Width,
|
|
||||||
Height,
|
|
||||||
ColorBits);
|
|
||||||
if (n < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return &dir->idEntries[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
static GRPCURSORICONDIRENTRY *
|
|
||||||
CURSORICON_FindBestCursorRes(GRPCURSORICONDIR *dir,
|
|
||||||
int Width,
|
|
||||||
int Height,
|
|
||||||
int ColorBits)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
n = CURSORICON_FindBestCursor(dir,
|
|
||||||
CURSORICON_GetResCursorEntry,
|
|
||||||
Width,
|
|
||||||
Height,
|
|
||||||
ColorBits);
|
|
||||||
if (n < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return &dir->idEntries[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
INT WINAPI
|
|
||||||
LookupIconIdFromDirectoryEx(PBYTE xdir,
|
|
||||||
BOOL bIcon,
|
|
||||||
INT width,
|
|
||||||
INT height,
|
|
||||||
UINT cFlag)
|
|
||||||
{
|
|
||||||
GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)xdir;
|
|
||||||
UINT retVal = 0;
|
|
||||||
|
|
||||||
GetConnected();
|
|
||||||
|
|
||||||
if(dir && !dir->idReserved && (IMAGE_ICON == dir->idType || IMAGE_CURSOR == dir->idType))
|
|
||||||
{
|
|
||||||
GRPCURSORICONDIRENTRY *entry = NULL;
|
|
||||||
int ColorBits;
|
|
||||||
|
|
||||||
if (cFlag & LR_MONOCHROME)
|
|
||||||
{
|
|
||||||
ColorBits = 1;
|
|
||||||
}
|
|
||||||
else if (cFlag & LR_VGACOLOR)
|
|
||||||
{
|
|
||||||
ColorBits = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ColorBits = gpsi->BitsPixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bIcon)
|
|
||||||
entry = CURSORICON_FindBestIconRes(dir, width, height, ColorBits);
|
|
||||||
else
|
|
||||||
entry = CURSORICON_FindBestCursorRes(dir, width, height, 1);
|
|
||||||
|
|
||||||
if (entry)
|
|
||||||
retVal = entry->nID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
WARN("%s() : Invalid resource directory\n", __FUNCTION__);
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
|
@ -82,31 +82,27 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
WORD wXHotspot; // Number of Color Planes in the XOR image
|
WORD wWidth;
|
||||||
WORD wYHotspot; // Bits per pixel in the XOR image
|
WORD wHeight;
|
||||||
} CURSORDIR;
|
} CURSORDIR;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{ union
|
||||||
BYTE bWidth; // Width, in pixels, of the icon image
|
{ ICONRESDIR icon;
|
||||||
BYTE bHeight; // Height, in pixels, of the icon image
|
CURSORDIR cursor;
|
||||||
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
|
} ResInfo;
|
||||||
BYTE bReserved; // Reserved ( must be 0)
|
WORD wPlanes;
|
||||||
union
|
WORD wBitCount;
|
||||||
{
|
DWORD dwBytesInRes;
|
||||||
ICONDIR icon;
|
WORD wResId;
|
||||||
CURSORDIR cursor;
|
|
||||||
} Info;
|
|
||||||
DWORD dwBytesInRes; // How many bytes in this resource?
|
|
||||||
DWORD dwImageOffset; // Where in the file is this image?
|
|
||||||
} CURSORICONDIRENTRY;
|
} CURSORICONDIRENTRY;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
WORD idReserved; // Reserved (must be 0)
|
WORD idReserved;
|
||||||
WORD idType; // Resource Type (1 for icons, 0 for cursors)
|
WORD idType;
|
||||||
WORD idCount; // How many images?
|
WORD idCount;
|
||||||
CURSORICONDIRENTRY idEntries[1];// An entry for idCount number of images
|
CURSORICONDIRENTRY idEntries[1];
|
||||||
} CURSORICONDIR;
|
} CURSORICONDIR;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
Loading…
Reference in a new issue