Source code of Windows XP (NT5)
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.

2202 lines
74 KiB

  1. /*---------------------------------------------------------------------------
  2. | DOVERB.C
  3. | This file is used to be called server.c in the OLE1 versions of MPlayer.
  4. | This file has the ReallyDoVerb function which is called by the the
  5. | OLE DoVerb method. This file also has some functions to do the
  6. | InPlace activation in OLE1 apps.
  7. |
  8. | Modified for OLE2 By: Vij Rajarajan (VijR)
  9. +---------------------------------------------------------------------------*/
  10. #define SERVERONLY
  11. #include <windows.h>
  12. #include <mmsystem.h>
  13. #include <shellapi.h>
  14. #undef _MAX_PATH // ??? someone hacking?
  15. #undef _MAX_DIR // ??? someone hacking?
  16. #undef _MAX_FNAME // ??? someone hacking?
  17. #undef _MAX_EXT // ??? someone hacking?
  18. #include "ctrls.h"
  19. #include "mpole.h"
  20. #include "mplayer.h"
  21. #include "toolbar.h"
  22. #include "ole2ui.h"
  23. #define OLE_OK S_OK
  24. #define NOVERB 1000
  25. extern HANDLE ghInst;
  26. extern HWND ghwndFocus; // Who had focus when we went inactive
  27. extern HWND ghwndFocusSave; // saved focus window
  28. extern HOOKPROC fpMouseHook; // Mouse hook proc address.
  29. extern UINT gwPlaybarHeight; //tell playbar how tall to make
  30. //itself so it covers the title
  31. DWORD gdwPosition;
  32. LONG glCurrentVerb = NOVERB;
  33. BOOL gfBrokenLink = FALSE;
  34. static BOOL gfMouseUpSeen = FALSE; // OK to close play in place?
  35. static BOOL gfKeyStateUpSeen = FALSE; // OK to close play in place?
  36. extern HMODULE hMciOle;
  37. /*
  38. ** These functions are exported from mciole32.dll.
  39. **
  40. */
  41. typedef BOOL (*LPINSTALLHOOK)( HWND, DWORD );
  42. typedef BOOL (*LPREMOVEHOOK)( VOID );
  43. LPINSTALLHOOK fpInstallHook;
  44. LPREMOVEHOOK fpRemoveHook;
  45. BOOL fHookInstalled = FALSE;
  46. char aszInstallHook[] = "InstallHook";
  47. char aszRemoveHook[] = "RemoveHook";
  48. /* Height of picture given to client to be pasted */
  49. static UINT gwPastedHeight;
  50. static DWORD gwOldOptions;
  51. static DWORD gwOldHeight;
  52. TCHAR gachFile[_MAX_PATH];
  53. static int gerr;
  54. static HWND ghwndClient = NULL;
  55. static RECT grcClient;
  56. BOOL gfOle1Client = FALSE;
  57. WNDPROC gfnMCIWndProc;
  58. HWND ghwndSubclass;
  59. BOOL SkipInPlaceEdit = FALSE; //TRUE if we are just reactivating
  60. BOOL gfSeenPBCloseMsg; //TRUE if the subclasses PlayBack WIndow Proc
  61. //has seen the WM_CLOSE message
  62. HWND ghwndFocusSave; //Who had the focus when we were activated.?
  63. #define abs(x) ((x) < 0 ? -(x) : (x))
  64. #ifndef GetWS
  65. #define GetWS(hwnd) GetWindowLongPtr(hwnd, GWL_STYLE)
  66. #define PutWS(hwnd, f) SetWindowLongPtr(hwnd, GWL_STYLE, f)
  67. #define TestWS(hwnd,f) (GetWS(hwnd) & f)
  68. #define SetWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) | f)
  69. #define ClrWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) & ~(f))
  70. #endif
  71. static SZCODE aszAppName[] = TEXT("MPlayer");
  72. STATICFN BOOL FileExists(LPTSTR szFile, LPTSTR szFullName, int iLen);
  73. STATICFN BOOL NetParseFile(LPTSTR szFile, LPTSTR szDrive, LPTSTR szPath);
  74. HPALETTE FAR PASCAL CreateSystemPalette(void);
  75. void TransferTools(HWND hwndToolWindow);
  76. #ifdef DEBUG
  77. BOOL ShowAppWindow(int nCmdShow)
  78. {
  79. return ShowWindow(ghwndApp, nCmdShow);
  80. }
  81. #define SHOWAPPWINDOW(nCmdShow) ShowAppWindow(nCmdShow)
  82. #else
  83. #define SHOWAPPWINDOW(nCmdShow) ShowWindow(ghwndApp, nCmdShow)
  84. #endif
  85. /*************************************************************************
  86. * DirtyObject(BOOL fDocStgChangeOnly) - mark the "object" dirty,
  87. * ie has been changed.
  88. *
  89. * We set the gfDirty flag to TRUE and iff we are a embedded object tell
  90. * the client we have changed by sending a SendDocMsg(OLE_CHANGED).
  91. * fDocStgChangeOnly is TRUE if the change would affect the Embedding if there
  92. * is one but not appearence of the object i.e. the Metafile.
  93. * OLE_CHANGED message is sent only if fDocStgChangeOnly is FALSE;
  94. ***************************************************************************/
  95. void DirtyObject(BOOL fDocStgChangeOnly)
  96. {
  97. //
  98. // NOTE we want to send OLE_CHANGED even if selection has changed
  99. //
  100. if (gfOle2IPEditing && ((gwOptions & OPT_BAR) != (gwOldOptions &OPT_BAR)) && !fDocStgChangeOnly)
  101. {
  102. RECT rc;
  103. BOOL fCanWindow = gwDeviceType & DTMCI_CANWINDOW;
  104. if (fCanWindow)
  105. {
  106. GetWindowRect(ghwndApp, (LPRECT)&rc);
  107. OffsetRect((LPRECT)&rc, -rc.left, -rc.top);
  108. /* rc contains the coordinates of the current app window.
  109. * If we have a playbar, we must allow space for it:
  110. */
  111. if ((gwOptions & OPT_BAR) && !(gwOldOptions &OPT_BAR))
  112. {
  113. /* Add bar */
  114. Layout();
  115. gwPlaybarHeight = TOOLBAR_HEIGHT;
  116. }
  117. else if(!(gwOptions & OPT_BAR) && (gwOldOptions &OPT_BAR))
  118. {
  119. /* Remove bar */
  120. Layout();
  121. gwPlaybarHeight = 0;
  122. }
  123. }
  124. else
  125. {
  126. HBITMAP hbm;
  127. BITMAP bm;
  128. GetWindowRect(ghwndIPHatch, (LPRECT)&rc);
  129. if (gwOptions & OPT_BAR)
  130. gwPlaybarHeight = TOOLBAR_HEIGHT;
  131. else
  132. gwPlaybarHeight = 0;
  133. hbm = BitmapMCI();
  134. GetObject(hbm,sizeof(bm),&bm);
  135. rc.bottom = rc.top + bm.bmHeight;
  136. rc.right = rc.left + bm.bmWidth;
  137. DeleteObject(hbm);
  138. MapWindowPoints(NULL,ghwndCntr,(LPPOINT)&rc, (UINT)2);
  139. DPF("IOleInPlaceSite::OnPosRectChange %d, %d, %d, %d\n", rc);
  140. if (!gfInPPViewer)
  141. IOleInPlaceSite_OnPosRectChange(docMain.lpIpData->lpSite, &rc);
  142. }
  143. }
  144. if (gwOptions != gwOldOptions)
  145. {
  146. gwOldOptions = gwOptions;
  147. if (gfEmbeddedObject && !fDocStgChangeOnly)
  148. SendDocMsg(&docMain, OLE_CHANGED);
  149. }
  150. if (gfDirty /* IsObjectDirty() */)
  151. return;
  152. fDocChanged=gfDirty = TRUE;
  153. gfValidCaption = FALSE;
  154. }
  155. /**************************************************************************
  156. IsObjectDirty() - Object is dirty if the dirty flag is set or the selection
  157. has changed since we last cleaned or the Metafile has
  158. changed
  159. ***************************************************************************/
  160. BOOL FAR PASCAL IsObjectDirty(void)
  161. {
  162. // don't let anyone insert an empty mplayer into a document
  163. if (gwDeviceID == (UINT)0)
  164. return FALSE;
  165. return (gfDirty
  166. || glSelStart != (long)SendMessage(ghwndTrackbar, TBM_GETSELSTART, 0, 0L)
  167. || glSelEnd != (long)SendMessage(ghwndTrackbar, TBM_GETSELEND, 0, 0L)
  168. /// I don't see this. This line results in the Update Object dialog coming
  169. /// up when it shouldn't. What has it got to do with metafiles?
  170. /// ??? || gdwPosition != (DWORD)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L)
  171. );
  172. }
  173. /**************************************************************************
  174. CleanObject() - mark the "object" clean.
  175. ***************************************************************************/
  176. void CleanObject(void)
  177. {
  178. if (!IsObjectDirty())
  179. return;
  180. fDocChanged = gfDirty = FALSE;
  181. /* Reset selection globals so we can see if they changed */
  182. glSelStart = (long)SendMessage(ghwndTrackbar, TBM_GETSELSTART, 0, 0L);
  183. glSelEnd = (long)SendMessage(ghwndTrackbar, TBM_GETSELEND, 0, 0L);
  184. gdwPosition = (DWORD)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L);
  185. gfValidCaption = FALSE;
  186. }
  187. /**************************************************************************
  188. //## Just parses the play etc options in the embedded object
  189. //## description string
  190. ***************************************************************************/
  191. SCODE FAR PASCAL ParseOptions(LPSTR pOpt)
  192. {
  193. #ifdef UNICODE
  194. DWORD OptLen;
  195. #endif
  196. PTSTR pT, pSave;
  197. int c;
  198. if (pOpt == NULL || *pOpt == 0)
  199. return OLE_OK;
  200. #ifdef UNICODE
  201. OptLen = ANSI_STRING_BYTE_COUNT( pOpt );
  202. pT = AllocMem( OptLen * sizeof( TCHAR ) );
  203. if (pT == NULL)
  204. return E_OUTOFMEMORY;
  205. MultiByteToWideChar( CP_ACP,
  206. MB_PRECOMPOSED,
  207. pOpt,
  208. OptLen,
  209. pT,
  210. OptLen );
  211. #else
  212. pT = pOpt;
  213. #endif
  214. pSave = pT; // wasn't NULL terminated before
  215. for (c = 0; *pT && c < 5; pT++) // change 1st 5 ','s to '\0'
  216. if (*pT == TEXT(','))
  217. {
  218. c++;
  219. *pT = TEXT('\0');
  220. }
  221. pT = pSave; // restore back to beginning
  222. pT += STRLEN(pT) + 1; // skip over Device Name
  223. gwOptions = ATOI(pT);
  224. gwCurScale = (gwOptions & OPT_SCALE);
  225. /* Can't set selection now because Media isn't initialized (UpdateMCI) */
  226. pT += STRLEN(pT) + 1;
  227. glSelStart = ATOL(pT); // remember start of selection for later
  228. pT += STRLEN(pT) + 1;
  229. glSelEnd = ATOL(pT); // remember end of selection for later
  230. pT += STRLEN(pT) + 1;
  231. // remember position in a global so we can Seek later!!
  232. gdwPosition = ATOL(pT);
  233. /* Maybe there is the original height of the picture given to the client in */
  234. /* here hidden in the Position string after a semicolon. */
  235. /* Old versions of Mplayer didn't have any such thing. */
  236. for (; *pT && *pT != TEXT(';'); pT++);
  237. if (*pT == TEXT(';'))
  238. {
  239. pT++;
  240. gwPastedHeight = (UINT)ATOL(pT);
  241. }
  242. else
  243. gwPastedHeight = 0;
  244. pT += STRLEN(pT) + 1;
  245. lstrcpy(gachCaption, pT);
  246. #ifdef UNICODE
  247. FreeMem( pSave, OptLen * sizeof( TCHAR ) );
  248. #endif
  249. return OLE_OK;
  250. }
  251. /**************************************************************************
  252. //## Used to find the parent window of the window handle passed till the
  253. //## window handle is a top level handle
  254. ***************************************************************************/
  255. HWND TopWindow(HWND hwnd)
  256. {
  257. HWND hwndP;
  258. while ((hwndP = GetParent(hwnd)) != NULL)
  259. hwnd = hwndP;
  260. return hwnd;
  261. }
  262. /**************************************************************************
  263. ***************************************************************************/
  264. void FAR PASCAL SetEmbeddedObjectFlag(BOOL flag)
  265. {
  266. TCHAR ach[60];
  267. TCHAR achText[_MAX_PATH];
  268. gfEmbeddedObject = flag;
  269. srvrMain.fEmbedding = flag;
  270. if (!ghMenu)
  271. return;
  272. /*** First fix the Close/Update menu item ***/
  273. LOADSTRING(flag ? IDS_UPDATE : IDS_CLOSE, ach);
  274. if (flag)
  275. wsprintf(achText, ach, (LPTSTR)FileName(szClientDoc));
  276. else
  277. lstrcpy(achText, ach);
  278. /* Menu option will either say "Close" or "Update" (for embedded obj) */
  279. /* and for update, will have the doc name in the text. */
  280. ModifyMenu(ghMenu, IDM_CLOSE, MF_BYCOMMAND, IDM_CLOSE, achText);
  281. /*** Now fix the Exit menu item ***/
  282. LOADSTRING(flag ? IDS_EXITRETURN : IDS_EXIT, ach);
  283. if (flag)
  284. wsprintf(achText, ach, (LPTSTR)FileName(szClientDoc));
  285. else
  286. lstrcpy(achText, ach);
  287. /* Menu option will either say "Close" or "Update" (for embedded obj) */
  288. /* and for update, will have the doc name in the text. */
  289. ModifyMenu(ghMenu, IDM_EXIT, MF_BYCOMMAND, IDM_EXIT, achText);
  290. DrawMenuBar(ghwndApp); /* Can't hurt... */
  291. }
  292. /**************************************************************************
  293. //## MORE STUFF FOR PLAY IN PLACE, should disappear in OLE2.
  294. //VIJR: Nope. Still needed for playing inplace in OLE1 clients.
  295. ***************************************************************************/
  296. void PASCAL DinkWithWindowStyles(HWND hwnd, BOOL fRestore)
  297. {
  298. #define MAX_DINK 80
  299. static LONG_PTR lStyleSave[MAX_DINK];
  300. static HWND hwndSave[MAX_DINK];
  301. static int nSave;
  302. int i;
  303. HWND hwndT;
  304. RECT rc, rcT;
  305. if (!TestWS(hwnd, WS_CHILD))
  306. return;
  307. if (fRestore)
  308. for (i=0; i<nSave; i++)
  309. {
  310. if(IsWindow(hwndSave[i])) {
  311. ClrWS(hwndSave[i],WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  312. SetWS(hwndSave[i],lStyleSave[i] & (WS_CLIPSIBLINGS|WS_CLIPCHILDREN));
  313. }
  314. }
  315. else
  316. {
  317. //
  318. // walk all the siblings that intersect us and set CLIPSIBLINGS
  319. //
  320. i = 0;
  321. GetWindowRect(hwnd, &rc);
  322. for (hwndT = GetWindow(hwnd, GW_HWNDFIRST);
  323. hwndT;
  324. hwndT = GetWindow(hwndT, GW_HWNDNEXT))
  325. {
  326. GetWindowRect(hwndT, &rcT);
  327. if (IntersectRect(&rcT, &rcT, &rc))
  328. {
  329. lStyleSave[i] = GetWS(hwndT);
  330. hwndSave[i] = hwndT;
  331. SetWS(hwndT,WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  332. if (++i == MAX_DINK-4)
  333. break;
  334. }
  335. }
  336. //
  337. // walk up the window chain, making sure we get clipped from our
  338. // parent(s).
  339. //
  340. for (hwndT = hwnd; hwndT; hwndT = GetParent(hwndT))
  341. {
  342. lStyleSave[i] = GetWS(hwndT);
  343. hwndSave[i] = hwndT;
  344. if(IsWindow(hwndT))
  345. SetWS(hwndT,WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  346. if (++i == MAX_DINK)
  347. break;
  348. }
  349. nSave = i;
  350. }
  351. }
  352. #define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
  353. /**************************************************************************
  354. FileName - return a pointer to the filename part of szPath
  355. with no preceding path.
  356. ***************************************************************************/
  357. LPTSTR FAR FileName(LPCTSTR lszPath)
  358. {
  359. LPCTSTR lszCur;
  360. for (lszCur = lszPath + STRLEN(lszPath); lszCur > lszPath && !SLASH(*lszCur) && *lszCur != TEXT(':');)
  361. lszCur = CharPrev(lszPath, lszCur);
  362. if (lszCur == lszPath)
  363. return (LPTSTR)lszCur;
  364. else
  365. return (LPTSTR)(lszCur + 1);
  366. }
  367. /**************************************************************************
  368. //## This function should be handled by OLE2
  369. //VIJR: Nope. Still needed for playing inplace in OLE1 clients.
  370. ***************************************************************************/
  371. void FAR PASCAL PlayInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc)
  372. {
  373. if (gfPlayingInPlace) // this is bad
  374. return;
  375. DPF("Using Child window for playback\n");
  376. SetWS(hwndApp, WS_CHILD);
  377. SetParent(hwndApp, hwndClient);
  378. if(!(gfOle2IPEditing || gfOle2IPPlaying))
  379. DinkWithWindowStyles(hwndApp, FALSE);
  380. if(!gfOle2IPEditing)
  381. gfPlayingInPlace = TRUE;
  382. if(gfOle2IPPlaying)
  383. MapWindowPoints(NULL,hwndClient,(LPPOINT)prc,2);
  384. /* For OLE2, now calls MoveWindow in DoInPlaceEdit (inplace.c).
  385. * This fixes 23429, window positioning in Word.
  386. */
  387. if(!(gfOle2IPEditing || gfOle2IPPlaying))
  388. {
  389. SetWindowPos(hwndApp, HWND_TOP,
  390. prc->left,prc->top,
  391. prc->right - prc->left,
  392. prc->bottom - prc->top,
  393. SWP_NOACTIVATE);
  394. }
  395. if(!gfOle2IPPlaying) // OLE1 Clients
  396. {
  397. /*
  398. ** On NT we have to install a global mouse HookProc which has to
  399. ** in a DLL. Also we have to tell the DLL which process/thread we are
  400. ** interested in, therefore let the DLL install the HookProc. When the
  401. ** HookProc detects an "interesting" mouse message it stops the
  402. ** device from playing. However, the device "stopping" function is
  403. ** inside mplayer, so we have to export it so that the HookProc can
  404. ** call it.
  405. */
  406. if ( hMciOle ) {
  407. fpInstallHook = (LPINSTALLHOOK)GetProcAddress( hMciOle,
  408. aszInstallHook );
  409. fpRemoveHook = (LPREMOVEHOOK)GetProcAddress( hMciOle,
  410. aszRemoveHook );
  411. }
  412. else {
  413. fpInstallHook = NULL;
  414. fpRemoveHook = NULL;
  415. }
  416. // Is the key down at this INSTANT ??? Then wait until it comes up before
  417. // we allow GetAsyncKeyState to make us go away
  418. gfMouseUpSeen = !((GetAsyncKeyState(VK_LBUTTON) & 0x8000) ||
  419. (GetAsyncKeyState(VK_RBUTTON) & 0x8000));
  420. // Is GetKeyState saying it's down? If so, wait until GetKeyState returns
  421. // up before we let GetKeyState kill us.
  422. gfKeyStateUpSeen= !(GetKeyState(VK_LBUTTON) || GetKeyState(VK_RBUTTON));
  423. #ifdef DEBUG
  424. if ( fHookInstalled ) {
  425. DPF( "Hook already installed\n" );
  426. DebugBreak();
  427. }
  428. #endif
  429. if ( fpInstallHook ) {
  430. DWORD wow_thread_id = 0L;
  431. /*
  432. ** This is a HACK. If the client applications is a WOW app the
  433. ** HIWORD of the window handle will be 0x0000 or 0xFFFF.
  434. ** Chandan tells me that on Daytona the HIWORD could be
  435. ** either of the above.
  436. */
  437. if ( HIWORD(hwndClient) == 0x0000 || HIWORD(hwndClient) == 0xFFFF) {
  438. wow_thread_id = GetWindowThreadProcessId( hwndClient, NULL );
  439. }
  440. fHookInstalled = (*fpInstallHook)( ghwndApp, wow_thread_id );
  441. }
  442. }
  443. ghwndFocusSave = GetFocus();
  444. }
  445. //This function is new for OLE2. It sets the container window as
  446. //our window's (actually the hatch window's) parent and positions the window
  447. void FAR PASCAL EditInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc)
  448. {
  449. RECT rc;
  450. rc = *prc;
  451. SetWS(hwndApp, WS_CHILD);
  452. SetParent(hwndApp, hwndClient);
  453. ScreenToClient(hwndClient,(LPPOINT)&rc);
  454. ScreenToClient(hwndClient,(LPPOINT)&rc+1);
  455. if(gwDeviceType & DTMCI_CANWINDOW)
  456. {
  457. /* Sometimes the position (though not the size) of this rectangle
  458. * gets messed up (most reliably in PowerPoint 7).
  459. * I can't figure out why this is happening (see the nightmarish
  460. * code in ReallyDoVerb() to get a flavour of what happens).
  461. * But it turns out that this call is unnecessary in any case,
  462. * since the window has already been positioned properly in
  463. * IPObjSetObjectRects().
  464. * I suspect there's a lot of surplus window-positioning code,
  465. * but now isn't the time to start making major changes.
  466. * This is the minimal change that makes things work.
  467. */
  468. //This fixes NTRaid bug #236641 in Excel. AND bug #247393 in Word
  469. //Sometimes there is confusion between who the parent is. mplay32 sets the document
  470. //window as the parent and the rectangle sent in SetObjectRects might not be with respect to
  471. //the document window (this might happen when the document window is not in the maximized state).
  472. //In this function we know the parent and the rectangle in that parent. Setting
  473. //the position here places our OLE object as the client requires. This change is even safe in
  474. //terms of introducing regressions.
  475. SetWindowPos(hwndApp, HWND_TOP,
  476. rc.left, rc.top,
  477. rc.right - rc.left,
  478. rc.bottom - rc.top,
  479. SWP_NOACTIVATE | SWP_FRAMECHANGED);
  480. }
  481. else if(gwDeviceID)
  482. SetWindowPos(hwndApp, HWND_TOP,
  483. rc.left,rc.top,
  484. rc.right - rc.left,
  485. rc.bottom - rc.top,
  486. SWP_SHOWWINDOW);
  487. else
  488. SetWindowPos(hwndApp, HWND_TOP,
  489. rc.left,rc.top,
  490. rc.right - rc.left,
  491. rc.bottom - rc.top,
  492. SWP_HIDEWINDOW);
  493. ghwndFocusSave = GetFocus();
  494. //Set the focus for the parent.
  495. if((gwDeviceID == (UINT)0) && IsWindow(hwndClient))
  496. {
  497. SetFocus(hwndClient);
  498. }
  499. }
  500. /**************************************************************************
  501. //## This is called to end PlayInPlace and make sure that the window goes
  502. //## away and the also to manage the palette stuff (May go away in OLE2)
  503. //## This function should be handled by OLE2
  504. ***************************************************************************/
  505. void FAR PASCAL EndPlayInPlace(HWND hwndApp)
  506. {
  507. HWND hwndP;
  508. HWND hwndT;
  509. if (!gfPlayingInPlace || !IsWindow(hwndApp))
  510. return;
  511. /* Do this BEFORE hiding our window and BEFORE we do anything that */
  512. /* might yield so client can't redraw with the wrong styles set. */
  513. if (!(gfOle2IPEditing || gfOle2IPPlaying))
  514. DinkWithWindowStyles(hwndApp, TRUE);
  515. gfPlayingInPlace = FALSE;
  516. /*
  517. ** Tell mciole32.dll to remove its mouse HookProc.
  518. */
  519. if ( fHookInstalled && fpRemoveHook ) {
  520. fHookInstalled = !(*fpRemoveHook)();
  521. }
  522. if (gfOle2IPPlaying)
  523. hwndP = ghwndCntr;
  524. else
  525. hwndP = GetParent(hwndApp);
  526. //
  527. // If we have the focus, then restore it to who used to have it.
  528. // ACK!! If the person who used to have it is GONE, we must give it away
  529. // to somebody (who choose our parent) because our child can't
  530. // keep the focus without making windows crash hard during the WM_DESTROY
  531. // (or maybe later whenever it feels like crashing at some random time).
  532. // See bug #8634.
  533. //
  534. if (((hwndT = GetFocus()) != NULL) && GetWindowTask(hwndT) == MGetCurrentTask) {
  535. if (IsWindow(ghwndFocusSave))
  536. SetFocus(ghwndFocusSave);
  537. else
  538. SetFocus(hwndP);
  539. }
  540. if (!hwndP ||
  541. (gwOptions & OPT_BAR) ||
  542. (gwOptions & OPT_BORDER) ||
  543. (gwOptions & OPT_AUTORWD))
  544. {
  545. // hide the aplication window
  546. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  547. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE);
  548. }
  549. else
  550. {
  551. //
  552. // hide our window, but don't redraw it will look
  553. // like we are still on the last frame.
  554. //
  555. // this is when we are playing in place, and there is
  556. // no playbar, and no rewind
  557. //
  558. // this is for Playing a AVI in a PowerPoint slide
  559. // without redraw problems.
  560. //
  561. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  562. SWP_NOREDRAW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|
  563. SWP_HIDEWINDOW|SWP_NOACTIVATE);
  564. }
  565. SetParent(hwndApp, NULL);
  566. ClrWS(hwndApp, WS_CHILD);
  567. if (hwndP && gfParentWasEnabled)
  568. EnableWindow(hwndP, TRUE);
  569. //
  570. // set either the owner or the WS_CHILD bit so it will
  571. // not act up because we have the palette bit set and cause the
  572. // desktop to steal the palette.
  573. //
  574. SetWS(hwndApp, WS_CHILD);
  575. }
  576. //If we were InPlace editing restore the windows state.
  577. void FAR PASCAL EndEditInPlace(HWND hwndApp)
  578. {
  579. HWND hwndP;
  580. HWND hwndT;
  581. if (!gfOle2IPEditing || !IsWindow(hwndApp))
  582. return;
  583. /* Do this BEFORE hiding our window and BEFORE we do anything that */
  584. /* might yield so client can't redraw with the wrong styles set. */
  585. DinkWithWindowStyles(hwndApp, TRUE);
  586. gfOle2IPEditing = FALSE;
  587. if (gfOle2IPPlaying)
  588. hwndP = ghwndCntr;
  589. else
  590. hwndP = GetParent(hwndApp);
  591. //
  592. // If we have the focus, then restore it to who used to have it.
  593. // ACK!! If the person who used to have it is GONE, we must give it away
  594. // to somebody (who choose our parent) because our child can't
  595. // keep the focus without making windows crash hard during the WM_DESTROY
  596. // (or maybe later whenever it feels like crashing at some random time).
  597. // See bug #8634.
  598. //
  599. if (((hwndT = GetFocus()) != NULL) && GetWindowTask(hwndT) == MGetCurrentTask) {
  600. if (IsWindow(ghwndFocusSave))
  601. SetFocus(ghwndFocusSave);
  602. else
  603. if (IsWindow(hwndP))
  604. SetFocus(hwndP);
  605. }
  606. if (!IsWindow(hwndP) ||
  607. (gwOptions & OPT_BAR) ||
  608. (gwOptions & OPT_BORDER) ||
  609. (gwOptions & OPT_AUTORWD))
  610. {
  611. // hide the aplication window
  612. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  613. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE);
  614. }
  615. else
  616. {
  617. //
  618. // hide our window, but don't redraw it will look
  619. // like we are still on the last frame.
  620. //
  621. // this is when we are playing in place, and there is
  622. // no playbar, and no rewind
  623. //
  624. // this is for Playing a AVI in a PowerPoint slide
  625. // without redraw problems.
  626. //
  627. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  628. SWP_NOREDRAW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|
  629. SWP_HIDEWINDOW|SWP_NOACTIVATE);
  630. }
  631. SetParent(hwndApp, NULL);
  632. ClrWS(hwndApp, WS_CHILD);
  633. if (IsWindow(hwndP) && gfParentWasEnabled)
  634. EnableWindow(hwndP, TRUE);
  635. //
  636. // set either the owner or the WS_CHILD bit so it will
  637. // not act up because we have the palette bit set and cause the
  638. // desktop to steal the palette.
  639. //
  640. SetWS(hwndApp, WS_CHILD);
  641. }
  642. /* Tell the user that something's amiss with a network call.
  643. * For network-specific errors, call WNetGetLastError,
  644. * otherwise see if it's a system error.
  645. */
  646. void DisplayNetError(DWORD Error)
  647. {
  648. DWORD ErrorCode; // address of error code
  649. TCHAR szDescription[512]; // address of string describing error
  650. TCHAR szProviderName[64]; // address of buffer for network provider name
  651. if (Error == ERROR_EXTENDED_ERROR)
  652. {
  653. if (WNetGetLastError(&ErrorCode, szDescription, CHAR_COUNT(szDescription),
  654. szProviderName, CHAR_COUNT(szProviderName)) == NO_ERROR)
  655. {
  656. Error1(ghwndApp, IDS_NETWORKERROR, szDescription);
  657. return;
  658. }
  659. }
  660. else
  661. {
  662. if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, Error, 0,
  663. szDescription, CHAR_COUNT(szDescription), NULL) > 0)
  664. {
  665. Error1(ghwndApp, IDS_NETWORKERROR, szDescription);
  666. return;
  667. }
  668. }
  669. /* If all else fails:
  670. */
  671. Error(ghwndApp, IDS_UNKNOWNNETWORKERROR);
  672. }
  673. /**************************************************************************
  674. convert a file name to a fully qualifed path name, if the file
  675. exists on a net drive the UNC name is returned.
  676. ***************************************************************************/
  677. STATICFN BOOL NetParseFile(LPTSTR szFile, LPTSTR szDrive, LPTSTR szPath)
  678. {
  679. BYTE UNBuffer[(MAX_PATH * sizeof(TCHAR)) + sizeof(UNIVERSAL_NAME_INFO)];
  680. DWORD UNBufferSize = sizeof UNBuffer;
  681. DWORD_PTR Error;
  682. LPTSTR pUniversalName;
  683. //
  684. // Turn into a fully qualified path name
  685. //
  686. if (!FileExists(szFile, szPath, MAX_PATH))
  687. return FALSE;
  688. //
  689. // if the file is not drive based (probably UNC)
  690. //
  691. if (szPath[1] != TEXT(':'))
  692. return TRUE;
  693. Error = WNetGetUniversalName(szDrive, UNIVERSAL_NAME_INFO_LEVEL,
  694. UNBuffer, &UNBufferSize);
  695. if (Error == ERROR_NOT_SUPPORTED)
  696. {
  697. /* This means that the network provider doesn't support
  698. * UNC conventions. Give WNetGetConnection a try.
  699. * Note: dynalink.h assumes that WNetGetUniversalName
  700. * will always be called before WNetGetConnection.
  701. */
  702. UNBufferSize = CHAR_COUNT(UNBuffer);
  703. Error = WNetGetConnection(szDrive, (LPTSTR)UNBuffer, &UNBufferSize);
  704. if (Error == NO_ERROR)
  705. {
  706. /* What does the following mean? It was in the original code.
  707. */
  708. if (!SLASH(UNBuffer[0]) || !SLASH(UNBuffer[1]))
  709. return TRUE;
  710. lstrcat((LPTSTR)UNBuffer, szPath+2);
  711. lstrcpy(szPath, (LPTSTR)UNBuffer);
  712. return TRUE;
  713. }
  714. }
  715. if (Error != NO_ERROR)
  716. {
  717. DisplayNetError((DWORD)Error);
  718. return FALSE;
  719. }
  720. pUniversalName = ((LPUNIVERSAL_NAME_INFO)UNBuffer)->lpUniversalName;
  721. lstrcat(pUniversalName, szPath+2);
  722. lstrcpy(szPath, pUniversalName);
  723. return TRUE;
  724. }
  725. /**************************************************************************
  726. Get the data that represents the currently open MCI file/device. as
  727. a link. MPlayer links look like this:
  728. MPLAYER|<filename>!<MCIDevice> [selection]
  729. //## This is the opposite of parse options and sets the data string to be
  730. //## embedded in the OLE object.
  731. Note we store the data in an ANSI string, regardless of whether we're
  732. compiled as a Unicode app, for Daytona/Chicago/OLE1/OLE2 compatibility.
  733. ***************************************************************************/
  734. HANDLE GetLink( VOID )
  735. {
  736. TCHAR szFileName[MAX_PATH];
  737. TCHAR szFullName[MAX_PATH];
  738. TCHAR szDevice[40];
  739. TCHAR szDrive[4];
  740. HANDLE h;
  741. LPSTR p; /* NOT LPTSTR */
  742. int len;
  743. int lenAppName;
  744. int lenFullName;
  745. lstrcpy(szFileName,gachFileDevice);
  746. lstrcpy(szFullName,gachFileDevice);
  747. //
  748. // convert the filename into a UNC file name, if it exists on the net
  749. //
  750. if (gwDeviceType & DTMCI_FILEDEV)
  751. {
  752. if (szFileName[1] == TEXT(':'))
  753. {
  754. /* This is a file name with a drive letter.
  755. * Find out if it's redirected:
  756. */
  757. szDrive[0] = szFileName[0];
  758. szDrive[1] = szFileName[1];
  759. szDrive[2] = TEXT('\\'); // GetDriveType requires the root.
  760. szDrive[3] = TEXT('\0'); // Null-terminate.
  761. if ((szDrive[1] == TEXT(':')) && GetDriveType(szDrive) == DRIVE_REMOTE)
  762. {
  763. szDrive[2] = TEXT('\0'); // Zap backslash.
  764. if (!NetParseFile(szFileName, szDrive, szFullName))
  765. return NULL;
  766. }
  767. }
  768. }
  769. else if (gwDeviceType & DTMCI_SIMPLEDEV)
  770. {
  771. szFullName[0] = 0;
  772. }
  773. if (gwCurDevice == 0)
  774. GetDeviceNameMCI(szDevice, BYTE_COUNT(szDevice));
  775. else
  776. lstrcpy(szDevice, garMciDevices[gwCurDevice].szDevice);
  777. #ifdef UNICODE
  778. // length of the string in bytes != length of the string in characters
  779. lenAppName = WideCharToMultiByte(CP_ACP, 0, aszAppName, -1, NULL, 0, NULL, NULL) - 1;
  780. lenFullName = WideCharToMultiByte(CP_ACP, 0, szFullName, -1, NULL, 0, NULL, NULL) - 1;
  781. #else
  782. lenAppName = STRLEN(aszAppName);
  783. lenFullName = STRLEN(szFullName);
  784. #endif
  785. /* How much data will we be writing? */
  786. #ifdef UNICODE
  787. // length of the string in bytes != length of the string in characters
  788. len = 9 + // all the delimeters
  789. lenAppName +
  790. lenFullName +
  791. WideCharToMultiByte(CP_ACP, 0, szDevice, -1, NULL, 0, NULL, NULL)-1 +
  792. 5 + 10 + 10 + 10 + // max length of int and long strings
  793. WideCharToMultiByte(CP_ACP, 0, gachCaption, -1, NULL, 0, NULL, NULL)-1;
  794. #else
  795. len = 9 + // all the delimeters
  796. lenAppName +
  797. lenFullName +
  798. STRLEN(szDevice) +
  799. 5 + 10 + 10 + 10 + // max length of int and long strings
  800. STRLEN(gachCaption);
  801. #endif
  802. h = GlobalAlloc(GMEM_DDESHARE|GMEM_ZEROINIT, len * sizeof(CHAR));
  803. if (!h)
  804. return NULL;
  805. p = GLOBALLOCK(h);
  806. /* This string must have two terminating null characters.
  807. * The GlobalAlloc GMEM_ZEROINIT flag should ensure this.
  808. */
  809. #ifdef UNICODE
  810. wsprintfA(p, "%ws%c%ws%c%ws%c%d%c%d%c%d%c%d%c%d%c%ws",
  811. #else
  812. wsprintfA(p, "%s%c%s%c%s%c%d%c%d%c%d%c%d%c%d%c%s",
  813. #endif
  814. aszAppName,
  815. '*', // placeholder
  816. szFullName,
  817. '*', // placeholder
  818. szDevice, ',',
  819. (gwOptions & ~OPT_SCALE) | gwCurScale, ',',
  820. (long)SendMessage(ghwndTrackbar, TBM_GETSELSTART, 0, 0L), ',',
  821. (long)SendMessage(ghwndTrackbar, TBM_GETSELEND, 0, 0L), ',',
  822. (long)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L), ';',
  823. // new parameter snuck in since initial version
  824. // Height of picture we're giving the client - w/o caption
  825. grcSize.bottom - grcSize.top, ',',
  826. gachCaption);
  827. /* Replace *'s with NULL characters (wsprintf doesn't accept
  828. * 0 as a replacement parameter for %c):
  829. */
  830. p[lenAppName] = '\0';
  831. p[lenAppName + 1 + lenFullName] = '\0';
  832. DPF("Native data %hs has been created\n", p);
  833. GLOBALUNLOCK(h);
  834. return h;
  835. }
  836. /****************************************************************************
  837. AttachDir - Take the path part of szPath, append the
  838. filename part of szName, and return it as szResult.
  839. ****************************************************************************/
  840. STATICFN void AttachDir(LPTSTR szResult, LPTSTR szPath, LPTSTR szName)
  841. {
  842. lstrcpy(szResult, szPath);
  843. lstrcpy(FileName(szResult), FileName(szName));
  844. }
  845. /****************************************************************************
  846. DOS share has a bug. If the file we're testing for existence is open
  847. already by someone else, we have to give it the same flag for SHARE as
  848. the other person is using. So we have to try both on and off. Only one
  849. of these will return TRUE but if one of them does, the file exists. Also
  850. we have to try with SHARE first, because the test without share might
  851. give a system modal error box!!!
  852. //## Check to see if DOS 7 has this bug or is it fixed
  853. Parameter iLen is the number of characters in the szFullName buffer
  854. ****************************************************************************/
  855. STATICFN BOOL FileExists(LPTSTR szFile, LPTSTR szFullName, int iLen)
  856. {
  857. DWORD rc;
  858. LPTSTR pFilePart;
  859. rc = SearchPath(NULL, /* Default path search order */
  860. szFile,
  861. NULL, /* szFile includes extension */
  862. (DWORD)iLen,
  863. szFullName,
  864. &pFilePart);
  865. if(rc > (DWORD)iLen)
  866. {
  867. DPF0("Buffer passed to FileExists is of insufficient length\n");
  868. }
  869. return (BOOL)rc;
  870. }
  871. /****************************************************************************
  872. FindRealFileName - If szFile isn't valid, try searching
  873. client directory for it, or anywhere on
  874. the path, or bringing up a locate dlg.
  875. Set szFile to the valid path name.
  876. //## This function is used to repair broken links
  877. Parameter iLen is the number of characters in the szFile buffer
  878. ****************************************************************************/
  879. BOOL FindRealFileName(LPTSTR szFile, int iLen)
  880. {
  881. TCHAR achFile[_MAX_PATH + 1]; /* file or device name buffer */
  882. /* This isn't a file device, so don't do anything */
  883. if (!szFile || *szFile == 0)
  884. return TRUE;
  885. /* The file name we've been given is valid, so do nothing. */
  886. //!!! what about share
  887. if (FileExists(szFile, achFile, iLen))
  888. {
  889. lstrcpy(szFile, achFile);
  890. return TRUE;
  891. }
  892. DPF("FindRealFileName: Can't find file '%"DTS"'\n", szFile);
  893. #if 0
  894. /* This could never have worked: */
  895. /* Look for the file in the directory of the client doc */
  896. AttachDir(achFile, gachDocTitle, szFile);
  897. DPF("FindRealFileName: ...Looking for '%"DTS"'\n", (LPTSTR)achFile);
  898. if (FileExists(achFile, szFile, iLen))
  899. return TRUE;
  900. #endif
  901. DPF("FindRealFileName: ...Looking on the $PATH\n");
  902. /* Look for the file anywhere */
  903. lstrcpy(achFile, FileName(szFile));
  904. if (FileExists(achFile, szFile, iLen))
  905. return TRUE;
  906. return FALSE;
  907. }
  908. /**************************************************************************
  909. * SubClassedMCIWndProc:
  910. * This the WndProc function used to sub-class the Play Back window.
  911. * This function is used to trap the drag-drops and also
  912. * to route the WM_CLOSE to the IDM_CLOSE of Mplayer.
  913. **************************************************************************/
  914. LONG_PTR FAR PASCAL SubClassedMCIWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  915. {
  916. static BOOL fDragCapture = FALSE;
  917. static RECT rcWin;
  918. POINT pt;
  919. LONG_PTR lRc;
  920. switch(wMsg)
  921. {
  922. case WM_LBUTTONDOWN:
  923. // break; // Disable drag from MPlayer! It's broken.
  924. if (!gfOle2IPEditing)
  925. {
  926. fDragCapture = TRUE;
  927. SetCapture(hwnd);
  928. GetClientRect(hwnd, (LPRECT)&rcWin);
  929. MapWindowPoints(hwnd, NULL, (LPPOINT)&rcWin, 2);
  930. }
  931. break;
  932. case WM_LBUTTONUP:
  933. if (!fDragCapture)
  934. break;
  935. fDragCapture = FALSE;
  936. ReleaseCapture();
  937. break;
  938. case WM_MOUSEMOVE:
  939. if (!fDragCapture)
  940. break;
  941. LONG2POINT(lParam, pt);
  942. MapWindowPoints(hwnd, NULL, &pt, 1);
  943. if (!PtInRect((LPRECT)&rcWin, pt))
  944. {
  945. ReleaseCapture();
  946. DoDrag();
  947. fDragCapture = FALSE;
  948. }
  949. SetCursor(LoadCursor(ghInst,MAKEINTRESOURCE(IDC_DRAG)));
  950. break;
  951. case WM_CLOSE:
  952. if (gfSeenPBCloseMsg || gfOle2IPEditing || gfOle2IPPlaying) {
  953. lRc = CallWindowProc(gfnMCIWndProc, hwnd, wMsg, wParam, lParam);
  954. } else {
  955. gfSeenPBCloseMsg = TRUE;
  956. PostMessage(ghwndApp,WM_COMMAND,IDM_CLOSE,0L);
  957. lRc = 0L;
  958. }
  959. CleanUpDrag();
  960. return lRc;
  961. case WM_DESTROY:
  962. ghwndSubclass = NULL;
  963. CleanUpDrag();
  964. break;
  965. case WM_ACTIVATE:
  966. /* Get the app's main window somewhere it can be seen
  967. * if the MCI window gets activated:
  968. */
  969. if (((WORD)wParam != 0) && !IsIconic(ghwndApp))
  970. {
  971. SetWindowPos(ghwndApp, hwnd, 0, 0, 0, 0,
  972. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  973. }
  974. break;
  975. }
  976. return CallWindowProc(gfnMCIWndProc, hwnd, wMsg, wParam, lParam);
  977. }
  978. /**************************************************************************
  979. * SubClassMCIWindow:
  980. * This function sub-classes the Play Back window by hooking in
  981. * SubClassedMCIWndProc function.
  982. **************************************************************************/
  983. void SubClassMCIWindow(void)
  984. {
  985. HWND hwndMCI;
  986. hwndMCI = GetWindowMCI();
  987. if(!IsWindow(hwndMCI))
  988. return;
  989. if (gfnMCIWndProc != NULL && IsWindow(ghwndSubclass)) {
  990. SetWindowLongPtr(ghwndSubclass, GWLP_WNDPROC, (LONG_PTR)gfnMCIWndProc);
  991. }
  992. gfnMCIWndProc = (WNDPROC)GetWindowLongPtr(hwndMCI, GWLP_WNDPROC);
  993. if (hwndMCI)
  994. SetWindowLongPtr(hwndMCI, GWLP_WNDPROC, (LONG_PTR)SubClassedMCIWndProc);
  995. ghwndSubclass = hwndMCI;
  996. gfSeenPBCloseMsg = FALSE;
  997. #ifdef CHICAGO_PRODUCT
  998. SendMessage(hwndMCI, WM_SETICON, FALSE,
  999. (LPARAM)GetIconForCurrentDevice(GI_SMALL, IDI_DDEFAULT));
  1000. SetWindowText(hwndMCI, gachCaption);
  1001. #endif
  1002. }
  1003. INT_PTR FAR PASCAL FixLinkDialog(LPTSTR szFile, LPTSTR szDevice, int iLen);
  1004. /* ANSI-to-Unicode version of lstrcpyn:
  1005. *
  1006. * Zero terminates the buffer in case it isn't long enough,
  1007. * then maps as many characters as will fit into the Unicode buffer.
  1008. *
  1009. */
  1010. #define LSTRCPYNA2W(strW, strA, buflen) \
  1011. strW[buflen-1] = L'\0', \
  1012. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, \
  1013. (strA), min( strlen( strA )+1, (buflen)-1 ), \
  1014. (strW), ((buflen)-1) )
  1015. /**************************************************************************
  1016. * ItemSetData(LPBYTE p): This function is left over from OLE1 days, but is
  1017. * very important because the embedded data is still the same. This function
  1018. * parses the embedded data and opens the appropriate device/file and sets
  1019. * everything in motion. "p" is the pointer memory block having the embedded
  1020. * data.
  1021. * Note we store the data in an ANSI string, regardless of whether we're
  1022. * compiled as a Unicode app, for Daytona/Chicago/OLE1/OLE2 compatibility.
  1023. **************************************************************************/
  1024. SCODE ItemSetData(LPBYTE p)
  1025. {
  1026. LPSTR pSave, pT;
  1027. LPSTR szFile, szDevice;
  1028. CHAR ach[40];
  1029. TCHAR achFile[_MAX_PATH];
  1030. TCHAR achCaption[_MAX_PATH];
  1031. LPTSTR pDevice;
  1032. SCODE scode = E_FAIL;
  1033. if (p && *p != 0)
  1034. {
  1035. szFile = p + strlen(p) + 1; // pick off the Filename
  1036. p = szFile + strlen(szFile) + 1;
  1037. pSave = p;
  1038. szDevice = ach; // copy over Device name and
  1039. for (pT = ach; *p && *p != ',';) // NULL terminate it (it ends
  1040. *pT++ = *p++; // with a ',' right now).
  1041. *pT = '\0';
  1042. /* It is OK for szFile and szDevice to be empty, since we may have
  1043. * a Media Clip object with no device or file selected
  1044. */
  1045. DPF("%hs|%hs!%hs\n", p, szFile, szDevice);
  1046. CloseMCI(TRUE); // nuke old gachCaption
  1047. scode = ParseOptions(pSave); // this will set new gachCaption
  1048. if (scode != S_OK)
  1049. return scode;
  1050. // If this file doesn't exist, we won't continue setting data, we
  1051. // will succeed and get out, and do it later, because we can't
  1052. // bring up a dialog right now because clients like WinWord
  1053. // won't dispatch any msgs.
  1054. #ifdef UNICODE
  1055. LSTRCPYNA2W(achFile, szFile, CHAR_COUNT(achFile));
  1056. #else
  1057. lstrcpyn(achFile, szFile, CHAR_COUNT(achFile));
  1058. #endif
  1059. // Check for file existence. if the filename we were given is bad,
  1060. // try and find it somewhere on the disk
  1061. #ifdef UNICODE
  1062. pDevice = AllocateUnicodeString(szDevice);
  1063. if (!pDevice)
  1064. return E_OUTOFMEMORY;
  1065. #else
  1066. pDevice = szDevice;
  1067. #endif
  1068. if (FindRealFileName(achFile, CHAR_COUNT(achFile)))
  1069. {
  1070. lstrcpy(achCaption, gachCaption); //Save caption.
  1071. if (OpenMciDevice(achFile, pDevice))
  1072. {
  1073. /* Set the selection to what we parsed in ParseOptions. */
  1074. SendMessage(ghwndTrackbar, TBM_SETSELSTART, 0, glSelStart);
  1075. SendMessage(ghwndTrackbar, TBM_SETSELEND, 0, glSelEnd);
  1076. }
  1077. lstrcpy(gachCaption, achCaption); //Restore Caption
  1078. }
  1079. else if (FixLinkDialog(achFile, pDevice, sizeof(achFile)) )
  1080. {
  1081. if (OpenMciDevice(achFile, pDevice))
  1082. {
  1083. /* Set the selection to what we parsed in ParseOptions. */
  1084. SendMessage(ghwndTrackbar, TBM_SETSELSTART, 0, glSelStart);
  1085. SendMessage(ghwndTrackbar, TBM_SETSELEND, 0, glSelEnd);
  1086. gfBrokenLink = TRUE;
  1087. }
  1088. }
  1089. else
  1090. scode = E_FAIL;
  1091. }
  1092. #ifdef UNICODE
  1093. FreeUnicodeString(pDevice);
  1094. #endif
  1095. return scode;
  1096. }
  1097. /**************************************************************************
  1098. * UpdateObject() - handle the update of the object
  1099. * If the object has changed in content or appearance a message is
  1100. * sent to the container.
  1101. ***************************************************************************/
  1102. void UpdateObject(void)
  1103. {
  1104. LONG lPos;
  1105. if((gfOle2IPPlaying || gfPlayingInPlace) && !fDocChanged)
  1106. return;
  1107. if (IsWindow(ghwndTrackbar))
  1108. lPos = (LONG)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L);
  1109. else
  1110. lPos = -1;
  1111. if (gfEmbeddedObject &&
  1112. (fDocChanged || ((lPos >= 0) && (lPos != (LONG)gdwPosition)
  1113. && (gwDeviceType & DTMCI_CANWINDOW))))
  1114. {
  1115. //
  1116. // Some clients (e.g. Excel 3.00 and PowerPoint 1.0) don't
  1117. // handle saved notifications; they expect to get an
  1118. // OLE_CLOSED message.
  1119. //
  1120. // We will send an OLE_CLOSED message right before we
  1121. // revoke the DOC iff gfDirty == -1 (see FileNew()).
  1122. //
  1123. if ((lPos >= 0) && (lPos != (LONG)gdwPosition) && (gwDeviceType & DTMCI_CANWINDOW))
  1124. {
  1125. gdwPosition = (DWORD)lPos;
  1126. SendDocMsg((LPDOC)&docMain,OLE_CHANGED);
  1127. }
  1128. if (fDocChanged)
  1129. SendDocMsg(&docMain, OLE_SAVEOBJ);
  1130. }
  1131. }
  1132. /**************************************************************************
  1133. * int FAR PASCAL ReallyDoVerb: This is the main function in the server stuff.
  1134. * This function used to implement the PlayInPlace in OLE1. Most of the code
  1135. * has not been changed and has been used to munge the MPlayer for EditInPlace
  1136. * in OLE2. For OLE2 this function calls DoInPlaceEdit to get the containers
  1137. * hwnd and Object rectangle. For OLE1 clients the rectangle is still got
  1138. * from the OleQueryObjPos funtion in mciole.dll. A new twist in the PlayVerb
  1139. * is that if we are just hidden in a deactivated state we just reappear
  1140. * and play instead of PlayingInPlace without the toolbars etc. This function
  1141. * is also called when reactivating, deactivating etc. The BOOL SkipInPlaceEdit
  1142. * is used to avoid redoing all the stuff if we are just reactivating.
  1143. ***************************************************************************/
  1144. int FAR PASCAL ReallyDoVerb (
  1145. LPDOC lpobj,
  1146. LONG verb,
  1147. LPMSG lpmsg,
  1148. LPOLECLIENTSITE lpActiveSite,
  1149. BOOL fShow,
  1150. BOOL fActivate)
  1151. {
  1152. BOOL fWindowWasVisible = IsWindowVisible(ghwndApp);
  1153. int dx,dy;
  1154. HWND hwndClient;
  1155. HWND hwndT;
  1156. RECT rcSave;
  1157. RECT rcClient;
  1158. RECT rc;
  1159. LONG err;
  1160. SCODE sc;
  1161. HPALETTE hpal;
  1162. HDC hdc;
  1163. INT xTextExt;
  1164. int yOrig, yNow, xOrig, ytitleNow, xtitleOrig, xNow;
  1165. int xIndent = 0; // Avoid warning C4701: local variable 'xIndent'
  1166. // may be used without having been initialized
  1167. int wWinNow;
  1168. HWND hwndMCI;
  1169. int Result = S_OK;
  1170. DPFI("VERB = %d\n", verb);
  1171. /* MSProject assumes that our primary verb is Edit; in fact it's Play.
  1172. * So when we're called with the default verb, make sure we've loaded
  1173. * something from storage and, if not, do the Edit thing.
  1174. *
  1175. * Nope, that doesn't work, because if you insert an object, deactivate
  1176. * it and then play it, PSLoad hasn't been called. A better bet is
  1177. * to check whether we have a current device.
  1178. */
  1179. if (gfRunWithEmbeddingFlag && gwDeviceType == 0)
  1180. {
  1181. if (verb == OLEIVERB_PRIMARY)
  1182. {
  1183. DPF("Primary Verb called without current device -- changing verb to Edit...\n");
  1184. verb = verbEdit;
  1185. }
  1186. }
  1187. /* If a Media Clip is currently open, the user can give the focus back
  1188. * to the container and issue another verb or double-click the object.
  1189. * If this happens, set the focus back to the open object.
  1190. *
  1191. * We don't need to worry about resetting fObjectOpen, since the server
  1192. * shuts down when the user exits and returns to the container.
  1193. */
  1194. if (gfOle2Open)
  1195. {
  1196. SetFocus(ghwndApp);
  1197. return S_OK;
  1198. }
  1199. // This is the first verb we are seeing. So the container must
  1200. // have the focus. Save it so that we can return it later.
  1201. if (glCurrentVerb == NOVERB)
  1202. ghwndFocusSave = GetFocus();
  1203. if (verb == OLEIVERB_PRIMARY && !gfOle2IPEditing && (glCurrentVerb != verbEdit))
  1204. {
  1205. EnableMenuItem((HMENU)GetMenu(ghwndApp), IDM_CLOSE, MF_GRAYED);
  1206. }
  1207. glCurrentVerb = verb;
  1208. //
  1209. // dont even try to nest things.
  1210. //
  1211. if (gfPlayingInPlace && verb != OLEIVERB_HIDE)
  1212. return OLE_OK;
  1213. if (gfBrokenLink)
  1214. {
  1215. PostMessage(ghwndApp, WM_SEND_OLE_CHANGE, 0, 0L);
  1216. gfBrokenLink = FALSE;
  1217. }
  1218. //We are just reactivating. Don't do through all the steps again.
  1219. if (gfOle2IPEditing)
  1220. SkipInPlaceEdit = TRUE;
  1221. // Make sure the timer's doing the right thing:
  1222. gfAppActive = ( verb != OLEIVERB_HIDE );
  1223. // NTVDM can get into a spin if we have too meany TIMER messages,
  1224. // so make sure we don't have any if there's no device.
  1225. if (gwDeviceID)
  1226. EnableTimer( gfAppActive );
  1227. else
  1228. EnableTimer( FALSE );
  1229. if (verb == OLEIVERB_PRIMARY)
  1230. {
  1231. gfOle1Client = FALSE;
  1232. //We are already up but deactivated. Just come up and play.
  1233. if (gfOle2IPEditing)
  1234. {
  1235. if (!(gwDeviceType & DTMCI_CANWINDOW))
  1236. {
  1237. Result = ReallyDoVerb(lpobj, verbEdit, lpmsg, lpActiveSite, fShow, fActivate);
  1238. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1239. }
  1240. else
  1241. {
  1242. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1243. err = GetScode(DoInPlaceEdit(lpobj, lpmsg, lpActiveSite, verbEdit, &hwndClient,
  1244. &rcClient));
  1245. if (err)
  1246. {
  1247. SHOWAPPWINDOW(SW_HIDE);
  1248. PostMessage(ghwndApp,WM_CLOSE,0,0);
  1249. return((int)err);
  1250. }
  1251. gfInPlaceResize = TRUE;
  1252. rcClient = gInPlacePosRect;
  1253. MapWindowPoints(NULL,ghwndCntr,(LPPOINT)&rcClient,2);
  1254. DPF("IOleInPlaceSite::OnPosRectChange %d, %d, %d, %d\n", rcClient);
  1255. if (!gfInPPViewer)
  1256. IOleInPlaceSite_OnPosRectChange(docMain.lpIpData->lpSite, &rcClient);
  1257. toolbarSetFocus(ghwndToolbar, BTN_PLAY);
  1258. SetFocus(ghwndToolbar);
  1259. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1260. }
  1261. }
  1262. else
  1263. {
  1264. if(gwDeviceID == (UINT)0) //Play without a device !?!!!
  1265. {
  1266. PostMessage(ghwndApp, WM_CLOSE, 0, 0L);
  1267. sc = E_FAIL;
  1268. return (int)sc;
  1269. }
  1270. // if the device can't window and the user does not want a playbar
  1271. // dont play in place - just start the media and run invisible.
  1272. //
  1273. if (!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
  1274. gwOptions &= ~OPT_PLAY;
  1275. // Select the palette in right now on behalf of the active
  1276. // window, so USER will think it is palette aware.
  1277. //
  1278. // any palette will do we dont even have to realize it!!
  1279. //
  1280. if (((hpal = PaletteMCI()) != NULL) && ((hwndT = GetActiveWindow()) != NULL))
  1281. {
  1282. hdc = GetDC(hwndT);
  1283. hpal = SelectPalette(hdc, hpal, FALSE);
  1284. SelectPalette(hdc, hpal, FALSE);
  1285. ReleaseDC(hwndT, hdc);
  1286. }
  1287. if (ghwndClient)
  1288. {
  1289. hwndClient = ghwndClient;
  1290. err = gerr;
  1291. rcClient = grcClient;
  1292. ghwndClient = NULL;
  1293. }
  1294. else
  1295. {
  1296. err = GetScode(DoInPlaceEdit(lpobj, lpmsg, lpActiveSite, verb, &hwndClient,
  1297. &rcClient));
  1298. if (err != S_OK)
  1299. {
  1300. err = OleQueryObjPos(lpobj, &hwndClient, &rcClient, NULL);
  1301. if (err == S_OK)
  1302. {
  1303. gfOle1Client = TRUE;
  1304. ghwndCntr = hwndClient;
  1305. }
  1306. }
  1307. else
  1308. {
  1309. if (gwOptions & OPT_TITLE)
  1310. gwOptions |= OPT_BAR;
  1311. else
  1312. gwOptions &= ~OPT_BAR;
  1313. }
  1314. }
  1315. /* We want to play in place and we can. */
  1316. /* If we're a link, not an embedded object, and there was an instance*/
  1317. /* of MPlayer up when we said "Play" that was already editing this */
  1318. /* file, we don't want to play in place... we'll just play in that */
  1319. /* instance. We can tell this by the fact that our main MPlayer */
  1320. /* window is already visible. */
  1321. if ((err == S_OK)
  1322. && (!gfOle1Client
  1323. || (gwOptions & OPT_PLAY)) /* Ignore Play in client doc for OLE2 clients */
  1324. && (gfOle2IPPlaying
  1325. || (IsWindow(hwndClient)
  1326. && IsWindowVisible(hwndClient)
  1327. && !fWindowWasVisible)))
  1328. {
  1329. rc = grcSize; // default playback window size for this movie
  1330. /* If we can't window, or something's wrong, use ICON size */
  1331. if (IsRectEmpty(&rc))
  1332. SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON),
  1333. GetSystemMetrics(SM_CYICON));
  1334. /* rcSave is the area for the MCI window above the control bar */
  1335. /* (if we have one). */
  1336. /* rcClient is the area of the MCI window (0 based) to play in.*/
  1337. /* Control bar may be longer than picture, so rcClient may be */
  1338. /* smaller than rcSave. */
  1339. rcSave = rcClient; // remember stretched size
  1340. /* Make rcClient 0 based from rcSave */
  1341. rcClient.left = 0;
  1342. rcClient.right = rcSave.right - rcSave.left;
  1343. rcClient.top = 0;
  1344. rcClient.bottom = rcSave.bottom - rcSave.top;
  1345. /* Assume playbar will be regular height for now */
  1346. if (gwOptions & OPT_BAR)
  1347. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1348. else
  1349. gwPlaybarHeight = 0;
  1350. //
  1351. // munge rectangle to account for a title in the picture
  1352. // and the fact that picture is centred above title.
  1353. // Remember, it's been stretched around.
  1354. //
  1355. if (gwOptions & OPT_TITLE)
  1356. {
  1357. SIZE Size;
  1358. hdc = GetDC(NULL);
  1359. if (ghfontMap)
  1360. SelectObject(hdc, ghfontMap);
  1361. GetTextExtentPoint32(hdc, gachCaption,
  1362. STRLEN(gachCaption), &Size);
  1363. xTextExt = Size.cx;
  1364. ReleaseDC(NULL, hdc);
  1365. yOrig = rc.bottom - rc.top;
  1366. xOrig = rc.right - rc.left;
  1367. xtitleOrig = max(xTextExt + 4, xOrig);
  1368. yNow = rcClient.bottom - rcClient.top;
  1369. xNow = rcClient.right - rcClient.left;
  1370. ytitleNow = (int)((long)yNow - ((long)yOrig * yNow)
  1371. / (yOrig + TITLE_HEIGHT));
  1372. /* for windowed devices, center the playback area above the */
  1373. /* control bar if the control bar is longer. */
  1374. if (gwDeviceType & DTMCI_CANWINDOW)
  1375. {
  1376. wWinNow =(int)((long)xOrig * (long)xNow / (long)xtitleOrig);
  1377. xIndent = (xNow - wWinNow) / 2;
  1378. rcClient.left += xIndent;
  1379. rcClient.right = rcClient.left + wWinNow;
  1380. }
  1381. // Align top of control bar with the top of the title bar.
  1382. // The control bar (if there) will appear under rcSave.
  1383. rcClient.bottom = rcClient.top + yNow - ytitleNow;
  1384. rcSave.bottom = rcSave.top + yNow - ytitleNow;
  1385. /* When we make the playbar, make it cover the title */
  1386. /* if the caption was stretched taller than ordinary.*/
  1387. if (gwOptions & OPT_BAR)
  1388. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1389. }
  1390. /* Enforce a minimum width for the control bar */
  1391. if ((gwOptions & OPT_BAR) &&
  1392. (rcSave.right - rcSave.left < 3 * GetSystemMetrics(SM_CXICON)))
  1393. {
  1394. rcSave.right = rcSave.left + 3 * GetSystemMetrics(SM_CXICON);
  1395. if (gwDeviceType & DTMCI_CANWINDOW)
  1396. xIndent = TRUE; // force SetWindowMCI to be called to
  1397. // avoid stretching to this new size.
  1398. }
  1399. if (gwDeviceType & DTMCI_CANWINDOW)
  1400. {
  1401. // THIS CODE IS USED TO AVOID SLOW PLAYBACK
  1402. // If we've only stretched a bit, don't stretch at all.
  1403. // We might be off a bit due to rounding problems.
  1404. //
  1405. dx = (rcClient.right - rcClient.left) - (rc.right - rc.left);
  1406. dy = (rcClient.bottom - rcClient.top) - (rc.bottom - rc.top);
  1407. if (dx && abs(dx) <= 2)
  1408. {
  1409. rcClient.right = rcClient.left + (rc.right - rc.left);
  1410. // Fix Save rect too
  1411. rcSave.right = rcSave.left + (rc.right - rc.left);
  1412. }
  1413. if (dy && abs(dy) <= 2)
  1414. {
  1415. rcClient.bottom = rcClient.top + (rc.bottom - rc.top);
  1416. // Fix Save rect, too.
  1417. rcSave.bottom = rcSave.top + (rc.bottom - rc.top);
  1418. }
  1419. //
  1420. // Try to get the right palette from the client. If our
  1421. // presentation data was dithered, or the user asked us to
  1422. // always use the object palette, then ignore any client
  1423. // palette.
  1424. //
  1425. #ifdef DEBUG
  1426. if (GetProfileInt(TEXT("options"), TEXT("UseClientPalette"),
  1427. !(gwOptions & OPT_USEPALETTE)))
  1428. gwOptions &= ~OPT_USEPALETTE;
  1429. else
  1430. gwOptions |= OPT_USEPALETTE;
  1431. #endif
  1432. if (!(gwOptions & OPT_USEPALETTE)&& !(gwOptions & OPT_DITHER))
  1433. {
  1434. //
  1435. // Try to get a OWNDC Palette of the client. PowerPoint
  1436. // uses a PC_RESERVED palette in "SlideShow" mode, so
  1437. // we must use its exact palette.
  1438. //
  1439. hdc = GetDC(ghwndCntr);
  1440. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  1441. SelectPalette(hdc, hpal, FALSE);
  1442. ReleaseDC(ghwndCntr, hdc);
  1443. if (hpal == NULL || hpal==GetStockObject(DEFAULT_PALETTE))
  1444. {
  1445. /* Assume client realized the proper palette for us */
  1446. if (ghpalApp)
  1447. DeleteObject(ghpalApp);
  1448. hpal = ghpalApp = CreateSystemPalette();
  1449. }
  1450. else
  1451. DPF("Using clients OWNDC palette\n");
  1452. if (hpal)
  1453. SetPaletteMCI(hpal);
  1454. }
  1455. else
  1456. DPF("Using MCI Object's normal palette\n");
  1457. }
  1458. else
  1459. {
  1460. //
  1461. // for non window devices, just have the playbar show up!
  1462. // so use a zero height MCI Window area.
  1463. //
  1464. rcSave.top = rcSave.bottom;
  1465. }
  1466. //
  1467. // if we are not in small mode, get there now
  1468. //
  1469. if (!gfPlayOnly)
  1470. {
  1471. SHOWAPPWINDOW(SW_HIDE);
  1472. gfPlayOnly = TRUE;
  1473. SizeMPlayer();
  1474. }
  1475. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1476. if (gwOptions & OPT_BORDER)
  1477. SetWS(ghwndApp, WS_BORDER);
  1478. /* Set the size of Mplayer to have enough space for the MCI */
  1479. /* playback area and a playbar and the non-client area. */
  1480. rcSave.bottom += gwPlaybarHeight;
  1481. AdjustWindowRect(&rcSave, (DWORD)GetWS(ghwndApp), FALSE);
  1482. if (!(gwDeviceType & DTMCI_CANWINDOW))
  1483. {
  1484. rcSave.left += 2*GetSystemMetrics(SM_CXBORDER);
  1485. rcSave.right -= 2*GetSystemMetrics(SM_CXBORDER);
  1486. }
  1487. PlayInPlace(ghwndApp, hwndClient, &rcSave);
  1488. if (!gfOle2IPEditing)
  1489. gfCloseAfterPlaying = TRUE;
  1490. fShow = FALSE;
  1491. fActivate = FALSE;
  1492. /* become visible */
  1493. SHOWAPPWINDOW(SW_SHOW);
  1494. /* Remember to play the video in the rcClient area of rcSave */
  1495. if ((gwDeviceType & DTMCI_CANWINDOW) &&
  1496. (gwOptions & OPT_TITLE) && xIndent != 0)
  1497. SetDestRectMCI(&rcClient);
  1498. /* Let keyboard interface work on control bar, and let the */
  1499. /* accelerators go through. */
  1500. toolbarSetFocus(ghwndToolbar, BTN_PLAY);
  1501. SetFocus(ghwndToolbar);
  1502. /* We won't play in place - use a popup window or nothing. */
  1503. }
  1504. else
  1505. {
  1506. /* If we want a playbar, then use MPlayer reduced mode to play. */
  1507. /* If we don't want one, then don't show mplayer's window - */
  1508. /* we'll just use the default MCI window (for a windowed device)*/
  1509. /* or nothing for a non-windowed device. If we stole an already*/
  1510. /* running instance of mplayer, we must use it and not run */
  1511. /* silently. */
  1512. DPF("DoVerb: Not is play in place stuff ");
  1513. if ((gwOptions & OPT_BAR) || fWindowWasVisible)
  1514. {
  1515. DPF("Using Toplevel window for playback\n");
  1516. /* go to our little miniature version */
  1517. if (!gfPlayOnly && !fWindowWasVisible)
  1518. {
  1519. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1520. gfPlayOnly = TRUE;
  1521. SizeMPlayer();
  1522. }
  1523. fShow = fActivate = TRUE;
  1524. gfCloseAfterPlaying = !fWindowWasVisible;
  1525. }
  1526. else
  1527. {
  1528. DPF("Running silently\n");
  1529. if (!fWindowWasVisible)
  1530. SetWindowMCI(NULL);
  1531. // make sure we're using default MCI win
  1532. fShow = fActivate = FALSE;
  1533. // DIE when you are done playing
  1534. gfCloseAfterPlaying = TRUE; // we're invisible, so close auto.
  1535. }
  1536. }
  1537. Yield(); // If play goes to full screen mode, PowerPig will
  1538. Yield(); // time out and put up errors thinking we didn't play.
  1539. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1540. }
  1541. }
  1542. else if (verb == verbEdit ||
  1543. verb == verbOpen ||
  1544. verb == OLEIVERB_OPEN ||
  1545. verb == OLEIVERB_SHOW ||
  1546. verb == OLEIVERB_INPLACEACTIVATE ||
  1547. verb == OLEIVERB_UIACTIVATE)
  1548. {
  1549. gfOle1Client = FALSE;
  1550. #ifdef DEBUG
  1551. switch(verb)
  1552. {
  1553. case verbEdit: DPFI("VERBEDIT\r\n");break;
  1554. case OLEIVERB_SHOW: DPFI("OLEIVERB_SHOW\r\n");break;
  1555. case OLEIVERB_INPLACEACTIVATE: DPFI("OLEIVERB_IPACTIVATE\r\n");break;
  1556. case OLEIVERB_UIACTIVATE: DPFI("OLEIVERB_UIACTIVATE\r\n");break;
  1557. }
  1558. #endif
  1559. // If we are already playing inside an Icon, then restore..
  1560. hwndMCI = GetWindowMCI();
  1561. if (IsWindow(hwndMCI) && IsIconic(hwndMCI))
  1562. SendMessage(hwndMCI, WM_SYSCOMMAND, SC_RESTORE, 0L);
  1563. // If we come up empty, it's OK to be in OPEN or NOT_READY mode
  1564. // and don't try to seek anywhere.
  1565. if (gwDeviceID)
  1566. {
  1567. switch (gwStatus)
  1568. {
  1569. case MCI_MODE_OPEN:
  1570. case MCI_MODE_NOT_READY:
  1571. Error(ghwndApp, IDS_CANTPLAY);
  1572. break;
  1573. default:
  1574. // Seek to the position we were when we copied.
  1575. // Stop first.
  1576. if (StopMCI())
  1577. {
  1578. // fix state so Seek recognizes we're stopped
  1579. gwStatus = MCI_MODE_STOP;
  1580. SeekMCI(gdwPosition);
  1581. }
  1582. break;
  1583. }
  1584. }
  1585. // Let UpdateDisplay set focus properly by saying we're invalid
  1586. // FORCES UPDATE
  1587. gwStatus = (UINT)(-1);
  1588. if (((hpal = PaletteMCI()) != NULL) && ((hwndT = GetActiveWindow()) != NULL))
  1589. {
  1590. hdc = GetDC(hwndT);
  1591. hpal = SelectPalette(hdc, hpal, FALSE);
  1592. SelectPalette(hdc, hpal, FALSE);
  1593. ReleaseDC(hwndT, hdc);
  1594. }
  1595. if (verb == verbOpen || verb == OLEIVERB_OPEN)
  1596. {
  1597. DoInPlaceDeactivate(lpobj);
  1598. gfOle2IPEditing = FALSE;
  1599. gfPlayOnly = FALSE;
  1600. SetWindowPos(ghwndApp, NULL, 0, 0, 0, 0,
  1601. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE);
  1602. SetParent(ghwndApp, NULL);
  1603. PutWS(ghwndApp, WS_THICKFRAME | WS_OVERLAPPED | WS_CAPTION |
  1604. WS_CLIPCHILDREN | WS_SYSMENU | WS_MINIMIZEBOX);
  1605. TransferTools(ghwndApp);
  1606. if (lpobj->lpoleclient) /* This is NULL if it's the first verb issued to a link */
  1607. IOleClientSite_OnShowWindow(lpobj->lpoleclient, TRUE);
  1608. SendMessage(ghwndTrackbar, TBM_SHOWTICS, TRUE, FALSE);
  1609. gfOle2Open = TRUE; /* This global is referenced in SizeMPlayer */
  1610. SizeMPlayer();
  1611. SHOWAPPWINDOW(SW_SHOW);
  1612. }
  1613. else if((err = GetScode(DoInPlaceEdit(lpobj, lpmsg, lpActiveSite, verb, &hwndClient,
  1614. &rcClient))) !=S_OK)
  1615. {
  1616. err = OleQueryObjPos(lpobj, &hwndClient, &rcClient, NULL);
  1617. if (err == S_OK)
  1618. {
  1619. gfOle1Client = TRUE;
  1620. }
  1621. gfOle2IPEditing = FALSE;
  1622. if (gfPlayOnly)
  1623. {
  1624. gfPlayOnly = FALSE;
  1625. SizeMPlayer();
  1626. }
  1627. }
  1628. else
  1629. {
  1630. if (gwOptions & OPT_TITLE)
  1631. gwOptions |= OPT_BAR;
  1632. else
  1633. gwOptions &= ~OPT_BAR;
  1634. }
  1635. if (gfOle2IPEditing && SkipInPlaceEdit)
  1636. {
  1637. gfInPlaceResize = TRUE;
  1638. if(!(gwDeviceType & DTMCI_CANWINDOW) && (gwOptions & OPT_BAR))
  1639. {
  1640. yNow = rcClient.bottom - rcClient.top;
  1641. if (gwOldHeight)
  1642. {
  1643. ytitleNow = (int)((long)yNow * gwPlaybarHeight/gwOldHeight);
  1644. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1645. gwOldHeight = yNow;
  1646. rcClient.top = rcClient.bottom - gwPlaybarHeight;
  1647. }
  1648. else
  1649. {
  1650. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1651. rcClient.top = rcClient.bottom - gwPlaybarHeight;
  1652. ytitleNow = rcClient.bottom - rcClient.top;
  1653. gwOldHeight = yNow;
  1654. }
  1655. }
  1656. if(!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
  1657. rcClient.bottom = rcClient.top = rcClient.left = rcClient.right = 0;
  1658. EditInPlace(ghwndApp, hwndClient, &rcClient);
  1659. Layout();
  1660. }
  1661. else
  1662. if (gfOle2IPEditing && gwDeviceID == (UINT)0 && IsWindow(ghwndFrame))
  1663. EditInPlace(ghwndApp, hwndClient, &rcClient);
  1664. if(gfOle2IPEditing && gwDeviceID != (UINT)0 && !SkipInPlaceEdit)
  1665. {
  1666. gwOldOptions = gwOptions;
  1667. rc = grcSize; // default playback window size for this movie
  1668. /* If we can't window, or something's wrong, use ICON size */
  1669. if (IsRectEmpty(&rc))
  1670. SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON),
  1671. GetSystemMetrics(SM_CYICON));
  1672. /* rcSave is the area for the MCI window above the control bar */
  1673. /* (if we have one). */
  1674. /* rcClient is the area of the MCI window (0 based) to play in.*/
  1675. /* Control bar may be longer than picutre, so rcClient may be */
  1676. /* smaller than rcSave. */
  1677. rcSave = rcClient; // remember stretched size
  1678. /* Make rcClient 0 based from rcSave */
  1679. rcClient.left = 0;
  1680. rcClient.right = rcSave.right - rcSave.left;
  1681. rcClient.top = 0;
  1682. rcClient.bottom = rcSave.bottom - rcSave.top;
  1683. /* Assume playbar will be regular height for now */
  1684. if (gwOptions & OPT_BAR)
  1685. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1686. else
  1687. gwPlaybarHeight = 0;
  1688. //
  1689. // munge rectangle to account for a title in the picture
  1690. // and the fact that picture is centred above title.
  1691. // Remember, it's been stretched around.
  1692. //
  1693. if (gwOptions & OPT_TITLE)
  1694. {
  1695. SIZE Size;
  1696. hdc = GetDC(NULL);
  1697. if (ghfontMap)
  1698. SelectObject(hdc, ghfontMap);
  1699. GetTextExtentPoint32(hdc, gachCaption,
  1700. STRLEN(gachCaption), &Size);
  1701. xTextExt = Size.cx;
  1702. ReleaseDC(NULL, hdc);
  1703. if (gwPastedHeight && !(gwDeviceType & DTMCI_CANWINDOW) )
  1704. yOrig = gwPastedHeight;
  1705. else
  1706. yOrig = rc.bottom - rc.top;
  1707. xOrig = rc.right - rc.left;
  1708. xtitleOrig = max(xTextExt + 4, xOrig);
  1709. yNow = rcClient.bottom - rcClient.top;
  1710. xNow = rcClient.right - rcClient.left;
  1711. if (gwDeviceType & DTMCI_CANWINDOW)
  1712. ytitleNow = TITLE_HEIGHT;
  1713. else
  1714. {
  1715. ytitleNow = (int)((long)yNow - ((long)yOrig * yNow)
  1716. / (yOrig + TITLE_HEIGHT));
  1717. gwOldHeight = yNow;
  1718. }
  1719. /* for windowed devices, center the playback area above the */
  1720. /* control bar if the control bar is longer. */
  1721. if (gwDeviceType & DTMCI_CANWINDOW)
  1722. {
  1723. wWinNow =(int)((long)xOrig * (long)xNow / (long)xtitleOrig);
  1724. xIndent = (xNow - wWinNow) / 2;
  1725. rcClient.left += xIndent;
  1726. rcClient.right = rcClient.left + wWinNow;
  1727. }
  1728. // Align top of control bar with the top of the title bar.
  1729. // The control bar (if there) will appear under rcSave.
  1730. rcClient.bottom = rcClient.top + yNow - ytitleNow;
  1731. rcSave.bottom = rcSave.top + yNow - ytitleNow;
  1732. /* When we make the playbar, make it cover the title */
  1733. /* if the caption was stretched taller than ordinary.*/
  1734. if (gwOptions & OPT_BAR)
  1735. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1736. }
  1737. /* Enforce a minimum width for the control bar */
  1738. #if 0
  1739. /* No, don't, because this screws up PowerPoint, which is usually
  1740. * scaled. If anything, it would be better to hide the control bar
  1741. * under these circumstances.
  1742. */
  1743. if ((gwOptions & OPT_BAR) &&
  1744. (rcSave.right - rcSave.left < 3 * GetSystemMetrics(SM_CXICON)))
  1745. {
  1746. rcSave.right = rcSave.left + 3 * GetSystemMetrics(SM_CXICON);
  1747. if (gwDeviceType & DTMCI_CANWINDOW)
  1748. xIndent = TRUE; // force SetWindowMCI to be called to
  1749. // avoid stretching to this new size.
  1750. }
  1751. #endif
  1752. if (!(gwOptions & OPT_USEPALETTE)&& !(gwOptions & OPT_DITHER))
  1753. {
  1754. //
  1755. // try to get a OWNDC Palette of the client, PowerPoint
  1756. // uses a PC_RESERVED palette in "SlideShow" mode. so
  1757. // we must use it's exact palette.
  1758. //
  1759. hdc = GetDC(ghwndCntr);
  1760. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE),
  1761. FALSE);
  1762. SelectPalette(hdc, hpal, FALSE);
  1763. ReleaseDC(ghwndCntr, hdc);
  1764. if (hpal == NULL || hpal==GetStockObject(DEFAULT_PALETTE))
  1765. {
  1766. /* Assume client realized the proper palette for us */
  1767. if (ghpalApp)
  1768. DeleteObject(ghpalApp);
  1769. hpal = ghpalApp = CreateSystemPalette();
  1770. }
  1771. else
  1772. DPF("Using clients OWNDC palette\n");
  1773. if (hpal)
  1774. SetPaletteMCI(hpal);
  1775. }
  1776. else
  1777. DPF("Using MCI Object's normal palette\n");
  1778. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1779. if (gwOptions & OPT_BORDER)
  1780. SetWS(ghwndApp, WS_BORDER);
  1781. /* Set the size of Mplayer to have enough space for the MCI */
  1782. /* playback area and a playbar and the non-client area. */
  1783. rcSave.bottom += gwPlaybarHeight;
  1784. if(!(gwDeviceType & DTMCI_CANWINDOW) && (gwOptions & OPT_BAR))
  1785. rcSave.top = rcSave.bottom - gwPlaybarHeight;
  1786. AdjustWindowRect(&rcSave, (DWORD)GetWS(ghwndApp), FALSE);
  1787. if(!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
  1788. rcSave.bottom = rcSave.top = rcSave.left = rcSave.right = 0;
  1789. EditInPlace(ghwndApp, hwndClient, &rcSave);
  1790. /* become visible */
  1791. SHOWAPPWINDOW(SW_SHOW);
  1792. /* Remember to play the video in the rcClient area of rcSave */
  1793. if ((gwDeviceType & DTMCI_CANWINDOW) &&
  1794. (gwOptions & OPT_TITLE) && xIndent != 0)
  1795. SetDestRectMCI(&rcClient);
  1796. }
  1797. }
  1798. else
  1799. if (verb == verbOpen || verb == OLEIVERB_OPEN)
  1800. {
  1801. DPFI("\n*verbopen");
  1802. DoInPlaceDeactivate(lpobj);
  1803. if (gwDeviceID)
  1804. return ReallyDoVerb(lpobj, verbEdit, lpmsg, lpActiveSite, fShow, fActivate);
  1805. }
  1806. else
  1807. if (verb == OLEIVERB_HIDE)
  1808. {
  1809. DPFI("\n*^*^* OLEVERB_HIDE *^*^");
  1810. DoInPlaceDeactivate(lpobj);
  1811. return S_OK;
  1812. }
  1813. else
  1814. if (verb > 0)
  1815. {
  1816. Result = ReallyDoVerb(lpobj, OLEIVERB_PRIMARY, lpmsg, lpActiveSite, fShow, fActivate);
  1817. if (Result = S_OK)
  1818. Result = OLEOBJ_S_INVALIDVERB;
  1819. }
  1820. else
  1821. return E_NOTIMPL;
  1822. if (fShow )
  1823. {
  1824. if (ghwndMCI || !gfOle2IPEditing)
  1825. SHOWAPPWINDOW(SW_SHOW);
  1826. /* MUST BE A POST or palette realization will not happen properly */
  1827. if (IsIconic(ghwndApp))
  1828. SendMessage(ghwndApp, WM_SYSCOMMAND, SC_RESTORE, 0L);
  1829. }
  1830. if (fActivate )
  1831. {
  1832. BringWindowToTop (ghwndApp); // let WM_ACTIVATE put client
  1833. SetActiveWindow (ghwndApp); // underneath us
  1834. }
  1835. return Result;
  1836. }