/* * VFWDIB - a sample Embedded Window DLL for MediaView. This DLL uses * the Video for Windows DIB library to decompress and Blt a DIB * display. DIBs can be compressed with any of the VFW CODECs. * It will also display an uncompressed DIB. * * The Video for Windows DIB routines handle all the necessary * palette changing. * * To use this DLL, the MediaView title uses an embedded window * statement of the form: * {ewX VFWDIB, VFWDIB, filename optional-arguments} * Where X is L, R, or C (left, right, character) * filename is the filename of the dib (must be in baggage) * optional arguments are: * /Wx - where x is the desired width * /Hy - where y is the desired height * If the optional arguments are given, the picture will be stretched * into the W and H dimensions. Otherwise the size will default to * the DIB picture size. */ #include #include #include #include #include #include #include "vfwdib.h" /* forward declarations */ extern int WINAPI InitiateVFWDIB(HINSTANCE hInstance); extern int WINAPI TerminateVFWDIB(HINSTANCE hInstance); extern int WINAPI LibMain(HINSTANCE hInstance,unsigned short wDataSeg,unsigned short wHeapSize,char __far *lpCmdLine); extern long CALLBACK EWProc(HWND hWnd,unsigned int msg,unsigned int wParam,long lParam); extern long InitEW(HWND hWnd, WPARAM wParam, LPARAM lParam); extern long DestroyEW(HWND hWnd, WPARAM wParam, LPARAM lParam); extern long PrintEW(HWND hWnd, LPRENDERINFO lpRI); extern long _export GetEWSize(HWND hWnd, HDC hDC, LPPOINT lpP); extern long ActivateEW(HWND hWnd, WPARAM wParam, LPARAM lParam); extern long GetEWPalette(HWND hWnd, WPARAM wParam, LPARAM lParam); extern long CopyEW(HWND hWnd, UINT flags, LPRENDERINFO lpRI); extern long PaintEW(HWND hWnd, HDC hDC, LPRECT lprc); LPSTR dupString(LPSTR lp); int _loadds ParseAuthorData(LPDIBINFO lpDIB); int ReadDIB(LPDIBINFO lpDIB); int szToInt(LPSTR lp); /* preserve the instance handle */ HINSTANCE ghInst = 0; char szEWClassName[] = "VFWDIB"; /* * Initilize the DLL: create the Window class. */ int WINAPI InitiateVFWDIB(HINSTANCE hInst) { WNDCLASS wc; wc.lpszClassName = szEWClassName; wc.style = CS_VREDRAW | CS_HREDRAW; wc.hCursor = 0; wc.hIcon = 0; wc.lpszMenuName = 0; wc.hbrBackground = COLOR_WINDOW + 1; wc.hInstance = hInst; wc.lpfnWndProc = EWProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(long); if (!RegisterClass(&wc)) return FALSE; /* any other initialization code goes here */ return TRUE; } /* * Exiting DLL. Clean up Window class. */ int WINAPI TerminateVFWDIB(HINSTANCE hInst) { UnregisterClass(szEWClassName, hInst); return(0); } /**************************************************************************** ** FUNCTION: LibMain ** ** PURPOSE: initialize the embedded window DLL ** ** COMMENTS: ** ****************************************************************************/ BOOL WINAPI LibMain( HINSTANCE hInstance, WORD wDataSeg, WORD wHeapSize, LPSTR lpCmdLine) { return(InitiateVFWDIB(hInstance)); } /**************************************************************************** ** FUNCTION: EWProc ** ** PURPOSE: Embedded Window procedure. Handles all messages, ** ** including the EWM_* messages sent from MediaView. ** ** COMMENTS: ** ** Return TRUE/FALSE for EWM_* messages, or Windows message ** ** returns as needed. ** ****************************************************************************/ long CALLBACK EWProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { long iRet; PAINTSTRUCT ps; RECT rect; switch(msg) { case WM_CREATE: /* put any window initialization code here */ return InitEW(hWnd, wParam, lParam); case WM_DESTROY: return DestroyEW(hWnd, wParam, lParam); break; case WM_PAINT: { BeginPaint( hWnd, &ps); GetClientRect(hWnd, &rect); iRet = PaintEW(hWnd, ps.hdc, &rect); EndPaint( hWnd, &ps); return(iRet); } case EWM_COPY: /* Copy text if there is any. */ return CopyEW(hWnd, wParam, (LPRENDERINFO)lParam); case EWM_PRINT: /* print the pane */ return(PrintEW(hWnd, (LPRENDERINFO)lParam)); case EWM_QUERYSIZE: /* return the embedded window size */ return GetEWSize(hWnd, (HDC)wParam, (LPPOINT)lParam); case EWM_ACTIVATE: return ActivateEW(hWnd, wParam, lParam); case EWM_ASKPALETTE: return GetEWPalette(hWnd, wParam, lParam); default: return DefWindowProc(hWnd, msg, wParam, lParam); } } /**************************************************************************** ** FUNCTION: InitEW ** ** PURPOSE: Initialize the embedded window. ** ** COMMENTS: ** ****************************************************************************/ long InitEW(HWND hWnd, WPARAM wParam, LPARAM lParam) { LPCREATESTRUCT lpCreate; LPEWDATA lpEW; LPDIBINFO lpDIB; /* * The Embedded Window is being created. The lpCreateParams * contains an EWDATA structure. */ lpCreate = (LPCREATESTRUCT)lParam; lpEW = (LPEWDATA)lpCreate->lpCreateParams; if (lpEW == NULL) return -1; /* create a structure that keeps track of the DIB */ lpDIB = (LPDIBINFO)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(DIBINFO)); if (lpDIB == NULL) return(-1); /* save it with the window */ SetLPDIB(hWnd, lpDIB); SetLPDIB(hWnd, lpDIB); /* and make copies of volatile data */ _fmemcpy(&lpDIB->ew, lpEW, sizeof(EWDATA)); lpDIB->ew.szFileName = dupString(lpDIB->ew.szFileName); lpDIB->ew.szAuthorData = dupString(lpDIB->ew.szAuthorData); /* parse the author data string */ if (ParseAuthorData(lpDIB)) { DestroyEW(hWnd, wParam, lParam); return(-1); } /* read the bitmap out of the title */ if (ReadDIB(lpDIB)) { DestroyEW(hWnd, wParam, lParam); return(-1); } return(0); } /**************************************************************************** ** FUNCTION: DestroyEW ** ** PURPOSE: Destroy the embedded window. ** ** COMMENTS: ** ****************************************************************************/ long DestroyEW(HWND hWnd, WPARAM wParam, LPARAM lParam) { LPDIBINFO lpDIB = GetLPDIB(hWnd); if (lpDIB->hdd) DrawDibClose(lpDIB->hdd); if (lpDIB->ew.szFileName) GlobalFreePtr(lpDIB->ew.szFileName); if (lpDIB->ew.szAuthorData) GlobalFreePtr(lpDIB->ew.szAuthorData); if (lpDIB->szBagFileName) GlobalFreePtr(lpDIB->szBagFileName); GlobalFreePtr(lpDIB); return(0); } /**************************************************************************** ** FUNCTION: PrintEW ** ** PURPOSE: Render the Embedded Window. ** ** COMMENTS: ** ** The DIB is kept compressed in memory (saving space) and is ** ** explicitly decompressed only when we print. ****************************************************************************/ long PrintEW(HWND hWnd, LPRENDERINFO lpRI) { HDC hScreenDC, hMemDC; LPDIBINFO lpDIB = GetLPDIB(hWnd); HBITMAP hMemBM, hOldBM; UINT offBits; LPBITMAPINFOHEADER lpBI; HIC hic; LPBYTE scratch[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)]; LPBYTE lpBits; int cleanup = FALSE; offBits = (WORD)lpDIB->lpBI->biSize + (WORD)lpDIB->lpBI->biClrUsed * sizeof(RGBQUAD); lpBI = (LPBITMAPINFOHEADER)scratch; hic = ICGetDisplayFormat(0, lpDIB->lpBI, lpBI, 0, 0, 0); if (hic) { lpBits = GlobalAllocPtr(GHND, lpBI->biSizeImage); ICDecompress(hic, 0, lpDIB->lpBI, (LPBYTE)lpDIB->lpBI + offBits, lpBI, lpBits); ICClose(hic); cleanup = TRUE; } else return(FALSE); /* create a memory DC for decompressing */ hScreenDC = GetDC(hWnd); /* get the picture into a MemDC */ hMemDC = CreateCompatibleDC(hScreenDC); hMemBM = CreateCompatibleBitmap(hScreenDC, (WORD)lpDIB->lpBI->biWidth, (WORD)lpDIB->lpBI->biHeight); SetDIBits(hScreenDC, hMemBM, 0, (WORD)lpDIB->lpBI->biHeight, lpBits, (LPBITMAPINFO)lpDIB->lpBI, DIB_RGB_COLORS); hOldBM = SelectObject(hMemDC, hMemBM); StretchBlt( lpRI->hdc, lpRI->rc.left, lpRI->rc.top, lpRI->rc.right - lpRI->rc.left, lpRI->rc.bottom - lpRI->rc.top, hMemDC, 0, 0, (int)lpDIB->lpBI->biWidth, (int)lpDIB->lpBI->biHeight, SRCCOPY); SelectObject(hMemDC, hOldBM); DeleteDC(hMemDC); DeleteObject(hMemBM); if (cleanup) GlobalFreePtr(lpBits); return(TRUE); } /**************************************************************************** ** FUNCTION: GetEWSize ** ** PURPOSE: Tell MediaView the Embedded Window size ... this might ** ** be the Author declared size, or by default, the bitmap size. ** ** COMMENTS: ** ****************************************************************************/ long _export GetEWSize(HWND hWnd, HDC hDC, LPPOINT lpP) { LPDIBINFO lpDIB = GetLPDIB(hWnd); HDC hDCDisplay; int displayX, displayY; int printerX, printerY; if (lpDIB == 0) return(FALSE); lpP->x = lpDIB->width; lpP->y = lpDIB->height; /* If this is a printer DC, scale the size appropriately. */ if (GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER) { /* get the display characteristics */ hDCDisplay = CreateIC("DISPLAY", 0, 0, 0); displayX = GetDeviceCaps (hDCDisplay, LOGPIXELSX); displayY = GetDeviceCaps (hDCDisplay, LOGPIXELSY); DeleteDC(hDCDisplay); /* scale the bitmap to fit the printer */ printerX = GetDeviceCaps (hDC, LOGPIXELSX); printerY = GetDeviceCaps (hDC, LOGPIXELSY); // determine amount to magnify or shrink if (printerX < displayX) printerX = lpP->x / (displayX/printerX); else printerX = lpP->x * (printerX/displayX); if (printerY < displayX) printerY = lpP->y / (displayY/printerY); else printerY = lpP->y * (printerY/displayY); lpP->x = printerX; lpP->y = printerY; } return(TRUE); } /**************************************************************************** ** FUNCTION: ActivateEW ** ** PURPOSE: MediaView wants any Media engines in this EW activated. ** ** COMMENTS: ** ****************************************************************************/ long ActivateEW(HWND hWnd, WPARAM wParam, LPARAM lParam) { return(TRUE); } /**************************************************************************** ** FUNCTION: GetEWPalette ** ** PURPOSE: Return a palette if one is needed. ** ** COMMENTS: ** ****************************************************************************/ long GetEWPalette(HWND hWnd, WPARAM wParam, LPARAM lParam) { return(0); } /**************************************************************************** ** FUNCTION: CopyEW ** ** PURPOSE: If this EW contains text, pass the CF_TEXT back to ** ** MediaView. ** ** COMMENTS: ** ****************************************************************************/ long CopyEW(HWND hWnd, WPARAM flags, LPRENDERINFO lpRI) { return(FALSE); } /**************************************************************************** ** FUNCTION: PaintEW ** ** PURPOSE: Paint the DIB into the hDC ** ** COMMENTS: ** ** If the DIB is compressed using an installed CODEC, the ** ** DrawDibDraw routine will automatically decompress it. ** ****************************************************************************/ long PaintEW(HWND hWnd, HDC hDC, LPRECT lpR) { LPDIBINFO lpDIB = GetLPDIB(hWnd); HDRAWDIB hdd; UINT offBits; if (lpDIB) { hdd = DrawDibOpen(); /* * This is ICDecompress + Dither + StretchBlt all in one. */ offBits = (WORD)lpDIB->lpBI->biSize + (WORD)lpDIB->lpBI->biClrUsed * sizeof(RGBQUAD); if (DrawDibDraw(hdd, hDC, lpR->left, lpR->top, lpR->right - lpR->left, lpR->bottom - lpR->top, lpDIB->lpBI, (LPBYTE)(lpDIB->lpBI) + offBits, 0, 0, (int)lpDIB->lpBI->biWidth, (int)lpDIB->lpBI->biHeight, DDF_BACKGROUNDPAL) == 0) { /* on draw error, paint it gray */ FillRect(hDC, lpR, GetStockObject(DKGRAY_BRUSH)); } DrawDibClose(hdd); } return(TRUE); } /**************************************************************************** ** FUNCTION: dupString ** ** PURPOSE: allocate a duplicate of the string ** ** COMMENTS: ** ****************************************************************************/ LPSTR dupString(LPSTR lp) { LPSTR nlp = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, _fstrlen(lp) + 1); _fstrcpy(nlp, lp); return(nlp); } /**************************************************************************** ** FUNCTION: ParseAuthorData ** ** PURPOSE: get the baggage filename and any arguments ** ** COMMENTS: ** ** optional arguments (in AuthorData) are ** ** /Hxxx (height) ** ** /Wxxx (width) ** ****************************************************************************/ int _loadds ParseAuthorData(LPDIBINFO lpDIB) { LPSTR lp = lpDIB->ew.szAuthorData; LPSTR lpEnd; /* skip leading space */ while (*lp && *lp == ' ') ++lp; /* all files must be in baggage; ignore '!' inidicator */ if (*lp == '!') ++lp; /* find end of name */ lpEnd = lp; while (*lpEnd && *lpEnd != ' ') ++lpEnd; *lpEnd++ = 0; if ((lpDIB->szBagFileName = dupString(lp)) == 0) return(-1); /* any optional arguments? */ lp = lpEnd; while (*lp) { /* skip white space */ while (*lp && *lp == ' ') ++lp; if (*lp) { lpEnd = lp; while (*lpEnd && *lpEnd != ' ') ++lpEnd; *lpEnd++ = 0; /* match any arguments? */ if (_fstrnicmp("/H", lp, 2) == 0) { /* set the Height */ lpDIB->height = szToInt(lp+2); } else if (_fstrnicmp("/w", lp, 2) == 0) { /* set the Width */ lpDIB->width = szToInt(lp+2); } lp = lpEnd; } } return(0); } int szToInt(LPSTR lp) { int i; i = 0; while (*lp && *lp >= '0' && *lp <= '9') { i = i*10 + *lp - '0'; ++lp; } return(i); } /**************************************************************************** ** FUNCTION: ReadDib ** ** PURPOSE: Read the DIB from the (baggage) internal file system. ** ** Do some consistancy checking on the header. ** ** COMMENTS: ** ****************************************************************************/ int ReadDIB(LPDIBINFO lpDIB) { char szPath[2*_MAX_PATH]; HFILE hFile; int len, iRet = 0; long size; BITMAPFILEHEADER bf; /* Construct a baggage filename (title+fil) and try to open the file. */ _fstrcpy(szPath, lpDIB->ew.szFileName); len = _fstrlen(szPath); szPath[len] = '+'; szPath[len+1] = 0; _fstrcat(szPath, lpDIB->szBagFileName); hFile = mmioOpen(szPath, NULL, MMIO_READ); if (hFile == 0) return(-1); /* how big is the file? */ size = mmioSeek(hFile, 0, SEEK_END) - sizeof(bf); mmioSeek(hFile, 0, SEEK_SET); /* read the file header */ if (mmioRead(hFile, (LPBYTE)&bf, sizeof(bf)) != sizeof(bf)) { iRet = -1; goto earlyExit; } /* check the file type */ if ( ((LPSTR)&bf.bfType)[0] != 'B' || ((LPSTR)&bf.bfType)[1] != 'M') { iRet = -1; goto earlyExit; } /* read the file into memory */ if ((lpDIB->lpBI = (LPBITMAPINFOHEADER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, size)) == 0) { iRet = -1; goto earlyExit; } if (mmioRead(hFile, (LPBYTE)lpDIB->lpBI, size) != size) { iRet = -1; goto earlyExit; } /* * if there was no Author size, then update the lpDIB to use * the default (bitmap) size. */ if (lpDIB->width == 0 || lpDIB->height == 0) { /* no ... use the bitmap default size */ lpDIB->width = (int)lpDIB->lpBI->biWidth; lpDIB->height = (int)lpDIB->lpBI->biHeight; } earlyExit: mmioClose(hFile, 0); return(iRet); } /**************************************************************************** ** FUNCTION: WEP ** ** PURPOSE: Standard Windows Exit Procedure ** ** COMMENTS: ** ** The _export makes sure we can access the global variable in DS. ** ****************************************************************************/ int CALLBACK _export WEP(int nExitType) { TerminateVFWDIB(ghInst); return(1); }