/**************************************************************************** * * DRAWPROC.C * * Standard AVI drawing handler. * * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved. * * You have a royalty-free right to use, modify, reproduce and * distribute the Sample Files (and/or any modified version) in * any way you find useful, provided that you agree that * Microsoft has no warranty obligations or liability for any * Sample Application Files which are modified. * ***************************************************************************/ #ifdef _WIN32 #include "graphic.h" #include #include "profile.h" #endif #include #include #include #ifdef _WIN32 static SZCODE szAtomFlag[] = TEXT("aviFullscreen"); static SZCODE szDisplayDibLib[] = TEXT("DISPDB32.DLL"); #else static SZCODE szDisplayDibLib[] = TEXT("DISPDIB.DLL"); #endif static SZCODEA szDisplayDibEx[] = "DisplayDibEx"; #define FOURCC_VIDS mmioFOURCC('v','i','d','s') #define FOURCC_AVIFull mmioFOURCC('F','U','L','L') #define VERSION_AVIFull 0x00010000 // 1.00 #ifndef HUGE #define HUGE _huge #endif extern FAR PASCAL LockCurrentTask(BOOL); static int siUsage = 0; static HINSTANCE ghDISPDIB = NULL; // handle to DISPDIB.DLL module UINT (FAR PASCAL *DisplayDibExProc)(LPBITMAPINFOHEADER lpbi, int x, int y, LPSTR hpBits, UINT wFlags)=NULL; /*************************************************************************** ***************************************************************************/ typedef struct { int xDst; // destination rectangle int yDst; int dxDst; int dyDst; int xSrc; // source rectangle int ySrc; int dxSrc; int dySrc; HWND hwnd; HWND hwndOldFocus; BOOL fRle; DWORD biSizeImage; } INSTINFO, *PINSTINFO; // static stuff in this file. LRESULT FAR PASCAL _loadds ICAVIFullProc(DWORD_PTR id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2); static LRESULT AVIFullOpen(ICOPEN FAR * icopen); static LONG AVIFullClose(PINSTINFO pi); static LONG AVIFullGetInfo(ICINFO FAR *icinfo, LONG lSize); static LONG AVIFullQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn); static LONG AVIFullSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd); static LONG AVIFullBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd); static LONG AVIFullDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd); static LONG AVIFullEnd(PINSTINFO pi); /* ------------------------------------------------------------------------- ** Private Globals ** These are only valid in the process that started playing the movie. ** ------------------------------------------------------------------------- */ #include "common.h" HWND hwndFullScreen; HDC hdcFullScreen; HDRAWDIB hdd; BOOL fClassRegistered; int dxScreen; int dyScreen; int iMovieSizeMultiplier; /*************************************************************************** ***************************************************************************/ LRESULT FAR PASCAL _loadds ICAVIFullProc(DWORD_PTR id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2) { INSTINFO *pi = (INSTINFO *)id; switch (uiMessage) { case DRV_LOAD: return 1; case DRV_FREE: return 1; /********************************************************************* open *********************************************************************/ case DRV_OPEN: if (ghDISPDIB == NULL) { UINT w; w = SetErrorMode(SEM_NOOPENFILEERRORBOX); if ((INT_PTR)(ghDISPDIB = (HINSTANCE)LoadLibrary(szDisplayDibLib)) > HINSTANCE_ERROR) { (FARPROC)DisplayDibExProc = GetProcAddress(ghDISPDIB, szDisplayDibEx); } else ghDISPDIB = (HINSTANCE)-1; SetErrorMode(w); } if (DisplayDibExProc == NULL) DisplayDibExProc = DisplayDibEx; if (lParam2 == 0L) return 1; return AVIFullOpen((ICOPEN FAR *)lParam2); case DRV_CLOSE: if (id == 1) return 1; return AVIFullClose(pi); /********************************************************************* Configure/Info messages *********************************************************************/ case DRV_QUERYCONFIGURE: // configuration from drivers applet return 0; case DRV_CONFIGURE: return 1; case ICM_CONFIGURE: case ICM_ABOUT: return ICERR_UNSUPPORTED; /********************************************************************* state messages *********************************************************************/ case ICM_GETSTATE: case ICM_SETSTATE: return 0L; #if 0 case ICM_GETINFO: return AVIFullGetInfo((ICINFO FAR *)lParam1, lParam2); #endif /********************************************************************* decompress messages *********************************************************************/ case ICM_DRAW_QUERY: return AVIFullQuery(pi, (LPBITMAPINFOHEADER)lParam1); case ICM_DRAW_SUGGESTFORMAT: return AVIFullSuggestFormat(pi, (ICDRAWSUGGEST FAR *) lParam1, (LONG) lParam2); case ICM_DRAW_BEGIN: return AVIFullBegin(pi, (ICDRAWBEGIN FAR *) lParam1, (LONG) lParam2); case ICM_DRAW_REALIZE: if (DisplayDibExProc == DisplayDibEx) { if (hdd == NULL || hdcFullScreen == NULL) { break; } return DrawDibRealize( hdd, hdcFullScreen, (BOOL)lParam2 ); } break; case ICM_DRAW_GET_PALETTE: if (DisplayDibExProc == DisplayDibEx) { if (NULL != hdd) { return (LONG_PTR)DrawDibGetPalette(hdd); } } break; case ICM_DRAW: return AVIFullDraw(pi, (ICDRAW FAR *)lParam1, (LONG) lParam2); case ICM_DRAW_CHANGEPALETTE: DisplayDibExProc((LPBITMAPINFOHEADER) lParam1, 0, 0, NULL, DISPLAYDIB_NOWAIT | DISPLAYDIB_NOIMAGE); return ICERR_OK; case ICM_DRAW_END: return AVIFullEnd(pi); /********************************************************************* standard driver messages *********************************************************************/ case DRV_DISABLE: case DRV_ENABLE: return 1; case DRV_INSTALL: case DRV_REMOVE: return 1; } if (uiMessage < DRV_USER) return DefDriverProc(id,hDriver,uiMessage,lParam1,lParam2); else return ICERR_UNSUPPORTED; } /***************************************************************************** * * AVIFullOpen() is called from the DRV_OPEN message * ****************************************************************************/ static LONG_PTR AVIFullOpen(ICOPEN FAR * icopen) { INSTINFO * pinst; // // refuse to open if we are not being opened as a Video compressor // if (icopen->dwFlags & ICMODE_COMPRESS) return 0; if (icopen->dwFlags & ICMODE_DECOMPRESS) return 0; pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO)); if (!pinst) { icopen->dwError = ICERR_MEMORY; return 0; } ++siUsage; // // return success. // icopen->dwError = ICERR_OK; return (LONG_PTR) (UINT_PTR) pinst; } /***************************************************************************** * * Close() is called on the DRV_CLOSE message. * ****************************************************************************/ static LONG AVIFullClose(PINSTINFO pi) { LocalFree((HLOCAL) pi); if (--siUsage == 0) { /* unload DISPDIB library (if loaded) */ if (ghDISPDIB != NULL && ghDISPDIB != (HINSTANCE) -1) FreeLibrary(ghDISPDIB), ghDISPDIB = NULL; } return 1; } #if 0 /***************************************************************************** * * AVIFullGetInfo() implements the ICM_GETINFO message * ****************************************************************************/ static LONG AVIFullGetInfo(ICINFO FAR *icinfo, LONG lSize) { if (icinfo == NULL) return sizeof(ICINFO); if (lSize < sizeof(ICINFO)) return 0; icinfo->dwSize = sizeof(ICINFO); icinfo->fccType = FOURCC_VIDS; icinfo->fccHandler = FOURCC_AVIFull; icinfo->dwFlags = VIDCF_DRAW; icinfo->dwVersion = VERSION_AVIFull; icinfo->dwVersionICM = ICVERSION; lstrcpy(icinfo->szDescription, szDescription); lstrcpy(icinfo->szName, szName); return sizeof(ICINFO); } #endif /***************************************************************************** * * AVIFullQuery() implements ICM_DRAW_QUERY * ****************************************************************************/ static LONG AVIFullQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn) { // // determine if the input DIB data is in a format we like. // if (lpbiIn == NULL) return ICERR_BADFORMAT; if (DisplayDibExProc(lpbiIn, 0, 0, 0, DISPLAYDIB_MODE_DEFAULT|DISPLAYDIB_NOWAIT|DISPLAYDIB_TEST) != 0) return ICERR_BADFORMAT; return ICERR_OK; } static LONG AVIFullSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd) { HIC hic; static int iFull = -1; int iDepth; if (iFull < 0) { BITMAPINFOHEADER bih; bih.biSize = sizeof(bih); bih.biBitCount = 16; bih.biCompression = BI_RGB; bih.biWidth = 160; bih.biHeight = 120; iFull = (AVIFullQuery(pi, &bih) == ICERR_OK) ? 1 : 0; } iDepth = lpicd->lpbiIn->biBitCount > 8 && iFull == 1 ? 16 : 8; if (lpicd->lpbiSuggest == NULL) return sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); hic = ICGetDisplayFormat(NULL, lpicd->lpbiIn, lpicd->lpbiSuggest, iDepth, 0, 0); if (hic) ICClose(hic); return sizeof(BITMAPINFOHEADER) + lpicd->lpbiSuggest->biClrUsed * sizeof(RGBQUAD); } /***************************************************************************** * * AVIFullBegin() implements ICM_DRAW_BEGIN * ****************************************************************************/ static LONG AVIFullBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd) { UINT w; LONG lRet; UINT wFlags = DISPLAYDIB_BEGIN | DISPLAYDIB_NOWAIT; if (!(lpicd->dwFlags & ICDRAW_FULLSCREEN)) return ICERR_UNSUPPORTED; // !!! Necessary? lRet = AVIFullQuery(pi, lpicd->lpbi); if (lRet != 0 || (lpicd->dwFlags & ICDRAW_QUERY)) return lRet; // Copy over whatever we want to remember pi->hwnd = lpicd->hwnd; pi->xDst = lpicd->xDst; pi->yDst = lpicd->yDst; pi->dxDst = lpicd->dxDst; pi->dyDst = lpicd->dyDst; pi->xSrc = lpicd->xSrc; pi->ySrc = lpicd->ySrc; pi->dxSrc = lpicd->dxSrc; pi->dySrc = lpicd->dySrc; if (pi->dxDst > pi->dxSrc) wFlags |= DISPLAYDIB_ZOOM2; // // remember if this is RLE because we may need to hack it later. // pi->fRle = lpicd->lpbi->biCompression == BI_RLE8; pi->biSizeImage = (DWORD)(((UINT)lpicd->lpbi->biWidth+3)&~3)*(DWORD)(UINT)lpicd->lpbi->biHeight; pi->hwndOldFocus = GetFocus(); SetFocus(NULL); /* ** If we are using the built in fullscreen support we have to ** get the hdd and set its palette here. This is because I am unable to ** pass this information to DispDib code (there arn't any free parameters). */ if (DisplayDibExProc == DisplayDibEx) { hdd = DrawDibOpen(); if (lpicd->hpal == (HPALETTE)MCI_AVI_SETVIDEO_PALETTE_HALFTONE) { DrawDibSetPalette(hdd, NULL); } else { DrawDibSetPalette(hdd, lpicd->hpal); } } // Don't animate if we're realizing in the background if (lpicd->dwFlags & ICDRAW_ANIMATE) { wFlags |= DISPLAYDIB_ANIMATE; } if (lpicd->hpal == (HPALETTE)MCI_AVI_SETVIDEO_PALETTE_HALFTONE) { wFlags |= DISPLAYDIB_HALFTONE; } // // we dont need to do this, DISPDIB will do it for us // #if 0 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); LockCurrentTask(TRUE); #endif /* Capture the mouse, so other apps don't get called. */ SetCapture(pi->hwnd); /* We don't explicitly specify a graphics mode; DispDib will ** choose one for us. */ w = DisplayDibExProc(lpicd->lpbi, 0, 0, NULL, wFlags ); switch (w) { case DISPLAYDIB_INVALIDFORMAT: return ICERR_BADFORMAT; case 0: return ICERR_OK; default: return ICERR_UNSUPPORTED; } } /***************************************************************************** * * AVIFullDraw() implements ICM_DRAW * ****************************************************************************/ STATICFN LONG AVIFullDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd) { UINT wFlags; UINT w; wFlags = DISPLAYDIB_NOPALETTE | DISPLAYDIB_NOWAIT; if (pi->dxDst > pi->dxSrc) { wFlags |= DISPLAYDIB_ZOOM2; } if (lpicd->dwFlags & ICDRAW_NULLFRAME) { return ICERR_OK; // !!! } if (lpicd->dwFlags & ICDRAW_PREROLL) { if (((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression == BI_RGB) // !!! return ICERR_OK; } if (lpicd->dwFlags & ICDRAW_HURRYUP) ; // !!! DONTDRAW? if (lpicd->lpData == NULL) return ICERR_UNSUPPORTED; // // We need a hack here for the RLE case, to make sure that // DIBs are marked correctly as BI_RLE8 or BI_RGB.... // if (pi->fRle) { if (lpicd->cbData == pi->biSizeImage) ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RGB; else { ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8; // We MUST set the correct size ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biSizeImage = lpicd->cbData; } } w = DisplayDibExProc(lpicd->lpFormat, 0, 0, lpicd->lpData, wFlags); if (pi->fRle) ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8; switch (w) { case DISPLAYDIB_STOP: return ICERR_STOPDRAWING; case DISPLAYDIB_NOERROR: return ICERR_OK; default: return ICERR_ERROR; } } /***************************************************************************** * * AVIFullEnd() implements ICM_DRAW_END * ****************************************************************************/ static LONG AVIFullEnd(PINSTINFO pi) { MSG msg; DisplayDibExProc(NULL, 0, 0, NULL, DISPLAYDIB_END | DISPLAYDIB_NOWAIT); // // we dont need to do this, DISPDIB will do it for us // #if 0 LockCurrentTask(FALSE); /* Can we assume the error mode should be 0? */ SetErrorMode(0); #endif ReleaseCapture(); /* Clear out left-over key messages */ while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE | PM_NOYIELD)) ; /* Clear out left-over mouse messages */ while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE | PM_NOYIELD)) ; SetFocus(pi->hwndOldFocus); return ICERR_OK; } /* ------------------------------------------------------------------------- ** Private constants ** ------------------------------------------------------------------------- */ #define CX_MAX_MOVIE_DEFAULT 640 #define CY_MAX_MOVIE_DEFAULT 480 /* ------------------------------------------------------------------------- ** Private functions prototypes ** ------------------------------------------------------------------------- */ LRESULT CALLBACK FullScreenWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); LRESULT CALLBACK KeyboardHookProc( int nCode, WPARAM wParam, LPARAM lParam ); UINT DisplayDibEnter( LPBITMAPINFOHEADER lpbi, UINT wFlags ); void DisplayDibLeave( UINT wFlags ); int DisplayCalcMovieMultiplier( int cxOriginal, int cyOriginal, DWORD dwCompression ); /* ------------------------------------------------------------------------- ** Global data shared between all processes that attach to this library. ** This is required to make the keyboard hook work correctly. ** ------------------------------------------------------------------------- */ //#define StopRequested() (fStop) #define StopRequested() (GlobalFindAtom(szAtomFlag)) /* This is a holdover from x86 where the name of the shared data section was .sdata (vs. .data). The fix is to remove the DEF file entry, pragma, or linker option and ensure that the component doesn't otherwise require a shared data section. If it does require a shared data section, that section needs to be renamed. In general shared writable data sections are a security risk and should be avoided. */ #pragma data_seg( ".shared" , "DATA") BOOL fStop; HHOOK hHookK; #pragma data_seg() /******************************Public*Routine******************************\ * @doc EXTERNAL DISPDIB * * @api UINT | DisplayDibEx | This function displays a 256-color bitmap on a * standard VGA display. It reduces the display resolution to 320-by-200 * or 320-by-240 and uses the full screen to display the bitmap, clipping * and centering it as necessary. The function normally does not return to * the application until the user presses a key or clicks a mouse button. * * To call , an application must be the active * application. All inactive applications and GDI screen updates * are suspended while temporarily reconfigures * the display. * * @parm LPBITMAPINFO | lpbi | Specifies a pointer to a * header describing the bitmap to be displayed. * * @parm int | x | x position to place DIB iff DISPLAYDIB_NOCENTER flags is set * the lower left is (0,0) * * @parm int | y | y position to place DIB iff DISPLAYDIB_NOCENTER flags is set * the lower left is (0,0) * * @parm LPSTR | lpBits | Specifies a pointer to the bitmap bits. If this * parameter is NULL, the bits are assumed to follow the * structure pointed to by

