home *** CD-ROM | disk | FTP | other *** search
- /*
- ** $id: ssvcid icnfile.c 1.0 10/15/91 9:49 am$
- ** This file contains the code needed to read in a Windows icon file
- ** and generate a valid icon from it.
- */
- #include <windows.h>
- #include <malloc.h>
- #include <memory.h>
- #include "bitmaps.h"
- #include "icnfile.h"
-
- /*
- ** Global variables - used for InfoDisplay()
- */
- ICONDATA CurIcon;
- ICONFILEHEADER CurIconFile;
-
- /*
- ** HICON handle of created icon
- ** ReadIconFile(const char *filename); name of file to load
- **
- ** This function will read the passed file in, and create a icon
- ** whose handle will be returned to the caller.
- **
- ** Modification History:
- ** 09/06/91 LCW Created
- */
- HICON
- ReadIconFile(const char *filename)
- {
- int file;
- int i, j;
- int offset;
- int rc;
- HICON hicon = (HICON)NULL;
- HDC hdc;
- int iconx, icony, ncolors;
- OFSTRUCT reopen;
- ICONFILEHEADER header;
- ICONDATA icon, best;
- char *buffer;
- BITMAPINFO *bmi;
- char *cp, *cp2;
- char mask[512];
- char *iconDIB;
-
- /*
- ** Get some system values
- */
- hdc = GetDC(MainWindow);
- if (hdc == (HDC)NULL)
- {
- ErrorBox("ReadIconFile(): Unable to get a device context");
- return (HICON)NULL;
- }
- iconx = GetSystemMetrics(SM_CXICON);
- icony = GetSystemMetrics(SM_CYICON);
- ncolors = GetDeviceCaps(hdc, NUMCOLORS);
- ReleaseDC(MainWindow, hdc);
-
- /*
- ** Allocate some needed buffers
- */
- buffer = malloc(4712);
- if (buffer == NULL)
- {
- ErrorBox("ReadIconFile(): Unable to allocate memory for icon buffer");
- return (HICON)NULL;
- }
- bmi = (BITMAPINFO *)buffer;
- iconDIB = malloc(4096);
- if (iconDIB == NULL)
- {
- ErrorBox("ReadIconFile(): Unable to allocate memory for icon DIB");
- free(buffer);
- return (HICON)NULL;
- }
-
- file = OpenFile((LPSTR)filename, (LPOFSTRUCT)&reopen, OF_READ | OF_SHARE_DENY_NONE);
-
- if (file >= 0)
- {
- /*
- ** Read in Icon File header
- */
- rc = _lread(file, (char far *)&header, sizeof(header));
- if (rc == sizeof(header) && header.icoReserved == 0
- && header.icoResourceType == 1)
- {
- if (header.icoResourceCount != 0)
- {
- /*
- ** Look for the correct Icon by scanning through the directory for
- ** an extact match.
- */
- memset(&best, 0, sizeof(best));
-
- for (i = rc = 0 ; rc >= 0 && i < header.icoResourceCount ; ++i)
- {
- rc = _lread(file, (char far *)&icon, sizeof(ICONDATA));
- if (rc == sizeof(ICONDATA))
- {
- if (icon.width == iconx && icon.height == icony)
- {
- if (icon.colorCount == ncolors)
- {
- best = icon;
- break;
- }
- else if (icon.colorCount > best.colorCount)
- {
- if (icon.colorCount < ncolors)
- best = icon;
- }
- else
- {
- if (icon.colorCount > ncolors)
- best = icon;
- }
- }
- }
- else
- {
- ErrorBox("ReadIconFile(): Error reading icon directory");
- rc = -1;
- }
- }
-
- if (rc >= 0)
- {
- if (best.width != 0)
- {
- _llseek(file, best.icoDIBOffset, 0);
- rc = _lread(file, (LPSTR)buffer, (int)best.icoDIBSize);
- if (rc == (int)best.icoDIBSize)
- {
- offset = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * (best.colorCount - 1);
- bmi->bmiHeader.biSizeImage -= best.width * best.height / 8;
-
- if (bmi->bmiHeader.biBitCount == 1)
- {
- /*
- ** Invert Icon image - only if monochrome
- ** rc == line width in bytes
- ** cp == pointer to DIB from file
- ** cp2 == pointer to proper line in iconDIB
- */
- rc = best.width / 8 * bmi->bmiHeader.biPlanes
- * bmi->bmiHeader.biBitCount;
- cp = buffer + offset;
- cp2 = iconDIB + (best.height - 1) * rc;
-
- for (j = 0 ; j < best.height ; ++j)
- {
- memcpy(cp2, cp, rc);
- cp += rc;
- cp2 -= rc;
- }
- }
-
- /*
- ** Invert Icon mask
- ** rc == line width in bytes
- ** cp == pointer to mask DIB from file
- ** cp2 == pointer to proper line in mask
- */
- rc = best.width / 8;
- cp = buffer + offset + (int)bmi->bmiHeader.biSizeImage;
- cp2 = mask + (best.height - 1) * rc;
-
- for (j = 0 ; j < best.height ; ++j)
- {
- memcpy(cp2, cp, rc);
- cp += rc;
- cp2 -= rc;
- }
-
- if (bmi->bmiHeader.biBitCount > 1)
- {
- HBITMAP hbm;
- BITMAP bm;
-
- /*
- ** Create the DIB portion of the bitmap
- */
- bmi->bmiHeader.biHeight = best.height;
- bmi->bmiHeader.biWidth = best.width;
-
- hbm = CreateDIBitmap(hdc, (BITMAPINFOHEADER FAR *)bmi,
- CBM_INIT, (LPSTR)buffer + offset,
- (BITMAPINFO FAR *)bmi, DIB_RGB_COLORS);
-
- if (hbm != (HBITMAP)NULL)
- {
- if (GetObject(hbm, sizeof(bm), (LPSTR)&bm)
- == sizeof(bm))
- {
- rc = bm.bmWidthBytes * bm.bmPlanes * bm.bmHeight;
- if (GetBitmapBits(hbm, rc, (LPSTR)iconDIB) == rc)
- {
- bmi->bmiHeader.biPlanes = bm.bmPlanes;
- bmi->bmiHeader.biBitCount = bm.bmBitsPixel;
- }
- else
- {
- ErrorBox("ReadIconFile(): Error getting bitmap bits");
- }
- }
- else
- {
- ErrorBox("ReadIconFile(): Error getting bitmap data");
- }
- DeleteObject(hbm);
- }
- else
- {
- ErrorBox("ReadIconFile(): Error creating bitmap");
- }
- }
-
- /*
- ** Now to create the icon
- */
- hicon = CreateIcon(AppInstance, best.width, best.height,
- bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount,
- (LPSTR)mask, (LPSTR)iconDIB);
-
- if (hicon != (HICON)NULL)
- {
- CurIcon = best;
- CurIconFile = header;
- }
- }
- else
- {
- ErrorBox("ReadIconFile(): Error reading icon data");
- }
- }
- }
- }
- else
- {
- ErrorBox("ReadIconFile(): Error Icon Count is 0");
- }
- }
- else
- {
- ErrorBox("ReadIconFile(): Error Reading Icon Header");
- }
- _lclose(file);
- }
- else
- {
- ErrorBox("ReadIconFile(): Error Opening Icon File");
- }
-
- /*
- ** Free up allocated memory
- */
- free(buffer);
- free(iconDIB);
-
- return hicon;
- }
-
- /*
- ** Modification History
- ** --------------------
- ** $lgb$
- ** 10/15/91 Larry Widing Initial version for Win Tech Journal Article.
- ** $lge$
- */
-