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.

978 lines
23 KiB

  1. /* picture.c - This file contains OLE object handling routines.
  2. *
  3. * Created by Microsoft Corporation.
  4. */
  5. #include "packager.h"
  6. #include "dialogs.h"
  7. static OLECLIENTVTBL clientTbl;
  8. static OLESTREAMVTBL streamTbl;
  9. static VOID PicGetBounds(LPOLEOBJECT lpObject, LPRECT lprc);
  10. /* InitClient() - Initialize the OLE client structures.
  11. */
  12. BOOL
  13. InitClient(
  14. VOID
  15. )
  16. {
  17. gcfFileName = (OLECLIPFORMAT)RegisterClipboardFormat("FileName");
  18. gcfLink = (OLECLIPFORMAT)RegisterClipboardFormat("ObjectLink");
  19. gcfNative = (OLECLIPFORMAT)RegisterClipboardFormat("Native");
  20. gcfOwnerLink = (OLECLIPFORMAT)RegisterClipboardFormat("OwnerLink");
  21. glpclient = PicCreateClient(&CallBack, (LPOLECLIENTVTBL)&clientTbl);
  22. if (!(glpStream = (LPAPPSTREAM)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(APPSTREAM))))
  23. goto Error;
  24. glpStream->lpstbl = (LPOLESTREAMVTBL)&streamTbl;
  25. streamTbl.Get = (DWORD (CALLBACK*)(LPOLESTREAM, void FAR*, DWORD))ReadStream;
  26. streamTbl.Put = (DWORD (CALLBACK*)(LPOLESTREAM, OLE_CONST void FAR*, DWORD))WriteStream;
  27. return TRUE;
  28. Error:
  29. if (glpStream)
  30. {
  31. GlobalFree(glpStream);
  32. glpStream = NULL;
  33. }
  34. if (glpclient)
  35. {
  36. GlobalFree(glpclient);
  37. glpclient = NULL;
  38. }
  39. return FALSE;
  40. }
  41. /* EndClient() - Clean up for termination.
  42. */
  43. VOID
  44. EndClient(
  45. VOID
  46. )
  47. {
  48. if (glpStream)
  49. {
  50. GlobalFree(glpStream);
  51. glpStream = NULL;
  52. }
  53. if (glpclient)
  54. {
  55. GlobalFree(glpclient);
  56. glpclient = NULL;
  57. }
  58. }
  59. /* PicCreate() -
  60. */
  61. LPPICT
  62. PicCreate(
  63. LPOLEOBJECT lpObject,
  64. LPRECT lprcObject
  65. )
  66. {
  67. HANDLE hpict = NULL;
  68. LPPICT lppict = NULL;
  69. RECT rc;
  70. if (lpObject)
  71. {
  72. if (!(hpict = GlobalAlloc(GMEM_MOVEABLE, sizeof(PICT)))
  73. || !(lppict = (LPPICT)GlobalLock(hpict)))
  74. goto errRtn;
  75. //
  76. // If size of window is specified, use it; otherwise, retrieve
  77. // the size of the item synchronously.
  78. //
  79. if (lprcObject)
  80. rc = *lprcObject;
  81. else {
  82. SetRectEmpty(&rc);
  83. PicGetBounds(lpObject, &rc);
  84. }
  85. // Store the data in the window itself
  86. lppict->hdata = hpict;
  87. lppict->lpObject = lpObject;
  88. lppict->rc = rc;
  89. lppict->fNotReady = FALSE;
  90. }
  91. return lppict;
  92. errRtn:
  93. ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
  94. if (lppict)
  95. GlobalUnlock(hpict);
  96. if (hpict)
  97. GlobalFree(hpict);
  98. return NULL;
  99. }
  100. /* PicDelete() - Deletes an object (called when the item window is destroyed).
  101. */
  102. VOID
  103. PicDelete(
  104. LPPICT lppict
  105. )
  106. {
  107. HANDLE hdata;
  108. LPOLEOBJECT lpObject;
  109. if (!lppict)
  110. return;
  111. if (lppict && lppict->lpObject)
  112. {
  113. lpObject = lppict->lpObject;
  114. lppict->lpObject = NULL;
  115. // Wait until the object isn't busy
  116. WaitForObject(lpObject);
  117. if (Error(OleDelete(lpObject)))
  118. ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
  119. // Wait until the object deletion is complete
  120. WaitForObject(lpObject);
  121. }
  122. GlobalUnlock(hdata = lppict->hdata);
  123. GlobalFree(hdata);
  124. }
  125. /* PicDraw() - Draws the item associated with hwnd in the DC hDC.
  126. */
  127. BOOL
  128. PicDraw(
  129. LPPICT lppict,
  130. HDC hDC,
  131. LPRECT lprc,
  132. INT xHSB,
  133. INT yVSB,
  134. BOOL fPicture,
  135. BOOL fFocus
  136. )
  137. {
  138. BOOL fSuccess = FALSE;
  139. DWORD ot;
  140. HANDLE hdata;
  141. HFONT hfont;
  142. LPOLEOBJECT lpObjectUndo;
  143. LPSTR lpdata;
  144. RECT rc;
  145. RECT rcFocus;
  146. CHAR szDesc[CBMESSAGEMAX];
  147. CHAR szFileName[CBPATHMAX];
  148. CHAR szMessage[CBMESSAGEMAX + CBPATHMAX];
  149. INT iDelta;
  150. INT iPane;
  151. iPane = (lppict == glpobj[CONTENT]);
  152. lpObjectUndo = (gptyUndo[iPane] == PICTURE)
  153. ? ((LPPICT)glpobjUndo[iPane])->lpObject : NULL;
  154. // If drawing the Picture, offset by scroll bars and draw
  155. if (fPicture)
  156. {
  157. if (IsRectEmpty(&(lppict->rc)))
  158. PicGetBounds(lppict->lpObject, &(lppict->rc));
  159. rc = lppict->rc;
  160. // If image is smaller than pane, center horizontally
  161. if ((iDelta = lprc->right - lppict->rc.right) > 0)
  162. OffsetRect(&rc, iDelta >> 1, 0);
  163. else /* else, use the scroll bar value */
  164. OffsetRect(&rc, -xHSB, 0);
  165. // If image is smaller than pane, center vertically
  166. if ((iDelta = lprc->bottom - lppict->rc.bottom) > 0)
  167. OffsetRect(&rc, 0, iDelta >> 1);
  168. else /* else, use the scroll bar value */
  169. OffsetRect(&rc, 0, -yVSB);
  170. // If we have an object, call OleDraw()
  171. fSuccess = !Error(OleDraw(lppict->lpObject, hDC, &rc, NULL, NULL));
  172. if (fFocus)
  173. DrawFocusRect(hDC, &rc);
  174. return fSuccess;
  175. }
  176. // Otherwise, draw the description string
  177. OleQueryType(lppict->lpObject, &ot);
  178. if ((ot == OT_LINK
  179. && Error(OleGetData(lppict->lpObject, gcfLink, &hdata)))
  180. || (ot == OT_EMBEDDED
  181. && Error(OleGetData(lppict->lpObject, gcfOwnerLink, &hdata)))
  182. || (ot == OT_STATIC
  183. && (!lpObjectUndo || Error(OleGetData(lpObjectUndo, gcfOwnerLink,
  184. &hdata)))))
  185. {
  186. LoadString(ghInst, IDS_OBJECT, szFileName, CBMESSAGEMAX);
  187. LoadString(ghInst, IDS_FROZEN, szDesc, CBMESSAGEMAX);
  188. goto DrawString;
  189. }
  190. if (hdata && (lpdata = GlobalLock(hdata)))
  191. {
  192. switch (ot)
  193. {
  194. case OT_LINK:
  195. while (*lpdata++)
  196. ;
  197. // return value ignored
  198. if(SUCCEEDED(StringCchCopy(szFileName, ARRAYSIZE(szFileName), lpdata)))
  199. {
  200. Normalize(szFileName);
  201. LoadString(ghInst, IDS_LINKTOFILE, szDesc, CBMESSAGEMAX);
  202. }
  203. break;
  204. case OT_EMBEDDED:
  205. RegGetClassId(szFileName, ARRAYSIZE(szFileName), lpdata);
  206. LoadString(ghInst, IDS_EMBEDFILE, szDesc, CBMESSAGEMAX);
  207. break;
  208. case OT_STATIC:
  209. RegGetClassId(szFileName, ARRAYSIZE(szFileName), lpdata);
  210. LoadString(ghInst, IDS_FROZEN, szDesc, CBMESSAGEMAX);
  211. break;
  212. }
  213. GlobalUnlock(hdata);
  214. DrawString:
  215. if(SUCCEEDED(StringCchPrintf(szMessage, ARRAYSIZE(szMessage), szDesc, szFileName))) // return value ignored
  216. {
  217. hfont = SelectObject(hDC, ghfontChild);
  218. DrawText(hDC, szMessage, -1, lprc,
  219. DT_NOPREFIX | DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  220. if (fFocus)
  221. {
  222. rcFocus = *lprc;
  223. DrawText(hDC, szMessage, -1, &rcFocus,
  224. DT_CALCRECT | DT_NOPREFIX | DT_LEFT | DT_TOP | DT_SINGLELINE);
  225. OffsetRect(&rcFocus, (lprc->left + lprc->right - rcFocus.right) / 2,
  226. (lprc->top + lprc->bottom - rcFocus.bottom) / 2);
  227. DrawFocusRect(hDC, &rcFocus);
  228. }
  229. if (hfont)
  230. SelectObject(hDC, hfont);
  231. fSuccess = TRUE;
  232. }
  233. }
  234. return fSuccess;
  235. }
  236. /* PicPaste() - Retrieves an object from the clipboard.
  237. */
  238. LPPICT
  239. PicPaste(
  240. BOOL fPaste,
  241. LPSTR lpstrName
  242. )
  243. {
  244. LPOLEOBJECT lpObject;
  245. if (!OpenClipboard(ghwndFrame))
  246. return NULL; /* Couldn't open the clipboard */
  247. Hourglass(TRUE);
  248. // Don't replace the current object unless we're successful
  249. if (fPaste)
  250. {
  251. if (Error(OleCreateFromClip(gszProtocol, glpclient, glhcdoc, lpstrName,
  252. &lpObject, olerender_draw, 0)))
  253. {
  254. if (Error(OleCreateFromClip(gszSProtocol, glpclient, glhcdoc,
  255. lpstrName, &lpObject, olerender_draw, 0)))
  256. lpObject = NULL;
  257. }
  258. }
  259. else if (Error(OleCreateLinkFromClip(
  260. gszProtocol, glpclient, glhcdoc, lpstrName, &lpObject,
  261. olerender_draw, 0)))
  262. {
  263. lpObject = NULL;
  264. }
  265. CloseClipboard();
  266. Hourglass(FALSE);
  267. if (!lpObject)
  268. return NULL;
  269. return PicCreate(lpObject, NULL);
  270. }
  271. /* Error() - check for OLE function error conditions
  272. *
  273. * This function increments gcOleWait as appropriate.
  274. *
  275. * Pre: Initialize ghwndError to where the focus should return.
  276. *
  277. * Returns: TRUE if an immediate error occurred.
  278. */
  279. BOOL
  280. Error(
  281. OLESTATUS olestat
  282. )
  283. {
  284. DWORD ot;
  285. INT iPane;
  286. switch (olestat)
  287. {
  288. case OLE_WAIT_FOR_RELEASE:
  289. gcOleWait++;
  290. return FALSE;
  291. case OLE_OK:
  292. return FALSE;
  293. case OLE_ERROR_STATIC: /* Only happens w/ dbl click */
  294. ErrorMessage(W_STATIC_OBJECT);
  295. break;
  296. case OLE_ERROR_ADVISE_PICT:
  297. case OLE_ERROR_OPEN: /* Invalid link? */
  298. case OLE_ERROR_NAME:
  299. iPane = (GetTopWindow(ghwndFrame) == ghwndPane[CONTENT]);
  300. if ((LPPICT)glpobj[iPane] == NULL)
  301. {
  302. ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  303. return FALSE;
  304. }
  305. else
  306. {
  307. OleQueryType(((LPPICT)glpobj[iPane])->lpObject, &ot);
  308. if (ot == OT_LINK)
  309. {
  310. if (ghwndError == ghwndFrame)
  311. {
  312. if (DialogBoxAfterBlock (
  313. MAKEINTRESOURCE(DTINVALIDLINK), ghwndError,
  314. fnInvalidLink) == IDD_CHANGE)
  315. PostMessage(ghwndFrame, WM_COMMAND, IDM_LINKS, 0L);
  316. }
  317. else
  318. {
  319. // Failed, but already in Link Properties!!
  320. ErrorMessage(E_FAILED_TO_UPDATE_LINK);
  321. }
  322. return FALSE;
  323. }
  324. }
  325. break;
  326. default:
  327. break;
  328. }
  329. return TRUE;
  330. }
  331. /* CallBack() - Routine that OLE client DLL calls when events occur.
  332. *
  333. * This routine is called when the object has been updated and may
  334. * need to be redisplayed; if asynchronous operations have completed;
  335. * and if the application allows the user to cancel long operations
  336. * (like Painting, or other asynchronous operations).
  337. */
  338. INT CALLBACK
  339. CallBack(
  340. LPOLECLIENT lpclient,
  341. OLE_NOTIFICATION flags,
  342. LPOLEOBJECT lpObject
  343. )
  344. {
  345. INT iPane;
  346. switch (flags)
  347. {
  348. case OLE_CLOSED:
  349. if (gfInvisible)
  350. PostMessage(ghwndFrame, WM_SYSCOMMAND, SC_CLOSE, 0L);
  351. else
  352. SetFocus(ghwndError);
  353. break;
  354. case OLE_SAVED:
  355. case OLE_CHANGED:
  356. {
  357. //
  358. // The OLE libraries make sure that we only receive
  359. // update messages according to the Auto/Manual flags.
  360. //
  361. iPane = (gpty[CONTENT] == PICTURE
  362. && ((LPPICT)glpobj[CONTENT])->lpObject == lpObject);
  363. if (gpty[iPane] == PICTURE)
  364. {
  365. ((LPPICT)glpobj[iPane])->fNotReady = FALSE;
  366. InvalidateRect(ghwndPane[iPane], NULL, TRUE);
  367. SetRect(&(((LPPICT)glpobj[iPane])->rc), 0, 0, 0, 0);
  368. Dirty();
  369. }
  370. break;
  371. }
  372. case OLE_RELEASE:
  373. {
  374. if (gcOleWait)
  375. gcOleWait--;
  376. else
  377. ErrorMessage(E_UNEXPECTED_RELEASE);
  378. switch (Error(OleQueryReleaseError(lpObject)))
  379. {
  380. case FALSE:
  381. switch (OleQueryReleaseMethod(lpObject))
  382. {
  383. case OLE_SETUPDATEOPTIONS:
  384. iPane = (gpty[CONTENT] == PICTURE
  385. && ((LPPICT)glpobj[CONTENT])->lpObject ==
  386. lpObject);
  387. PostMessage(ghwndPane[iPane], WM_COMMAND,
  388. IDM_LINKDONE, 0L);
  389. default:
  390. break;
  391. }
  392. break;
  393. case TRUE:
  394. switch (OleQueryReleaseMethod(lpObject))
  395. {
  396. case OLE_DELETE:
  397. ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
  398. break;
  399. case OLE_LOADFROMSTREAM:
  400. ErrorMessage(E_FAILED_TO_READ_OBJECT);
  401. break;
  402. case OLE_LNKPASTE:
  403. ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
  404. break;
  405. case OLE_ACTIVATE:
  406. ErrorMessage(E_FAILED_TO_LAUNCH_SERVER);
  407. break;
  408. case OLE_UPDATE:
  409. ErrorMessage(E_FAILED_TO_UPDATE);
  410. break;
  411. case OLE_RECONNECT:
  412. ErrorMessage(E_FAILED_TO_RECONNECT_OBJECT);
  413. break;
  414. }
  415. break;
  416. }
  417. break;
  418. }
  419. case OLE_QUERY_RETRY:
  420. // if lpObject doesn't match any one of these 4 objects, it means
  421. // that PicDelete() has been called on lpObject, so there is no
  422. // point in continueing the RETRIES.
  423. // See PicDelete() code for more info.
  424. if ((glpobj[CONTENT]
  425. && lpObject == ((LPPICT)glpobj[CONTENT])->lpObject)
  426. || (glpobj[APPEARANCE]
  427. && lpObject == ((LPPICT) glpobj[APPEARANCE])->lpObject)
  428. || (glpobjUndo[CONTENT]
  429. && lpObject == ((LPPICT) glpobjUndo[CONTENT])->lpObject)
  430. || (glpobjUndo[APPEARANCE]
  431. && lpObject == ((LPPICT) glpobjUndo[APPEARANCE])->lpObject))
  432. {
  433. return TRUE;
  434. }
  435. else
  436. {
  437. return FALSE;
  438. }
  439. case OLE_QUERY_PAINT:
  440. return TRUE;
  441. default:
  442. break;
  443. }
  444. return 0;
  445. }
  446. /* WaitForObject() - Waits, dispatching messages, until the object is free.
  447. *
  448. * If the object is busy, spin in a dispatch loop.
  449. */
  450. VOID
  451. WaitForObject(
  452. LPOLEOBJECT lpObject
  453. )
  454. {
  455. while (OleQueryReleaseStatus(lpObject) == OLE_BUSY)
  456. ProcessMessage();
  457. }
  458. /* PicSetUpdateOptions() - Sets the update options of the object.
  459. *
  460. * Returns: TRUE if the command completed synchronously.
  461. */
  462. BOOL
  463. PicSetUpdateOptions(
  464. LPPICT lppict,
  465. UINT idCmd
  466. )
  467. {
  468. OLESTATUS olestat = OLE_ERROR_GENERIC;
  469. olestat = OleSetLinkUpdateOptions(
  470. lppict->lpObject,
  471. (idCmd == IDD_AUTO) ? oleupdate_always : oleupdate_oncall);
  472. if (Error(olestat))
  473. ErrorMessage(E_FAILED_TO_UPDATE_LINK);
  474. return (olestat == OLE_OK);
  475. }
  476. /* PicReadFromNative() - Reads an object from the pointer lpstr.
  477. *
  478. * SIDE EFFECT: Advances the pointer past the object.
  479. */
  480. LPPICT
  481. PicReadFromNative(
  482. LPSTR *lplpstr,
  483. LPSTR lpstrName
  484. )
  485. {
  486. LPOLEOBJECT lpObject;
  487. LPSTR lpstrStart;
  488. RECT rcObject;
  489. WORD w;
  490. // Save current position of file pointer
  491. lpstrStart = *lplpstr;
  492. SetFile(SOP_MEMORY, 0, lplpstr);
  493. // Load the new object
  494. if (Error(OleLoadFromStream((LPOLESTREAM)glpStream, gszProtocol, glpclient,
  495. glhcdoc, lpstrName, &lpObject)))
  496. {
  497. // Reset file pointer, and try again
  498. *lplpstr = lpstrStart;
  499. SetFile(SOP_MEMORY, 0, lplpstr);
  500. // Read it with the "Static" protocol
  501. if (Error(OleLoadFromStream((LPOLESTREAM)glpStream, gszSProtocol,
  502. glpclient, glhcdoc, lpstrName, &lpObject)))
  503. return NULL;
  504. }
  505. MemRead(lplpstr, (LPSTR)&w, sizeof(WORD));
  506. rcObject.left = (INT)w;
  507. MemRead(lplpstr, (LPSTR)&w, sizeof(WORD));
  508. rcObject.top = (INT)w;
  509. MemRead(lplpstr, (LPSTR)&w, sizeof(WORD));
  510. rcObject.right = (INT)w;
  511. MemRead(lplpstr, (LPSTR)&w, sizeof(WORD));
  512. rcObject.bottom = (INT)w;
  513. // Create a window at the right place, and display the object
  514. return PicCreate(lpObject, &rcObject);
  515. }
  516. /* PicWriteToNative() - Writes an object to memory.
  517. *
  518. * SIDE EFFECT: Moves pointer to end of written object
  519. */
  520. DWORD
  521. PicWriteToNative(
  522. LPPICT lppict,
  523. LPOLEOBJECT lpObject,
  524. LPSTR *lplpstr
  525. )
  526. {
  527. DWORD cb = 0L;
  528. WORD w;
  529. // Save the object
  530. SetFile(SOP_MEMORY, 0, lplpstr);
  531. if (Error(OleSaveToStream(lpObject, (LPOLESTREAM)glpStream)))
  532. goto Done;
  533. cb += gcbObject;
  534. if (lplpstr)
  535. {
  536. w = (WORD)lppict->rc.left;
  537. MemWrite(lplpstr, (LPSTR)&w, sizeof(WORD));
  538. w = (WORD)lppict->rc.top;
  539. MemWrite(lplpstr, (LPSTR)&w, sizeof(WORD));
  540. w = (WORD)lppict->rc.right;
  541. MemWrite(lplpstr, (LPSTR)&w, sizeof(WORD));
  542. w = (WORD)lppict->rc.bottom;
  543. MemWrite(lplpstr, (LPSTR)&w, sizeof(WORD));
  544. }
  545. cb += (DWORD)(4 * sizeof(WORD));
  546. Done:
  547. return cb;
  548. }
  549. /* Hourglass() - Puts up the hourglass as needed.
  550. */
  551. VOID
  552. Hourglass(
  553. BOOL fOn
  554. )
  555. {
  556. static HCURSOR hcurSaved = NULL; // Cursor saved when hourglass is up
  557. static UINT cWait = 0; // Number of "Hourglass"es up
  558. if (fOn)
  559. {
  560. if (!(cWait++))
  561. hcurSaved = SetCursor(ghcurWait);
  562. }
  563. else
  564. {
  565. if (!(--cWait) && hcurSaved)
  566. {
  567. SetCursor(hcurSaved);
  568. hcurSaved = NULL;
  569. }
  570. }
  571. }
  572. VOID
  573. PicActivate(
  574. LPPICT lppict,
  575. UINT idCmd
  576. )
  577. {
  578. DWORD ot;
  579. DWORD ot2;
  580. RECT rc;
  581. INT iPane;
  582. BOOL bAlreadyOpen = FALSE;
  583. iPane = (lppict == glpobj[CONTENT]);
  584. OleQueryType(lppict->lpObject, &ot);
  585. if (ot != OT_STATIC)
  586. {
  587. // Compute the window dimensions
  588. GetClientRect(ghwndPane[iPane], &rc);
  589. bAlreadyOpen = (OleQueryOpen(lppict->lpObject) == OLE_OK);
  590. // Open the object
  591. if (Error(OleActivate(lppict->lpObject,
  592. (idCmd == IDD_PLAY ? OLE_PLAY : OLE_EDIT),
  593. TRUE, TRUE, ghwndPane[iPane], &rc)))
  594. {
  595. ErrorMessage(E_FAILED_TO_LAUNCH_SERVER);
  596. goto errRtn;
  597. }
  598. else
  599. {
  600. WaitForObject(lppict->lpObject);
  601. if (!glpobj[iPane])
  602. goto errRtn;
  603. OleQueryType(lppict->lpObject, &ot2);
  604. if (ot2 == OT_EMBEDDED)
  605. Error(OleSetHostNames(lppict->lpObject, gszAppClassName,
  606. (iPane == CONTENT) ? szContent : szAppearance));
  607. }
  608. return;
  609. }
  610. else
  611. {
  612. ErrorMessage(W_STATIC_OBJECT);
  613. }
  614. errRtn:
  615. if (gfInvisible && !bAlreadyOpen)
  616. PostMessage(ghwndFrame, WM_SYSCOMMAND, SC_CLOSE, 0L);
  617. }
  618. VOID
  619. PicUpdate(
  620. LPPICT lppict
  621. )
  622. {
  623. DWORD ot;
  624. OleQueryType(lppict->lpObject, &ot);
  625. if (ot == OT_LINK)
  626. {
  627. if (Error(OleUpdate(lppict->lpObject)))
  628. ErrorMessage(E_FAILED_TO_UPDATE);
  629. }
  630. }
  631. VOID
  632. PicFreeze(
  633. LPPICT lppict
  634. )
  635. {
  636. DWORD ot;
  637. LPOLEOBJECT lpObject;
  638. INT iPane;
  639. iPane = (lppict == glpobj[CONTENT]);
  640. OleQueryType(lppict->lpObject, &ot);
  641. if (ot != OT_STATIC)
  642. {
  643. if (Error(OleObjectConvert(lppict->lpObject, gszSProtocol, glpclient,
  644. glhcdoc, gszCaption[iPane], &lpObject)))
  645. {
  646. ErrorMessage(E_FAILED_TO_FREEZE);
  647. return;
  648. }
  649. if (Error(OleDelete(lppict->lpObject)))
  650. ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
  651. lppict->lpObject = lpObject;
  652. // Redraw the list box contents
  653. PostMessage(ghwndError, WM_REDRAW, 0, 0L);
  654. }
  655. }
  656. VOID
  657. PicChangeLink(
  658. LPPICT lppict
  659. )
  660. {
  661. HANDLE hData;
  662. OLESTATUS olestat;
  663. // Change the link information
  664. olestat = OleGetData(lppict->lpObject, gcfLink, &hData);
  665. if (!Error(olestat) && hData)
  666. {
  667. hData = OfnGetNewLinkName(ghwndError, hData);
  668. if (hData && !Error(OleSetData(lppict->lpObject, gcfLink, hData)))
  669. PostMessage(ghwndError, WM_REDRAW, 0, 0L);
  670. }
  671. }
  672. /* PicCopy() - Puts an object onto the clipboard.
  673. *
  674. * Returns: TRUE iff successful.
  675. */
  676. BOOL
  677. PicCopy(
  678. LPPICT lppict
  679. )
  680. {
  681. BOOL fSuccess = FALSE;
  682. // If we can't open the clipboard, fail
  683. if (!lppict->lpObject || !OpenClipboard(ghwndFrame))
  684. return FALSE;
  685. // Empty the clipboard
  686. EmptyClipboard();
  687. // Successful if we managed to copy to the clipboard
  688. fSuccess = !Error(OleCopyToClipboard(lppict->lpObject));
  689. CloseClipboard();
  690. return fSuccess;
  691. }
  692. /* PicGetBounds() -
  693. */
  694. static VOID
  695. PicGetBounds(
  696. LPOLEOBJECT lpObject,
  697. LPRECT lprc
  698. )
  699. {
  700. if (IsRectEmpty(lprc))
  701. {
  702. switch (OleQueryBounds(lpObject, lprc))
  703. {
  704. case OLE_WAIT_FOR_RELEASE:
  705. Hourglass(TRUE);
  706. gcOleWait++;
  707. WaitForObject(lpObject);
  708. Hourglass(FALSE);
  709. case OLE_OK:
  710. // Map from HIMETRIC into screen coordinates
  711. lprc->right = MulDiv(giXppli,
  712. lprc->right - lprc->left, HIMETRIC_PER_INCH);
  713. lprc->bottom = MulDiv (giYppli,
  714. lprc->top - lprc->bottom, HIMETRIC_PER_INCH);
  715. lprc->left = 0;
  716. lprc->top = 0;
  717. default:
  718. break;
  719. }
  720. }
  721. }
  722. /* PicSaveUndo() - Saves a copy of the object for Undo.
  723. */
  724. VOID
  725. PicSaveUndo(
  726. LPPICT lppict
  727. )
  728. {
  729. INT iPane = (lppict == glpobj[CONTENT]);
  730. LPOLEOBJECT lpObject;
  731. // Clone the object
  732. if (Error(OleClone(lppict->lpObject, glpclient, glhcdoc, gszTemp, &lpObject))
  733. || !lpObject)
  734. {
  735. ErrorMessage(W_FAILED_TO_CLONE_UNDO);
  736. }
  737. else
  738. {
  739. // Save the undo, delete the prior Undo
  740. DeletePane(iPane, FALSE);
  741. OleRename(lpObject, gszCaption[iPane]);
  742. glpobj[iPane] = PicCreate(lpObject, &(lppict->rc));
  743. gpty[iPane] = PICTURE;
  744. if (iPane == CONTENT)
  745. EnableWindow(ghwndPict, TRUE);
  746. }
  747. }
  748. /* PicPaste() - Creates object from a file
  749. */
  750. LPPICT
  751. PicFromFile(
  752. BOOL fEmbedded,
  753. LPSTR szFile
  754. )
  755. {
  756. HRESULT hr;
  757. LPOLEOBJECT lpObject;
  758. Hourglass(TRUE);
  759. // Don't replace the current object unless we're successful
  760. if (fEmbedded)
  761. {
  762. hr = OleCreateFromFile(gszProtocol, glpclient, NULL, szFile,
  763. glhcdoc, gszCaption[CONTENT], &lpObject, olerender_draw, 0);
  764. }
  765. else
  766. {
  767. hr = OleCreateLinkFromFile(gszProtocol, glpclient, NULL, szFile,
  768. NULL, glhcdoc, gszCaption[CONTENT], &lpObject, olerender_draw, 0);
  769. }
  770. Hourglass(FALSE);
  771. if (FAILED(hr))
  772. return NULL;
  773. WaitForObject(lpObject);
  774. return PicCreate(lpObject, NULL);
  775. }
  776. LPOLECLIENT
  777. PicCreateClient(
  778. PCALL_BACK fnCallBack,
  779. LPOLECLIENTVTBL lpclivtbl
  780. )
  781. {
  782. LPOLECLIENT pclient;
  783. if (!(pclient = (LPOLECLIENT)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLECLIENT))))
  784. return NULL;
  785. pclient->lpvtbl = lpclivtbl;
  786. pclient->lpvtbl->CallBack = fnCallBack;
  787. return pclient;
  788. }