|
|
/****************************************************************************
* * 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 <mmddk.h>
#include "profile.h"
#endif
#include <win32.h>
#include <vfw.h>
#include <dispdib.h>
#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))
#pragma data_seg( ".sdata" , "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 <f DisplayDibEx>, an application must be the active * application. All inactive applications and GDI screen updates * are suspended while <f DisplayDib> temporarily reconfigures * the display. * * @parm LPBITMAPINFO | lpbi | Specifies a pointer to a <t BITMAPINFO> * 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 * <t BITMAPINFO> structure pointed to by <p lpbi>. * * @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 <f DisplayDib> with this flag to prepare the display for * the bitmaps, then make a series of <f DisplayDib> 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 <f DisplayDib> 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 <f DisplayDib>. With this flag, you can specify * NULL for the <p lpbi> and <p lpBits> parameters. * * @rdesc Returns zero if successful, otherwise returns an error code. * Error codes are as follows: * * @flag DISPLAYDIB_NOTSUPPORTED | <f DisplayDib> is not supported * in the current mode. * @flag DISPLAYDIB_INVALIDDIB | The bitmap specified by * <p lpbi> is not a valid bitmap. * @flag DISPLAYDIB_INVALIDFORMAT | The bitmap specified by * <p lpbi> specifes a type of bitmap that is not supported. * @flag DISPLAYDIB_INVALIDTASK | The caller is an inactive application. * <f DisplayDib> can only be called by an active application. * * @comm The <f DisplayDib> function displays bitmaps described with * the Windows 3.0 <t BITMAPINFO> data structure in either BI_RGB * or BI_RLE8 format; it does not support bitmaps described with * the OS/2 <t BITMAPCOREHEADER> data structure. * * When <f DisplayDib> 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 <f DisplayDib> 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 ); }
|