Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1243 lines
35 KiB

  1. /****************************************************************************
  2. *
  3. * DRAWPROC.C
  4. *
  5. * Standard AVI drawing handler.
  6. *
  7. * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved.
  8. *
  9. * You have a royalty-free right to use, modify, reproduce and
  10. * distribute the Sample Files (and/or any modified version) in
  11. * any way you find useful, provided that you agree that
  12. * Microsoft has no warranty obligations or liability for any
  13. * Sample Application Files which are modified.
  14. *
  15. ***************************************************************************/
  16. #ifdef _WIN32
  17. #include "graphic.h"
  18. #include <mmddk.h>
  19. #include "profile.h"
  20. #endif
  21. #include <win32.h>
  22. #include <vfw.h>
  23. #include <dispdib.h>
  24. #ifdef _WIN32
  25. static SZCODE szAtomFlag[] = TEXT("aviFullscreen");
  26. static SZCODE szDisplayDibLib[] = TEXT("DISPDB32.DLL");
  27. #else
  28. static SZCODE szDisplayDibLib[] = TEXT("DISPDIB.DLL");
  29. #endif
  30. static SZCODEA szDisplayDibEx[] = "DisplayDibEx";
  31. #define FOURCC_VIDS mmioFOURCC('v','i','d','s')
  32. #define FOURCC_AVIFull mmioFOURCC('F','U','L','L')
  33. #define VERSION_AVIFull 0x00010000 // 1.00
  34. #ifndef HUGE
  35. #define HUGE _huge
  36. #endif
  37. extern FAR PASCAL LockCurrentTask(BOOL);
  38. static int siUsage = 0;
  39. static HINSTANCE ghDISPDIB = NULL; // handle to DISPDIB.DLL module
  40. UINT (FAR PASCAL *DisplayDibExProc)(LPBITMAPINFOHEADER lpbi, int x, int y, LPSTR hpBits, UINT wFlags)=NULL;
  41. /***************************************************************************
  42. ***************************************************************************/
  43. typedef struct {
  44. int xDst; // destination rectangle
  45. int yDst;
  46. int dxDst;
  47. int dyDst;
  48. int xSrc; // source rectangle
  49. int ySrc;
  50. int dxSrc;
  51. int dySrc;
  52. HWND hwnd;
  53. HWND hwndOldFocus;
  54. BOOL fRle;
  55. DWORD biSizeImage;
  56. } INSTINFO, *PINSTINFO;
  57. // static stuff in this file.
  58. LRESULT FAR PASCAL _loadds ICAVIFullProc(DWORD_PTR id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2);
  59. static LRESULT AVIFullOpen(ICOPEN FAR * icopen);
  60. static LONG AVIFullClose(PINSTINFO pi);
  61. static LONG AVIFullGetInfo(ICINFO FAR *icinfo, LONG lSize);
  62. static LONG AVIFullQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn);
  63. static LONG AVIFullSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd);
  64. static LONG AVIFullBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd);
  65. static LONG AVIFullDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd);
  66. static LONG AVIFullEnd(PINSTINFO pi);
  67. /* -------------------------------------------------------------------------
  68. ** Private Globals
  69. ** These are only valid in the process that started playing the movie.
  70. ** -------------------------------------------------------------------------
  71. */
  72. #include "common.h"
  73. HWND hwndFullScreen;
  74. HDC hdcFullScreen;
  75. HDRAWDIB hdd;
  76. BOOL fClassRegistered;
  77. int dxScreen;
  78. int dyScreen;
  79. int iMovieSizeMultiplier;
  80. /***************************************************************************
  81. ***************************************************************************/
  82. LRESULT FAR PASCAL _loadds ICAVIFullProc(DWORD_PTR id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2)
  83. {
  84. INSTINFO *pi = (INSTINFO *)id;
  85. switch (uiMessage)
  86. {
  87. case DRV_LOAD:
  88. return 1;
  89. case DRV_FREE:
  90. return 1;
  91. /*********************************************************************
  92. open
  93. *********************************************************************/
  94. case DRV_OPEN:
  95. if (ghDISPDIB == NULL) {
  96. UINT w;
  97. w = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  98. if ((INT_PTR)(ghDISPDIB = (HINSTANCE)LoadLibrary(szDisplayDibLib)) > HINSTANCE_ERROR) {
  99. (FARPROC)DisplayDibExProc = GetProcAddress(ghDISPDIB, szDisplayDibEx);
  100. }
  101. else
  102. ghDISPDIB = (HINSTANCE)-1;
  103. SetErrorMode(w);
  104. }
  105. if (DisplayDibExProc == NULL)
  106. DisplayDibExProc = DisplayDibEx;
  107. if (lParam2 == 0L)
  108. return 1;
  109. return AVIFullOpen((ICOPEN FAR *)lParam2);
  110. case DRV_CLOSE:
  111. if (id == 1)
  112. return 1;
  113. return AVIFullClose(pi);
  114. /*********************************************************************
  115. Configure/Info messages
  116. *********************************************************************/
  117. case DRV_QUERYCONFIGURE: // configuration from drivers applet
  118. return 0;
  119. case DRV_CONFIGURE:
  120. return 1;
  121. case ICM_CONFIGURE:
  122. case ICM_ABOUT:
  123. return ICERR_UNSUPPORTED;
  124. /*********************************************************************
  125. state messages
  126. *********************************************************************/
  127. case ICM_GETSTATE:
  128. case ICM_SETSTATE:
  129. return 0L;
  130. #if 0
  131. case ICM_GETINFO:
  132. return AVIFullGetInfo((ICINFO FAR *)lParam1, lParam2);
  133. #endif
  134. /*********************************************************************
  135. decompress messages
  136. *********************************************************************/
  137. case ICM_DRAW_QUERY:
  138. return AVIFullQuery(pi, (LPBITMAPINFOHEADER)lParam1);
  139. case ICM_DRAW_SUGGESTFORMAT:
  140. return AVIFullSuggestFormat(pi, (ICDRAWSUGGEST FAR *) lParam1, (LONG) lParam2);
  141. case ICM_DRAW_BEGIN:
  142. return AVIFullBegin(pi, (ICDRAWBEGIN FAR *) lParam1, (LONG) lParam2);
  143. case ICM_DRAW_REALIZE:
  144. if (DisplayDibExProc == DisplayDibEx) {
  145. if (hdd == NULL || hdcFullScreen == NULL) {
  146. break;
  147. }
  148. return DrawDibRealize( hdd, hdcFullScreen, (BOOL)lParam2 );
  149. }
  150. break;
  151. case ICM_DRAW_GET_PALETTE:
  152. if (DisplayDibExProc == DisplayDibEx) {
  153. if (NULL != hdd) {
  154. return (LONG_PTR)DrawDibGetPalette(hdd);
  155. }
  156. }
  157. break;
  158. case ICM_DRAW:
  159. return AVIFullDraw(pi, (ICDRAW FAR *)lParam1, (LONG) lParam2);
  160. case ICM_DRAW_CHANGEPALETTE:
  161. DisplayDibExProc((LPBITMAPINFOHEADER) lParam1, 0, 0, NULL,
  162. DISPLAYDIB_NOWAIT | DISPLAYDIB_NOIMAGE);
  163. return ICERR_OK;
  164. case ICM_DRAW_END:
  165. return AVIFullEnd(pi);
  166. /*********************************************************************
  167. standard driver messages
  168. *********************************************************************/
  169. case DRV_DISABLE:
  170. case DRV_ENABLE:
  171. return 1;
  172. case DRV_INSTALL:
  173. case DRV_REMOVE:
  174. return 1;
  175. }
  176. if (uiMessage < DRV_USER)
  177. return DefDriverProc(id,hDriver,uiMessage,lParam1,lParam2);
  178. else
  179. return ICERR_UNSUPPORTED;
  180. }
  181. /*****************************************************************************
  182. *
  183. * AVIFullOpen() is called from the DRV_OPEN message
  184. *
  185. ****************************************************************************/
  186. static LONG_PTR AVIFullOpen(ICOPEN FAR * icopen)
  187. {
  188. INSTINFO * pinst;
  189. //
  190. // refuse to open if we are not being opened as a Video compressor
  191. //
  192. if (icopen->dwFlags & ICMODE_COMPRESS)
  193. return 0;
  194. if (icopen->dwFlags & ICMODE_DECOMPRESS)
  195. return 0;
  196. pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  197. if (!pinst)
  198. {
  199. icopen->dwError = ICERR_MEMORY;
  200. return 0;
  201. }
  202. ++siUsage;
  203. //
  204. // return success.
  205. //
  206. icopen->dwError = ICERR_OK;
  207. return (LONG_PTR) (UINT_PTR) pinst;
  208. }
  209. /*****************************************************************************
  210. *
  211. * Close() is called on the DRV_CLOSE message.
  212. *
  213. ****************************************************************************/
  214. static LONG AVIFullClose(PINSTINFO pi)
  215. {
  216. LocalFree((HLOCAL) pi);
  217. if (--siUsage == 0) {
  218. /* unload DISPDIB library (if loaded) */
  219. if (ghDISPDIB != NULL && ghDISPDIB != (HINSTANCE) -1)
  220. FreeLibrary(ghDISPDIB), ghDISPDIB = NULL;
  221. }
  222. return 1;
  223. }
  224. #if 0
  225. /*****************************************************************************
  226. *
  227. * AVIFullGetInfo() implements the ICM_GETINFO message
  228. *
  229. ****************************************************************************/
  230. static LONG AVIFullGetInfo(ICINFO FAR *icinfo, LONG lSize)
  231. {
  232. if (icinfo == NULL)
  233. return sizeof(ICINFO);
  234. if (lSize < sizeof(ICINFO))
  235. return 0;
  236. icinfo->dwSize = sizeof(ICINFO);
  237. icinfo->fccType = FOURCC_VIDS;
  238. icinfo->fccHandler = FOURCC_AVIFull;
  239. icinfo->dwFlags = VIDCF_DRAW;
  240. icinfo->dwVersion = VERSION_AVIFull;
  241. icinfo->dwVersionICM = ICVERSION;
  242. lstrcpy(icinfo->szDescription, szDescription);
  243. lstrcpy(icinfo->szName, szName);
  244. return sizeof(ICINFO);
  245. }
  246. #endif
  247. /*****************************************************************************
  248. *
  249. * AVIFullQuery() implements ICM_DRAW_QUERY
  250. *
  251. ****************************************************************************/
  252. static LONG AVIFullQuery(PINSTINFO pi,
  253. LPBITMAPINFOHEADER lpbiIn)
  254. {
  255. //
  256. // determine if the input DIB data is in a format we like.
  257. //
  258. if (lpbiIn == NULL)
  259. return ICERR_BADFORMAT;
  260. if (DisplayDibExProc(lpbiIn, 0, 0, 0,
  261. DISPLAYDIB_MODE_DEFAULT|DISPLAYDIB_NOWAIT|DISPLAYDIB_TEST) != 0)
  262. return ICERR_BADFORMAT;
  263. return ICERR_OK;
  264. }
  265. static LONG AVIFullSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd)
  266. {
  267. HIC hic;
  268. static int iFull = -1;
  269. int iDepth;
  270. if (iFull < 0) {
  271. BITMAPINFOHEADER bih;
  272. bih.biSize = sizeof(bih);
  273. bih.biBitCount = 16;
  274. bih.biCompression = BI_RGB;
  275. bih.biWidth = 160;
  276. bih.biHeight = 120;
  277. iFull = (AVIFullQuery(pi, &bih) == ICERR_OK) ? 1 : 0;
  278. }
  279. iDepth = lpicd->lpbiIn->biBitCount > 8 && iFull == 1 ? 16 : 8;
  280. if (lpicd->lpbiSuggest == NULL)
  281. return sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
  282. hic = ICGetDisplayFormat(NULL, lpicd->lpbiIn,
  283. lpicd->lpbiSuggest,
  284. iDepth, 0, 0);
  285. if (hic)
  286. ICClose(hic);
  287. return sizeof(BITMAPINFOHEADER) + lpicd->lpbiSuggest->biClrUsed * sizeof(RGBQUAD);
  288. }
  289. /*****************************************************************************
  290. *
  291. * AVIFullBegin() implements ICM_DRAW_BEGIN
  292. *
  293. ****************************************************************************/
  294. static LONG AVIFullBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd)
  295. {
  296. UINT w;
  297. LONG lRet;
  298. UINT wFlags = DISPLAYDIB_BEGIN | DISPLAYDIB_NOWAIT;
  299. if (!(lpicd->dwFlags & ICDRAW_FULLSCREEN))
  300. return ICERR_UNSUPPORTED; // !!! Necessary?
  301. lRet = AVIFullQuery(pi, lpicd->lpbi);
  302. if (lRet != 0 || (lpicd->dwFlags & ICDRAW_QUERY))
  303. return lRet;
  304. // Copy over whatever we want to remember
  305. pi->hwnd = lpicd->hwnd;
  306. pi->xDst = lpicd->xDst;
  307. pi->yDst = lpicd->yDst;
  308. pi->dxDst = lpicd->dxDst;
  309. pi->dyDst = lpicd->dyDst;
  310. pi->xSrc = lpicd->xSrc;
  311. pi->ySrc = lpicd->ySrc;
  312. pi->dxSrc = lpicd->dxSrc;
  313. pi->dySrc = lpicd->dySrc;
  314. if (pi->dxDst > pi->dxSrc)
  315. wFlags |= DISPLAYDIB_ZOOM2;
  316. //
  317. // remember if this is RLE because we may need to hack it later.
  318. //
  319. pi->fRle = lpicd->lpbi->biCompression == BI_RLE8;
  320. pi->biSizeImage = (DWORD)(((UINT)lpicd->lpbi->biWidth+3)&~3)*(DWORD)(UINT)lpicd->lpbi->biHeight;
  321. pi->hwndOldFocus = GetFocus();
  322. SetFocus(NULL);
  323. /*
  324. ** If we are using the built in fullscreen support we have to
  325. ** get the hdd and set its palette here. This is because I am unable to
  326. ** pass this information to DispDib code (there arn't any free parameters).
  327. */
  328. if (DisplayDibExProc == DisplayDibEx) {
  329. hdd = DrawDibOpen();
  330. if (lpicd->hpal == (HPALETTE)MCI_AVI_SETVIDEO_PALETTE_HALFTONE) {
  331. DrawDibSetPalette(hdd, NULL);
  332. }
  333. else {
  334. DrawDibSetPalette(hdd, lpicd->hpal);
  335. }
  336. }
  337. // Don't animate if we're realizing in the background
  338. if (lpicd->dwFlags & ICDRAW_ANIMATE) {
  339. wFlags |= DISPLAYDIB_ANIMATE;
  340. }
  341. if (lpicd->hpal == (HPALETTE)MCI_AVI_SETVIDEO_PALETTE_HALFTONE) {
  342. wFlags |= DISPLAYDIB_HALFTONE;
  343. }
  344. //
  345. // we dont need to do this, DISPDIB will do it for us
  346. //
  347. #if 0
  348. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
  349. LockCurrentTask(TRUE);
  350. #endif
  351. /* Capture the mouse, so other apps don't get called. */
  352. SetCapture(pi->hwnd);
  353. /* We don't explicitly specify a graphics mode; DispDib will
  354. ** choose one for us.
  355. */
  356. w = DisplayDibExProc(lpicd->lpbi, 0, 0, NULL, wFlags );
  357. switch (w) {
  358. case DISPLAYDIB_INVALIDFORMAT:
  359. return ICERR_BADFORMAT;
  360. case 0:
  361. return ICERR_OK;
  362. default:
  363. return ICERR_UNSUPPORTED;
  364. }
  365. }
  366. /*****************************************************************************
  367. *
  368. * AVIFullDraw() implements ICM_DRAW
  369. *
  370. ****************************************************************************/
  371. STATICFN LONG AVIFullDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd)
  372. {
  373. UINT wFlags;
  374. UINT w;
  375. wFlags = DISPLAYDIB_NOPALETTE | DISPLAYDIB_NOWAIT;
  376. if (pi->dxDst > pi->dxSrc) {
  377. wFlags |= DISPLAYDIB_ZOOM2;
  378. }
  379. if (lpicd->dwFlags & ICDRAW_NULLFRAME) {
  380. return ICERR_OK; // !!!
  381. }
  382. if (lpicd->dwFlags & ICDRAW_PREROLL) {
  383. if (((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression == BI_RGB) // !!!
  384. return ICERR_OK;
  385. }
  386. if (lpicd->dwFlags & ICDRAW_HURRYUP)
  387. ; // !!! DONTDRAW?
  388. if (lpicd->lpData == NULL)
  389. return ICERR_UNSUPPORTED;
  390. //
  391. // We need a hack here for the RLE case, to make sure that
  392. // DIBs are marked correctly as BI_RLE8 or BI_RGB....
  393. //
  394. if (pi->fRle) {
  395. if (lpicd->cbData == pi->biSizeImage)
  396. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RGB;
  397. else {
  398. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8;
  399. // We MUST set the correct size
  400. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biSizeImage = lpicd->cbData;
  401. }
  402. }
  403. w = DisplayDibExProc(lpicd->lpFormat, 0, 0, lpicd->lpData, wFlags);
  404. if (pi->fRle)
  405. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8;
  406. switch (w) {
  407. case DISPLAYDIB_STOP: return ICERR_STOPDRAWING;
  408. case DISPLAYDIB_NOERROR: return ICERR_OK;
  409. default: return ICERR_ERROR;
  410. }
  411. }
  412. /*****************************************************************************
  413. *
  414. * AVIFullEnd() implements ICM_DRAW_END
  415. *
  416. ****************************************************************************/
  417. static LONG AVIFullEnd(PINSTINFO pi)
  418. {
  419. MSG msg;
  420. DisplayDibExProc(NULL, 0, 0, NULL, DISPLAYDIB_END | DISPLAYDIB_NOWAIT);
  421. //
  422. // we dont need to do this, DISPDIB will do it for us
  423. //
  424. #if 0
  425. LockCurrentTask(FALSE);
  426. /* Can we assume the error mode should be 0? */
  427. SetErrorMode(0);
  428. #endif
  429. ReleaseCapture();
  430. /* Clear out left-over key messages */
  431. while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST,
  432. PM_REMOVE | PM_NOYIELD))
  433. ;
  434. /* Clear out left-over mouse messages */
  435. while (PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST,
  436. PM_REMOVE | PM_NOYIELD))
  437. ;
  438. SetFocus(pi->hwndOldFocus);
  439. return ICERR_OK;
  440. }
  441. /* -------------------------------------------------------------------------
  442. ** Private constants
  443. ** -------------------------------------------------------------------------
  444. */
  445. #define CX_MAX_MOVIE_DEFAULT 640
  446. #define CY_MAX_MOVIE_DEFAULT 480
  447. /* -------------------------------------------------------------------------
  448. ** Private functions prototypes
  449. ** -------------------------------------------------------------------------
  450. */
  451. LRESULT CALLBACK
  452. FullScreenWndProc(
  453. HWND hwnd,
  454. UINT message,
  455. WPARAM wParam,
  456. LPARAM lParam
  457. );
  458. LRESULT CALLBACK
  459. KeyboardHookProc(
  460. int nCode,
  461. WPARAM wParam,
  462. LPARAM lParam
  463. );
  464. UINT
  465. DisplayDibEnter(
  466. LPBITMAPINFOHEADER lpbi,
  467. UINT wFlags
  468. );
  469. void
  470. DisplayDibLeave(
  471. UINT wFlags
  472. );
  473. int
  474. DisplayCalcMovieMultiplier(
  475. int cxOriginal,
  476. int cyOriginal,
  477. DWORD dwCompression
  478. );
  479. /* -------------------------------------------------------------------------
  480. ** Global data shared between all processes that attach to this library.
  481. ** This is required to make the keyboard hook work correctly.
  482. ** -------------------------------------------------------------------------
  483. */
  484. //#define StopRequested() (fStop)
  485. #define StopRequested() (GlobalFindAtom(szAtomFlag))
  486. /*
  487. 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.
  488. */
  489. #pragma data_seg( ".shared" , "DATA")
  490. BOOL fStop;
  491. HHOOK hHookK;
  492. #pragma data_seg()
  493. /******************************Public*Routine******************************\
  494. * @doc EXTERNAL DISPDIB
  495. *
  496. * @api UINT | DisplayDibEx | This function displays a 256-color bitmap on a
  497. * standard VGA display. It reduces the display resolution to 320-by-200
  498. * or 320-by-240 and uses the full screen to display the bitmap, clipping
  499. * and centering it as necessary. The function normally does not return to
  500. * the application until the user presses a key or clicks a mouse button.
  501. *
  502. * To call <f DisplayDibEx>, an application must be the active
  503. * application. All inactive applications and GDI screen updates
  504. * are suspended while <f DisplayDib> temporarily reconfigures
  505. * the display.
  506. *
  507. * @parm LPBITMAPINFO | lpbi | Specifies a pointer to a <t BITMAPINFO>
  508. * header describing the bitmap to be displayed.
  509. *
  510. * @parm int | x | x position to place DIB iff DISPLAYDIB_NOCENTER flags is set
  511. * the lower left is (0,0)
  512. *
  513. * @parm int | y | y position to place DIB iff DISPLAYDIB_NOCENTER flags is set
  514. * the lower left is (0,0)
  515. *
  516. * @parm LPSTR | lpBits | Specifies a pointer to the bitmap bits. If this
  517. * parameter is NULL, the bits are assumed to follow the
  518. * <t BITMAPINFO> structure pointed to by <p lpbi>.
  519. *
  520. * @parm UINT | wFlags | Specifies options for displaying the bitmap. Use
  521. * the following flags:
  522. *
  523. * @flag DISPLAYDIB_MODE_DEFAULT | Use the default mode (320 by 240)
  524. * to display the bitmap.
  525. * @flag DISPLAYDIB_MODE_320x200x8 | Use 320-by-200 mode to display
  526. * the bitmap.
  527. * @flag DISPLAYDIB_MODE_320x240x8 | Use 320-by-240 mode to display
  528. * the bitmap. This is the default.
  529. * @flag DISPLAYDIB_NOWAIT | Return immediately after displaying the
  530. * bitmap; don't wait for a key press or mouse click before returning.
  531. * @flag DISPLAYDIB_NOPALETTE | Ignore the palette associated
  532. * with the bitmap. You can use this flag when displaying a series
  533. * of bitmaps that use a common palette.
  534. * @flag DISPLAYDIB_NOCENTER | Don't center the image. The function
  535. * displays the bitmap in the lower-left corner of the display.
  536. * @flag DISPLAYDIB_NOIMAGE | Don't draw image
  537. * @flag DISPLAYDIB_ZOOM2 | Stretch image by 2
  538. * @flag DISPLAYDIB_DONTLOCKTASK | dont lock out other tasks
  539. * @flag DISPLAYDIB_TEST | dont do any thing just test for support
  540. * @flag DISPLAYDIB_BEGIN | Switch to the low-resolution
  541. * display mode and set the palette. The bitmap is not displayed.
  542. *
  543. * If you are displaying a series of images that use the same palette,
  544. * you can call <f DisplayDib> with this flag to prepare the display for
  545. * the bitmaps, then make a series of <f DisplayDib> calls with the
  546. * DISPLAYDIB_NOPALETTE flag. This technique
  547. * eliminates the screen flicker that occurs when the display is
  548. * switched between the low-resolution and standard VGA modes.
  549. * To return the display to standard VGA mode, subsequently
  550. * call <f DisplayDib> with the DISPLAYDIB_END flag.
  551. *
  552. * @flag DISPLAYDIB_END | Switch back to standard VGA mode
  553. * and return without displaying a bitmap. Signifies the end of multiple
  554. * calls to <f DisplayDib>. With this flag, you can specify
  555. * NULL for the <p lpbi> and <p lpBits> parameters.
  556. *
  557. * @rdesc Returns zero if successful, otherwise returns an error code.
  558. * Error codes are as follows:
  559. *
  560. * @flag DISPLAYDIB_NOTSUPPORTED | <f DisplayDib> is not supported
  561. * in the current mode.
  562. * @flag DISPLAYDIB_INVALIDDIB | The bitmap specified by
  563. * <p lpbi> is not a valid bitmap.
  564. * @flag DISPLAYDIB_INVALIDFORMAT | The bitmap specified by
  565. * <p lpbi> specifes a type of bitmap that is not supported.
  566. * @flag DISPLAYDIB_INVALIDTASK | The caller is an inactive application.
  567. * <f DisplayDib> can only be called by an active application.
  568. *
  569. * @comm The <f DisplayDib> function displays bitmaps described with
  570. * the Windows 3.0 <t BITMAPINFO> data structure in either BI_RGB
  571. * or BI_RLE8 format; it does not support bitmaps described with
  572. * the OS/2 <t BITMAPCOREHEADER> data structure.
  573. *
  574. * When <f DisplayDib> switches to a low-resolution display, it
  575. * disables the current display driver. As a result, you cannot use GDI
  576. * functions to update the display while <f DisplayDib> is displaying a
  577. * bitmap.
  578. *
  579. *
  580. * History:
  581. * 23-03-94 - StephenE - Created
  582. *
  583. \**************************************************************************/
  584. UINT FAR PASCAL
  585. DisplayDibEx(
  586. LPBITMAPINFOHEADER lpbi,
  587. int x,
  588. int y,
  589. LPSTR lpBits,
  590. UINT wFlags
  591. )
  592. {
  593. DWORD wNumColors;
  594. LONG yExt;
  595. LONG xExt;
  596. int xScreen,yScreen;
  597. /*
  598. ** If not already done so:
  599. ** Register our class and Create our window "fullscreen"
  600. */
  601. if (wFlags & DISPLAYDIB_BEGIN) {
  602. DPF4(( "DISPLAYDIB_BEGIN..." ));
  603. return DisplayDibEnter( lpbi, wFlags );
  604. }
  605. /*
  606. ** Just testing return OK
  607. */
  608. else if (wFlags & DISPLAYDIB_TEST) {
  609. DPF1(( "lpbi->biCompression = 0x%X = %c%c%c%c",
  610. lpbi->biCompression,
  611. *((LPSTR)&lpbi->biCompression + 0),
  612. *((LPSTR)&lpbi->biCompression + 1),
  613. *((LPSTR)&lpbi->biCompression + 2),
  614. *((LPSTR)&lpbi->biCompression + 3) ));
  615. DPF4(( "DISPLAYDIB_TEST... returning OK" ));
  616. return DISPLAYDIB_NOERROR;
  617. }
  618. /*
  619. ** Palette change message
  620. */
  621. else if ( (wFlags & (DISPLAYDIB_NOWAIT | DISPLAYDIB_NOIMAGE)) ==
  622. (DISPLAYDIB_NOWAIT | DISPLAYDIB_NOIMAGE) ) {
  623. PALETTEENTRY ape[256];
  624. LPRGBQUAD lprgb;
  625. int i;
  626. lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize);
  627. for (i = 0; i < (int) lpbi->biClrUsed; i++) {
  628. ape[i].peRed = lprgb[i].rgbRed;
  629. ape[i].peGreen = lprgb[i].rgbGreen;
  630. ape[i].peBlue = lprgb[i].rgbBlue;
  631. ape[i].peFlags = 0;
  632. }
  633. DrawDibChangePalette(hdd, 0, (int)lpbi->biClrUsed, (LPPALETTEENTRY)ape);
  634. return DISPLAYDIB_NOERROR;
  635. }
  636. /*
  637. ** Time to kill the window and the class
  638. */
  639. else if (wFlags & DISPLAYDIB_END) {
  640. DPF4(( "DISPLAYDIB_END..." ));
  641. DisplayDibLeave( wFlags );
  642. return DISPLAYDIB_NOERROR;
  643. }
  644. /*
  645. ** Do the drawing here !!
  646. */
  647. else if ( !StopRequested() ) {
  648. /*
  649. ** If we were'nt asked to draw anything just return.
  650. */
  651. if ( wFlags & DISPLAYDIB_NOIMAGE ) {
  652. return DISPLAYDIB_NOERROR;
  653. }
  654. xExt = lpbi->biWidth;
  655. yExt = lpbi->biHeight;
  656. if ( wFlags & DISPLAYDIB_ZOOM2 ) {
  657. xExt <<= 1;
  658. yExt <<= 1;
  659. }
  660. else if ( iMovieSizeMultiplier ) {
  661. //The movie needs to be stretched to full screen.
  662. xExt = GetSystemMetrics( SM_CXSCREEN );
  663. yExt = GetSystemMetrics( SM_CYSCREEN );
  664. }
  665. wNumColors = lpbi->biClrUsed;
  666. if (wNumColors == 0 && lpbi->biBitCount <= 8) {
  667. wNumColors = 1 << (UINT)lpbi->biBitCount;
  668. }
  669. /*
  670. ** setup pointers
  671. */
  672. if (lpBits == NULL) {
  673. lpBits = (LPBYTE)lpbi + lpbi->biSize + wNumColors * sizeof(RGBQUAD);
  674. }
  675. /*
  676. ** center the image
  677. */
  678. if (!(wFlags & DISPLAYDIB_NOCENTER)) {
  679. xScreen = ((int)dxScreen - xExt) / 2;
  680. yScreen = ((int)dyScreen - yExt) / 2;
  681. }
  682. else {
  683. xScreen = 0;
  684. yScreen = 0;
  685. }
  686. DPF4(( "Drawing to the screen..." ));
  687. DrawDibDraw( hdd, hdcFullScreen,
  688. xScreen, yScreen, xExt, yExt,
  689. lpbi, lpBits,
  690. 0, 0, lpbi->biWidth, lpbi->biHeight,
  691. DDF_SAME_HDC | DDF_SAME_DRAW );
  692. /*
  693. ** Hack time !!
  694. **
  695. ** We have to remove keyboard message from the queue to enable the
  696. ** keyboard hook to see them !!
  697. */
  698. {
  699. MSG msg;
  700. PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST,
  701. PM_REMOVE | PM_NOYIELD );
  702. }
  703. return DISPLAYDIB_NOERROR;
  704. // return fStop;
  705. }
  706. /*
  707. ** The user pressed a key... time to stop
  708. */
  709. else {
  710. DPF1(( "The keyboard hook is telling us to stop..." ));
  711. //DisplayDibLeave( wFlags );
  712. return DISPLAYDIB_STOP;
  713. }
  714. }
  715. /*****************************Private*Routine******************************\
  716. * DisplayDibEnter
  717. *
  718. *
  719. *
  720. * History:
  721. * 23-03-94 - StephenE - Created
  722. *
  723. \**************************************************************************/
  724. UINT
  725. DisplayDibEnter(
  726. LPBITMAPINFOHEADER lpbi,
  727. UINT wFlags
  728. )
  729. {
  730. WNDCLASS wc;
  731. HINSTANCE hInst = GetModuleHandle( NULL );
  732. /*
  733. ** If our class isn't already registered with windows register it
  734. */
  735. fClassRegistered = GetClassInfo( hInst, TEXT("SJE_FULLSCREEN"), &wc );
  736. if ( fClassRegistered == FALSE ) {
  737. ZeroMemory( &wc, sizeof(wc) );
  738. wc.style = CS_OWNDC;
  739. wc.lpfnWndProc = FullScreenWndProc;
  740. wc.hInstance = hInst;
  741. wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
  742. wc.lpszClassName = TEXT("SJE_FULLSCREEN");
  743. fClassRegistered = RegisterClass( &wc );
  744. DPF4(( "Class registered... %s", fClassRegistered ? "OK" : "FAILED" ));
  745. }
  746. if ( fClassRegistered ) {
  747. /*
  748. ** Do we already have a window ??
  749. */
  750. if ( hwndFullScreen == NULL ) {
  751. hwndFullScreen = CreateWindowEx( WS_EX_TOPMOST,
  752. TEXT("SJE_FULLSCREEN"),
  753. NULL,
  754. WS_POPUP,
  755. 0, 0, 0, 0,
  756. NULL, NULL,
  757. hInst, NULL );
  758. DPF4(( "Window created... %s", hwndFullScreen ? "OK" : "FAILED" ));
  759. }
  760. if ( hwndFullScreen ) {
  761. LONG yExt;
  762. LONG xExt;
  763. fStop = FALSE;
  764. hHookK = SetWindowsHookEx( WH_KEYBOARD, KeyboardHookProc,
  765. ghModule,
  766. 0 );
  767. DPF4(( "Hook created... %s", hHookK ? "OK" : "FAILED" ));
  768. dxScreen = GetSystemMetrics( SM_CXSCREEN );
  769. dyScreen = GetSystemMetrics( SM_CYSCREEN );
  770. hdcFullScreen = GetDC( hwndFullScreen );
  771. SetStretchBltMode(hdcFullScreen, COLORONCOLOR);
  772. xExt = lpbi->biWidth;
  773. yExt = lpbi->biHeight;
  774. iMovieSizeMultiplier =
  775. DisplayCalcMovieMultiplier( xExt, yExt, lpbi->biCompression );
  776. if ( wFlags & DISPLAYDIB_ZOOM2 ) {
  777. xExt <<= 1;
  778. yExt <<= 1;
  779. }
  780. else if ( iMovieSizeMultiplier ) {
  781. //The movie needs to be stretched to full screen.
  782. xExt = GetSystemMetrics( SM_CXSCREEN );
  783. yExt = GetSystemMetrics( SM_CYSCREEN );
  784. }
  785. if ( wFlags & DISPLAYDIB_ANIMATE ) {
  786. wFlags = DDF_ANIMATE;
  787. }
  788. else if ( wFlags & DISPLAYDIB_HALFTONE ) {
  789. wFlags = DDF_HALFTONE;
  790. }
  791. else {
  792. wFlags = 0;
  793. }
  794. DPF1(( "Drawing at %d by %d... Flags = 0x%X", xExt, yExt, wFlags ));
  795. DrawDibBegin( hdd, hdcFullScreen, xExt, yExt,
  796. lpbi, lpbi->biWidth, lpbi->biHeight, wFlags );
  797. MoveWindow( hwndFullScreen, 0, 0, dxScreen, dyScreen, FALSE );
  798. ShowWindow( hwndFullScreen, SW_SHOW );
  799. UpdateWindow( hwndFullScreen );
  800. ShowCursor( FALSE );
  801. SetForegroundWindow( hwndFullScreen );
  802. SetFocus( hwndFullScreen );
  803. }
  804. }
  805. return hwndFullScreen != NULL ? DISPLAYDIB_NOERROR : DISPLAYDIB_NOTSUPPORTED;
  806. }
  807. /*****************************Private*Routine******************************\
  808. * DisplayDibLeave
  809. *
  810. *
  811. *
  812. * History:
  813. * 23-03-94 - StephenE - Created
  814. *
  815. \**************************************************************************/
  816. void
  817. DisplayDibLeave(
  818. UINT wFlags
  819. )
  820. {
  821. if (hwndFullScreen) {
  822. DestroyWindow( hwndFullScreen );
  823. hwndFullScreen = NULL;
  824. }
  825. }
  826. /*****************************Private*Routine******************************\
  827. * DisplayCalcMovieMultiplier
  828. *
  829. * Determines the largest movie that the display is capable of displaying.
  830. *
  831. * History:
  832. * dd-mm-94 - StephenE - Created
  833. *
  834. \**************************************************************************/
  835. int
  836. DisplayCalcMovieMultiplier(
  837. int cxOriginal,
  838. int cyOriginal,
  839. DWORD dwCompression
  840. )
  841. {
  842. SYSTEM_INFO SysInfo;
  843. int iMult;
  844. int iMultTemp;
  845. int cxOriginalSave, cyOriginalSave;
  846. int iMax = 8;
  847. GetSystemInfo( &SysInfo );
  848. iMultTemp = iMult = 0;
  849. cxOriginalSave = cxOriginal;
  850. cyOriginalSave = cyOriginal;
  851. switch ( SysInfo.wProcessorArchitecture ) {
  852. case PROCESSOR_ARCHITECTURE_INTEL:
  853. if ( SysInfo.wProcessorLevel <= 3 ) {
  854. break;
  855. } else
  856. if ( SysInfo.wProcessorLevel == 4 ) {
  857. iMax = 2;
  858. iMax = mmGetProfileInt(szIni, TEXT("MaxFullScreenShift"), iMax);
  859. //DPF0(("Setting the maximum shift multiplier to %d\n", iMax));
  860. }
  861. /*
  862. ** maybe later we will do something more different for i486's
  863. ** for now they just fall through to the RISC / Pentium default
  864. ** case below.
  865. */
  866. default:
  867. while ( ( (cxOriginal<<=1) <= CX_MAX_MOVIE_DEFAULT)
  868. && ( (cyOriginal<<=1) <= CY_MAX_MOVIE_DEFAULT)
  869. && (iMax >= iMult)) {
  870. ++iMult;
  871. }
  872. break;
  873. }
  874. return iMult;
  875. }
  876. /******************************Public*Routine******************************\
  877. * FullScreenWndProc
  878. *
  879. *
  880. *
  881. * History:
  882. * 23-03-94 - StephenE - Created
  883. *
  884. \**************************************************************************/
  885. LRESULT CALLBACK
  886. FullScreenWndProc(
  887. HWND hwnd,
  888. UINT message,
  889. WPARAM wParam,
  890. LPARAM lParam
  891. )
  892. {
  893. switch ( message ) {
  894. case WM_PAINT:
  895. {
  896. PAINTSTRUCT ps;
  897. RECT rc;
  898. DPF4(( "Window needs painting" ));
  899. BeginPaint( hwnd, &ps );
  900. GetUpdateRect( hwnd, &rc, FALSE );
  901. FillRect( hdcFullScreen, &rc, GetStockObject( BLACK_BRUSH ) );
  902. EndPaint( hwnd, &ps );
  903. }
  904. break;
  905. case WM_PALETTECHANGED:
  906. if ( (HWND)wParam == hwnd ) {
  907. break;
  908. }
  909. /* fall thru */
  910. case WM_QUERYNEWPALETTE:
  911. if ( DrawDibRealize( hdd, hdcFullScreen, FALSE ) > 0 ) {
  912. InvalidateRect( hwnd, NULL, TRUE );
  913. return TRUE;
  914. }
  915. break;
  916. case WM_DESTROY:
  917. {
  918. ATOM atm;
  919. DPF4(( "Window destroyed releasing DC" ));
  920. ReleaseDC( hwnd, hdcFullScreen );
  921. DrawDibEnd( hdd );
  922. DrawDibClose( hdd );
  923. hdd = NULL;
  924. hdcFullScreen = NULL;
  925. UnregisterClass( TEXT("SJE_FULLSCREEN"), GetModuleHandle( NULL ) );
  926. fClassRegistered = FALSE;
  927. ShowCursor( TRUE );
  928. UnhookWindowsHookEx( hHookK );
  929. while (atm = GlobalFindAtom(szAtomFlag)) {
  930. GlobalDeleteAtom(atm);
  931. }
  932. }
  933. break;
  934. //case WM_KILLFOCUS:
  935. //case WM_ACTIVATE:
  936. //case WM_SETFOCUS:
  937. // DPF0(("FullWindowProc, message==%8x, wp/lp %8x/%8x\n", message, wParam, lParam));
  938. default:
  939. return DefWindowProc( hwnd, message, wParam, lParam );
  940. }
  941. return (LRESULT)FALSE;
  942. }
  943. /******************************Public*Routine******************************\
  944. * KeyboardHookProc
  945. *
  946. *
  947. *
  948. * History:
  949. * 23-03-94 - StephenE - Created
  950. *
  951. \**************************************************************************/
  952. LRESULT CALLBACK
  953. KeyboardHookProc(
  954. int nCode,
  955. WPARAM wParam,
  956. LPARAM lParam
  957. )
  958. {
  959. //DPF0(("HookProc, ncode == %d, lParam==%8x\n", nCode, lParam));
  960. if ( nCode == HC_ACTION) {
  961. DPF1(( "lParam = 0x%X", lParam ));
  962. DPF1(( "! wParam = 0x%X\n", wParam ));
  963. /*
  964. ** Don't mess about with the control or shift key. This is because
  965. ** mciwnd uses them to start playing fullscreen. This causes the movie
  966. ** to start start playing and then immediately stop. 0x001D0000 is
  967. ** the scan code for the control keys, 0x002A0000 is the scan code
  968. ** for the shift key.
  969. */
  970. if ( (lParam & 0x00FF0000) == 0x001D0000
  971. || (lParam & 0x00FF0000) == 0x002A0000 ) {
  972. return CallNextHookEx( hHookK, nCode, wParam, lParam );
  973. }
  974. /*
  975. ** The most significant bit of lParam is set if the key is being
  976. ** released. We are only interested in keydowns. Bits 16 - 23 are
  977. ** the hardware scan code of the key being pressed, 0x00010000
  978. ** is the scan code for the escape key.
  979. */
  980. if ( !(lParam & 0x80000000) || ((lParam & 0x00FF0000) == 0x00010000)) {
  981. if (!fStop) {
  982. fStop = TRUE;
  983. GlobalAddAtom(szAtomFlag);
  984. /*
  985. ** Don't let windows see this message.
  986. */
  987. return -1;
  988. }
  989. DPF1(( "Stop requested from the keyboard hook" ));
  990. }
  991. }
  992. return CallNextHookEx( hHookK, nCode, wParam, lParam );
  993. }