home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 ;
- }
-
-