mirror of
https://github.com/reactos/reactos.git
synced 2025-05-13 14:20:31 +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 name="windows">
|
||||
<file>accel.c</file>
|
||||
<file>bitmap.c</file>
|
||||
<file>caret.c</file>
|
||||
<file>class.c</file>
|
||||
<file>clipboard.c</file>
|
||||
<file>cursor.c</file>
|
||||
<file>cursoricon.c</file>
|
||||
<file>dc.c</file>
|
||||
<file>defwnd.c</file>
|
||||
<file>dialog.c</file>
|
||||
<file>draw.c</file>
|
||||
<file>font.c</file>
|
||||
<file>hook.c</file>
|
||||
<file>icon.c</file>
|
||||
<file>input.c</file>
|
||||
<file>mdi.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
|
||||
{
|
||||
WORD wXHotspot; // Number of Color Planes in the XOR image
|
||||
WORD wYHotspot; // Bits per pixel in the XOR image
|
||||
WORD wWidth;
|
||||
WORD wHeight;
|
||||
} CURSORDIR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE bWidth; // Width, in pixels, of the icon image
|
||||
BYTE bHeight; // Height, in pixels, of the icon image
|
||||
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
|
||||
BYTE bReserved; // Reserved ( must be 0)
|
||||
union
|
||||
{
|
||||
ICONDIR icon;
|
||||
CURSORDIR cursor;
|
||||
} Info;
|
||||
DWORD dwBytesInRes; // How many bytes in this resource?
|
||||
DWORD dwImageOffset; // Where in the file is this image?
|
||||
{ union
|
||||
{ ICONRESDIR icon;
|
||||
CURSORDIR cursor;
|
||||
} ResInfo;
|
||||
WORD wPlanes;
|
||||
WORD wBitCount;
|
||||
DWORD dwBytesInRes;
|
||||
WORD wResId;
|
||||
} CURSORICONDIRENTRY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD idReserved; // Reserved (must be 0)
|
||||
WORD idType; // Resource Type (1 for icons, 0 for cursors)
|
||||
WORD idCount; // How many images?
|
||||
CURSORICONDIRENTRY idEntries[1];// An entry for idCount number of images
|
||||
WORD idReserved;
|
||||
WORD idType;
|
||||
WORD idCount;
|
||||
CURSORICONDIRENTRY idEntries[1];
|
||||
} CURSORICONDIR;
|
||||
|
||||
typedef struct
|
||||
|
|
Loading…
Reference in a new issue