463 lines
12 KiB
C
463 lines
12 KiB
C
/*****************************************************************************
|
|
*
|
|
* drawicon.c
|
|
*
|
|
* Copyright (C) Microsoft Corporation 1990.
|
|
* All Rights reserved.
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* Module Intent
|
|
* Contains the functions to display an icon present in the helpfile most
|
|
* suitable for the current display driver.
|
|
* ALERT: This module strongly depends on the Windows source tree
|
|
* \\pucus\corero!core\user.It is dependent on files
|
|
* core\shell\progman\newexe.h and pmextrac.c and \core\user\rmload.c
|
|
* It uses some of the undocumented calls of Windows.
|
|
* 1. HICON STDCALL LoadIconHandler(HICON, BOOL);
|
|
* 2. DWORD STDCALL DirectResAlloc(HANDLE, WORD, WORD);
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* Revision History: Created 09/27/90 by Maha
|
|
* 04-Oct-1990 LeoN hwndHelp => ahwnd[iCurWindow].hwndParent; hwndTopic => hwndTopicCur
|
|
* 26-Oct-1990 LeoN Move overloaded icon into additional window word
|
|
* 18-Jul-1991 RussPJ Fixed 3.1 #1219 - Losing authored icon no more.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "help.h"
|
|
#pragma hdrstop
|
|
|
|
#include "inc\hwproc.h"
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Defines
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define NSMOVE 0x0010
|
|
#define VER 0x0300
|
|
|
|
#define MAGIC_ICON30 0
|
|
|
|
// The width of the name field in the Data for the group resources
|
|
|
|
#define NAMELEN 14
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Types
|
|
*
|
|
*****************************************************************************/
|
|
/**
|
|
** Header for the New version of RC.EXE. This contains the structures
|
|
** for new format of BITMAP files.
|
|
**/
|
|
|
|
#ifndef RES_ICON
|
|
|
|
typedef struct tagNEWHEADER
|
|
{
|
|
WORD Reserved;
|
|
WORD ResType;
|
|
WORD ResCount;
|
|
} NEWHEADER;
|
|
typedef NEWHEADER *LPNEWHEADER;
|
|
|
|
#endif
|
|
|
|
typedef struct tagDESCRIPTOR
|
|
{
|
|
WORD xPixelsPerInch;
|
|
WORD yPixelsPerInch;
|
|
WORD xHotSpot;
|
|
WORD yHotSpot;
|
|
DWORD BytesInRes;
|
|
DWORD OffsetToBits;
|
|
} DESCRIPTOR;
|
|
typedef DESCRIPTOR *LPDESCRIPTOR;
|
|
|
|
typedef struct tagRESDIR
|
|
{
|
|
WORD xPixelsPerInch;
|
|
WORD yPixelsPerInch;
|
|
WORD Planes;
|
|
WORD BitCount;
|
|
DWORD BytesInRes;
|
|
BYTE ResName[NAMELEN];
|
|
} RESDIR;
|
|
typedef RESDIR *LPRESDIR;
|
|
|
|
typedef struct
|
|
{
|
|
BYTE Width;
|
|
BYTE Height;
|
|
BYTE ColorCount;
|
|
BYTE Reserved;
|
|
} RESINFO, * LPRESINFO;
|
|
|
|
typedef struct tagBITMAPHEADER
|
|
{
|
|
DWORD Size;
|
|
WORD Width;
|
|
WORD Height;
|
|
WORD Planes;
|
|
WORD BitCount;
|
|
} BITMAPHEADER;
|
|
typedef struct new_exe NEWEXEHDR;
|
|
typedef NEWEXEHDR *PNEWEXEHDR;
|
|
|
|
typedef struct rsrc_nameinfo RESNAMEINFO;
|
|
typedef RESNAMEINFO *LPRESNAMEINFO;
|
|
|
|
typedef struct rsrc_typeinfo RESTYPEINFO;
|
|
typedef RESTYPEINFO *LPRESTYPEINFO;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Prototypes
|
|
*
|
|
*****************************************************************************/
|
|
extern HICON STDCALL LoadIconHandler(HICON, BOOL);
|
|
extern DWORD STDCALL DirectResAlloc(HANDLE, WORD, WORD);
|
|
|
|
HICON STDCALL MyLoadIcon(HDC, LPSTR);
|
|
__inline static WORD STDCALL MyGetBestFormIcon(HDC, LPRESDIR, WORD);
|
|
__inline static WORD STDCALL MyGetIconId(HDC hdc, HANDLE hRes);
|
|
|
|
/* ## */
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Variables
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL STDCALL FMyLoadIcon(GH ghIconFile)
|
|
{
|
|
|
|
/*
|
|
* BUGBUG: Lynn, this uses some undocumented API calls which apparently
|
|
* aren't supported by the Win32 API, namely LoadIconHandler and
|
|
* DirectResAlloc. Tom just blew this off in the NT code, but I'd like you to
|
|
* look at this and see if there is some way of supporting it -- basically
|
|
* loading and icon from a help file and using that as the class icon instead
|
|
* of loading it from a resource file.
|
|
*/
|
|
|
|
#if 0
|
|
WORD wMagic;
|
|
HANDLE hIconDir; // Icon directory
|
|
WORD nIconIndex;
|
|
HICON hIcon = NULL;
|
|
QB qv, qvSave, qvCur;
|
|
HDC hdc;
|
|
WORD fIcon;
|
|
|
|
if (ghIconFile == NULL || ((qv = qvSave = PtrFromGh(ghIconFile)) == NULL))
|
|
return( FALSE );
|
|
|
|
/* Return 1 if the file is not an EXE or ICO file. */
|
|
hIcon = 1;
|
|
hdc = GetDC( ahwnd[iCurWindow].hwndParent );
|
|
if ( hdc == NULL )
|
|
return( FALSE );
|
|
|
|
wMagic = (WORD)*((WORD *)qv );
|
|
qv += 2;
|
|
|
|
switch (wMagic) {
|
|
case MAGIC_ICON30:
|
|
{
|
|
INT16 i;
|
|
DWORD DescOffset;
|
|
LPSTR lpIcon;
|
|
NEWHEADER NewHeader;
|
|
LPNEWHEADER lpHeader;
|
|
LPRESDIR lpResDir;
|
|
DESCRIPTOR Descriptor;
|
|
BITMAPHEADER BitMapHeader;
|
|
|
|
// Read the header and check if it is a valid ICO file.
|
|
|
|
MoveMemory(((char *) &NewHeader) + 2, qv, (sizeof(NEWHEADER) - 2));
|
|
qv += ( sizeof( NEWHEADER ) -2 );
|
|
|
|
NewHeader.Reserved = MAGIC_ICON30;
|
|
|
|
// Check if the file is in correct format
|
|
|
|
if (NewHeader.ResType != 1)
|
|
goto EICleanup1;
|
|
|
|
// Allocate enough space to create a Global Directory Resource.
|
|
|
|
hIconDir = GlobalAlloc(GPTR,
|
|
(LONG) (sizeof(NEWHEADER) + NewHeader.ResCount * sizeof(RESDIR)));
|
|
if (hIconDir == NULL)
|
|
goto EICleanup1;
|
|
|
|
if ((lpHeader = (LPNEWHEADER) PtrFromGh(hIconDir)) == NULL)
|
|
goto EICleanup2;
|
|
|
|
// Assign the values in the header that has been read already.
|
|
|
|
*lpHeader = NewHeader;
|
|
lpResDir = (LPRESDIR)(lpHeader + 1);
|
|
|
|
// Now Fillup the Directory structure by reading all resource descriptors.
|
|
|
|
for (i = 1; i <= (INT16) NewHeader.ResCount; i++) {
|
|
|
|
// Read the Descriptor.
|
|
|
|
MoveMemory((char *) &Descriptor, qv, sizeof(DESCRIPTOR));
|
|
|
|
// Save the current offset
|
|
|
|
qvCur = qv;
|
|
|
|
qv = qvSave + Descriptor.OffsetToBits;
|
|
|
|
// Get the bitcount and Planes data
|
|
|
|
MoveMemory((char *) &BitMapHeader, qv, sizeof(BITMAPHEADER));
|
|
|
|
lpResDir->xPixelsPerInch = Descriptor.xPixelsPerInch;
|
|
lpResDir->yPixelsPerInch = Descriptor.yPixelsPerInch;
|
|
lpResDir->Planes = BitMapHeader.Planes;
|
|
lpResDir->BitCount = BitMapHeader.BitCount;
|
|
lpResDir->BytesInRes = Descriptor.BytesInRes;
|
|
|
|
// Form the unique name for this resource.
|
|
|
|
lpResDir->ResName[0] = (char)i;
|
|
lpResDir->ResName[1] = 0;
|
|
|
|
// Save the offset to the bits of the icon as a part of the name.
|
|
|
|
*((DWORD *)&(lpResDir->ResName[4])) = Descriptor.OffsetToBits;
|
|
|
|
qv = qvCur;
|
|
|
|
lpResDir++;
|
|
}
|
|
|
|
/*
|
|
* Now that we have the Complete resource directory, let us
|
|
* find out the suitable form of icon (that matches the current
|
|
* display driver). Because we built the ResDir such that the
|
|
* IconId to be the same as the index of the Icon, we can use the
|
|
* return value of GetIconId() as the Index; No need to call
|
|
* GetResIndex();
|
|
*/
|
|
|
|
nIconIndex = MyGetIconId(hdc, hIconDir) - 1;
|
|
|
|
lpResDir = (LPRESDIR)(lpHeader+1) + nIconIndex;
|
|
|
|
// The offset to Bits of the selected Icon is also part of ResName.
|
|
|
|
DescOffset = *((DWORD *)&(lpResDir->ResName[4]));
|
|
|
|
// Allocate memory for the Resource to be loaded.
|
|
|
|
if ((hIcon =
|
|
(WORD)DirectResAlloc(hInsNow, NSMOVE, (WORD)lpResDir->BytesInRes)) == NULL)
|
|
goto EICleanup3;
|
|
if ((lpIcon = PtrFromGh(hIcon)) == NULL)
|
|
goto EICleanup4;
|
|
|
|
qv = qvSave + DescOffset;
|
|
MoveMemory((QV) lpIcon, qv, (INT16) lpResDir->BytesInRes);
|
|
|
|
// Stretch and shrink the icon depending upon resolution of display
|
|
|
|
hIcon = LoadIconHandler(hIcon, TRUE);
|
|
/*------------------------------------------------------------*\
|
|
| hIcon may now be discardable; let's change that!
|
|
\*------------------------------------------------------------*/
|
|
fIcon = GlobalFlags( hIcon );
|
|
fIcon &= ~GMEM_DISCARDABLE;
|
|
GlobalReAlloc( hIcon, 0, GMEM_MODIFY | fIcon );
|
|
goto EICleanup3;
|
|
|
|
EICleanup4:
|
|
GlobalFree(hIcon);
|
|
hIcon = (HICON)1;
|
|
|
|
EICleanup3:
|
|
|
|
EICleanup2:
|
|
GlobalFree(hIconDir);
|
|
|
|
EICleanup1:
|
|
break;
|
|
}
|
|
}
|
|
ReleaseDC( ahwnd[iCurWindow].hwndParent, hdc );
|
|
|
|
// Set up the icon word in the window struct appropriately.
|
|
|
|
if ( hIcon && hIcon != 1 ) {
|
|
SetWindowLong (ahwnd[iCurWindow].hwndParent, GHWL_HICON, (LONG) hIcon);
|
|
return(TRUE);
|
|
}
|
|
#endif
|
|
SetWindowLong(ahwnd[iCurWindow].hwndParent, (int) GHWL_HICON, 0);
|
|
return FALSE;
|
|
}
|
|
|
|
#if 0
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name MyGetIconId()
|
|
-
|
|
* Purpose Used for finding the index no. of the icon to be used.
|
|
* Arguments Display context handle and the handle to the icon resource
|
|
* resource directory present in the icon file.
|
|
*
|
|
* Returns
|
|
* The icon no. to be used.
|
|
*
|
|
* +++
|
|
*
|
|
* Notes
|
|
*
|
|
***************************************************************************/
|
|
|
|
__inline static WORD STDCALL MyGetIconId(HDC hdc, HANDLE hRes)
|
|
{
|
|
LPRESDIR ResDirPtr;
|
|
LPNEWHEADER DataPtr;
|
|
WORD RetIndex;
|
|
WORD ResCount;
|
|
|
|
if ((DataPtr = (LPNEWHEADER) PtrFromGh(hRes)) == NULL)
|
|
return(0);
|
|
|
|
ResCount = DataPtr->ResCount;
|
|
ResDirPtr = (LPRESDIR) (DataPtr + 1);
|
|
|
|
RetIndex = MyGetBestFormIcon(hdc, ResDirPtr, ResCount);
|
|
|
|
if (RetIndex == ResCount)
|
|
RetIndex = 0;
|
|
|
|
ResCount = (WORD)(((LPRESDIR)(ResDirPtr+RetIndex))->ResName[0]);
|
|
|
|
return ResCount;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
- Name MyBestFormIcon()
|
|
-
|
|
* Purpose Used for finding the index no. of the icon to be used.
|
|
* Among the different forms of Icons present, choose the one that
|
|
* matches the PixelsPerInch values and the number of colors of the
|
|
* current display.
|
|
* Arguments Display context handle and the
|
|
* resource directory pointer present in the icon file and
|
|
* resource count present in the resource file.
|
|
*
|
|
* Returns
|
|
* The icon no. to be used.
|
|
*
|
|
* +++
|
|
*
|
|
* Notes
|
|
*
|
|
***************************************************************************/
|
|
|
|
__inline static WORD STDCALL MyGetBestFormIcon(HDC hdc,
|
|
LPRESDIR ResDirPtr, WORD ResCount)
|
|
{
|
|
UINT16 wIndex;
|
|
UINT16 ColorCount;
|
|
UINT16 MaxColorCount;
|
|
UINT16 MaxColorIndex;
|
|
UINT16 MoreColorCount;
|
|
UINT16 MoreColorIndex;
|
|
UINT16 LessColorCount;
|
|
UINT16 LessColorIndex;
|
|
INT16 cxIcon, cyIcon, ScreenBitCount;
|
|
LPRESINFO lpResInfo;
|
|
|
|
cxIcon = GetSystemMetrics(SM_CXICON);
|
|
cyIcon = GetSystemMetrics(SM_CYICON);
|
|
ScreenBitCount = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
|
|
|
|
// Initialse all the values to zero
|
|
|
|
MaxColorCount = MaxColorIndex = MoreColorCount =
|
|
MoreColorIndex = LessColorIndex = LessColorCount = 0;
|
|
|
|
for (wIndex = 0; wIndex < ResCount; wIndex++, ResDirPtr++) {
|
|
lpResInfo = (LPRESINFO)ResDirPtr;
|
|
|
|
// Check for the number of colors
|
|
|
|
if ((ColorCount = (WORD)(lpResInfo->ColorCount)) <= (WORD)(1 << ScreenBitCount))
|
|
{
|
|
if (ColorCount > MaxColorCount)
|
|
{
|
|
MaxColorCount = ColorCount;
|
|
MaxColorIndex = wIndex;
|
|
}
|
|
}
|
|
|
|
/* Check for the size */
|
|
/* Match the pixels per inch information */
|
|
if ((lpResInfo->Width == (BYTE)cxIcon) &&
|
|
(lpResInfo->Height == (BYTE)cyIcon))
|
|
{
|
|
/* Matching size found */
|
|
/* Check if the color also matches */
|
|
if (ColorCount == (WORD)(1 << ScreenBitCount))
|
|
return(wIndex); /* Exact match found */
|
|
|
|
if (ColorCount < (WORD)(1 << ScreenBitCount))
|
|
{
|
|
/* Choose the one with max colors, but less than reqd */
|
|
if (ColorCount > LessColorCount)
|
|
{
|
|
LessColorCount = ColorCount;
|
|
LessColorIndex = wIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((LessColorCount == 0) && (ColorCount < MoreColorCount))
|
|
{
|
|
MoreColorCount = ColorCount;
|
|
MoreColorIndex = wIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if we have a correct sized but with less colors than reqd
|
|
|
|
if (LessColorCount)
|
|
return(LessColorIndex);
|
|
|
|
// Check if we have a correct sized but with more colors than reqd
|
|
|
|
if (MoreColorCount)
|
|
return(MoreColorIndex);
|
|
|
|
// Check if we have one that has maximum colors but less than reqd
|
|
|
|
if (MaxColorCount)
|
|
return(MaxColorIndex);
|
|
|
|
return(0);
|
|
}
|
|
|
|
#endif // 0
|