. * * @parm UINT | wFlags | Specifies options for displaying the bitmap. Use * the following flags: * * @flag DISPLAYDIB_MODE_DEFAULT | Use the default mode (320 by 240) * to display the bitmap. * @flag DISPLAYDIB_MODE_320x200x8 | Use 320-by-200 mode to display * the bitmap. * @flag DISPLAYDIB_MODE_320x240x8 | Use 320-by-240 mode to display * the bitmap. This is the default. * @flag DISPLAYDIB_NOWAIT | Return immediately after displaying the * bitmap; don't wait for a key press or mouse click before returning. * @flag DISPLAYDIB_NOPALETTE | Ignore the palette associated * with the bitmap. You can use this flag when displaying a series * of bitmaps that use a common palette. * @flag DISPLAYDIB_NOCENTER | Don't center the image. The function * displays the bitmap in the lower-left corner of the display. * @flag DISPLAYDIB_NOIMAGE | Don't draw image * @flag DISPLAYDIB_ZOOM2 | Stretch image by 2 * @flag DISPLAYDIB_DONTLOCKTASK | dont lock out other tasks * @flag DISPLAYDIB_TEST | dont do any thing just test for support * @flag DISPLAYDIB_BEGIN | Switch to the low-resolution * display mode and set the palette. The bitmap is not displayed. * * If you are displaying a series of images that use the same palette, * you can call with this flag to prepare the display for * the bitmaps, then make a series of calls with the * DISPLAYDIB_NOPALETTE flag. This technique * eliminates the screen flicker that occurs when the display is * switched between the low-resolution and standard VGA modes. * To return the display to standard VGA mode, subsequently * call with the DISPLAYDIB_END flag. * * @flag DISPLAYDIB_END | Switch back to standard VGA mode * and return without displaying a bitmap. Signifies the end of multiple * calls to . With this flag, you can specify * NULL for the

