home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / icon_c.zip / ICON.C
Text File  |  1994-05-24  |  13KB  |  400 lines

  1. /*
  2.  * ICON.C
  3.  *
  4.  * Function to create an OS/2 pointer or icon.  Pass the window handle
  5.  * of the parent window and the ASCIIZ string file name of the .PTR or .ICO
  6.  * file to read in.  The function returns a pointer handle (HPOINTER) or
  7.  * NULLHANDLE if an error occured.  The pointer should be freed with
  8.  * WinDestroyPointer when you are finished with it.
  9.  *
  10.  * Icons and pointers are maitained in a file as a single or multiple
  11.  * sets of bitmaps.  Most icons or pointers actually consist of two
  12.  * bitmaps, an XOR image and color bitmap.
  13.  *
  14.  * If the file consists of a single bitmap the header will be
  15.  * the actual bitmap info header.
  16.  *
  17.  * If the file consists of one icon made up of the two bitmaps then
  18.  * the initial header is made up of a bitmapfileheader which in turn
  19.  * points to the bitmapinfoheaders.
  20.  *
  21.  * Finally if the file is multiple dual bitmap icons then the initial
  22.  * header is actually a bitmaparrayfileheader.  This in turn points
  23.  * to a bitmapfileheader structure that then points to the bitmapinfo
  24.  * structures.
  25.  *
  26.  * The actual structures are detailed in the online PM Reference with
  27.  * the developers toolkit.  Search the index for BITMAPARRAYFILEHEADER
  28.  * this will in turn be cross linked to bit-map file format which details
  29.  * the structures and layouts.
  30.  *
  31.  * Author Bryan Walker <WalkerWerks> [OS/2 Advisor]
  32.  * CIS ID 70304,2705.
  33.  *
  34.  * Use as you like.  If you improve on or find errors please post a copy
  35.  * of the fix to me.
  36.  */
  37. HPOINTER CreatePointer(HWND hwnddlg, PSZ pszbitmap)
  38. {
  39. FILESTATUS3        filestatus3;
  40. HFILE              hfile;
  41. HPS                hps;
  42. PBITMAPARRAYFILEHEADER  pbmpheader;
  43. PBITMAPARRAYFILEHEADER2 pbmpheader2;
  44. PBITMAPFILEHEADER2 pbmpfile1;
  45. PBITMAPFILEHEADER  pbmpf1;
  46. PBITMAPFILEHEADER2 pbmpfile2;
  47. PBITMAPFILEHEADER  pbmpf2;
  48. PBITMAPINFOHEADER2 pbmpxor2, pbmpcolor2;
  49. PBITMAPINFOHEADER  pbmpxor1, pbmpcolor1;
  50. POINTERINFO        ptrinfo ;
  51. PBYTE              pBitsxor, pBitsColor;
  52. HBITMAP            phbmxor, phbmcolor;
  53. ULONG              rc, ulAction, ulColorTable ;
  54. ULONG              cBytes;
  55. HPOINTER           hptr ;
  56. SHORT              bmpversion ;
  57. BOOL               bmparray = FALSE ;
  58.  
  59.  
  60. pbmpxor2 = NULL; pbmpxor1 = NULL;
  61.  
  62. /*
  63.  * Read in the entire file allocating a buffer first
  64.  */
  65. rc = DosOpen(  pszbitmap,
  66.                &hfile,
  67.                &ulAction,
  68.                0L,
  69.                FILE_NORMAL,
  70.                FILE_OPEN,
  71.                OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,
  72.                NULL );
  73. if( rc != 0 )
  74.     return NULLHANDLE;
  75.  
  76.  
  77. rc = DosQueryFileInfo( hfile, FIL_STANDARD,
  78.                               (PVOID)&filestatus3, sizeof( filestatus3 ));
  79.  
  80. if( (pbmpheader2 = malloc( filestatus3.cbFile )) == NULL)
  81.    {
  82.    DosClose( hfile );
  83.    return NULLHANDLE;
  84.    }
  85.  
  86. rc = DosRead( hfile, (PVOID)pbmpheader2, filestatus3.cbFile, &cBytes );
  87. if( rc != 0  ||  cBytes == 0 )
  88.     {
  89.     free( pbmpheader2 );
  90.     DosClose( hfile );
  91.     return NULLHANDLE;
  92.     }
  93.  
  94. DosClose( hfile );
  95.  
  96.  
  97.  
  98. /*
  99.  * Now look at the header for the file.  It should be either an arrayheader
  100.  * or a fileheader.  If a fileheader there is only one icon
  101.  * in the file.  If an arrayheader then it will have multiple icons in the
  102.  * file.
  103.  *
  104.  * NOTE: this code grabs the first set of pointer information in the
  105.  *       file.  This is suppossed to be the device independent icon.
  106.  *       You could expand this to move through the arrayheaders until
  107.  *       the pointer matching the current device was located.
  108.  */
  109.  
  110. switch( pbmpheader2->usType )
  111.     {
  112.     case BFT_BITMAPARRAY:
  113.        /*
  114.         * Ok we have a arrayheader of multiple icons or pointers
  115.         * The first bitmap is pointed to by bfh2.
  116.         */
  117.         bmparray = TRUE ;
  118.         pbmpfile1 = &pbmpheader2->bfh2;
  119.         /*
  120.          * determine if a 1.x or 2.x file layout
  121.          */
  122.         if(pbmpheader2->cbSize == sizeof(BITMAPARRAYFILEHEADER))
  123.            {
  124.            /*
  125.             * set 1.x pointers equal to the original 2.x pointers
  126.             * to make manipulation a little easier.
  127.             */
  128.            pbmpheader = (PBITMAPARRAYFILEHEADER)pbmpheader2 ;
  129.            pbmpf1 = (PBITMAPFILEHEADER)&pbmpheader->bfh ;
  130.            bmpversion =  1;
  131.            }
  132.         else
  133.            bmpversion = 2 ;
  134.  
  135.         break;
  136.  
  137.     case BFT_BMAP:
  138.     case BFT_ICON:
  139.     case BFT_POINTER:
  140.     case BFT_COLORICON:
  141.     case BFT_COLORPOINTER:
  142.        /*
  143.         * Its a fileheader and not an arrayfileheader.
  144.         */
  145.        pbmpfile1 = (PBITMAPFILEHEADER2)pbmpheader2;
  146.        if( ((PBITMAPFILEHEADER2)pbmpheader2)->cbSize == sizeof(PBITMAPFILEHEADER2) )
  147.           bmpversion =  2;
  148.        else
  149.           {
  150.           pbmpf1 = (PBITMAPFILEHEADER)pbmpheader2;
  151.           bmpversion =  1;
  152.           }
  153.        break;
  154.  
  155.     default :
  156.         free(pbmpheader2) ;
  157.         return NULLHANDLE ;
  158.     }
  159.  
  160. switch(pbmpfile1->usType)
  161.     {
  162.     case BFT_BMAP:
  163.     case BFT_ICON:
  164.     case BFT_POINTER:
  165.        /*
  166.         * Only one bitmap contained in the file if it is
  167.         * one of the above types.
  168.         */
  169.        pbmpxor2 = &pbmpfile1->bmp2;
  170.        pBitsxor = (PBYTE)pbmpfile1 ;
  171.        pBitsxor += pbmpfile1->offBits;
  172.        break;
  173.  
  174.     case BFT_COLORICON:
  175.     case BFT_COLORPOINTER:
  176.        /*
  177.         * These bitmap types are the most common for an ICO or PTR
  178.         * file.  The pointer actually consists of two bitmaps.
  179.         * The first is a color bitmap.  The second is an XOR bitmap
  180.         * for use when drawing the bitmap over various backgrounds.
  181.         * The first structure for this type is actually a bitmap array
  182.         * header and not a bitmap header.
  183.         */
  184.        if(bmpversion == 2)
  185.           {
  186.           /*
  187.            * Get the address of the bitmap header for the XOR bitmap
  188.            */
  189.           pbmpxor2 = &pbmpfile1->bmp2;
  190.           if(bmparray)
  191.              /*
  192.               * If we're working from a fileheader then the actual bitmap
  193.               * is located slightly differently than if it is a arrayheader.
  194.               * (I learned this one through trial and error so verify).
  195.               *
  196.               * For each array type the offset is calculated from the
  197.               * beginning of the structure.  The difference is the
  198.               * actual head of the structure for a file array is at
  199.               * the bmparrayfileheader and not the bmpfileheader position.
  200.               */
  201.              pBitsxor = (PBYTE)((PBYTE)pbmpheader2 + pbmpfile1->offBits ) ;
  202.           else
  203.              pBitsxor = (PBYTE)((PBYTE)pbmpfile1 + pbmpfile1->offBits ) ;
  204.  
  205.           /*
  206.            * Now get the header for the color bitmap
  207.            * it starts after the first header and the
  208.            * color table.  First add the size of the first bitmap's
  209.            * headers and data.
  210.            */
  211.           pbmpfile2 = (PBITMAPFILEHEADER2)((PBYTE)pbmpfile1 + pbmpfile1->cbSize);
  212.  
  213.           /*
  214.            * Now calculate the size of the color table.
  215.            * which is the number of bitmap planes by the bitcount.
  216.            */
  217.           rc = ((PBITMAPINFOHEADER2)pbmpxor2)->cPlanes * ((PBITMAPINFOHEADER2)pbmpxor2)->cBitCount ;
  218.  
  219.           /*
  220.            * A color table exists if rc != 24 or either of two flags cclrUsed
  221.            * and cclrImportant is set.  So if true add the color table's size
  222.            * to our offset for the second bitmap.
  223.            */
  224.           if(rc != 24 || ((PBITMAPINFOHEADER2)pbmpxor2)->cclrUsed != 0 || ((PBITMAPINFOHEADER2)pbmpxor2)->cclrImportant != 0)
  225.              {
  226.              ulColorTable = ( sizeof(RGB2) * (ULONG) pow(2, rc) ) ;
  227.              pbmpfile2 = (PBITMAPFILEHEADER2)((PBYTE)pbmpfile2 + ulColorTable) ;
  228.              }
  229.  
  230.           /*
  231.            * Ok now  we have the color bitmap.  Again calculate the
  232.            * offset to the bits from the head of the structure depending
  233.            * on wether this is a bitmaparray or bitmapfile structure.
  234.            */
  235.           pbmpcolor2  = &pbmpfile2->bmp2;
  236.           if(bmparray)
  237.              pBitsColor = (PBYTE)((PBYTE)pbmpheader2 + pbmpfile2->offBits ) ;
  238.           else
  239.              pBitsColor = (PBYTE)((PBYTE)pbmpfile2 + pbmpfile2->offBits ) ;
  240.           }
  241.        else
  242.           {
  243.           /*
  244.            * The same concept for 1.x bitmaps.  Only the structures do
  245.            * not contain as many elements so it is broken out using
  246.            * seperate structure pointers for clearer reading than
  247.            * casting everything for every call
  248.            */
  249.           pbmpxor1 = &pbmpf1->bmp;
  250.           if(bmparray)
  251.              pBitsxor = (PBYTE)( (PBYTE) pbmpheader + pbmpf1->offBits ) ;
  252.           else
  253.              pBitsxor = (PBYTE)( (PBYTE) pbmpf1 + pbmpf1->offBits ) ;
  254.           pbmpf2 = (PBITMAPFILEHEADER)((PBYTE)pbmpf1 + pbmpf1->cbSize);
  255.  
  256.           rc = ((PBITMAPINFOHEADER)pbmpxor1)->cPlanes * ((PBITMAPINFOHEADER)pbmpxor1)->cBitCount ;
  257.           if(rc != 24)
  258.              {
  259.              ulColorTable = ( sizeof(RGB) * (ULONG) pow(2, rc) ) ;
  260.              pbmpf2 = (PBITMAPFILEHEADER)((PBYTE) pbmpf2 + ulColorTable) ;
  261.              }
  262.           pbmpcolor1  = &pbmpf2->bmp;
  263.           pbmpcolor2  = (PBITMAPINFOHEADER2)pbmpcolor1 ;
  264.           if(bmparray)
  265.              pBitsColor  = (PBYTE) ((PBYTE)pbmpheader + pbmpf2->offBits ) ;
  266.           else
  267.              pBitsColor  = (PBYTE) ((PBYTE)pbmpf2 + pbmpf2->offBits ) ;
  268.           }
  269.        break;
  270.     }
  271.  
  272. /*
  273.  * Get the Presentation space for the
  274.  * dialog or window handle passed to this
  275.  * function
  276.  */
  277. hps = WinGetPS (hwnddlg) ;
  278.  
  279. /*
  280.  * Create a bitmap for the XOR and Color bitmap data
  281.  */
  282. if(bmpversion == 2)
  283.    phbmxor = GpiCreateBitmap( hps,
  284.                            pbmpxor2,
  285.                            CBM_INIT,
  286.                            (PBYTE)pBitsxor,
  287.                            (PBITMAPINFO2)pbmpxor2 );
  288.  
  289. else
  290.    phbmxor = GpiCreateBitmap( hps,
  291.                            (PBITMAPINFOHEADER2)pbmpxor1,
  292.                            CBM_INIT,
  293.                            (PBYTE)pBitsxor,
  294.                            (PBITMAPINFO2)pbmpxor1 );
  295.  
  296. if(phbmxor == 0 || phbmxor == GPI_ERROR)
  297.    {
  298.    free( pbmpheader2 );
  299.    WinReleasePS(hps) ;
  300.    return NULLHANDLE ;
  301.    }
  302.  
  303. /*
  304.  * If the type was anything other than coloricon or colorpointer
  305.  * above then only one set of bitmap info existed so no need to create a
  306.  * second bitmap.
  307.  */
  308. if(pbmpcolor2 != NULL)
  309.    {
  310.    if( bmpversion == 2)
  311.       phbmcolor = GpiCreateBitmap( hps,
  312.                                (PBITMAPINFOHEADER2)pbmpcolor2,
  313.                                CBM_INIT,
  314.                                (PBYTE)pBitsColor,
  315.                                (PBITMAPINFO2)pbmpcolor2 );
  316.    else
  317.       phbmcolor = GpiCreateBitmap( hps,
  318.                                (PBITMAPINFOHEADER2)pbmpcolor1,
  319.                                CBM_INIT,
  320.                                (PBYTE)pBitsColor,
  321.                                (PBITMAPINFO2)pbmpcolor1 );
  322.    if(phbmcolor == 0 || phbmcolor == GPI_ERROR)
  323.       {
  324.       free( pbmpheader2 );
  325.       WinReleasePS(hps) ;
  326.       return NULLHANDLE ;
  327.       }
  328.  
  329.    }
  330.  
  331. if(pbmpcolor2 == NULL)
  332.    {
  333.   /*
  334.    * Only one bitmap so use WinCreatePointer.  This type has the
  335.    * actual bitmap drawn as the two parts required.  If not the
  336.    * icon won't be created correctly.
  337.    */
  338.    hptr = WinCreatePointer( HWND_DESKTOP, phbmxor, FALSE, 0L, 0L) ;
  339.    /*
  340.     * delete the bitmap as it was copied during 
  341.     * the createpointer call
  342.     */
  343.    GpiDeleteBitmap( phbmxor );
  344.    }
  345. else
  346.    {
  347.    /*
  348.     * I wanted it drawn the size of an icon.  Instead of the
  349.     * size of a pointer.  Change the flag to alter this setting.
  350.     */
  351.    ptrinfo.fPointer = FALSE ;
  352.  
  353.    /*
  354.     * Set the hotspot from the bitmap info
  355.     */
  356.    if( bmpversion == 2)
  357.       {
  358.       ptrinfo.xHotspot = pbmpfile1->xHotspot ;
  359.       ptrinfo.yHotspot = pbmpfile1->yHotspot ;
  360.       }
  361.    else
  362.       {
  363.       ptrinfo.xHotspot = pbmpf1->xHotspot ;
  364.       ptrinfo.yHotspot = pbmpf1->yHotspot ;
  365.       }
  366.    ptrinfo.hbmPointer = phbmxor ;
  367.    ptrinfo.hbmColor = phbmcolor ;
  368.    ptrinfo.hbmMiniPointer = NULLHANDLE ;
  369.    ptrinfo.hbmMiniColor = NULLHANDLE ;
  370.  
  371.    /*
  372.     * CreatePointerIndirect is used when you have the two
  373.     * bitmaps normal to an ICO or PTR file.
  374.     */
  375.    hptr = WinCreatePointerIndirect( HWND_DESKTOP, &ptrinfo) ;
  376.  
  377.    /*
  378.     * Free up the bitmaps from the HPS
  379.     */
  380.    GpiDeleteBitmap( phbmxor );
  381.    GpiDeleteBitmap( phbmcolor );
  382.    }
  383.  
  384. /*
  385.  * Free the structure info read into our buffer from the file.
  386.  */
  387. free( pbmpheader2 );
  388.  
  389. /*
  390.  * Release the PS
  391.  */
  392. WinReleasePS(hps) ;
  393.  
  394. /*
  395.  * return the handle to the pointer or NULLHANDLE
  396.  */
  397. return hptr ;
  398. }
  399.  
  400.