home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows
- // (C) Copyright 1994 by Borland International, All Rights Reserved
- //
- // Implementation of TOleMetaPict, manipulates Ole2 MetafilePict/Icon
- //----------------------------------------------------------------------------
- #define INC_OLE2
- #include <owl/owlpch.h>
- #include <owl/oledlg.h>
-
- //
- // OWL OLE Dialog diagnostic group.
- //
- DIAG_DECLARE_GROUP(OwlOleDlg);
-
- //
- // Class used for label and source extraction from a metafile
- //
- class _OWLCLASS TLabelExtract {
- public:
- //
- // Use memset to initialize PODS
- //
- TLabelExtract() {memset(this, 0, sizeof(TLabelExtract));}
-
- LPSTR lpsz;
- UINT Index; // index in lpsz (so we can retrieve 2+ lines)
- DWORD PrevIndex; // index of last line (so we can mimic word wrap)
-
- union {
- UINT cch; //Length of label for label extraction
- UINT iIcon; //Index of icon in source extraction.
- } u;
-
- //
- //For internal use in enum procs
- //
- BOOL fFoundIconOnly;
- BOOL fFoundSource;
- BOOL fFoundIndex;
- };
-
- //
- // Class used for extracting icons from a metafile (CreateIcon parameters)
- //
- class _OWLCLASS TIconExtract {
- public:
- //
- // Use memset to initialize PODS
- //
- TIconExtract() {memset(this, 0, sizeof(TIconExtract));}
-
- HICON hIcon; // Icon created in the enumeration proc.
- BOOL fAND;
- HGLOBAL hMemAND; // Enumeration proc allocates and copies
- HINSTANCE hInst; // Module instance handle
- };
-
- //
- // Class used to pass info to EnumMetafileDraw
- //
- class _OWLCLASS TDrawInfo {
- public:
- //
- // Use memset to initialize PODS
- //
- TDrawInfo() {memset(this, 0, sizeof(TDrawInfo));}
-
- RECT Rect;
- BOOL fIconOnly;
- };
-
- //
- // String [comment] in Metafile which flags that the label follows
- //
- static char szIconOnly[] = "IconOnly";
-
- int CALLBACK __export EnumMetafileIconDraw(HDC, HANDLETABLE FAR*, METARECORD FAR*, int, LPARAM);
- int CALLBACK __export EnumMetafileExtractLabel(HDC, HANDLETABLE FAR*, METARECORD FAR*, int, TLabelExtract far*);
- int CALLBACK __export EnumMetafileExtractIcon(HDC, HANDLETABLE FAR*, METARECORD FAR*, int, TIconExtract far*);
- int CALLBACK __export EnumMetafileExtractIconSource(HDC, HANDLETABLE FAR*, METARECORD FAR*, int, TLabelExtract far*);
-
- //
- //
- //
- static uint
- MapLogHimToPix(int hiMetric, int pelsPerInch)
- {
- return (uint)(((double)hiMetric * pelsPerInch)/HiMetricPerInch);
- }
-
- //
- //
- //
- static int
- XformWidthInHimetricToPixels(TDC& dc, int widthInHiMetric)
- {
- int logPix = dc.GetDeviceCaps(LOGPIXELSX);
- int pixWidth = MapLogHimToPix(widthInHiMetric, logPix);
- return pixWidth;
- }
-
- //
- //
- //
- static int
- XformHeightInHimetricToPixels(TDC& dc, int heightInHiMetric)
- {
- int logPix = dc.GetDeviceCaps(LOGPIXELSY);
- int pixHeight = MapLogHimToPix(heightInHiMetric, logPix);
- return pixHeight;
- }
-
- //
- //
- //
- BOOL
- OleUIMetafilePictIconDraw(HDC hDC, LPRECT pRect,
- HGLOBAL hMetaPict, BOOL fIconOnly)
- {
- LPMETAFILEPICT pMF;
- TDrawInfo di;
- int cx, cy;
- SIZE size;
- POINT point;
-
- if (!hMetaPict)
- return FALSE;
-
- pMF = (LPMETAFILEPICT)GlobalLock(hMetaPict);
-
- if (NULL==pMF) {
- TRACEX(OwlOleDlg, 1, "Unable to lock MetaPict Handle");
- return FALSE;
- }
-
- di.Rect = *pRect;
- di.fIconOnly = fIconOnly;
-
- //
- // Transform to back to pixels
- //
- cx = XformWidthInHimetricToPixels(TDC(hDC), pMF->xExt);
- cy = XformHeightInHimetricToPixels(TDC(hDC), pMF->yExt);
-
- SaveDC(hDC);
-
- SetMapMode(hDC, pMF->mm);
- SetViewportOrgEx(hDC, (pRect->right - cx) / 2, 0, &point);
-
- SetViewportExtEx(hDC, min ((pRect->right - cx) / 2 + cx, cx), cy, &size);
-
- if (fIconOnly) {
- EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileIconDraw,
- (LPARAM)(TDrawInfo far*)&di);
- }
- else {
- PlayMetaFile(hDC, pMF->hMF);
- }
-
- RestoreDC(hDC, -1);
- GlobalUnlock(hMetaPict);
- return TRUE;
- }
-
- int CALLBACK __export
- EnumMetafileIconDraw(HDC hDC, HANDLETABLE FAR *phTable,
- METARECORD FAR *pMFR,
- int cObj, LPARAM lParam)
- {
- TDrawInfo far* lpdi = (TDrawInfo far*)lParam;
-
- //
- // We play everything blindly except for DIBBITBLT (or DIBSTRETCHBLT)
- // and ESCAPE with MFCOMMENT. For the BitBlts we change the x,y to
- // draw at (0,0) instead of wherever it was written to draw. The
- // comment tells us there to stop if we don't want to draw the label.
- //
-
- //
- //If we're playing icon only, stop enumeration at the comment.
- //
- if (lpdi->fIconOnly) {
- if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) {
- if (0==lstrcmpi(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
- return 0;
- }
-
- //
- // Check for the records in which we want to munge the coordinates.
- // destX is offset 6 for BitBlt, offset 9 for StretchBlt, either of
- // which may appear in the metafile.
- //
- if (META_DIBBITBLT==pMFR->rdFunction)
- pMFR->rdParm[6]=0;
-
- if (META_DIBSTRETCHBLT==pMFR->rdFunction)
- pMFR->rdParm[9] = 0;
- }
-
- PlayMetaFileRecord(hDC, phTable, pMFR, cObj);
- return 1;
- }
-
- UINT
- OleUIMetafilePictExtractLabel(HGLOBAL hMetaPict, LPSTR lpszLabel,
- UINT cchLabel, LPDWORD lpWrapIndex)
- {
- LPMETAFILEPICT pMF;
- TLabelExtract le;
- HDC hDC;
-
- //
- // We extract the label by getting a screen DC and walking the metafile
- // records until we see the ExtTextOut record we put there. That
- // record will have the string embedded in it which we then copy out.
- //
- if (!hMetaPict || !lpszLabel || !cchLabel)
- return FALSE;
-
- pMF= (LPMETAFILEPICT)GlobalLock(hMetaPict);
-
- if (NULL==pMF)
- return FALSE;
-
- le.lpsz=lpszLabel;
- le.u.cch=cchLabel;
- le.Index=0;
- le.fFoundIconOnly=FALSE;
- le.fFoundSource=FALSE;
- le.fFoundIndex=FALSE;
- le.PrevIndex = 0;
-
- //
- // Use a screen DC so we have something valid to pass in.
- //
- hDC=GetDC(NULL);
- EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractLabel,
- (LONG)(TLabelExtract far*)&le);
- ReleaseDC(NULL, hDC);
-
- GlobalUnlock(hMetaPict);
-
- //
- // Tell where we wrapped (if calling function cares)
- //
- if (lpWrapIndex)
- *lpWrapIndex = le.PrevIndex;
-
- //
- // Return amount of text copied
- //
- return le.u.cch;
- }
-
- int CALLBACK __export
- EnumMetafileExtractLabel(HDC /*hDC*/,
- HANDLETABLE FAR* /*phTable*/,
- METARECORD FAR *pMFR,
- int /*cObj*/,
- TLabelExtract far* pLE)
- {
- //
- // We don't allow anything to happen until we see "IconOnly"
- // in an MFCOMMENT that is used to enable everything else.
- //
- if (!pLE->fFoundIconOnly) {
- if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) {
- if (0==lstrcmpi(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
- pLE->fFoundIconOnly=TRUE;
- }
-
- return 1;
- }
-
- //
- // Enumerate all records looking for META_EXTTEXTOUT - there can be more
- // than one.
- //
- if (META_EXTTEXTOUT==pMFR->rdFunction) {
- UINT cchMax;
- LPSTR lpszTemp;
-
- //
- // If ExtTextOut has NULL fuOptions, then the rectangle is omitted
- // from the record, and the string starts at rdParm[4]. If
- // fuOptions is non-NULL, then the string starts at rdParm[8]
- // (since the rectange takes up four WORDs in the array). In
- // both cases, the string continues for (rdParm[2]+1) >> 1
- // words. We just cast a pointer to rdParm[8] to an LPSTR and
- // lstrcpyn into the buffer we were given.
- //
- // Note that we use element 8 in rdParm instead of 4 because we
- // passed ETO_CLIPPED in for the options on ExtTextOut--docs say
- // [4] which is rect doesn't exist if we passed zero there.
- //
- //
- cchMax=min(pLE->u.cch - pLE->Index, (UINT)pMFR->rdParm[2]);
- lpszTemp = pLE->lpsz + pLE->Index;
-
- lstrcpyn(lpszTemp, (LPSTR)&(pMFR->rdParm[8]), cchMax + 1);
-
- pLE->PrevIndex = pLE->Index;
- pLE->Index += cchMax;
- }
-
- return 1;
- }
-
- HICON
- OleUIMetafilePictExtractIcon(HGLOBAL hMetaPict, HINSTANCE hinst)
- {
- LPMETAFILEPICT pMF;
- HDC hDC;
- TIconExtract ie;
-
- //
- // We extract the label by getting a screen DC and walking the metafile
- // records until we see the ExtTextOut record we put there. That
- // record will have the string embedded in it which we then copy out.
- //
-
- if (NULL==hMetaPict)
- return NULL;
-
- pMF= (LPMETAFILEPICT)GlobalLock(hMetaPict);
-
- if (NULL==pMF)
- return FALSE;
-
- ie.fAND=TRUE;
- ie.hInst = hinst;
-
- hDC=GetDC(NULL);
- EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIcon,
- (LONG)(TIconExtract far*)&ie);
- ReleaseDC(NULL, hDC);
- GlobalUnlock(hMetaPict);
-
- return ie.hIcon;
- }
-
- int CALLBACK __export
- EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR* /*phTable*/,
- METARECORD FAR *pMFR, int /*cObj*/,
- TIconExtract far* pIE)
- {
- LPBITMAPINFO lpBI;
- LPBITMAPINFOHEADER lpBH;
- LPBYTE lpbSrc;
- LPBYTE lpbDst;
- UINT uWidth, uHeight;
- DWORD cb;
- HGLOBAL hMem;
- BITMAP bm;
- HBITMAP hBmp;
-
- //
- // Continue enumeration if we don't see the records we want.
- //
- if (META_DIBBITBLT != pMFR->rdFunction &&
- META_DIBSTRETCHBLT != pMFR->rdFunction)
- return 1;
-
- //
- // Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses
- // META_DIBSTRETCHBLT so we have to handle each case separately.
- //
-
- if (META_DIBBITBLT==pMFR->rdFunction) {
- //
- // Get dimensions and the BITMAPINFO struct.
- //
- uHeight=pMFR->rdParm[1];
- uWidth =pMFR->rdParm[2];
- lpBI=(LPBITMAPINFO)&(pMFR->rdParm[8]);
- }
- if (META_DIBSTRETCHBLT==pMFR->rdFunction) {
- //
- // Get dimensions and the BITMAPINFO struct.
- //
- uHeight=pMFR->rdParm[2];
- uWidth =pMFR->rdParm[3];
- lpBI=(LPBITMAPINFO)&(pMFR->rdParm[10]);
- }
-
- lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader);
-
- //
- // Pointer to the bits which follows the BITMAPINFO structure.
- //
- lpbSrc=(LPBYTE)lpBI+sizeof(BITMAPINFOHEADER);
-
- //
- // Add the length of the color table.
- //
- if (0!=lpBH->biClrUsed)
- lpbSrc+=(int)(DWORD)(lpBH->biClrUsed*sizeof(RGBQUAD));
- else {
- //
- // 1 << bc gives 2, 16, 256 for 1, 4, or 256 colors
- lpbSrc+=(int)(DWORD)((1 << (lpBH->biBitCount))*sizeof(RGBQUAD));
- }
-
- //
- // All the bits we have in lpbSrc are device-independent, so we
- // need to change them over to be device-dependent using SetDIBits.
- // Once we have a bitmap with the device-dependent bits, we can
- // GetBitmapBits to have buffers with the real data.
- //
- // For each pass we have to allocate memory for the bits. We save
- // the memory for the mask between passes.
- //
-
- //
- // Use CreateBitmap for ANY monochrome bitmaps
- //
- if (pIE->fAND || 1==lpBH->biBitCount || lpBH->biBitCount > 8)
- hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL);
- else if (lpBH->biBitCount <= 8)
- hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight);
-
- if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight,
- (LPVOID)lpbSrc, lpBI, DIB_RGB_COLORS)) {
- if (!pIE->fAND)
- GlobalFree(pIE->hMemAND);
-
- DeleteObject(hBmp);
- return 0;
- }
-
- //
- // Allocate memory and get the DDBits into it.
- //
- GetObject(hBmp, sizeof(bm), &bm);
-
- cb=bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes;
-
- hMem=GlobalAlloc(GHND, cb);
-
- if (NULL==hMem) {
- if (NULL!=pIE->hMemAND)
- GlobalFree(pIE->hMemAND);
-
- DeleteObject(hBmp);
- return 0;
- }
-
- lpbDst=(LPBYTE)GlobalLock(hMem);
- GetBitmapBits(hBmp, cb, (LPVOID)lpbDst);
-
- DeleteObject(hBmp);
- GlobalUnlock(hMem);
-
- //
- // If this is the first pass (pIE->fAND==TRUE) then save the memory
- // of the AND bits for the next pass.
- //
- if (pIE->fAND) {
- pIE->fAND=FALSE;
- pIE->hMemAND=hMem;
-
- //
- // Continue enumeration looking for the next blt record.
- //
- return 1;
- }
- else {
- //
- // Get the AND pointer again.
- //
- lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND);
-
- //
- // Create the icon now that we have all the data. lpbDst already
- // points to the XOR bits.
- //
- pIE->hIcon=CreateIcon(pIE->hInst, uWidth, uHeight, (BYTE)bm.bmPlanes,
- (BYTE)bm.bmBitsPixel, (LPVOID)lpbSrc,
- (LPVOID)lpbDst);
-
- GlobalUnlock(pIE->hMemAND);
- GlobalFree(pIE->hMemAND);
- GlobalFree(hMem);
-
- //
- // We're done so we can stop.
- //
- return 0;
- }
- }
-
- BOOL OleUIMetafilePictExtractIconSource(HGLOBAL hMetaPict,
- LPSTR lpszSource,
- UINT FAR *piIcon)
- {
- LPMETAFILEPICT pMF;
- TLabelExtract le;
- HDC hDC;
-
- //
- // We will walk the metafile looking for the two comment records
- // following the IconOnly comment. The flags fFoundIconOnly and
- // fFoundSource indicate if we have found IconOnly and if we have
- // found the source comment already.
- //
- if (NULL==hMetaPict || NULL==lpszSource || NULL==piIcon)
- return FALSE;
-
- pMF=(LPMETAFILEPICT)GlobalLock(hMetaPict);
-
- if (NULL==pMF)
- return FALSE;
-
- le.lpsz=lpszSource;
- le.fFoundIconOnly=FALSE;
- le.fFoundSource=FALSE;
- le.fFoundIndex=FALSE;
-
- //
- // Use a screen DC so we have something valid to pass in.
- //
- hDC=GetDC(NULL);
- EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIconSource,
- (LONG)(TLabelExtract far*)&le);
- ReleaseDC(NULL, hDC);
-
- GlobalUnlock(hMetaPict);
-
- //
- // Copy the icon index to the caller's variable.
- //
- *piIcon=le.u.iIcon;
-
- //
- // Check that we found everything.
- //
- return (le.fFoundIconOnly && le.fFoundSource && le.fFoundIndex);
- }
-
- int CALLBACK __export
- EnumMetafileExtractIconSource(HDC /*hDC*/,
- HANDLETABLE FAR* /*phTable*/,
- METARECORD FAR *pMFR,
- int /*cObj*/,
- TLabelExtract far* pLE)
- {
- LPSTR psz;
-
- //
- // We don't allow anything to happen until we see "IconOnly"
- // in an MFCOMMENT that is used to enable everything else.
- //
- if (!pLE->fFoundIconOnly) {
- if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) {
- if (0==lstrcmpi(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
- pLE->fFoundIconOnly=TRUE;
- }
-
- return 1;
- }
-
- //
- // Now see if we find the source string.
- //
- if (!pLE->fFoundSource) {
- if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) {
- strcpyn(pLE->lpsz, (LPSTR)&pMFR->rdParm[2], MaxPathLen);
- pLE->lpsz[MaxPathLen-1] = '\0';
- pLE->fFoundSource=TRUE;
- }
-
- return 1;
- }
-
- //
- // Next comment will be the icon index.
- //
- if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0]) {
- //
- // This string contains the icon index in string form,
- // so we need to convert back to a UINT. After we see this
- // we can stop the enumeration. The comment will have
- // a null terminator because we made sure to save it.
- //
- psz=(LPSTR)&pMFR->rdParm[2];
- pLE->u.iIcon=0;
-
- //
- // Do Ye Olde atoi
- //
- while (*psz)
- pLE->u.iIcon=(10*pLE->u.iIcon)+((*psz++)-'0');
-
- pLE->fFoundIndex=TRUE;
- return 0;
- }
-
- return 1;
- }
-
- //
- // Aliases an OLE MetafilePictIcon
- //
- TOleMetaPict::TOleMetaPict(HGLOBAL metaPict, TAutoDelete autoDelete):
- MetaPict(metaPict), ShouldDelete(autoDelete==AutoDelete)
- {}
-
- //
- // Frees Metafile and Memory handle (if ShouldDelete)
- //
- TOleMetaPict::~TOleMetaPict()
- {
- if (ShouldDelete)
- Free(MetaPict);
- }
-
- //
- // Frees the Metafile Handle and Global Memory Handle
- //
- bool
- TOleMetaPict::Free(HGLOBAL& metaPict)
- {
- if (!metaPict)
- return false;
-
- LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(metaPict);
- if (!pMF) {
- TRACEX(OwlOleDlg, 1, "Unable to lock MetaPict Handle");
- return false;
- }
-
- if (pMF->hMF)
- DeleteMetaFile(pMF->hMF);
-
- GlobalUnlock(metaPict);
- GlobalFree(metaPict);
- metaPict = 0;
- return true;
- }
-
- //
- //
- //
- bool
- TOleMetaPict::Draw(TDC& dc, TRect& rect, bool iconOnly) const
- {
- PRECONDITION(MetaPict);
- return OleUIMetafilePictIconDraw(dc, &rect, MetaPict, iconOnly) ?
- true : false;
- }
-
- //
- //
- //
- int
- TOleMetaPict::ExtractLabel(char far* label, uint32 *wrap) const
- {
- PRECONDITION(MetaPict);
- return OleUIMetafilePictExtractLabel(MetaPict, label, MaxLabelLen, wrap);
- }
-
- //
- //
- //
- HICON
- TOleMetaPict::ExtractIcon(HINSTANCE hinst) const
- {
- PRECONDITION(MetaPict);
- return OleUIMetafilePictExtractIcon(MetaPict, hinst);
- }
-
- //
- //
- //
- bool
- TOleMetaPict::ExtractIconSource(char far* source, uint& index) const
- {
- PRECONDITION(MetaPict);
- return OleUIMetafilePictExtractIconSource(MetaPict, source, &index);
- }
-