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.

725 lines
20 KiB

  1. /******************************************************************************
  2. Copyright (C) Microsoft Corporation 1985-1991. All rights reserved.
  3. Title: window.c - Multimedia Systems Media Control Interface
  4. driver for AVI.
  5. *****************************************************************************/
  6. #include "graphic.h"
  7. #include "avitask.h" // for TASKIDLE
  8. //#define IDM_CONFIG 0x100
  9. //#define IDM_SKIPFRAMES 0x110
  10. #define IDM_MUTE 0x120
  11. #define IDM_STRETCH 0x130
  12. #ifdef WIN32
  13. // Use a different class name on 32 bit systems to ease the 16/32
  14. // coexistence problem. (We might want both classes defined at once.)
  15. TCHAR szClassName[] = TEXT("AVIWnd32");
  16. #else
  17. char szClassName[] = "AVIWnd";
  18. #endif
  19. DWORD NEAR PASCAL GraphicStop (NPMCIGRAPHIC npMCI, DWORD dwFlags);
  20. DWORD NEAR PASCAL GraphicPause (NPMCIGRAPHIC npMCI, DWORD dwFlags);
  21. DWORD NEAR PASCAL GraphicPlay (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  22. LPMCI_ANIM_PLAY_PARMS lpPlay );
  23. DWORD NEAR PASCAL GraphicSeek (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  24. LPMCI_SEEK_PARMS lpSeek);
  25. BOOL NEAR PASCAL GraphicWindowInit (void)
  26. {
  27. WNDCLASS cls;
  28. // define the class of window we want to register
  29. cls.lpszClassName = szClassName;
  30. cls.style = CS_GLOBALCLASS | CS_OWNDC;
  31. cls.hCursor = LoadCursor (NULL, IDC_ARROW);
  32. cls.hIcon = NULL;
  33. cls.lpszMenuName = NULL;
  34. ////cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  35. cls.hbrBackground = GetStockObject(BLACK_BRUSH);
  36. cls.hInstance = ghModule;
  37. cls.lpfnWndProc = GraphicWndProc;
  38. cls.cbClsExtra = 0;
  39. cls.cbWndExtra = sizeof (NPMCIGRAPHIC);
  40. return RegisterClass (&cls);
  41. }
  42. #ifdef WIN32
  43. /*
  44. * de-register the class on unloading the dll so that we can
  45. * successfully re-register the class next time we are loaded.
  46. * note that nt only unregisters a class when the app exits.
  47. */
  48. BOOL NEAR PASCAL GraphicWindowFree(void)
  49. {
  50. return(UnregisterClass(szClassName, ghModule));
  51. }
  52. #endif
  53. DWORD FAR PASCAL GraphicConfig(NPMCIGRAPHIC npMCI, DWORD dwFlags);
  54. #if 0
  55. static void NEAR PASCAL Credits(HWND hwnd);
  56. #endif
  57. long FAR PASCAL _LOADDS GraphicWndProc (HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  58. {
  59. PAINTSTRUCT ps;
  60. NPMCIGRAPHIC npMCI;
  61. HMENU hmenu;
  62. HDC hdc;
  63. RECT rc;
  64. MINMAXINFO FAR * lpmmi;
  65. TCHAR ach[80];
  66. #ifndef WIN32
  67. WORD ww;
  68. ww = GetWindowWord (hwnd, 0);
  69. #else
  70. DWORD ww;
  71. ww = GetWindowLong (hwnd, 0);
  72. #endif
  73. if ((ww == 0) && (wMsg != WM_CREATE)) {
  74. DPF(("null npMCI in windowproc!"));
  75. return DefWindowProc(hwnd, wMsg, wParam, lParam);
  76. }
  77. npMCI = (NPMCIGRAPHIC)ww;
  78. if (npMCI) {
  79. EnterCrit(npMCI);
  80. }
  81. switch (wMsg)
  82. {
  83. case WM_CREATE:
  84. npMCI = (NPMCIGRAPHIC)(UINT)(DWORD)
  85. ((LPCREATESTRUCT)lParam)->lpCreateParams;
  86. EnterCrit(npMCI);
  87. #ifndef WIN32
  88. SetWindowWord (hwnd, 0, (WORD)npMCI);
  89. #else
  90. SetWindowLong (hwnd, 0, (UINT)npMCI);
  91. #endif
  92. hmenu = GetSystemMenu(hwnd, 0);
  93. if (hmenu) {
  94. /* Our system menu is too long--get rid of extra stuff. */
  95. // DeleteMenu(hmenu, SC_RESTORE, MF_BYCOMMAND);
  96. // DeleteMenu(hmenu, SC_MINIMIZE, MF_BYCOMMAND);
  97. DeleteMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND);
  98. DeleteMenu(hmenu, SC_TASKLIST, MF_BYCOMMAND);
  99. /* Add additional menu items to the end of the system menu */
  100. // AppendMenu(hmenu, MF_SEPARATOR, 0, 0L);
  101. #ifdef IDM_CONFIG
  102. LoadString(ghModule, MCIAVI_MENU_CONFIG, ach, sizeof(ach)/sizeof(TCHAR));
  103. AppendMenu(hmenu, MF_STRING, IDM_CONFIG, ach);
  104. #endif
  105. LoadString(ghModule, MCIAVI_MENU_STRETCH, ach, sizeof(ach)/sizeof(TCHAR));
  106. AppendMenu(hmenu, MF_STRING, IDM_STRETCH, ach);
  107. LoadString(ghModule, MCIAVI_MENU_MUTE, ach, sizeof(ach)/sizeof(TCHAR));
  108. AppendMenu(hmenu, MF_STRING, IDM_MUTE, ach);
  109. }
  110. break;
  111. case WM_INITMENU:
  112. hmenu = GetSystemMenu(hwnd, 0);
  113. if (hmenu) {
  114. #ifdef IDM_SKIPFRAMES
  115. CheckMenuItem(hmenu, IDM_SKIPFRAMES, MF_BYCOMMAND |
  116. ((npMCI->dwOptionFlags & MCIAVIO_SKIPFRAMES) ?
  117. MF_CHECKED : MF_UNCHECKED));
  118. #endif
  119. CheckMenuItem(hmenu, IDM_STRETCH, MF_BYCOMMAND |
  120. ((npMCI->dwOptionFlags & MCIAVIO_STRETCHTOWINDOW) ?
  121. MF_CHECKED : MF_UNCHECKED));
  122. #ifdef IDM_CONFIG
  123. /* If in configure box, disable menu item. */
  124. EnableMenuItem(hmenu, IDM_CONFIG, MF_BYCOMMAND |
  125. (npMCI->wMessageCurrent == 0 ?
  126. MF_ENABLED : MF_GRAYED));
  127. #endif
  128. /* If in stupid mode, disable stretch menu item. */
  129. EnableMenuItem(hmenu, IDM_STRETCH, MF_BYCOMMAND |
  130. ((!(npMCI->dwOptionFlags & MCIAVIO_STUPIDMODE)) ?
  131. MF_ENABLED : MF_GRAYED));
  132. EnableMenuItem(hmenu, IDM_MUTE, MF_BYCOMMAND |
  133. (npMCI->nAudioStreams ?
  134. MF_ENABLED : MF_GRAYED));
  135. CheckMenuItem(hmenu, IDM_MUTE, MF_BYCOMMAND |
  136. (!(npMCI->dwFlags & MCIAVI_PLAYAUDIO) ?
  137. MF_CHECKED : MF_UNCHECKED));
  138. }
  139. break;
  140. case WM_SYSCOMMAND:
  141. switch (wParam & 0xfff0) {
  142. case SC_KEYMENU:
  143. case SC_MOUSEMENU:
  144. gfEvilSysMenu++;
  145. LeaveCrit(npMCI); // Must not hold while in DefWindowProc
  146. lParam = DefWindowProc(hwnd, wMsg, wParam, lParam);
  147. gfEvilSysMenu--;
  148. return lParam;
  149. #ifdef IDM_SKIPFRAMES
  150. case IDM_SKIPFRAMES:
  151. npMCI->dwOptionFlags ^= MCIAVIO_SKIPFRAMES;
  152. break;
  153. #endif
  154. case IDM_STRETCH:
  155. npMCI->dwOptionFlags ^= MCIAVIO_STRETCHTOWINDOW;
  156. if (!(npMCI->dwOptionFlags & MCIAVIO_STRETCHTOWINDOW)) {
  157. SetWindowToDefaultSize(npMCI);
  158. }
  159. ResetDestRect(npMCI);
  160. break;
  161. case IDM_MUTE:
  162. DeviceMute(npMCI, (npMCI->dwFlags & MCIAVI_PLAYAUDIO) != 0);
  163. break;
  164. #ifdef IDM_CONFIG
  165. case IDM_CONFIG:
  166. npMCI->wMessageCurrent = MCI_CONFIGURE;
  167. gfEvil++;
  168. GraphicConfig(npMCI, 0L);
  169. gfEvil--;
  170. npMCI->wMessageCurrent = 0;
  171. break;
  172. #endif
  173. }
  174. break;
  175. case WM_CLOSE:
  176. // Hide default window
  177. DeviceStop(npMCI, MCI_WAIT);
  178. ShowWindow(hwnd, SW_HIDE);
  179. LeaveCrit(npMCI);
  180. return 0L;
  181. case WM_DESTROY:
  182. // The window may be destroyed 2 ways.
  183. // a. the device is closed. In this case the animation is
  184. // freed in DeviceClose which is called from GraphicClose
  185. // and the animation ID is NULL by the time this window is
  186. // destroyed.
  187. // b. the window is closed. In this case, the animation is
  188. // not closed and we should set the stage to NULL. A new
  189. // default window will be created if needed.
  190. if (IsTask(npMCI->hTask)) {
  191. DeviceStop(npMCI, MCI_WAIT);
  192. }
  193. if (npMCI->hwnd == npMCI->hwndDefault)
  194. npMCI->hwnd = NULL;
  195. npMCI->hwndDefault = NULL;
  196. break;
  197. case WM_ERASEBKGND:
  198. hdc = (HDC) wParam;
  199. if (!(npMCI->dwFlags & MCIAVI_SHOWVIDEO)) {
  200. FillRect(hdc, &npMCI->rcDest, GetStockObject(GRAY_BRUSH));
  201. }
  202. SaveDC(hdc);
  203. ExcludeClipRect(hdc,
  204. npMCI->rcDest.left, npMCI->rcDest.top,
  205. npMCI->rcDest.right, npMCI->rcDest.bottom);
  206. GetClientRect(hwnd, &rc);
  207. FillRect(hdc, &rc, GetStockObject(BLACK_BRUSH));
  208. RestoreDC(hdc, -1);
  209. /* Hack: if we're in a WAIT state, we won't get
  210. ** a WM_PAINT, so we need to invalidate the streams here
  211. */
  212. GetClipBox(hdc, &rc);
  213. StreamInvalidate(npMCI, &rc);
  214. LeaveCrit(npMCI);
  215. return 0L;
  216. case WM_PAINT:
  217. #ifdef WIN32
  218. /*
  219. * on NT we have to poll more often to avoid deadlock between
  220. * threads (a SetWindowPos call on one thread will cause
  221. * the window-creating thread to issue the WM_SIZE message -
  222. * synchronously). The side effect of this is that we poll
  223. * for messages at times when it is not safe to process all
  224. * messages.
  225. *
  226. * So unless we know it is safe to paint, we punt...
  227. */
  228. //if (npMCI->wTaskState != TASKIDLE)
  229. if ((npMCI->wTaskState != TASKIDLE) && (npMCI->wTaskState != TASKPAUSED))
  230. {
  231. npMCI->dwFlags |= MCIAVI_NEEDUPDATE;
  232. DPF0(("Punting on painting, wTaskState = %x", npMCI->wTaskState));
  233. break;
  234. }
  235. #endif
  236. hdc = BeginPaint(hwnd, &ps);
  237. GetClientRect(hwnd, &rc);
  238. /* If updating fails, paint gray. */
  239. if (DeviceUpdate(npMCI, MCI_DGV_UPDATE_PAINT, hdc, &ps.rcPaint)
  240. == MCIERR_DEVICE_NOT_READY) {
  241. GetClientRect(hwnd, &rc);
  242. FillRect(hdc, &rc, GetStockObject(DKGRAY_BRUSH));
  243. }
  244. EndPaint(hwnd, &ps);
  245. return 0L;
  246. case WM_PALETTECHANGED:
  247. // We're not using the default window. We have no business here.
  248. if (npMCI->hwnd != hwnd)
  249. break;
  250. //
  251. // someone has realized a palette - so we need to re-realize our
  252. // palette (note that this will also cause drawdib to
  253. // check for PAL_INDICES vs PAL_COLOURS.
  254. //
  255. if ((HWND) wParam != hwnd) {
  256. DeviceRealize(npMCI);
  257. InvalidateRect(hwnd, NULL, FALSE);
  258. }
  259. break;
  260. case WM_QUERYNEWPALETTE:
  261. // We're not using the default window. We have no business here.
  262. if (npMCI->hwnd != hwnd)
  263. break;
  264. LeaveCrit(npMCI); // tomor -- maybe this should be after?
  265. return DeviceRealize(npMCI);
  266. case WM_WINDOWPOSCHANGED:
  267. CheckWindowMove(npMCI, TRUE);
  268. break;
  269. #ifdef WM_AVISWP
  270. case WM_AVISWP:
  271. {
  272. long res;
  273. res = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, lParam);
  274. LeaveCrit(npMCI);
  275. return(res);
  276. }
  277. #endif
  278. case WM_SIZE:
  279. ResetDestRect(npMCI);
  280. break;
  281. case WM_QUERYENDSESSION:
  282. DeviceStop(npMCI, MCI_WAIT);
  283. break;
  284. case WM_ENDSESSION:
  285. if (wParam) {
  286. DestroyWindow(hwnd); // we may not be able to destroy window?
  287. }
  288. break;
  289. case WM_GETMINMAXINFO:
  290. lpmmi = (MINMAXINFO FAR *)(lParam);
  291. lpmmi->ptMinTrackSize.x = GetSystemMetrics(SM_CXSIZE) * 2;
  292. break;
  293. case WM_NCACTIVATE:
  294. case WM_ACTIVATE:
  295. DeviceSetActive(npMCI, (BOOL)wParam);
  296. break;
  297. case WM_AUDIO_ON:
  298. Assert(npMCI->dwFlags & MCIAVI_PLAYAUDIO);
  299. Assert(npMCI->dwFlags & MCIAVI_LOSTAUDIO);
  300. Assert(npMCI->hWave == NULL);
  301. npMCI->dwFlags &= ~MCIAVI_PLAYAUDIO;
  302. DeviceMute(npMCI, FALSE);
  303. break;
  304. case WM_AUDIO_OFF:
  305. Assert(npMCI->dwFlags & MCIAVI_PLAYAUDIO);
  306. Assert(!(npMCI->dwFlags & MCIAVI_LOSTAUDIO));
  307. Assert(npMCI->hWave != NULL);
  308. DeviceMute(npMCI, TRUE);
  309. npMCI->dwFlags |= MCIAVI_LOSTAUDIO;
  310. npMCI->dwFlags |= MCIAVI_PLAYAUDIO;
  311. break;
  312. #if 0
  313. case WM_LBUTTONDOWN:
  314. {
  315. DWORD dw;
  316. static DWORD dwLastClick;
  317. static DWORD dwClicks = 0;
  318. #define MAX_CLICKS 7
  319. /* . = (0,300) - = (300,1000) word = (500,1500) */
  320. /* AVI: .- ...- .. */
  321. static DWORD adwClickHigh[MAX_CLICKS] =
  322. { 300, 1500, 300, 300, 300, 1500, 300 };
  323. static DWORD adwClickLow[MAX_CLICKS] =
  324. { 0, 500, 0, 0, 0, 500, 0 };
  325. dw = timeGetTime();
  326. if (((dw - dwLastClick) > adwClickLow[dwClicks]) &&
  327. ((dw - dwLastClick) <= adwClickHigh[dwClicks]))
  328. dwClicks++;
  329. else
  330. dwClicks = 0;
  331. dwLastClick = dw;
  332. if (dwClicks == MAX_CLICKS) {
  333. DeviceStop(npMCI, MCI_WAIT);
  334. Credits(hwnd);
  335. dwClicks = 0;
  336. }
  337. }
  338. #endif
  339. }
  340. if (npMCI) {
  341. LeaveCrit(npMCI);
  342. }
  343. return DefWindowProc(hwnd, wMsg, wParam, lParam);
  344. }
  345. #if 0
  346. static void NEAR PASCAL Credits(HWND hwnd)
  347. {
  348. /* Credits... */
  349. RECT rc;
  350. RECT rcUpdate;
  351. HDC hdc;
  352. MSG msg;
  353. int dyLine;
  354. int yLine;
  355. TEXTMETRIC tm;
  356. DWORD dwNextTime;
  357. long lScroll;
  358. DWORD rgb;
  359. HANDLE hResInfo;
  360. HANDLE hResData;
  361. LPSTR pchSrc, pchDst;
  362. char achLine[100];
  363. int iEncrypt;
  364. #define EOFCHAR '@' // end of credits file
  365. /* load the credits */
  366. if ((hResInfo = FindResource(ghModule, TEXT("MMS"), TEXT("MMSCR"))) == NULL)
  367. return;
  368. if ((hResData = LoadResource(ghModule, hResInfo)) == NULL)
  369. return;
  370. if ((pchSrc = LockResource(hResData)) == NULL)
  371. return;
  372. /* we want to get all mouse and keyboard events, to make
  373. * sure we stop the animation when the user clicks or
  374. * hits a key
  375. */
  376. SetFocus(hwnd);
  377. SetCapture(hwnd);
  378. /* Scroll the credits up, one pixel at a time. pchSrc
  379. * points to the encrypted data; achLine contains a decrypted
  380. * line (null-terminated). dyLine is the height of each
  381. * line (constant), and yLine is between 0 and dyLine,
  382. * indicating how many pixels of the line have been scrolled
  383. * in vertically from the bottom
  384. */
  385. hdc = GetDC(hwnd);
  386. SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
  387. GetClientRect(hwnd, &rc);
  388. SetTextAlign(hdc, TA_CENTER);
  389. SetBkColor(hdc, RGB(0, 0, 0));
  390. SetRect(&rcUpdate, 0, rc.bottom - 1, rc.right, rc.bottom);
  391. GetTextMetrics(hdc, &tm);
  392. if ((dyLine = tm.tmHeight + tm.tmExternalLeading) == 0)
  393. dyLine = 1;
  394. yLine = dyLine;
  395. dwNextTime = GetCurrentTime(); // time to do the next scroll
  396. lScroll = 0;
  397. iEncrypt = 0;
  398. while (TRUE) {
  399. /* If the user clicks the mouse or hits a key, exit.
  400. * However, ignore WM_LBUTTONUP because they will have
  401. * to let go of the mouse after clicking the icon.
  402. * Also, ignore mouse move messages.
  403. */
  404. if (PeekMessage(&msg, hwnd, WM_KEYFIRST, WM_KEYLAST,
  405. PM_NOREMOVE | PM_NOYIELD))
  406. break; // exit on key hit
  407. if (PeekMessage(&msg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
  408. PM_NOREMOVE | PM_NOYIELD)) {
  409. if ((msg.message == WM_MOUSEMOVE) ||
  410. (msg.message == WM_LBUTTONUP)) {
  411. /* remove and ignore message */
  412. PeekMessage(&msg, hwnd, msg.message,
  413. msg.message,
  414. PM_REMOVE | PM_NOYIELD);
  415. }
  416. else
  417. break; // exit on click
  418. }
  419. /* scroll at a fixed no. of vertical pixels per sec. */
  420. if (dwNextTime > GetCurrentTime())
  421. continue;
  422. dwNextTime += 50L; // millseconds per scroll
  423. if (yLine == dyLine) {
  424. /* decrypt a line and copy to achLine */
  425. pchDst = achLine;
  426. while (TRUE) {
  427. *pchDst = (char) (*pchSrc++ ^
  428. (128 | (iEncrypt++ & 127)));
  429. if ((*pchDst == '\r') ||
  430. (*pchDst == EOFCHAR))
  431. break;
  432. pchDst++;
  433. }
  434. if (*pchDst == EOFCHAR)
  435. break; // no more lines
  436. *pchDst = 0; // null-terminate
  437. pchSrc++, iEncrypt++; // skip '\n'
  438. yLine = 0;
  439. }
  440. /* scroll screen up one pixel */
  441. BitBlt(hdc, 0, 0, rcUpdate.right, rcUpdate.top,
  442. hdc, 0, 1, SRCCOPY);
  443. /* vary the text colors through a "rainbow" */
  444. switch ((int) (lScroll++ / 4) % 5/*num-of-cases*/) {
  445. case 0: rgb = RGB(255, 0, 0); break;
  446. case 1: rgb = RGB(255, 255, 0); break;
  447. case 2: rgb = RGB( 0, 255, 0); break;
  448. case 3: rgb = RGB( 0, 255, 255); break;
  449. case 4: rgb = RGB(255, 0, 255); break;
  450. }
  451. SetTextColor(hdc, rgb);
  452. /* fill in the bottom pixel */
  453. SaveDC(hdc);
  454. yLine++;
  455. IntersectClipRect(hdc, rcUpdate.left, rcUpdate.top,
  456. rcUpdate.right, rcUpdate.bottom);
  457. #ifdef WIN32
  458. ExtTextOutA(hdc, rc.right / 2, rc.bottom - yLine,
  459. ETO_OPAQUE, &rcUpdate,
  460. achLine, lstrlenA(achLine), NULL);
  461. #else
  462. ExtTextOut(hdc, rc.right / 2, rc.bottom - yLine,
  463. ETO_OPAQUE, &rcUpdate,
  464. achLine, lstrlen(achLine), NULL);
  465. #endif
  466. RestoreDC(hdc, -1);
  467. }
  468. ReleaseDC(hwnd, hdc);
  469. ReleaseCapture();
  470. UnlockResource(hResData);
  471. FreeResource(hResData);
  472. InvalidateRect(hwnd, NULL, TRUE);
  473. }
  474. #endif
  475. void FAR PASCAL SetWindowToDefaultSize(NPMCIGRAPHIC npMCI)
  476. {
  477. RECT rc;
  478. if (npMCI->hwnd && npMCI->hwnd == npMCI->hwndDefault) {
  479. rc = npMCI->rcMovie;
  480. if (npMCI->dwOptionFlags & MCIAVIO_ZOOMBY2)
  481. SetRect(&rc, 0, 0, rc.right*2, rc.bottom*2);
  482. AdjustWindowRect(&rc, GetWindowLong(npMCI->hwnd, GWL_STYLE), FALSE);
  483. if (IsIconic(npMCI->hwnd)) {
  484. WINDOWPLACEMENT wp;
  485. wp.length = sizeof(wp);
  486. GetWindowPlacement(npMCI->hwnd, &wp);
  487. wp.rcNormalPosition.right = wp.rcNormalPosition.left +
  488. (rc.right - rc.left);
  489. wp.rcNormalPosition.bottom = wp.rcNormalPosition.top +
  490. (rc.bottom - rc.top);
  491. SetWindowPlacement(npMCI->hwnd, &wp);
  492. } else {
  493. SetWindowPos(npMCI->hwnd, NULL, 0, 0,
  494. rc.right - rc.left, rc.bottom - rc.top,
  495. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  496. }
  497. }
  498. }
  499. void FAR PASCAL ResetDestRect(NPMCIGRAPHIC npMCI)
  500. {
  501. RECT rc;
  502. /* WM_SIZE messages (on NT at least) are sometimes sent
  503. * during CreateWindow processing (eg if the initial window size
  504. * is not CW_DEFAULT). Some fields in npMCI are only filled in
  505. * after CreateWindow has returned. So there is a danger that at this
  506. * point some fields are not valid.
  507. */
  508. if (npMCI->hwnd &&
  509. npMCI->hwnd == npMCI->hwndDefault &&
  510. (npMCI->dwOptionFlags & MCIAVIO_STRETCHTOWINDOW)) {
  511. GetClientRect(npMCI->hwnd, &rc);
  512. }
  513. else if (npMCI->streams > 0) {
  514. rc = npMCI->rcMovie;
  515. if (npMCI->dwOptionFlags & MCIAVIO_ZOOMBY2) {
  516. rc.right *= 2;
  517. rc.bottom *= 2;
  518. }
  519. }
  520. else {
  521. return;
  522. }
  523. if (!IsRectEmpty(&rc))
  524. DevicePut(npMCI, &rc, MCI_DGV_PUT_DESTINATION);
  525. }
  526. void CheckWindowMove(NPMCIGRAPHIC npMCI, BOOL fForce)
  527. {
  528. #ifdef WIN32
  529. POINT dwOrg;
  530. #else
  531. DWORD dwOrg;
  532. #endif
  533. UINT wRgn;
  534. HDC hdc;
  535. RECT rc;
  536. BOOL f;
  537. BOOL fGetDC;
  538. if (!(npMCI->dwFlags & MCIAVI_WANTMOVE))
  539. return;
  540. if (!npMCI->hicDraw || !npMCI->hwnd || npMCI->nVideoStreams == 0)
  541. return;
  542. Assert(IsWindow(npMCI->hwnd));
  543. Assert(npMCI->paStreamInfo);
  544. Assert(npMCI->nVideoStreams > 0);
  545. //
  546. // when the screen is locked for update by a window move operation
  547. // we dont want to turn off the video.
  548. //
  549. // we can tell if the screen is locked by checking a DC to the screen.
  550. //
  551. hdc = GetDC(NULL);
  552. f = GetClipBox(hdc, &rc) == NULLREGION;
  553. ReleaseDC(NULL, hdc);
  554. if (f)
  555. {
  556. npMCI->wRgnType = (UINT) -1;
  557. return;
  558. }
  559. if (fForce)
  560. npMCI->wRgnType = (UINT) -1;
  561. if (fGetDC = (npMCI->hdc == NULL))
  562. hdc = GetDC (npMCI->hwnd);
  563. else
  564. hdc = npMCI->hdc;
  565. wRgn = GetClipBox(hdc, &rc);
  566. #ifdef WIN32
  567. GetDCOrgEx(hdc, &dwOrg);
  568. #else
  569. dwOrg = GetDCOrg(hdc);
  570. #endif
  571. if (fGetDC)
  572. ReleaseDC(npMCI->hwnd, hdc);
  573. if (wRgn == npMCI->wRgnType &&
  574. #ifdef WIN32
  575. dwOrg.x == npMCI->dwOrg.x &&
  576. dwOrg.y == npMCI->dwOrg.y &&
  577. #else
  578. dwOrg == npMCI->dwOrg &&
  579. #endif
  580. EqualRect(&rc, &npMCI->rcClip))
  581. return;
  582. npMCI->wRgnType = wRgn;
  583. npMCI->dwOrg = dwOrg;
  584. npMCI->rcClip = rc;
  585. rc = npMCI->psiVideo->rcDest;
  586. ClientToScreen(npMCI->hwnd, (LPPOINT)&rc);
  587. ClientToScreen(npMCI->hwnd, (LPPOINT)&rc+1);
  588. if (wRgn == NULLREGION)
  589. SetRectEmpty(&rc);
  590. DPF2(("Sending ICM_DRAW_WINDOW message Rgn=%d, Org=(%d,%d) [%d, %d, %d, %d]\n", wRgn, dwOrg, rc));
  591. if (ICDrawWindow(npMCI->hicDraw, &rc) != ICERR_OK) {
  592. DPF2(("Draw device does not want ICM_DRAW_WINDOW messages!\n"));
  593. npMCI->dwFlags &= ~MCIAVI_WANTMOVE;
  594. }
  595. }