home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
icon_c.zip
/
ICON.C
Wrap
Text File
|
1994-05-24
|
13KB
|
400 lines
/*
* ICON.C
*
* Function to create an OS/2 pointer or icon. Pass the window handle
* of the parent window and the ASCIIZ string file name of the .PTR or .ICO
* file to read in. The function returns a pointer handle (HPOINTER) or
* NULLHANDLE if an error occured. The pointer should be freed with
* WinDestroyPointer when you are finished with it.
*
* Icons and pointers are maitained in a file as a single or multiple
* sets of bitmaps. Most icons or pointers actually consist of two
* bitmaps, an XOR image and color bitmap.
*
* If the file consists of a single bitmap the header will be
* the actual bitmap info header.
*
* If the file consists of one icon made up of the two bitmaps then
* the initial header is made up of a bitmapfileheader which in turn
* points to the bitmapinfoheaders.
*
* Finally if the file is multiple dual bitmap icons then the initial
* header is actually a bitmaparrayfileheader. This in turn points
* to a bitmapfileheader structure that then points to the bitmapinfo
* structures.
*
* The actual structures are detailed in the online PM Reference with
* the developers toolkit. Search the index for BITMAPARRAYFILEHEADER
* this will in turn be cross linked to bit-map file format which details
* the structures and layouts.
*
* Author Bryan Walker <WalkerWerks> [OS/2 Advisor]
* CIS ID 70304,2705.
*
* Use as you like. If you improve on or find errors please post a copy
* of the fix to me.
*/
HPOINTER CreatePointer(HWND hwnddlg, PSZ pszbitmap)
{
FILESTATUS3 filestatus3;
HFILE hfile;
HPS hps;
PBITMAPARRAYFILEHEADER pbmpheader;
PBITMAPARRAYFILEHEADER2 pbmpheader2;
PBITMAPFILEHEADER2 pbmpfile1;
PBITMAPFILEHEADER pbmpf1;
PBITMAPFILEHEADER2 pbmpfile2;
PBITMAPFILEHEADER pbmpf2;
PBITMAPINFOHEADER2 pbmpxor2, pbmpcolor2;
PBITMAPINFOHEADER pbmpxor1, pbmpcolor1;
POINTERINFO ptrinfo ;
PBYTE pBitsxor, pBitsColor;
HBITMAP phbmxor, phbmcolor;
ULONG rc, ulAction, ulColorTable ;
ULONG cBytes;
HPOINTER hptr ;
SHORT bmpversion ;
BOOL bmparray = FALSE ;
pbmpxor2 = NULL; pbmpxor1 = NULL;
/*
* Read in the entire file allocating a buffer first
*/
rc = DosOpen( pszbitmap,
&hfile,
&ulAction,
0L,
FILE_NORMAL,
FILE_OPEN,
OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,
NULL );
if( rc != 0 )
return NULLHANDLE;
rc = DosQueryFileInfo( hfile, FIL_STANDARD,
(PVOID)&filestatus3, sizeof( filestatus3 ));
if( (pbmpheader2 = malloc( filestatus3.cbFile )) == NULL)
{
DosClose( hfile );
return NULLHANDLE;
}
rc = DosRead( hfile, (PVOID)pbmpheader2, filestatus3.cbFile, &cBytes );
if( rc != 0 || cBytes == 0 )
{
free( pbmpheader2 );
DosClose( hfile );
return NULLHANDLE;
}
DosClose( hfile );
/*
* Now look at the header for the file. It should be either an arrayheader
* or a fileheader. If a fileheader there is only one icon
* in the file. If an arrayheader then it will have multiple icons in the
* file.
*
* NOTE: this code grabs the first set of pointer information in the
* file. This is suppossed to be the device independent icon.
* You could expand this to move through the arrayheaders until
* the pointer matching the current device was located.
*/
switch( pbmpheader2->usType )
{
case BFT_BITMAPARRAY:
/*
* Ok we have a arrayheader of multiple icons or pointers
* The first bitmap is pointed to by bfh2.
*/
bmparray = TRUE ;
pbmpfile1 = &pbmpheader2->bfh2;
/*
* determine if a 1.x or 2.x file layout
*/
if(pbmpheader2->cbSize == sizeof(BITMAPARRAYFILEHEADER))
{
/*
* set 1.x pointers equal to the original 2.x pointers
* to make manipulation a little easier.
*/
pbmpheader = (PBITMAPARRAYFILEHEADER)pbmpheader2 ;
pbmpf1 = (PBITMAPFILEHEADER)&pbmpheader->bfh ;
bmpversion = 1;
}
else
bmpversion = 2 ;
break;
case BFT_BMAP:
case BFT_ICON:
case BFT_POINTER:
case BFT_COLORICON:
case BFT_COLORPOINTER:
/*
* Its a fileheader and not an arrayfileheader.
*/
pbmpfile1 = (PBITMAPFILEHEADER2)pbmpheader2;
if( ((PBITMAPFILEHEADER2)pbmpheader2)->cbSize == sizeof(PBITMAPFILEHEADER2) )
bmpversion = 2;
else
{
pbmpf1 = (PBITMAPFILEHEADER)pbmpheader2;
bmpversion = 1;
}
break;
default :
free(pbmpheader2) ;
return NULLHANDLE ;
}
switch(pbmpfile1->usType)
{
case BFT_BMAP:
case BFT_ICON:
case BFT_POINTER:
/*
* Only one bitmap contained in the file if it is
* one of the above types.
*/
pbmpxor2 = &pbmpfile1->bmp2;
pBitsxor = (PBYTE)pbmpfile1 ;
pBitsxor += pbmpfile1->offBits;
break;
case BFT_COLORICON:
case BFT_COLORPOINTER:
/*
* These bitmap types are the most common for an ICO or PTR
* file. The pointer actually consists of two bitmaps.
* The first is a color bitmap. The second is an XOR bitmap
* for use when drawing the bitmap over various backgrounds.
* The first structure for this type is actually a bitmap array
* header and not a bitmap header.
*/
if(bmpversion == 2)
{
/*
* Get the address of the bitmap header for the XOR bitmap
*/
pbmpxor2 = &pbmpfile1->bmp2;
if(bmparray)
/*
* If we're working from a fileheader then the actual bitmap
* is located slightly differently than if it is a arrayheader.
* (I learned this one through trial and error so verify).
*
* For each array type the offset is calculated from the
* beginning of the structure. The difference is the
* actual head of the structure for a file array is at
* the bmparrayfileheader and not the bmpfileheader position.
*/
pBitsxor = (PBYTE)((PBYTE)pbmpheader2 + pbmpfile1->offBits ) ;
else
pBitsxor = (PBYTE)((PBYTE)pbmpfile1 + pbmpfile1->offBits ) ;
/*
* Now get the header for the color bitmap
* it starts after the first header and the
* color table. First add the size of the first bitmap's
* headers and data.
*/
pbmpfile2 = (PBITMAPFILEHEADER2)((PBYTE)pbmpfile1 + pbmpfile1->cbSize);
/*
* Now calculate the size of the color table.
* which is the number of bitmap planes by the bitcount.
*/
rc = ((PBITMAPINFOHEADER2)pbmpxor2)->cPlanes * ((PBITMAPINFOHEADER2)pbmpxor2)->cBitCount ;
/*
* A color table exists if rc != 24 or either of two flags cclrUsed
* and cclrImportant is set. So if true add the color table's size
* to our offset for the second bitmap.
*/
if(rc != 24 || ((PBITMAPINFOHEADER2)pbmpxor2)->cclrUsed != 0 || ((PBITMAPINFOHEADER2)pbmpxor2)->cclrImportant != 0)
{
ulColorTable = ( sizeof(RGB2) * (ULONG) pow(2, rc) ) ;
pbmpfile2 = (PBITMAPFILEHEADER2)((PBYTE)pbmpfile2 + ulColorTable) ;
}
/*
* Ok now we have the color bitmap. Again calculate the
* offset to the bits from the head of the structure depending
* on wether this is a bitmaparray or bitmapfile structure.
*/
pbmpcolor2 = &pbmpfile2->bmp2;
if(bmparray)
pBitsColor = (PBYTE)((PBYTE)pbmpheader2 + pbmpfile2->offBits ) ;
else
pBitsColor = (PBYTE)((PBYTE)pbmpfile2 + pbmpfile2->offBits ) ;
}
else
{
/*
* The same concept for 1.x bitmaps. Only the structures do
* not contain as many elements so it is broken out using
* seperate structure pointers for clearer reading than
* casting everything for every call
*/
pbmpxor1 = &pbmpf1->bmp;
if(bmparray)
pBitsxor = (PBYTE)( (PBYTE) pbmpheader + pbmpf1->offBits ) ;
else
pBitsxor = (PBYTE)( (PBYTE) pbmpf1 + pbmpf1->offBits ) ;
pbmpf2 = (PBITMAPFILEHEADER)((PBYTE)pbmpf1 + pbmpf1->cbSize);
rc = ((PBITMAPINFOHEADER)pbmpxor1)->cPlanes * ((PBITMAPINFOHEADER)pbmpxor1)->cBitCount ;
if(rc != 24)
{
ulColorTable = ( sizeof(RGB) * (ULONG) pow(2, rc) ) ;
pbmpf2 = (PBITMAPFILEHEADER)((PBYTE) pbmpf2 + ulColorTable) ;
}
pbmpcolor1 = &pbmpf2->bmp;
pbmpcolor2 = (PBITMAPINFOHEADER2)pbmpcolor1 ;
if(bmparray)
pBitsColor = (PBYTE) ((PBYTE)pbmpheader + pbmpf2->offBits ) ;
else
pBitsColor = (PBYTE) ((PBYTE)pbmpf2 + pbmpf2->offBits ) ;
}
break;
}
/*
* Get the Presentation space for the
* dialog or window handle passed to this
* function
*/
hps = WinGetPS (hwnddlg) ;
/*
* Create a bitmap for the XOR and Color bitmap data
*/
if(bmpversion == 2)
phbmxor = GpiCreateBitmap( hps,
pbmpxor2,
CBM_INIT,
(PBYTE)pBitsxor,
(PBITMAPINFO2)pbmpxor2 );
else
phbmxor = GpiCreateBitmap( hps,
(PBITMAPINFOHEADER2)pbmpxor1,
CBM_INIT,
(PBYTE)pBitsxor,
(PBITMAPINFO2)pbmpxor1 );
if(phbmxor == 0 || phbmxor == GPI_ERROR)
{
free( pbmpheader2 );
WinReleasePS(hps) ;
return NULLHANDLE ;
}
/*
* If the type was anything other than coloricon or colorpointer
* above then only one set of bitmap info existed so no need to create a
* second bitmap.
*/
if(pbmpcolor2 != NULL)
{
if( bmpversion == 2)
phbmcolor = GpiCreateBitmap( hps,
(PBITMAPINFOHEADER2)pbmpcolor2,
CBM_INIT,
(PBYTE)pBitsColor,
(PBITMAPINFO2)pbmpcolor2 );
else
phbmcolor = GpiCreateBitmap( hps,
(PBITMAPINFOHEADER2)pbmpcolor1,
CBM_INIT,
(PBYTE)pBitsColor,
(PBITMAPINFO2)pbmpcolor1 );
if(phbmcolor == 0 || phbmcolor == GPI_ERROR)
{
free( pbmpheader2 );
WinReleasePS(hps) ;
return NULLHANDLE ;
}
}
if(pbmpcolor2 == NULL)
{
/*
* Only one bitmap so use WinCreatePointer. This type has the
* actual bitmap drawn as the two parts required. If not the
* icon won't be created correctly.
*/
hptr = WinCreatePointer( HWND_DESKTOP, phbmxor, FALSE, 0L, 0L) ;
/*
* delete the bitmap as it was copied during
* the createpointer call
*/
GpiDeleteBitmap( phbmxor );
}
else
{
/*
* I wanted it drawn the size of an icon. Instead of the
* size of a pointer. Change the flag to alter this setting.
*/
ptrinfo.fPointer = FALSE ;
/*
* Set the hotspot from the bitmap info
*/
if( bmpversion == 2)
{
ptrinfo.xHotspot = pbmpfile1->xHotspot ;
ptrinfo.yHotspot = pbmpfile1->yHotspot ;
}
else
{
ptrinfo.xHotspot = pbmpf1->xHotspot ;
ptrinfo.yHotspot = pbmpf1->yHotspot ;
}
ptrinfo.hbmPointer = phbmxor ;
ptrinfo.hbmColor = phbmcolor ;
ptrinfo.hbmMiniPointer = NULLHANDLE ;
ptrinfo.hbmMiniColor = NULLHANDLE ;
/*
* CreatePointerIndirect is used when you have the two
* bitmaps normal to an ICO or PTR file.
*/
hptr = WinCreatePointerIndirect( HWND_DESKTOP, &ptrinfo) ;
/*
* Free up the bitmaps from the HPS
*/
GpiDeleteBitmap( phbmxor );
GpiDeleteBitmap( phbmcolor );
}
/*
* Free the structure info read into our buffer from the file.
*/
free( pbmpheader2 );
/*
* Release the PS
*/
WinReleasePS(hps) ;
/*
* return the handle to the pointer or NULLHANDLE
*/
return hptr ;
}