and

parameters. * * @rdesc Returns zero if successful, otherwise returns an error code. * Error codes are as follows: * * @flag DISPLAYDIB_NOTSUPPORTED | is not supported * in the current mode. * @flag DISPLAYDIB_INVALIDDIB | The bitmap specified by *

is not a valid bitmap. * @flag DISPLAYDIB_INVALIDFORMAT | The bitmap specified by *

specifes a type of bitmap that is not supported. * @flag DISPLAYDIB_INVALIDTASK | The caller is an inactive application. * can only be called by an active application. * * @comm The function displays bitmaps described with * the Windows 3.0 data structure in either BI_RGB * or BI_RLE8 format; it does not support bitmaps described with * the OS/2 data structure. * * When switches to a low-resolution display, it * disables the current display driver. As a result, you cannot use GDI * functions to update the display while is displaying a * bitmap. * * * History: * 23-03-94 - StephenE - Created * \**************************************************************************/ UINT FAR PASCAL DisplayDibEx( LPBITMAPINFOHEADER lpbi, int x, int y, LPSTR lpBits, UINT wFlags ) { DWORD wNumColors; LONG yExt; LONG xExt; int xScreen,yScreen; /* ** If not already done so: ** Register our class and Create our window "fullscreen" */ if (wFlags & DISPLAYDIB_BEGIN) { DPF4(( "DISPLAYDIB_BEGIN..." )); return DisplayDibEnter( lpbi, wFlags ); } /* ** Just testing return OK */ else if (wFlags & DISPLAYDIB_TEST) { DPF1(( "lpbi->biCompression = 0x%X = %c%c%c%c", lpbi->biCompression, *((LPSTR)&lpbi->biCompression + 0), *((LPSTR)&lpbi->biCompression + 1), *((LPSTR)&lpbi->biCompression + 2), *((LPSTR)&lpbi->biCompression + 3) )); DPF4(( "DISPLAYDIB_TEST... returning OK" )); return DISPLAYDIB_NOERROR; } /* ** Palette change message */ else if ( (wFlags & (DISPLAYDIB_NOWAIT | DISPLAYDIB_NOIMAGE)) == (DISPLAYDIB_NOWAIT | DISPLAYDIB_NOIMAGE) ) { PALETTEENTRY ape[256]; LPRGBQUAD lprgb; int i; lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize); for (i = 0; i < (int) lpbi->biClrUsed; i++) { ape[i].peRed = lprgb[i].rgbRed; ape[i].peGreen = lprgb[i].rgbGreen; ape[i].peBlue = lprgb[i].rgbBlue; ape[i].peFlags = 0; } DrawDibChangePalette(hdd, 0, (int)lpbi->biClrUsed, (LPPALETTEENTRY)ape); return DISPLAYDIB_NOERROR; } /* ** Time to kill the window and the class */ else if (wFlags & DISPLAYDIB_END) { DPF4(( "DISPLAYDIB_END..." )); DisplayDibLeave( wFlags ); return DISPLAYDIB_NOERROR; } /* ** Do the drawing here !! */ else if ( !StopRequested() ) { /* ** If we were'nt asked to draw anything just return. */ if ( wFlags & DISPLAYDIB_NOIMAGE ) { return DISPLAYDIB_NOERROR; } xExt = lpbi->biWidth; yExt = lpbi->biHeight; if ( wFlags & DISPLAYDIB_ZOOM2 ) { xExt <<= 1; yExt <<= 1; } else if ( iMovieSizeMultiplier ) { //The movie needs to be stretched to full screen. xExt = GetSystemMetrics( SM_CXSCREEN ); yExt = GetSystemMetrics( SM_CYSCREEN ); } wNumColors = lpbi->biClrUsed; if (wNumColors == 0 && lpbi->biBitCount <= 8) { wNumColors = 1 << (UINT)lpbi->biBitCount; } /* ** setup pointers */ if (lpBits == NULL) { lpBits = (LPBYTE)lpbi + lpbi->biSize + wNumColors * sizeof(RGBQUAD); } /* ** center the image */ if (!(wFlags & DISPLAYDIB_NOCENTER)) { xScreen = ((int)dxScreen - xExt) / 2; yScreen = ((int)dyScreen - yExt) / 2; } else { xScreen = 0; yScreen = 0; } DPF4(( "Drawing to the screen..." )); DrawDibDraw( hdd, hdcFullScreen, xScreen, yScreen, xExt, yExt, lpbi, lpBits, 0, 0, lpbi->biWidth, lpbi->biHeight, DDF_SAME_HDC | DDF_SAME_DRAW ); /* ** Hack time !! ** ** We have to remove keyboard message from the queue to enable the ** keyboard hook to see them !! */ { MSG msg; PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE | PM_NOYIELD ); } return DISPLAYDIB_NOERROR; // return fStop; } /* ** The user pressed a key... time to stop */ else { DPF1(( "The keyboard hook is telling us to stop..." )); //DisplayDibLeave( wFlags ); return DISPLAYDIB_STOP; } } /*****************************Private*Routine******************************\ * DisplayDibEnter * * * * History: * 23-03-94 - StephenE - Created * \**************************************************************************/ UINT DisplayDibEnter( LPBITMAPINFOHEADER lpbi, UINT wFlags ) { WNDCLASS wc; HINSTANCE hInst = GetModuleHandle( NULL ); /* ** If our class isn't already registered with windows register it */ fClassRegistered = GetClassInfo( hInst, TEXT("SJE_FULLSCREEN"), &wc ); if ( fClassRegistered == FALSE ) { ZeroMemory( &wc, sizeof(wc) ); wc.style = CS_OWNDC; wc.lpfnWndProc = FullScreenWndProc; wc.hInstance = hInst; wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); wc.lpszClassName = TEXT("SJE_FULLSCREEN"); fClassRegistered = RegisterClass( &wc ); DPF4(( "Class registered... %s", fClassRegistered ? "OK" : "FAILED" )); } if ( fClassRegistered ) { /* ** Do we already have a window ?? */ if ( hwndFullScreen == NULL ) { hwndFullScreen = CreateWindowEx( WS_EX_TOPMOST, TEXT("SJE_FULLSCREEN"), NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, hInst, NULL ); DPF4(( "Window created... %s", hwndFullScreen ? "OK" : "FAILED" )); } if ( hwndFullScreen ) { LONG yExt; LONG xExt; fStop = FALSE; hHookK = SetWindowsHookEx( WH_KEYBOARD, KeyboardHookProc, ghModule, 0 ); DPF4(( "Hook created... %s", hHookK ? "OK" : "FAILED" )); dxScreen = GetSystemMetrics( SM_CXSCREEN ); dyScreen = GetSystemMetrics( SM_CYSCREEN ); hdcFullScreen = GetDC( hwndFullScreen ); SetStretchBltMode(hdcFullScreen, COLORONCOLOR); xExt = lpbi->biWidth; yExt = lpbi->biHeight; iMovieSizeMultiplier = DisplayCalcMovieMultiplier( xExt, yExt, lpbi->biCompression ); if ( wFlags & DISPLAYDIB_ZOOM2 ) { xExt <<= 1; yExt <<= 1; } else if ( iMovieSizeMultiplier ) { //The movie needs to be stretched to full screen. xExt = GetSystemMetrics( SM_CXSCREEN ); yExt = GetSystemMetrics( SM_CYSCREEN ); } if ( wFlags & DISPLAYDIB_ANIMATE ) { wFlags = DDF_ANIMATE; } else if ( wFlags & DISPLAYDIB_HALFTONE ) { wFlags = DDF_HALFTONE; } else { wFlags = 0; } DPF1(( "Drawing at %d by %d... Flags = 0x%X", xExt, yExt, wFlags )); DrawDibBegin( hdd, hdcFullScreen, xExt, yExt, lpbi, lpbi->biWidth, lpbi->biHeight, wFlags ); MoveWindow( hwndFullScreen, 0, 0, dxScreen, dyScreen, FALSE ); ShowWindow( hwndFullScreen, SW_SHOW ); UpdateWindow( hwndFullScreen ); ShowCursor( FALSE ); SetForegroundWindow( hwndFullScreen ); SetFocus( hwndFullScreen ); } } return hwndFullScreen != NULL ? DISPLAYDIB_NOERROR : DISPLAYDIB_NOTSUPPORTED; } /*****************************Private*Routine******************************\ * DisplayDibLeave * * * * History: * 23-03-94 - StephenE - Created * \**************************************************************************/ void DisplayDibLeave( UINT wFlags ) { if (hwndFullScreen) { DestroyWindow( hwndFullScreen ); hwndFullScreen = NULL; } } /*****************************Private*Routine******************************\ * DisplayCalcMovieMultiplier * * Determines the largest movie that the display is capable of displaying. * * History: * dd-mm-94 - StephenE - Created * \**************************************************************************/ int DisplayCalcMovieMultiplier( int cxOriginal, int cyOriginal, DWORD dwCompression ) { SYSTEM_INFO SysInfo; int iMult; int iMultTemp; int cxOriginalSave, cyOriginalSave; int iMax = 8; GetSystemInfo( &SysInfo ); iMultTemp = iMult = 0; cxOriginalSave = cxOriginal; cyOriginalSave = cyOriginal; switch ( SysInfo.wProcessorArchitecture ) { case PROCESSOR_ARCHITECTURE_INTEL: if ( SysInfo.wProcessorLevel <= 3 ) { break; } else if ( SysInfo.wProcessorLevel == 4 ) { iMax = 2; iMax = mmGetProfileInt(szIni, TEXT("MaxFullScreenShift"), iMax); //DPF0(("Setting the maximum shift multiplier to %d\n", iMax)); } /* ** maybe later we will do something more different for i486's ** for now they just fall through to the RISC / Pentium default ** case below. */ default: while ( ( (cxOriginal<<=1) <= CX_MAX_MOVIE_DEFAULT) && ( (cyOriginal<<=1) <= CY_MAX_MOVIE_DEFAULT) && (iMax >= iMult)) { ++iMult; } break; } return iMult; } /******************************Public*Routine******************************\ * FullScreenWndProc * * * * History: * 23-03-94 - StephenE - Created * \**************************************************************************/ LRESULT CALLBACK FullScreenWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch ( message ) { case WM_PAINT: { PAINTSTRUCT ps; RECT rc; DPF4(( "Window needs painting" )); BeginPaint( hwnd, &ps ); GetUpdateRect( hwnd, &rc, FALSE ); FillRect( hdcFullScreen, &rc, GetStockObject( BLACK_BRUSH ) ); EndPaint( hwnd, &ps ); } break; case WM_PALETTECHANGED: if ( (HWND)wParam == hwnd ) { break; } /* fall thru */ case WM_QUERYNEWPALETTE: if ( DrawDibRealize( hdd, hdcFullScreen, FALSE ) > 0 ) { InvalidateRect( hwnd, NULL, TRUE ); return TRUE; } break; case WM_DESTROY: { ATOM atm; DPF4(( "Window destroyed releasing DC" )); ReleaseDC( hwnd, hdcFullScreen ); DrawDibEnd( hdd ); DrawDibClose( hdd ); hdd = NULL; hdcFullScreen = NULL; UnregisterClass( TEXT("SJE_FULLSCREEN"), GetModuleHandle( NULL ) ); fClassRegistered = FALSE; ShowCursor( TRUE ); UnhookWindowsHookEx( hHookK ); while (atm = GlobalFindAtom(szAtomFlag)) { GlobalDeleteAtom(atm); } } break; //case WM_KILLFOCUS: //case WM_ACTIVATE: //case WM_SETFOCUS: // DPF0(("FullWindowProc, message==%8x, wp/lp %8x/%8x\n", message, wParam, lParam)); default: return DefWindowProc( hwnd, message, wParam, lParam ); } return (LRESULT)FALSE; } /******************************Public*Routine******************************\ * KeyboardHookProc * * * * History: * 23-03-94 - StephenE - Created * \**************************************************************************/ LRESULT CALLBACK KeyboardHookProc( int nCode, WPARAM wParam, LPARAM lParam ) { //DPF0(("HookProc, ncode == %d, lParam==%8x\n", nCode, lParam)); if ( nCode == HC_ACTION) { DPF1(( "lParam = 0x%X", lParam )); DPF1(( "! wParam = 0x%X\n", wParam )); /* ** Don't mess about with the control or shift key. This is because ** mciwnd uses them to start playing fullscreen. This causes the movie ** to start start playing and then immediately stop. 0x001D0000 is ** the scan code for the control keys, 0x002A0000 is the scan code ** for the shift key. */ if ( (lParam & 0x00FF0000) == 0x001D0000 || (lParam & 0x00FF0000) == 0x002A0000 ) { return CallNextHookEx( hHookK, nCode, wParam, lParam ); } /* ** The most significant bit of lParam is set if the key is being ** released. We are only interested in keydowns. Bits 16 - 23 are ** the hardware scan code of the key being pressed, 0x00010000 ** is the scan code for the escape key. */ if ( !(lParam & 0x80000000) || ((lParam & 0x00FF0000) == 0x00010000)) { if (!fStop) { fStop = TRUE; GlobalAddAtom(szAtomFlag); /* ** Don't let windows see this message. */ return -1; } DPF1(( "Stop requested from the keyboard hook" )); } } return CallNextHookEx( hHookK, nCode, wParam, lParam ); }