home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / resource / iconpro / icons.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  49.1 KB  |  1,407 lines

  1. /****************************************************************************\
  2. *            
  3. *     FILE:     ICONS.C
  4. *
  5. *     PURPOSE:  IconPro Project Icon handing Code C file
  6. *
  7. *     COMMENTS: This file contains the icon handling code
  8. *
  9. *     FUNCTIONS:
  10. *      EXPORTS: 
  11. *               ReadIconFromICOFile        - Reads Icon from ICO file
  12. *               WriteIconToICOFile         - Writes Icon to ICO file
  13. *               MakeIconFromResource       - Makes HICON from a resource
  14. *               ReadIconFromEXEFile        - Reads Icon from a EXE or DLL file
  15. *               IconImageToClipBoard       - Puts icon image on clipboard
  16. *               IconImageFromClipBoard     - Gets icon image from clipboard
  17. *               CreateBlankNewFormatIcon   - Makes a new, blank icon image
  18. *               DrawXORMask                - Draws XOR mask using DIBs
  19. *               DrawANDMask                - Draws AND mask using DIBs
  20. *               GetXORImageRect            - Calculates XOR image position
  21. *               MakeNewANDMaskBasedOnPoint - Calculates new AND mask
  22. *               ConvertBMPFileToIcon       - Converts BMP to Icon
  23. *               IconImageToBMPFile         - Writes an icon image to BMP file
  24. *      LOCALS:
  25. *               ReadICOHeader              - Reads ICO file header
  26. *               AdjustIconImagePointers    - Adjusts internal pointers
  27. *               ExtractDlgProc             - Dlg Proc for extract dialog
  28. *               MyEnumProcedure            - For EnumResourceNames()
  29. *               GetIconFromInstance        - Extracts Icon from Instance
  30. *               ChooseIconFromEXEFile      - Gets a user's choice icon from file
  31. *               WriteICOHeader             - Writes ICO file header
  32. *               CalculateImageOffset       - Calcs offset in file of image
  33. *               DIBToIconImage             - Converts DIB to icon image
  34. *
  35. *     Copyright 1995 - 1997 Microsoft Corp.
  36. *
  37. *
  38. * History:
  39. *                July '95 - Created
  40. *
  41. \****************************************************************************/
  42. #include <Windows.h>
  43. #include "Resource.h"
  44. #include "IconPro.h"
  45. #include "Icons.H"
  46. #include "Dib.H"
  47.  
  48.  
  49. /****************************************************************************/
  50. // Structs used locally (file scope)
  51. // Resource Position info - size and offset of a resource in a file
  52. typedef struct
  53. {
  54.     DWORD    dwBytes;
  55.     DWORD    dwOffset;
  56. } RESOURCEPOSINFO, *LPRESOURCEPOSINFO;
  57. // EXE/DLL icon information - filename, instance handle and ID
  58. typedef struct
  59. {
  60.     LPCTSTR        szFileName;
  61.     HINSTANCE    hInstance;
  62.     LPTSTR        lpID;
  63. } EXEDLLICONINFO, *LPEXEDLLICONINFO;
  64. /****************************************************************************/
  65.  
  66.  
  67. /****************************************************************************/
  68. // External Globals
  69. extern HINSTANCE    hInst;
  70. extern HWND            hWndMain;
  71. /****************************************************************************/
  72.  
  73. /****************************************************************************/
  74. // Prototypes for local functions
  75. UINT ReadICOHeader( HANDLE hFile );
  76. BOOL AdjustIconImagePointers( LPICONIMAGE lpImage );
  77. BOOL CALLBACK ExtractDlgProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
  78. BOOL CALLBACK MyEnumProcedure( HANDLE  hModule, LPCTSTR  lpszType, LPTSTR  lpszName, LONG  lParam );
  79. HICON GetIconFromInstance( HINSTANCE hInstance, LPTSTR nIndex );
  80. LPTSTR ChooseIconFromEXEFile( LPEXEDLLICONINFO lpEDII );
  81. BOOL WriteICOHeader( HANDLE hFile, UINT nNumEntries );
  82. DWORD CalculateImageOffset( LPICONRESOURCE lpIR, UINT nIndex );
  83. BOOL DIBToIconImage( LPICONIMAGE lpii, LPBYTE lpDIB, BOOL bStretch );
  84. /****************************************************************************/
  85.  
  86.  
  87.  
  88. /****************************************************************************
  89. *
  90. *     FUNCTION: MakeIconFromResource
  91. *
  92. *     PURPOSE:  Makes an HICON from an icon resource
  93. *
  94. *     PARAMS:   LPICONIMAGE    lpIcon - pointer to the icon resource
  95. *
  96. *     RETURNS:  HICON - handle to the new icon, NULL for failure
  97. *
  98. * History:
  99. *                July '95 - Created
  100. *
  101. \****************************************************************************/
  102. HICON MakeIconFromResource( LPICONIMAGE lpIcon )
  103. {
  104.     HICON            hIcon = NULL;
  105.  
  106.     // Sanity Check
  107.     if( lpIcon == NULL )
  108.         return NULL;
  109.     if( lpIcon->lpBits == NULL )
  110.         return NULL;
  111.     // Let the OS do the real work :)
  112.     hIcon = CreateIconFromResourceEx( lpIcon->lpBits, lpIcon->dwNumBytes, TRUE, 0x00030000, 
  113.             (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biWidth, (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biHeight/2, 0 );
  114.     
  115.     // It failed, odds are good we're on NT so try the non-Ex way
  116.     if( hIcon == NULL )
  117.     {
  118.         // We would break on NT if we try with a 16bpp image
  119.         if(lpIcon->lpbi->bmiHeader.biBitCount != 16)
  120.         {    
  121.             hIcon = CreateIconFromResource( lpIcon->lpBits, lpIcon->dwNumBytes, TRUE, 0x00030000 );
  122.         }
  123.     }
  124.     return hIcon;
  125. }
  126. /* End MakeIconFromResource() **********************************************/
  127.  
  128.  
  129.  
  130.  
  131.  
  132. /****************************************************************************
  133. *
  134. *     FUNCTION: ReadIconFromICOFile
  135. *
  136. *     PURPOSE:  Reads an Icon Resource from an ICO file
  137. *
  138. *     PARAMS:   LPCTSTR szFileName - Name of the ICO file
  139. *
  140. *     RETURNS:  LPICONRESOURCE - pointer to the resource, NULL for failure
  141. *
  142. * History:
  143. *                July '95 - Created
  144. *
  145. \****************************************************************************/
  146. LPICONRESOURCE ReadIconFromICOFile( LPCTSTR szFileName )
  147. {
  148.     LPICONRESOURCE        lpIR = NULL, lpNew = NULL;
  149.     HANDLE                hFile = NULL;
  150.     LPRESOURCEPOSINFO    lpRPI = NULL;
  151.     UINT                i;
  152.     DWORD                dwBytesRead;
  153.     LPICONDIRENTRY        lpIDE = NULL;
  154.  
  155.  
  156.     // Open the file
  157.     if( (hFile = CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE )
  158.     {
  159.         MessageBox( hWndMain, "Error Opening File for Reading", szFileName, MB_OK );
  160.         return NULL;
  161.     }
  162.     // Allocate memory for the resource structure
  163.     if( (lpIR = malloc( sizeof(ICONRESOURCE) )) == NULL )
  164.     {
  165.         MessageBox( hWndMain, "Error Allocating Memory", szFileName, MB_OK );
  166.         CloseHandle( hFile );
  167.         return NULL;
  168.     }
  169.     // Read in the header
  170.     if( (lpIR->nNumImages = ReadICOHeader( hFile )) == (UINT)-1 )
  171.     {
  172.         MessageBox( hWndMain, "Error Reading File Header", szFileName, MB_OK );
  173.         CloseHandle( hFile );
  174.         free( lpIR );
  175.         return NULL;
  176.     }
  177.     // Adjust the size of the struct to account for the images
  178.     if( (lpNew = realloc( lpIR, sizeof(ICONRESOURCE) + ((lpIR->nNumImages-1) * sizeof(ICONIMAGE)) )) == NULL )
  179.     {
  180.         MessageBox( hWndMain, "Error Allocating Memory", szFileName, MB_OK );
  181.         CloseHandle( hFile );
  182.         free( lpIR );
  183.         return NULL;
  184.     }
  185.     lpIR = lpNew;
  186.     // Store the original name
  187.     lstrcpy( lpIR->szOriginalICOFileName, szFileName );
  188.     lstrcpy( lpIR->szOriginalDLLFileName, "" );
  189.     // Allocate enough memory for the icon directory entries
  190.     if( (lpIDE = malloc( lpIR->nNumImages * sizeof( ICONDIRENTRY ) ) ) == NULL )
  191.     {
  192.         MessageBox( hWndMain, "Error Allocating Memory", szFileName, MB_OK );
  193.         CloseHandle( hFile );
  194.         free( lpIR );
  195.         return NULL;
  196.     }
  197.     // Read in the icon directory entries
  198.     if( ! ReadFile( hFile, lpIDE, lpIR->nNumImages * sizeof( ICONDIRENTRY ), &dwBytesRead, NULL ) )
  199.     {
  200.         MessageBox( hWndMain, "Error Reading File", szFileName, MB_OK );
  201.         CloseHandle( hFile );
  202.         free( lpIR );
  203.         return NULL;
  204.     }
  205.     if( dwBytesRead != lpIR->nNumImages * sizeof( ICONDIRENTRY ) )
  206.     {
  207.         MessageBox( hWndMain, "Error Reading File", szFileName, MB_OK );
  208.         CloseHandle( hFile );
  209.         free( lpIR );
  210.         return NULL;
  211.     }
  212.     // Loop through and read in each image
  213.     for( i = 0; i < lpIR->nNumImages; i++ )
  214.     {
  215.         // Allocate memory for the resource
  216.         if( (lpIR->IconImages[i].lpBits = malloc(lpIDE[i].dwBytesInRes)) == NULL )
  217.         {
  218.             MessageBox( hWndMain, "Error Allocating Memory", szFileName, MB_OK );
  219.             CloseHandle( hFile );
  220.             free( lpIR );
  221.             free( lpIDE );
  222.             return NULL;
  223.         }
  224.         lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes;
  225.         // Seek to beginning of this image
  226.         if( SetFilePointer( hFile, lpIDE[i].dwImageOffset, NULL, FILE_BEGIN ) == 0xFFFFFFFF )
  227.         {
  228.             MessageBox( hWndMain, "Error Seeking in File", szFileName, MB_OK );
  229.             CloseHandle( hFile );
  230.             free( lpIR );
  231.             free( lpIDE );
  232.             return NULL;
  233.         }
  234.         // Read it in
  235.         if( ! ReadFile( hFile, lpIR->IconImages[i].lpBits, lpIDE[i].dwBytesInRes, &dwBytesRead, NULL ) )
  236.         {
  237.             MessageBox( hWndMain, "Error Reading File", szFileName, MB_OK );
  238.             CloseHandle( hFile );
  239.             free( lpIR );
  240.             free( lpIDE );
  241.             return NULL;
  242.         }
  243.         if( dwBytesRead != lpIDE[i].dwBytesInRes )
  244.         {
  245.             MessageBox( hWndMain, "Error Reading File", szFileName, MB_OK );
  246.             CloseHandle( hFile );
  247.             free( lpIDE );
  248.             free( lpIR );
  249.             return NULL;
  250.         }
  251.         // Set the internal pointers appropriately
  252.         if( ! AdjustIconImagePointers( &(lpIR->IconImages[i]) ) )
  253.         {
  254.             MessageBox( hWndMain, "Error Converting to Internal Format", szFileName, MB_OK );
  255.             CloseHandle( hFile );
  256.             free( lpIDE );
  257.             free( lpIR );
  258.             return NULL;
  259.         }
  260.     }
  261.     // Clean up    
  262.     free( lpIDE );
  263.     free( lpRPI );
  264.     CloseHandle( hFile );
  265.     return lpIR;
  266. }
  267. /* End ReadIconFromICOFile() **********************************************/
  268.  
  269.  
  270.  
  271.  
  272. /****************************************************************************
  273. *
  274. *     FUNCTION: AdjustIconImagePointers
  275. *
  276. *     PURPOSE:  Adjusts internal pointers in icon resource struct
  277. *
  278. *     PARAMS:   LPICONIMAGE lpImage - the resource to handle
  279. *
  280. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  281. *
  282. * History:
  283. *                July '95 - Created
  284. *
  285. \****************************************************************************/
  286. BOOL AdjustIconImagePointers( LPICONIMAGE lpImage )
  287. {
  288.     // Sanity check
  289.     if( lpImage==NULL )
  290.         return FALSE;
  291.     // BITMAPINFO is at beginning of bits
  292.     lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits;
  293.     // Width - simple enough
  294.     lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;
  295.     // Icons are stored in funky format where height is doubled - account for it
  296.     lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;
  297.     // How many colors?
  298.     lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * lpImage->lpbi->bmiHeader.biBitCount;
  299.     // XOR bits follow the header and color table
  300.     lpImage->lpXOR = FindDIBBits((LPSTR)lpImage->lpbi);
  301.     // AND bits follow the XOR bits
  302.     lpImage->lpAND = lpImage->lpXOR + (lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi)));
  303.     return TRUE;
  304. }
  305. /* End AdjustIconImagePointers() *******************************************/
  306.  
  307.  
  308.  
  309.  
  310. /****************************************************************************
  311. *
  312. *     FUNCTION: ReadICOHeader
  313. *
  314. *     PURPOSE:  Reads the header from an ICO file
  315. *
  316. *     PARAMS:   HANDLE hFile - handle to the file
  317. *
  318. *     RETURNS:  UINT - Number of images in file, -1 for failure
  319. *
  320. * History:
  321. *                July '95 - Created
  322. *
  323. \****************************************************************************/
  324. UINT ReadICOHeader( HANDLE hFile )
  325. {
  326.     WORD    Input;
  327.     DWORD    dwBytesRead;
  328.  
  329.     // Read the 'reserved' WORD
  330.     if( ! ReadFile( hFile, &Input, sizeof( WORD ), &dwBytesRead, NULL ) )
  331.         return (UINT)-1;
  332.     // Did we get a WORD?
  333.     if( dwBytesRead != sizeof( WORD ) )
  334.         return (UINT)-1;
  335.     // Was it 'reserved' ?   (ie 0)
  336.     if( Input != 0 )
  337.         return (UINT)-1;
  338.     // Read the type WORD
  339.     if( ! ReadFile( hFile, &Input, sizeof( WORD ), &dwBytesRead, NULL ) )
  340.         return (UINT)-1;
  341.     // Did we get a WORD?
  342.     if( dwBytesRead != sizeof( WORD ) )
  343.         return (UINT)-1;
  344.     // Was it type 1?
  345.     if( Input != 1 )
  346.         return (UINT)-1;
  347.     // Get the count of images
  348.     if( ! ReadFile( hFile, &Input, sizeof( WORD ), &dwBytesRead, NULL ) )
  349.         return (UINT)-1;
  350.     // Did we get a WORD?
  351.     if( dwBytesRead != sizeof( WORD ) )
  352.         return (UINT)-1;
  353.     // Return the count
  354.     return Input;
  355. }
  356. /* End ReadICOHeader() ****************************************************/
  357.  
  358.  
  359.  
  360.  
  361. /****************************************************************************
  362. *
  363. *     FUNCTION: MyEnumProcedure
  364. *
  365. *     PURPOSE:  Callback for enumerating resources in a DLL/EXE
  366. *
  367. *     PARAMS:   HANDLE  hModule  - Handle of the module
  368. *               LPCTSTR lpszType - Resource Type
  369. *               LPTSTR  lpszName - Resource Name
  370. *               LONG    lParam   - Handle of ListBox to add name to
  371. *
  372. *     RETURNS:  BOOL - TRUE to continue, FALSE to stop
  373. *
  374. * History:
  375. *                July '95 - Created
  376. *
  377. \****************************************************************************/
  378. BOOL CALLBACK MyEnumProcedure( HANDLE  hModule, LPCTSTR  lpszType, LPTSTR  lpszName, LONG  lParam )    
  379. {
  380.     TCHAR    szBuffer[256];
  381.     LONG    nIndex = LB_ERR;
  382.     LPTSTR    lpID = NULL;
  383.  
  384.     // Name is from MAKEINTRESOURCE()
  385.     if( HIWORD(lpszName) == 0 )
  386.     {
  387.         wsprintf( szBuffer, "Icon [%d]", (DWORD)lpszName );
  388.         lpID = lpszName;
  389.     }
  390.     else
  391.     {
  392.         // Name is string
  393.         lpID = strdup( lpszName );
  394.         wsprintf( szBuffer, "Icon [%s]", lpID );
  395.     }
  396.     // Add it to the listbox
  397.     nIndex = SendDlgItemMessage( (HWND)lParam, IDC_LIST1, LB_ADDSTRING, 0, (LPARAM)(szBuffer) );
  398.     // Set the item data to be the name of the resource so we can get it later
  399.     SendDlgItemMessage( (HWND)lParam, IDC_LIST1, LB_SETITEMDATA, (WPARAM)nIndex, (LPARAM)lpID );
  400.     return TRUE;
  401. }
  402. /* End MyEnumProcedure() ***************************************************/
  403.  
  404.  
  405.  
  406. /****************************************************************************
  407. *
  408. *     FUNCTION: GetIconFromInstance
  409. *
  410. *     PURPOSE:  Callback for enumerating resources in a DLL/EXE
  411. *
  412. *     PARAMS:   HINSTANCE hInstance - Instance handle for this module
  413. *               LPTSTR    nIndex    - Resource index
  414. *
  415. *     RETURNS:  HICON - Handle to the icon, NULL for failure
  416. *
  417. * History:
  418. *                July '95 - Created
  419. *
  420. \****************************************************************************/
  421. HICON GetIconFromInstance( HINSTANCE hInstance, LPTSTR nIndex )
  422. {
  423.     HICON    hIcon = NULL;
  424.     HRSRC    hRsrc = NULL;
  425.     HGLOBAL    hGlobal = NULL;
  426.     LPVOID    lpRes = NULL;
  427.     int        nID;
  428.  
  429.     // Find the group icon
  430.     if( (hRsrc = FindResource( hInstance, nIndex, RT_GROUP_ICON )) == NULL )
  431.         return NULL;
  432.     if( (hGlobal = LoadResource( hInstance, hRsrc )) == NULL )
  433.         return NULL;
  434.     if( (lpRes = LockResource(hGlobal)) == NULL )
  435.         return NULL;
  436.  
  437.     // Find this particular image
  438.     nID = LookupIconIdFromDirectory( lpRes, TRUE );
  439.     if( (hRsrc = FindResource( hInstance, MAKEINTRESOURCE(nID), RT_ICON )) == NULL )
  440.         return NULL;
  441.     if( (hGlobal = LoadResource( hInstance, hRsrc )) == NULL )
  442.         return NULL;
  443.     if( (lpRes = LockResource(hGlobal)) == NULL )
  444.         return NULL;
  445.     // Let the OS make us an icon
  446.     hIcon = CreateIconFromResource( lpRes, SizeofResource(hInstance,hRsrc), TRUE, 0x00030000 );
  447.     return hIcon;
  448. }
  449. /* End GetIconFromInstance() ***********************************************/
  450.  
  451.  
  452.  
  453. /****************************************************************************
  454. *
  455. *     FUNCTION: ExtractDlgProc
  456. *
  457. *     PURPOSE:  Window Procedure for the Extract Dialog
  458. *
  459. *     PARAMS:   HWND hWnd     - This window handle
  460. *               UINT Msg      - Which Message?
  461. *               WPARAM wParam - message parameter
  462. *               LPARAM lParam - message parameter
  463. *
  464. *     RETURNS:  BOOL - FALSE for cancel, TRUE for ok
  465. *
  466. * History:
  467. *                July '95 - Created
  468. *
  469. \****************************************************************************/
  470. BOOL CALLBACK ExtractDlgProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
  471. {
  472.     // Variable that holds info on this EXE/DLL
  473.     static LPEXEDLLICONINFO lpEDII;
  474.  
  475.     switch( Msg )
  476.     {
  477.         // During Paint, we will draw the currently selected icon
  478.         case WM_PAINT:
  479.         {
  480.             HDC                    hDC;
  481.             PAINTSTRUCT            ps;
  482.             DWORD                nIndex;
  483.             LPTSTR                lpIconID;
  484.  
  485.             hDC = BeginPaint( hWnd, &ps );
  486.             // Get the current selection
  487.             if( (nIndex = SendDlgItemMessage( hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0 )) != CB_ERR )
  488.             {
  489.                 // Get the data associated with the current selection - its the icon name
  490.                 if( (lpIconID = (LPTSTR)SendDlgItemMessage( hWnd, IDC_LIST1, LB_GETITEMDATA, nIndex, 0 )) != (LPTSTR)CB_ERR )
  491.                 {
  492.                     RECT        Rect, ButtonRect, DlgRect;
  493.                     HWND        hWndButton;
  494.                     HICON        hIcon;
  495.                     ICONINFO    IconInfo;
  496.                     BITMAP        bm;
  497.                     POINT        UpperLeft, LowerRight;
  498.  
  499.                     // Make an Icon
  500.                     hIcon = GetIconFromInstance( lpEDII->hInstance, lpIconID );
  501.                     // Locate the icon
  502.                     GetIconInfo( hIcon, &IconInfo );
  503.                     GetObject( IconInfo.hbmColor, sizeof(BITMAP), &bm );
  504.                     hWndButton = GetDlgItem( hWnd, IDCANCEL );
  505.                     GetWindowRect( hWndButton, &ButtonRect );
  506.                     GetWindowRect( hWnd, &DlgRect );
  507.                     UpperLeft.x = ButtonRect.left;
  508.                     UpperLeft.y = ButtonRect.bottom;
  509.                     LowerRight.x = ButtonRect.right;
  510.                     LowerRight.y = DlgRect.bottom;
  511.                     ScreenToClient( hWnd, &UpperLeft );
  512.                     ScreenToClient( hWnd, &LowerRight );
  513.                     SetRect( &Rect, UpperLeft.x, UpperLeft.y, LowerRight.x, LowerRight.y );
  514.                     // Draw it
  515.                     DrawIcon( hDC, Rect.left + ((Rect.right - Rect.left - bm.bmWidth)/2), 
  516.                             Rect.top + ((Rect.bottom - Rect.top - bm.bmHeight)/2), hIcon );
  517.                     // Kill it
  518.                     DestroyIcon( hIcon );
  519.                 }
  520.             }
  521.             EndPaint( hWnd, &ps );
  522.         }
  523.         break; // End WM_PAINT
  524.  
  525.         // Dialog is being initialized
  526.         case WM_INITDIALOG:
  527.         {
  528.             UINT    nCount;
  529.             TCHAR    szBuffer[MAX_PATH], szFileTitle[MAX_PATH];
  530.  
  531.             // Are we being sent data about an EXE/DLL?
  532.             if( (lpEDII = (LPEXEDLLICONINFO)lParam) != NULL )
  533.             {
  534.                 // Set the title of the dialog to reflect the EXE/DLL filename
  535.                 GetFileTitle( lpEDII->szFileName, szFileTitle, MAX_PATH );
  536.                 wsprintf( szBuffer, "Extract Icon [%s]", szFileTitle );
  537.                 SetWindowText( hWnd, szBuffer );
  538.                 // Fill in the listbox with the icons available
  539.                 if( ! EnumResourceNames( lpEDII->hInstance, RT_GROUP_ICON, MyEnumProcedure, (LPARAM)hWnd ) )
  540.                 {
  541.                     MessageBox( hWnd, "Error Enumerating Icons", "Error", MB_OK );
  542.                     PostMessage( hWnd, WM_CLOSE, 0, 0 );
  543.                 }
  544.                 SendDlgItemMessage( hWnd, IDC_LIST1, LB_SETCURSEL, 0, 0 );
  545.                 // If we have <= 1, post an OK message
  546.                 if( (nCount = SendDlgItemMessage(hWnd, IDC_LIST1, LB_GETCOUNT, 0, 0)) == 1 )
  547.                 {
  548.                     PostMessage( hWnd, WM_COMMAND, IDOK, 0 );
  549.                 }
  550.                 // If there were no icons, let the user know
  551.                 if( nCount == 0 )
  552.                 {
  553.                     MessageBox( hWnd, "No Icons in this File", "Error", MB_OK );
  554.                     PostMessage( hWnd, WM_CLOSE, 0, 0 );
  555.                 }
  556.             }
  557.             return FALSE;
  558.         }
  559.         break; // End WM_INITDIALOG
  560.  
  561.         // Shut 'er down
  562.         case WM_CLOSE:
  563.             PostMessage( hWnd, WM_COMMAND, IDCANCEL, 0l );
  564.         break; // End WM_CLOSE
  565.  
  566.         // Children are sending messages
  567.         case WM_COMMAND:
  568.             switch( LOWORD(wParam) )
  569.             {
  570.                 // Its the listbox, just redraw the icon
  571.                 case IDC_LIST1:
  572.                     switch( HIWORD(wParam) )
  573.                     {
  574.                         case CBN_SELCHANGE:
  575.                         case CBN_SELENDOK:
  576.                             InvalidateRect( hWnd, NULL, TRUE );
  577.                         break;
  578.                     }
  579.                 break; // End IDC_LIST1
  580.  
  581.                 // User has chosen an icon, shut it down
  582.                 case IDOK:
  583.                 {
  584.                     LONG nIndex;
  585.  
  586.                     lpEDII->lpID = NULL;
  587.                     if( (nIndex = SendDlgItemMessage( hWnd, IDC_LIST1, LB_GETCURSEL, 0, 0 )) != LB_ERR )
  588.                         lpEDII->lpID = (LPTSTR)SendDlgItemMessage( hWnd, IDC_LIST1, LB_GETITEMDATA, nIndex, 0 );
  589.                     EndDialog( hWnd, TRUE );
  590.                 }
  591.                 break; // End IDOK
  592.  
  593.                 // BAIL!
  594.                 case IDCANCEL:
  595.                     EndDialog( hWnd, FALSE );
  596.                 break; // End IDCANCEL
  597.  
  598.             }
  599.         break;
  600.         default:
  601.             return FALSE;
  602.         break;
  603.     }
  604.     return TRUE;
  605. }
  606. /* End ExtractDlgProc() ****************************************************/
  607.  
  608.  
  609.  
  610.  
  611. /****************************************************************************
  612. *
  613. *     FUNCTION: ChooseIconFromEXEFile
  614. *
  615. *     PURPOSE:  Ask the user which icon he/she wants from the DLL/EXE
  616. *
  617. *     PARAMS:   LPEXEDLLICONINFO lpEDII - info on this DLL/EXE
  618. *
  619. *     RETURNS:  LPTSTR - pointer to the resource name
  620. *
  621. * History:
  622. *                July '95 - Created
  623. *
  624. \****************************************************************************/
  625. LPTSTR ChooseIconFromEXEFile( LPEXEDLLICONINFO lpEDII )
  626. {
  627.     // Just launch the dialog box and let it handle it
  628.     if( DialogBoxParam( hInst, MAKEINTRESOURCE(IDD_EXTRACTDLG), hWndMain, ExtractDlgProc, (LPARAM)(lpEDII) ) )
  629.     {
  630.         // User chose 'Ok'
  631.         return lpEDII->lpID;
  632.     }
  633.     // User chose 'Cancel', or an error occurred, fail the call
  634.     return NULL;
  635. }
  636. /* End ChooseIconFromEXEFile() **********************************************/
  637.  
  638.  
  639.  
  640.  
  641. /****************************************************************************
  642. *
  643. *     FUNCTION: ReadIconFromEXEFile
  644. *
  645. *     PURPOSE:  Load an Icon Resource from a DLL/EXE file
  646. *
  647. *     PARAMS:   LPCTSTR szFileName - name of DLL/EXE file
  648. *
  649. *     RETURNS:  LPICONRESOURCE - pointer to icon resource
  650. *
  651. * History:
  652. *                July '95 - Created
  653. *
  654. \****************************************************************************/
  655. LPICONRESOURCE ReadIconFromEXEFile( LPCTSTR szFileName )
  656. {
  657.     LPICONRESOURCE        lpIR = NULL, lpNew = NULL;
  658.     HINSTANCE            hLibrary;
  659.     LPTSTR                lpID;
  660.     EXEDLLICONINFO        EDII;
  661.  
  662.     // Load the DLL/EXE - NOTE: must be a 32bit EXE/DLL for this to work
  663.     if( (hLibrary = LoadLibraryEx( szFileName, NULL, LOAD_LIBRARY_AS_DATAFILE )) == NULL )
  664.     {
  665.         // Failed to load - abort
  666.         MessageBox( hWndMain, "Error Loading File - Choose a 32bit DLL or EXE", szFileName, MB_OK );
  667.         return NULL;
  668.     }
  669.     // Store the info
  670.     EDII.szFileName = szFileName;
  671.     EDII.hInstance = hLibrary;
  672.     // Ask the user, "Which Icon?"
  673.     if( (lpID = ChooseIconFromEXEFile( &EDII )) != NULL )
  674.     {
  675.         HRSRC            hRsrc = NULL;
  676.         HGLOBAL            hGlobal = NULL;
  677.         LPMEMICONDIR    lpIcon = NULL;
  678.         UINT            i;
  679.  
  680.         // Find the group icon resource
  681.         if( (hRsrc = FindResource( hLibrary, lpID, RT_GROUP_ICON )) == NULL )
  682.         {
  683.             FreeLibrary( hLibrary );
  684.             return NULL;
  685.         }
  686.         if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL )
  687.         {
  688.             FreeLibrary( hLibrary );
  689.             return NULL;
  690.         }
  691.         if( (lpIcon = LockResource(hGlobal)) == NULL )
  692.         {
  693.             FreeLibrary( hLibrary );
  694.             return NULL;
  695.         }
  696.         // Allocate enough memory for the images
  697.         if( (lpIR = malloc( sizeof(ICONRESOURCE) + ((lpIcon->idCount-1) * sizeof(ICONIMAGE)) )) == NULL )
  698.         {
  699.             MessageBox( hWndMain, "Error Allocating Memory", szFileName, MB_OK );
  700.             FreeLibrary( hLibrary );
  701.             return NULL;
  702.         }
  703.         // Fill in local struct members
  704.         lpIR->nNumImages = lpIcon->idCount;
  705.         lstrcpy( lpIR->szOriginalDLLFileName, szFileName );
  706.         lstrcpy( lpIR->szOriginalICOFileName, "" );
  707.         // Loop through the images
  708.         for( i = 0; i < lpIR->nNumImages; i++ )
  709.         {
  710.             // Get the individual image
  711.             if( (hRsrc = FindResource( hLibrary, MAKEINTRESOURCE(lpIcon->idEntries[i].nID), RT_ICON )) == NULL )
  712.             {
  713.                 free( lpIR );
  714.                 FreeLibrary( hLibrary );
  715.                 return NULL;
  716.             }
  717.             if( (hGlobal = LoadResource( hLibrary, hRsrc )) == NULL )
  718.             {
  719.                 free( lpIR );
  720.                 FreeLibrary( hLibrary );
  721.                 return NULL;
  722.             }
  723.             // Store a copy of the resource locally
  724.             lpIR->IconImages[i].dwNumBytes = SizeofResource( hLibrary, hRsrc );
  725.             lpIR->IconImages[i].lpBits = malloc( lpIR->IconImages[i].dwNumBytes );
  726.             memcpy( lpIR->IconImages[i].lpBits, LockResource( hGlobal ), lpIR->IconImages[i].dwNumBytes );
  727.             // Adjust internal pointers
  728.             if( ! AdjustIconImagePointers( &(lpIR->IconImages[i]) ) )
  729.             {
  730.                 MessageBox( hWndMain, "Error Converting to Internal Format", szFileName, MB_OK );
  731.                 free( lpIR );
  732.                 FreeLibrary( hLibrary );
  733.                 return NULL;
  734.             }
  735.         }
  736.     }
  737.     FreeLibrary( hLibrary );
  738.     return lpIR;
  739. }
  740. /* End ReadIconFromEXEFile() ************************************************/
  741.  
  742.  
  743.  
  744. /****************************************************************************
  745. *
  746. *     FUNCTION: WriteICOHeader
  747. *
  748. *     PURPOSE:  Writes the header to an ICO file
  749. *
  750. *     PARAMS:   HANDLE hFile       - handle to the file
  751. *               UINT   nNumEntries - Number of images in file
  752. *
  753. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  754. *
  755. * History:
  756. *                July '95 - Created
  757. *
  758. \****************************************************************************/
  759. BOOL WriteICOHeader( HANDLE hFile, UINT nNumEntries )
  760. {
  761.     WORD    Output;
  762.     DWORD    dwBytesWritten;
  763.  
  764.     // Write 'reserved' WORD
  765.     Output = 0;
  766.     if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
  767.         return FALSE;
  768.     // Did we write a WORD?
  769.     if( dwBytesWritten != sizeof( WORD ) )
  770.         return FALSE;
  771.     // Write 'type' WORD (1)
  772.     Output = 1;
  773.     if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
  774.         return FALSE;
  775.     // Did we write a WORD?
  776.     if( dwBytesWritten != sizeof( WORD ) )
  777.         return FALSE;
  778.     // Write Number of Entries
  779.     Output = (WORD)nNumEntries;
  780.     if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
  781.         return FALSE;
  782.     // Did we write a WORD?
  783.     if( dwBytesWritten != sizeof( WORD ) )
  784.         return FALSE;
  785.     return TRUE;
  786. }
  787. /* End WriteICOHeader() ****************************************************/
  788.  
  789.  
  790.  
  791. /****************************************************************************
  792. *
  793. *     FUNCTION: CalculateImageOffset
  794. *
  795. *     PURPOSE:  Calculates the file offset for an icon image
  796. *
  797. *     PARAMS:   LPICONRESOURCE lpIR   - pointer to icon resource
  798. *               UINT           nIndex - which image?
  799. *
  800. *     RETURNS:  DWORD - the file offset for that image
  801. *
  802. * History:
  803. *                July '95 - Created
  804. *
  805. \****************************************************************************/
  806. DWORD CalculateImageOffset( LPICONRESOURCE lpIR, UINT nIndex )
  807. {
  808.     DWORD    dwSize;
  809.     UINT    i;
  810.  
  811.     // Calculate the ICO header size
  812.     dwSize = 3 * sizeof(WORD);
  813.     // Add the ICONDIRENTRY's
  814.     dwSize += lpIR->nNumImages * sizeof(ICONDIRENTRY);
  815.     // Add the sizes of the previous images
  816.     for(i=0;i<nIndex;i++)
  817.         dwSize += lpIR->IconImages[i].dwNumBytes;
  818.     // we're there - return the number
  819.     return dwSize;
  820. }
  821. /* End CalculateImageOffset() ***********************************************/
  822.  
  823.  
  824.  
  825.  
  826. /****************************************************************************
  827. *
  828. *     FUNCTION: WriteIconToICOFile
  829. *
  830. *     PURPOSE:  Writes the icon resource data to an ICO file
  831. *
  832. *     PARAMS:   LPICONRESOURCE lpIR       - pointer to icon resource
  833. *               LPCTSTR        szFileName - name for the ICO file
  834. *
  835. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  836. *
  837. * History:
  838. *                July '95 - Created
  839. *
  840. \****************************************************************************/
  841. BOOL WriteIconToICOFile( LPICONRESOURCE lpIR, LPCTSTR szFileName )
  842. {
  843.     HANDLE        hFile;
  844.     UINT        i;
  845.     DWORD        dwBytesWritten;
  846.  
  847.     // open the file
  848.     if( (hFile = CreateFile( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE )
  849.     {
  850.         MessageBox( hWndMain, "Error Opening File for Writing", szFileName, MB_OK );
  851.         return FALSE;
  852.     }
  853.     // Write the header
  854.     if( ! WriteICOHeader( hFile, lpIR->nNumImages ) )
  855.     {
  856.         MessageBox( hWndMain, "Error Writing ICO File", szFileName, MB_OK );
  857.         CloseHandle( hFile );
  858.         return FALSE;
  859.     }
  860.     // Write the ICONDIRENTRY's
  861.     for( i=0; i<lpIR->nNumImages; i++ )
  862.     {
  863.         ICONDIRENTRY    ide;
  864.  
  865.         // Convert internal format to ICONDIRENTRY
  866.         ide.bWidth = lpIR->IconImages[i].Width;
  867.         ide.bHeight = lpIR->IconImages[i].Height;
  868.         ide.bReserved = 0;
  869.         ide.wPlanes = lpIR->IconImages[i].lpbi->bmiHeader.biPlanes;
  870.         ide.wBitCount = lpIR->IconImages[i].lpbi->bmiHeader.biBitCount;
  871.         if( (ide.wPlanes * ide.wBitCount) >= 8 )
  872.             ide.bColorCount = 0;
  873.         else
  874.             ide.bColorCount = 1 << (ide.wPlanes * ide.wBitCount);
  875.         ide.dwBytesInRes = lpIR->IconImages[i].dwNumBytes;
  876.         ide.dwImageOffset = CalculateImageOffset( lpIR, i );
  877.         // Write the ICONDIRENTRY out to disk
  878.         if( ! WriteFile( hFile, &ide, sizeof( ICONDIRENTRY ), &dwBytesWritten, NULL ) )
  879.             return FALSE;
  880.         // Did we write a full ICONDIRENTRY ?
  881.         if( dwBytesWritten != sizeof( ICONDIRENTRY ) )
  882.             return FALSE;
  883.     }
  884.     // Write the image bits for each image
  885.     for( i=0; i<lpIR->nNumImages; i++ )
  886.     {
  887.         DWORD dwTemp = lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage;
  888.  
  889.         // Set the sizeimage member to zero
  890.         lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = 0;
  891.         // Write the image bits to file
  892.         if( ! WriteFile( hFile, lpIR->IconImages[i].lpBits, lpIR->IconImages[i].dwNumBytes, &dwBytesWritten, NULL ) )
  893.             return FALSE;
  894.         if( dwBytesWritten != lpIR->IconImages[i].dwNumBytes )
  895.             return FALSE;
  896.         // set it back
  897.         lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = dwTemp;
  898.     }
  899.     CloseHandle( hFile );
  900.     return FALSE;
  901. }
  902. /* End WriteIconToICOFile() **************************************************/
  903.  
  904.  
  905. /****************************************************************************
  906. *
  907. *     FUNCTION: IconImageToClipBoard
  908. *
  909. *     PURPOSE:  Copies an icon image to the clipboard in CF_DIB format
  910. *
  911. *     PARAMS:   LPICONIMAGE lpii - pointer to icon image data
  912. *
  913. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  914. *
  915. * History:
  916. *                July '95 - Created
  917. *
  918. \****************************************************************************/
  919. BOOL IconImageToClipBoard( LPICONIMAGE lpii )
  920. {
  921.     HANDLE    hGlobal;
  922.     LPSTR    lpBits;
  923.  
  924.     // Open the clipboard
  925.     if( OpenClipboard( hWndMain ) )
  926.     {
  927.         // empty it
  928.         if( EmptyClipboard() )
  929.         {
  930.             // Make a buffer to send to clipboard
  931.             hGlobal = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, lpii->dwNumBytes );
  932.             lpBits = GlobalLock( hGlobal );
  933.             // Copy the bits to the buffer
  934.             memcpy( lpBits, lpii->lpBits, lpii->dwNumBytes );
  935.             // Adjust for funky height*2 thing
  936.             ((LPBITMAPINFOHEADER)lpBits)->biHeight /= 2;
  937.             GlobalUnlock( hGlobal );
  938.             // Send it to the clipboard
  939.             SetClipboardData( CF_DIB, hGlobal );
  940.             CloseClipboard();
  941.             return TRUE;
  942.         }
  943.     }
  944.     return FALSE;
  945. }
  946. /* End IconImageToClipBoard() ***********************************************/
  947.  
  948.  
  949.  
  950. /****************************************************************************
  951. *
  952. *     FUNCTION: IconImageFromClipBoard
  953. *
  954. *     PURPOSE:  Creates an icon image from the CF_DIB clipboard entry
  955. *
  956. *     PARAMS:   LPICONIMAGE lpii          - pointer to icon image data
  957. *               BOOL        bStretchToFit - TRUE to stretch, FALSE to take
  958. *                                           the upper left corner of the DIB
  959. *
  960. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  961. *
  962. * History:
  963. *                July '95 - Created
  964. *
  965. \****************************************************************************/
  966. BOOL IconImageFromClipBoard( LPICONIMAGE lpii, BOOL bStretchToFit )
  967. {
  968.     LPBITMAPINFO    lpbi;
  969.     HANDLE            hClipGlobal;
  970.     BOOL            bRet = FALSE;
  971.  
  972.     // Open the clipboard
  973.     if( OpenClipboard( hWndMain ) )
  974.     {
  975.         // Get the CF_DIB data from it
  976.         if( (hClipGlobal = GetClipboardData( CF_DIB )) != NULL )
  977.         {
  978.             // Lock it down
  979.             if( (lpbi=GlobalLock(hClipGlobal)) != NULL )
  980.             {
  981.                 // Convert it to an icon image
  982.                 bRet = DIBToIconImage( lpii, (LPBYTE)lpbi, bStretchToFit );
  983.                 GlobalUnlock( hClipGlobal );
  984.             }
  985.         }
  986.         CloseClipboard();
  987.     }
  988.     return bRet;
  989. }
  990. /* End IconImageFromClipBoard() ********************************************/
  991.  
  992.  
  993.  
  994. /****************************************************************************
  995. *
  996. *     FUNCTION: DIBToIconImage
  997. *
  998. *     PURPOSE:  Converts a CF_DIB memory block to an icon image
  999. *
  1000. *     PARAMS:   LPICONIMAGE lpii          - pointer to icon image data
  1001. *               LPBYTE      lpDIB         - a pointer to the CF_DIB block
  1002. *               BOOL        bStretchToFit - TRUE to stretch, FALSE to take
  1003. *                                           the upper left corner of the DIB
  1004. *
  1005. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1006. *
  1007. * History:
  1008. *                July '95 - Created
  1009. *
  1010. \****************************************************************************/
  1011. BOOL DIBToIconImage( LPICONIMAGE lpii, LPBYTE lpDIB, BOOL bStretch )
  1012. {
  1013.     LPBYTE        lpNewDIB;
  1014.  
  1015.     // Sanity check
  1016.     if( lpDIB == NULL )
  1017.         return FALSE;
  1018.  
  1019.     // Let the DIB engine convert color depths if need be
  1020.     lpNewDIB = ConvertDIBFormat( (LPBITMAPINFO)lpDIB, lpii->Width, lpii->Height, lpii->Colors, bStretch );
  1021.  
  1022.     // Now we have a cool new DIB of the proper size/color depth
  1023.     // Lets poke it into our data structures and be done with it
  1024.  
  1025.     // How big is it?
  1026.     lpii->dwNumBytes = sizeof( BITMAPINFOHEADER )                        // Header
  1027.                     + PaletteSize( (LPSTR)lpNewDIB )                    // Palette
  1028.                     + lpii->Height * BytesPerLine( (LPBITMAPINFOHEADER)lpNewDIB )    // XOR mask
  1029.                     + lpii->Height * WIDTHBYTES( lpii->Width );            // AND mask
  1030.  
  1031.     // If there was already an image here, free it
  1032.     if( lpii->lpBits != NULL )
  1033.         free( lpii->lpBits );
  1034.     // Allocate enough room for the new image
  1035.     if( (lpii->lpBits = malloc( lpii->dwNumBytes )) == NULL )
  1036.     {
  1037.         free( lpii );
  1038.         return FALSE;
  1039.     }
  1040.     // Copy the bits
  1041.     memcpy( lpii->lpBits, lpNewDIB, sizeof( BITMAPINFOHEADER ) + PaletteSize( (LPSTR)lpNewDIB ) );
  1042.     // Adjust internal pointers/variables for new image
  1043.     lpii->lpbi = (LPBITMAPINFO)(lpii->lpBits);
  1044.     lpii->lpbi->bmiHeader.biHeight *= 2;
  1045.     lpii->lpXOR = FindDIBBits( (LPSTR)(lpii->lpBits) );
  1046.     memcpy( lpii->lpXOR, FindDIBBits((LPSTR)lpNewDIB), lpii->Height * BytesPerLine( (LPBITMAPINFOHEADER)lpNewDIB ) );
  1047.     lpii->lpAND = lpii->lpXOR + lpii->Height * BytesPerLine( (LPBITMAPINFOHEADER)lpNewDIB );
  1048.     memset( lpii->lpAND, 0, lpii->Height * WIDTHBYTES( lpii->Width ) );
  1049.     // Free the source
  1050.     free( lpNewDIB );
  1051.     return TRUE;
  1052. }
  1053. /* End DIBToIconImage() ***************************************************/
  1054.  
  1055.  
  1056.  
  1057.  
  1058. /****************************************************************************
  1059. *
  1060. *     FUNCTION: CreateBlankNewFormatIcon
  1061. *
  1062. *     PURPOSE:  Creates a blank icon image for a new format
  1063. *
  1064. *     PARAMS:   LPICONIMAGE lpii          - pointer to icon image data
  1065. *
  1066. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1067. *
  1068. * History:
  1069. *                July '95 - Created
  1070. *
  1071. \****************************************************************************/
  1072. BOOL CreateBlankNewFormatIcon( LPICONIMAGE lpii )
  1073. {
  1074.     DWORD                dwFinalSize;
  1075.     BITMAPINFOHEADER    bmih;
  1076.  
  1077.     // Fill in the bitmap header
  1078.     ZeroMemory( &bmih, sizeof( BITMAPINFOHEADER ) );
  1079.     bmih.biSize = sizeof( BITMAPINFOHEADER );
  1080.     bmih.biBitCount = lpii->Colors;
  1081.     bmih.biClrUsed = 0;
  1082.     
  1083.     // How big will the final thing be?
  1084.     // Well, it'll have a header
  1085.     dwFinalSize = sizeof( BITMAPINFOHEADER );
  1086.     // and a color table (even if it's zero length)
  1087.     dwFinalSize += PaletteSize( (LPSTR)&bmih );
  1088.     // and XOR bits
  1089.     dwFinalSize += lpii->Height * WIDTHBYTES( lpii->Width * lpii->Colors );
  1090.     // and AND bits. That's about it :)
  1091.     dwFinalSize += lpii->Height * WIDTHBYTES( lpii->Width );
  1092.  
  1093.     // Allocate some memory for it
  1094.     lpii->lpBits = malloc( dwFinalSize );
  1095.     ZeroMemory( lpii->lpBits, dwFinalSize );
  1096.     lpii->dwNumBytes = dwFinalSize;
  1097.     lpii->lpbi = (LPBITMAPINFO)(lpii->lpBits);
  1098.     lpii->lpXOR = (LPSTR)(lpii->lpbi) + sizeof(BITMAPINFOHEADER) + PaletteSize( (LPSTR)&bmih );
  1099.     lpii->lpAND = lpii->lpXOR + (lpii->Height * WIDTHBYTES( lpii->Width * lpii->Colors ));
  1100.  
  1101.     // The bitmap header is zeros, fill it out
  1102.     lpii->lpbi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); 
  1103.     lpii->lpbi->bmiHeader.biWidth = lpii->Width;
  1104.     // Don't forget the funky height*2 icon resource thing
  1105.     lpii->lpbi->bmiHeader.biHeight = lpii->Height * 2; 
  1106.     lpii->lpbi->bmiHeader.biPlanes = 1; 
  1107.     lpii->lpbi->bmiHeader.biBitCount = lpii->Colors; 
  1108.     lpii->lpbi->bmiHeader.biCompression = BI_RGB; 
  1109.                    
  1110.     return TRUE;
  1111. }
  1112. /* End CreateBlankNewFormatIcon() ******************************************/
  1113.  
  1114.  
  1115.  
  1116. /****************************************************************************
  1117. *
  1118. *     FUNCTION: GetXORImageRect
  1119. *
  1120. *     PURPOSE:  Given a bounding Rect, calculates the XOR mask display Rect 
  1121. *
  1122. *     PARAMS:   RECT        Rect   - Bounding rect for drawing area
  1123. *               LPICONIMAGE lpIcon - pointer to icon image data
  1124. *
  1125. *     RETURNS:  RECT - the rect where the XOR image will be drawn
  1126. *
  1127. * History:
  1128. *                July '95 - Created
  1129. *
  1130. \****************************************************************************/
  1131. RECT GetXORImageRect( RECT Rect, LPICONIMAGE lpIcon )
  1132. {
  1133.     RECT    NewRect;
  1134.  
  1135.     // Just center the thing in the bounding display rect
  1136.     NewRect.left = Rect.left + ((RectWidth(Rect)-lpIcon->lpbi->bmiHeader.biWidth)/2);
  1137.     NewRect.top = Rect.top + ((RectHeight(Rect)-(lpIcon->lpbi->bmiHeader.biHeight/2))/2);
  1138.     NewRect.bottom = NewRect.top + (lpIcon->lpbi->bmiHeader.biHeight/2);
  1139.     NewRect.right = NewRect.left + lpIcon->lpbi->bmiHeader.biWidth;
  1140.     return NewRect;
  1141. }
  1142. /* End GetXORImageRect() ***************************************************/
  1143.  
  1144.  
  1145.  
  1146.  
  1147. /****************************************************************************
  1148. *
  1149. *     FUNCTION: DrawXORMask
  1150. *
  1151. *     PURPOSE:  Using DIB functions, draw XOR mask on hDC in Rect
  1152. *
  1153. *     PARAMS:   HDC         hDC    - The DC on which to draw
  1154. *               RECT        Rect   - Bounding rect for drawing area
  1155. *               LPICONIMAGE lpIcon - pointer to icon image data
  1156. *
  1157. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1158. *
  1159. *     COMMENTS: Does not use any palette information since the
  1160. *               OS won't when it draws the icon anyway.
  1161. *
  1162. * History:
  1163. *                July '95 - Created
  1164. *
  1165. \****************************************************************************/
  1166. BOOL DrawXORMask( HDC hDC, RECT Rect, LPICONIMAGE lpIcon )
  1167. {
  1168.     int                x, y;
  1169.  
  1170.     // Sanity checks
  1171.     if( lpIcon == NULL )
  1172.         return FALSE;
  1173.     if( lpIcon->lpBits == NULL )
  1174.         return FALSE;
  1175.  
  1176.     // Account for height*2 thing
  1177.     lpIcon->lpbi->bmiHeader.biHeight /= 2;
  1178.  
  1179.     // Locate it
  1180.     x = Rect.left + ((RectWidth(Rect)-lpIcon->lpbi->bmiHeader.biWidth)/2);
  1181.     y = Rect.top + ((RectHeight(Rect)-lpIcon->lpbi->bmiHeader.biHeight)/2);
  1182.  
  1183.     // Blast it to the screen
  1184.     SetDIBitsToDevice( hDC, x, y, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, 0, 0, 0, lpIcon->lpbi->bmiHeader.biHeight, lpIcon->lpXOR, lpIcon->lpbi, DIB_RGB_COLORS );
  1185.  
  1186.     // UnAccount for height*2 thing
  1187.     lpIcon->lpbi->bmiHeader.biHeight *= 2;
  1188.  
  1189.     return TRUE;
  1190. }
  1191. /* End DrawXORMask() *******************************************************/
  1192.  
  1193.  
  1194.  
  1195.  
  1196. /****************************************************************************
  1197. *
  1198. *     FUNCTION: DrawANDMask
  1199. *
  1200. *     PURPOSE:  Using DIB functions, draw AND mask on hDC in Rect
  1201. *
  1202. *     PARAMS:   HDC         hDC    - The DC on which to draw
  1203. *               RECT        Rect   - Bounding rect for drawing area
  1204. *               LPICONIMAGE lpIcon - pointer to icon image data
  1205. *
  1206. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1207. *
  1208. * History:
  1209. *                July '95 - Created
  1210. *
  1211. \****************************************************************************/
  1212. BOOL DrawANDMask( HDC hDC, RECT Rect, LPICONIMAGE lpIcon )
  1213. {
  1214.     LPBITMAPINFO    lpbi;
  1215.     int                x, y;
  1216.  
  1217.     // Sanity checks
  1218.     if( lpIcon == NULL )
  1219.         return FALSE;
  1220.     if( lpIcon->lpBits == NULL )
  1221.         return FALSE;
  1222.  
  1223.     // Need a bitmap header for the mono mask
  1224.     lpbi = malloc( sizeof(BITMAPINFO) + (2 * sizeof( RGBQUAD )) );
  1225.     lpbi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
  1226.     lpbi->bmiHeader.biWidth = lpIcon->lpbi->bmiHeader.biWidth;
  1227.     lpbi->bmiHeader.biHeight = lpIcon->lpbi->bmiHeader.biHeight/2;
  1228.     lpbi->bmiHeader.biPlanes = 1;
  1229.     lpbi->bmiHeader.biBitCount = 1;
  1230.     lpbi->bmiHeader.biCompression = BI_RGB;
  1231.     lpbi->bmiHeader.biSizeImage = 0;
  1232.     lpbi->bmiHeader.biXPelsPerMeter = 0;
  1233.     lpbi->bmiHeader.biYPelsPerMeter = 0;
  1234.     lpbi->bmiHeader.biClrUsed = 0;
  1235.     lpbi->bmiHeader.biClrImportant = 0;
  1236.     lpbi->bmiColors[0].rgbRed = 0;
  1237.     lpbi->bmiColors[0].rgbGreen = 0;
  1238.     lpbi->bmiColors[0].rgbBlue = 0;
  1239.     lpbi->bmiColors[0].rgbReserved = 0;
  1240.     lpbi->bmiColors[1].rgbRed = 255;
  1241.     lpbi->bmiColors[1].rgbGreen = 255;
  1242.     lpbi->bmiColors[1].rgbBlue = 255;
  1243.     lpbi->bmiColors[1].rgbReserved = 0;
  1244.  
  1245.     // Locate it
  1246.     x = Rect.left + ((RectWidth(Rect)-lpbi->bmiHeader.biWidth)/2);
  1247.     y = Rect.top + ((RectHeight(Rect)-lpbi->bmiHeader.biHeight)/2);
  1248.  
  1249.     // Blast it to the screen
  1250.     SetDIBitsToDevice( hDC, x, y, lpbi->bmiHeader.biWidth, lpbi->bmiHeader.biHeight, 0, 0, 0, lpbi->bmiHeader.biHeight, lpIcon->lpAND, lpbi, DIB_RGB_COLORS );
  1251.  
  1252.     // clean up
  1253.     free( lpbi );
  1254.  
  1255.     return TRUE;
  1256. }
  1257. /* End DrawANDMask() *******************************************************/
  1258.  
  1259.  
  1260.  
  1261.  
  1262. /****************************************************************************
  1263. *
  1264. *     FUNCTION: MakeNewANDMaskBasedOnPoint
  1265. *
  1266. *     PURPOSE:  Creates a new AND mask for the icon image
  1267. *
  1268. *     PARAMS:   LPICONIMAGE lpIcon - pointer to icon image data
  1269. *               POINT       pt     - coords of transparent pixel
  1270. *
  1271. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1272. *
  1273. *     COMMENTS: Creates the AND mask using the color of the pixel at pt
  1274. *               as a transparent color. The XOR mask is changed as well.
  1275. *               This is because the OS expects the XOR mask to have the
  1276. *               AND mask already applied (ie black in transparent areas)
  1277. *
  1278. * History:
  1279. *                July '95 - Created
  1280. *
  1281. \****************************************************************************/
  1282. BOOL MakeNewANDMaskBasedOnPoint( LPICONIMAGE lpIcon, POINT pt )
  1283. {
  1284.     HBITMAP            hXORBitmap, hOldXORBitmap;
  1285.     HDC                hDC, hMemDC1;
  1286.     LPBYTE            pXORBits;
  1287.     COLORREF        crTransparentColor;
  1288.     LONG            i,j;
  1289.  
  1290.  
  1291.     // Account for height*2 thing
  1292.     lpIcon->lpbi->bmiHeader.biHeight /= 2;
  1293.  
  1294.     // Need a DC
  1295.     hDC = GetDC( NULL );
  1296.  
  1297.     // Use DIBSection for source
  1298.     hXORBitmap = CreateDIBSection( hDC, lpIcon->lpbi, DIB_RGB_COLORS, &pXORBits, NULL, 0  );
  1299.     memcpy( pXORBits, lpIcon->lpXOR, (lpIcon->lpbi->bmiHeader.biHeight) * BytesPerLine((LPBITMAPINFOHEADER)(lpIcon->lpbi)) );
  1300.     hMemDC1 = CreateCompatibleDC( hDC );
  1301.     hOldXORBitmap = SelectObject( hMemDC1, hXORBitmap );
  1302.  
  1303.     // Set the color table if need be
  1304.     if( lpIcon->lpbi->bmiHeader.biBitCount <= 8 )
  1305.         SetDIBColorTable( hMemDC1, 0, DIBNumColors((LPSTR)(lpIcon->lpbi)), lpIcon->lpbi->bmiColors);
  1306.     
  1307.     // What's the transparent color?
  1308.     crTransparentColor = GetPixel( hMemDC1, pt.x, pt.y );
  1309.  
  1310.     // Loop through the pixels
  1311.     for(i=0;i<lpIcon->lpbi->bmiHeader.biWidth;i++)
  1312.     {
  1313.         for(j=0;j<lpIcon->lpbi->bmiHeader.biHeight;j++)
  1314.         {
  1315.             // Is the source transparent at this point?
  1316.             if( GetPixel( hMemDC1, i, j ) == crTransparentColor )
  1317.             {
  1318.                 // Yes, so set the pixel in AND mask, and clear it in XOR mask
  1319.                 SetMonoDIBPixel( lpIcon->lpAND, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, i, j, TRUE );     
  1320.                 if( lpIcon->lpbi->bmiHeader.biBitCount == 1 )
  1321.                     SetMonoDIBPixel( pXORBits, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, i, j, FALSE );     
  1322.                 else
  1323.                     SetPixelV( hMemDC1, i, j, RGB(0,0,0) );
  1324.             }
  1325.             else
  1326.             {
  1327.                 // No, so clear pixel in AND mask
  1328.                 SetMonoDIBPixel( lpIcon->lpAND, lpIcon->lpbi->bmiHeader.biWidth, lpIcon->lpbi->bmiHeader.biHeight, i, j, FALSE );    
  1329.             }
  1330.         }
  1331.     }
  1332.     // Flush the SetPixelV() calls
  1333.     GdiFlush();
  1334.  
  1335.     SelectObject( hMemDC1, hOldXORBitmap );
  1336.  
  1337.     // Copy the new XOR bits back to our storage
  1338.     memcpy( lpIcon->lpXOR, pXORBits, (lpIcon->lpbi->bmiHeader.biHeight) * BytesPerLine((LPBITMAPINFOHEADER)(lpIcon->lpbi)) );
  1339.  
  1340.     // Clean up
  1341.     DeleteObject( hXORBitmap );
  1342.     DeleteDC( hMemDC1 );
  1343.     ReleaseDC( NULL, hDC );
  1344.  
  1345.  
  1346.     // UnAccount for height*2 thing
  1347.     lpIcon->lpbi->bmiHeader.biHeight *= 2;
  1348.     return TRUE;
  1349. }
  1350. /* End MakeNewANDMaskBasedOnPoint() *****************************************/
  1351.  
  1352.  
  1353. /****************************************************************************
  1354. *
  1355. *     FUNCTION: IconImageFromBMPFile
  1356. *
  1357. *     PURPOSE:  Creates an icon image from a BMP file
  1358. *
  1359. *     PARAMS:   LPCTSTR     szFileName    - Filename for BMP file
  1360. *               LPICONIMAGE lpii          - pointer to icon image data
  1361. *               BOOL        bStretchToFit - TRUE to stretch, FALSE to take
  1362. *                                           the upper left corner of the DIB
  1363. *
  1364. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1365. *
  1366. * History:
  1367. *                July '95 - Created
  1368. *
  1369. \****************************************************************************/
  1370. BOOL IconImageFromBMPFile( LPCTSTR szFileName, LPICONIMAGE lpii, BOOL bStretchToFit )
  1371. {
  1372.     LPBYTE            lpDIB = NULL;
  1373.     BOOL            bRet = FALSE;
  1374.  
  1375.     if( (lpDIB=ReadBMPFile(szFileName)) == NULL )
  1376.         return FALSE;
  1377.     // Convert it to an icon image
  1378.     bRet = DIBToIconImage( lpii, lpDIB, bStretchToFit );
  1379.     free( lpDIB );
  1380.     return bRet;
  1381. }
  1382. /* End IconImageFromBMPFile() ********************************************/
  1383.  
  1384.  
  1385.  
  1386.  
  1387. /****************************************************************************
  1388. *
  1389. *     FUNCTION: IconImageToBMPFile
  1390. *
  1391. *     PURPOSE:  Creates BMP file from an icon image
  1392. *
  1393. *     PARAMS:   LPCTSTR     szFileName    - Filename for BMP file
  1394. *               LPICONIMAGE lpii          - pointer to icon image data
  1395. *
  1396. *     RETURNS:  BOOL - TRUE for success, FALSE for failure
  1397. *
  1398. * History:
  1399. *                July '95 - Created
  1400. *
  1401. \****************************************************************************/
  1402. BOOL IconImageToBMPFile( LPCTSTR szFileName, LPICONIMAGE lpii )
  1403. {
  1404.     return WriteBMPFile( szFileName, (LPBYTE)lpii->lpbi );
  1405. }
  1406.  
  1407.