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.

1187 lines
30 KiB

  1. /*
  2. OLE SERVER DEMO
  3. Obj.c
  4. This file contains object methods and various object-related support
  5. functions.
  6. (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
  7. */
  8. /*
  9. Important Note:
  10. No method should ever dispatch a DDE message or allow a DDE message to
  11. be dispatched.
  12. Therefore, no method should ever enter a message dispatch loop.
  13. Also, a method should not show a dialog or message box, because the
  14. processing of the dialog box messages will allow DDE messages to be
  15. dispatched.
  16. */
  17. #define SERVERONLY
  18. #include <windows.h>
  19. #include <ole.h>
  20. #include "srvrdemo.h"
  21. // Static functions.
  22. static HBITMAP GetBitmap (LPOBJ lpobj);
  23. static HANDLE GetLink (LPOBJ lpobj);
  24. static HANDLE GetMetafilePict (LPOBJ lpobj);
  25. static HANDLE GetEnhMetafile (LPOBJ lpobj);
  26. static HANDLE GetNative (LPOBJ lpobj);
  27. static INT GetObjNum (LPOBJ lpobj);
  28. static HANDLE GetText (LPOBJ lpobj);
  29. static VOID DrawObj (HDC hdc, LPOBJ lpobj, RECT rc, INT dctype);
  30. /* CreateNewObj
  31. * ------------
  32. *
  33. * BOOL fDoc_Changed - The new value for the global variable fDocChanged.
  34. * When initializing a new document, we need to create
  35. * a new object without the creation counting as a
  36. * change to the document.
  37. *
  38. * RETURNS: A pointer to the new object
  39. *
  40. *
  41. * CUSTOMIZATION: Re-implement
  42. * Some applications (like Server Demo) have a finite number of
  43. * fixed, distinct, non-overlapping objects. Other applications
  44. * allow the user to create an object from any section of the
  45. * document. For example, the user might select a portion of
  46. * a bitmap from a paint program, or a few lines of text from
  47. * a word processor. This latter type of application probably
  48. * will not have a function like CreateNewObj.
  49. *
  50. */
  51. LPOBJ CreateNewObj (BOOL fDoc_Changed)
  52. {
  53. HANDLE hObj = NULL;
  54. LPOBJ lpobj = NULL;
  55. // index into an array of flags indicating if that object number is used.
  56. INT ifObj = 0;
  57. if ((hObj = LocalAlloc (LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof (OBJ))) == NULL)
  58. return NULL;
  59. if ((lpobj = (LPOBJ) LocalLock (hObj)) == NULL)
  60. {
  61. LocalFree (hObj);
  62. return NULL;
  63. }
  64. // Fill the fields in the object structure.
  65. // Find an unused number.
  66. for (ifObj=1; ifObj <= cfObjNums; ifObj++)
  67. {
  68. if (docMain.rgfObjNums[ifObj]==FALSE)
  69. {
  70. docMain.rgfObjNums[ifObj]=TRUE;
  71. break;
  72. }
  73. }
  74. if (ifObj==cfObjNums+1)
  75. {
  76. // Cannot create any more objects.
  77. MessageBeep(0);
  78. return NULL;
  79. }
  80. wsprintf (lpobj->native.szName, "Object %d", ifObj);
  81. lpobj->aName = GlobalAddAtom (lpobj->native.szName);
  82. lpobj->hObj = hObj;
  83. lpobj->oleobject.lpvtbl = &objvtbl;
  84. lpobj->native.idmColor = IDM_RED; // Default color
  85. lpobj->native.version = version;
  86. lpobj->native.nWidth = OBJECT_WIDTH; // Default size
  87. lpobj->native.nHeight = OBJECT_HEIGHT;
  88. SetHiMetricFields (lpobj);
  89. // Place object in a location corrsponding to its number, for aesthetics.
  90. lpobj->native.nX = (ifObj - 1) * 20;
  91. lpobj->native.nY = (ifObj - 1) * 20;
  92. if (!CreateWindow (
  93. "ObjClass",
  94. "Obj",
  95. WS_BORDER | WS_THICKFRAME | WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
  96. lpobj->native.nX,
  97. lpobj->native.nY,
  98. lpobj->native.nWidth,
  99. lpobj->native.nHeight,
  100. hwndMain,
  101. NULL,
  102. hInst,
  103. (LPSTR) lpobj ))
  104. return FALSE;
  105. fDocChanged = fDoc_Changed;
  106. return lpobj;
  107. }
  108. /* CutOrCopyObj
  109. * ------------
  110. *
  111. * Put data onto clipboard in all the formats supported. If the
  112. * fOpIsCopy is TRUE, the operation is COPY, otherwise it is CUT.
  113. * This is important, because we cannot put the Object Link format
  114. * onto the clipboard if the object was cut from the document (there is
  115. * no longer anything to link to).
  116. *
  117. * BOOL fOpIsCopy - TRUE if the operation is COPY; FALSE if CUT
  118. *
  119. * CUSTOMIZATION: None
  120. *
  121. *
  122. */
  123. VOID CutOrCopyObj (BOOL fOpIsCopy)
  124. {
  125. LPOBJ lpobj;
  126. HANDLE hData;
  127. // UINT hBit;
  128. if (OpenClipboard (hwndMain))
  129. {
  130. EmptyClipboard ();
  131. lpobj = SelectedObject();
  132. if ((hData = GetNative (lpobj)) != NULL)
  133. SetClipboardData(cfNative, hData);
  134. if ((hData = GetLink(lpobj)) != NULL)
  135. SetClipboardData(cfOwnerLink, hData);
  136. if (fOpIsCopy && docMain.doctype == doctypeFromFile)
  137. {
  138. // Can create a link if object exists in a file.
  139. if ((hData = GetLink(lpobj)) != NULL)
  140. SetClipboardData(cfObjectLink, hData);
  141. }
  142. if ((hData = GetEnhMetafile(lpobj)) != NULL)
  143. {
  144. SetClipboardData(CF_ENHMETAFILE, hData);
  145. GlobalFree(hData);
  146. }
  147. if ((hData = GetBitmap(lpobj)) != NULL)
  148. {
  149. // SetClipboardData(CF_BITMAP, GetBitmap(lpobj));
  150. SetClipboardData(CF_BITMAP, hData);
  151. DeleteObject(hData);
  152. }
  153. CloseClipboard ();
  154. }
  155. }
  156. /* DestroyObj
  157. * ----------
  158. *
  159. * Revoke an object, and free all memory that had been allocated for it.
  160. *
  161. * HWND hwnd - The object's window
  162. *
  163. * CUSTOMIZATION: Re-implement, making sure you free all the memory that
  164. * had been allocated for the OBJ structure and each of its
  165. * fields.
  166. *
  167. */
  168. VOID DestroyObj (HWND hwnd)
  169. {
  170. LPOBJ lpobj = HwndToLpobj (hwnd);
  171. if(lpobj->aName)
  172. {
  173. GlobalDeleteAtom (lpobj->aName);
  174. lpobj->aName = '\0';
  175. }
  176. if (lpobj->hpal)
  177. DeleteObject (lpobj->hpal);
  178. // Allow the object's number to be reused.
  179. docMain.rgfObjNums [GetObjNum(lpobj)] = FALSE;
  180. // Free the memory that had been allocated for the object structure itself.
  181. LocalUnlock (lpobj->hObj);
  182. LocalFree (lpobj->hObj);
  183. }
  184. /* DrawObj
  185. * -------
  186. *
  187. * This function draws an object onto the screen, into a metafile, or into
  188. * a bitmap.
  189. * The object will always look the same.
  190. *
  191. * HDC hdc - The device context to render the object into
  192. * LPOBJ lpobj - The object to render
  193. * RECT rc - The rectangle bounds of the object
  194. * DCTYPE dctype - The type of device context.
  195. *
  196. * CUSTOMIZATION: Server Demo specific
  197. *
  198. */
  199. static VOID DrawObj (HDC hdc, LPOBJ lpobj, RECT rc, INT dctype)
  200. {
  201. HPEN hpen;
  202. HPEN hpenOld;
  203. HPALETTE hpalOld = NULL;
  204. if (dctype == dctypeMetafile)
  205. {
  206. SetWindowOrgEx (hdc, 0, 0, NULL);
  207. // Paint entire object into the given rectangle.
  208. SetWindowExtEx (hdc, rc.right, rc.bottom, NULL);
  209. }
  210. if (lpobj->hpal)
  211. {
  212. hpalOld = SelectPalette (hdc, lpobj->hpal, TRUE);
  213. RealizePalette (hdc);
  214. }
  215. // Select brush of the color specified in the native data.
  216. SelectObject (hdc, hbrColor [lpobj->native.idmColor - IDM_RED] );
  217. hpen = CreatePen (PS_SOLID,
  218. /* Width */ (rc.bottom-rc.top) / 10,
  219. /* Gray */ 0x00808080);
  220. hpenOld = SelectObject (hdc, hpen);
  221. // Draw rectangle with the gray pen and fill it in with the selected brush.
  222. Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
  223. // Print name of object inside rectangle.
  224. SetBkMode (hdc, TRANSPARENT);
  225. SetTextAlign (hdc, TA_BASELINE | TA_CENTER);
  226. TextOut (hdc,
  227. rc.right/2,
  228. (rc.top+rc.bottom)/2,
  229. lpobj->native.szName,
  230. lstrlen (lpobj->native.szName));
  231. // Restore original objects
  232. SelectObject (hdc,
  233. (dctype == dctypeMetafile || dctype == dctypeEnhMetafile)
  234. ? GetStockObject (BLACK_PEN) : hpenOld);
  235. if (hpalOld)
  236. {
  237. SelectPalette (hdc,
  238. (dctype == dctypeMetafile || dctype == dctypeEnhMetafile)
  239. ? GetStockObject (DEFAULT_PALETTE) : hpalOld,
  240. TRUE);
  241. }
  242. DeleteObject (hpen);
  243. }
  244. /* GetBitmap
  245. * ---------
  246. *
  247. * Return a handle to an object's picture data in bitmap format.
  248. *
  249. * LPOBJ lpobj - The object
  250. *
  251. * RETURNS: A handle to the object's picture data
  252. *
  253. * CUSTOMIZATION: Re-implement
  254. *
  255. */
  256. static HBITMAP GetBitmap (LPOBJ lpobj)
  257. {
  258. HDC hdcObj;
  259. HDC hdcMem;
  260. RECT rc;
  261. HBITMAP hbitmap;
  262. HBITMAP hbitmapOld;
  263. hdcObj = GetDC (lpobj->hwnd);
  264. // Create a memory device context.
  265. hdcMem = CreateCompatibleDC (hdcObj);
  266. GetClientRect (lpobj->hwnd, (LPRECT)&rc);
  267. // Create new bitmap object based on the bitmap of the OLE object.
  268. hbitmap = CreateCompatibleBitmap
  269. (hdcObj, rc.right - rc.left, rc.bottom - rc.top);
  270. // Select new bitmap as the bitmap object for the memory device context.
  271. hbitmapOld = SelectObject (hdcMem, hbitmap);
  272. // Paint directly into the memory dc using the new bitmap object.
  273. DrawObj (hdcMem, lpobj, rc, dctypeBitmap);
  274. // Restore old bitmap object.
  275. hbitmap = SelectObject (hdcMem, hbitmapOld);
  276. DeleteDC (hdcMem);
  277. ReleaseDC (lpobj->hwnd, hdcObj);
  278. // convert width and height to HIMETRIC units
  279. rc.right = rc.right - rc.left;
  280. rc.bottom = rc.bottom - rc.top;
  281. DeviceToHiMetric ( (LPPOINT) &rc.right );
  282. // Set the 1/10 of HIMETRIC units for the bitmap
  283. SetBitmapDimensionEx (hbitmap, (DWORD) (rc.right/10), (DWORD) (rc.bottom/10), NULL);
  284. // if (OpenClipboard (hwndMain))
  285. // {
  286. // // EmptyClipboard ();
  287. // SetClipboardData(CF_BITMAP, hbitmap);
  288. // CloseClipboard();
  289. // }
  290. return hbitmap;
  291. }
  292. /* GetLink
  293. * -------
  294. *
  295. * Return a handle to an object's object or owner link data.
  296. * Link information is in the form of three zero-separated strings,
  297. * terminated with two zero bytes: CLASSNAME\0DOCNAME\0OBJNAME\0\0
  298. *
  299. * LPOBJ lpobj - The object
  300. *
  301. * RETURNS: A handle to the object's link data
  302. *
  303. * CUSTOMIZATION: Re-implement
  304. *
  305. */
  306. static HANDLE GetLink (LPOBJ lpobj)
  307. {
  308. CHAR sz[cchFilenameMax];
  309. LPSTR lpszLink = NULL;
  310. HANDLE hLink = NULL;
  311. INT cchLen;
  312. INT i;
  313. // First make the class name.
  314. lstrcpy (sz, szClassName);
  315. cchLen = lstrlen (sz) + 1;
  316. // Then the document name.
  317. cchLen += GlobalGetAtomName
  318. (docMain.aName, (LPSTR)sz + cchLen,
  319. cchFilenameMax - cchLen) + 1;
  320. // Then the object name.
  321. lstrcpy (sz + cchLen, lpobj->native.szName);
  322. cchLen += lstrlen (lpobj->native.szName) + 1;
  323. // Add a second null to the end.
  324. sz[cchLen++] = 0;
  325. hLink = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, cchLen);
  326. if (hLink == NULL)
  327. return NULL;
  328. if ((lpszLink = GlobalLock (hLink)) == NULL)
  329. {
  330. GlobalFree (hLink);
  331. return NULL;
  332. }
  333. for (i=0; i < cchLen; i++)
  334. lpszLink[i] = sz[i];
  335. GlobalUnlock (hLink);
  336. return hLink;
  337. }
  338. /* GetMetafilePict
  339. * ---------------
  340. *
  341. * Return a handle to an object's picture data in metafile format.
  342. *
  343. * LPOBJ lpobj - The object
  344. *
  345. * RETURNS: A handle to the object's data in metafile format.
  346. *
  347. * CUSTOMIZATION: Re-implement
  348. *
  349. */
  350. static HANDLE GetMetafilePict (LPOBJ lpobj)
  351. {
  352. LPMETAFILEPICT lppict = NULL;
  353. HANDLE hpict = NULL;
  354. HANDLE hMF = NULL;
  355. RECT rc;
  356. HDC hdc;
  357. hdc = CreateMetaFile(NULL);
  358. GetClientRect (lpobj->hwnd, (LPRECT)&rc);
  359. // Paint directly into the metafile.
  360. DrawObj (hdc, lpobj, rc, dctypeMetafile);
  361. // Get handle to the metafile.
  362. if ((hMF = CloseMetaFile (hdc)) == NULL)
  363. return NULL;
  364. if(!(hpict = GlobalAlloc (GMEM_DDESHARE, sizeof (METAFILEPICT))))
  365. {
  366. DeleteMetaFile (hMF);
  367. return NULL;
  368. }
  369. if ((lppict = (LPMETAFILEPICT)GlobalLock (hpict)) == NULL)
  370. {
  371. DeleteMetaFile (hMF);
  372. GlobalFree (hpict);
  373. return NULL;
  374. }
  375. rc.right = rc.right - rc.left;
  376. rc.bottom = rc.bottom - rc.top;
  377. DeviceToHiMetric ( (LPPOINT) &rc.right);
  378. lppict->mm = MM_ANISOTROPIC;
  379. lppict->hMF = hMF;
  380. lppict->xExt = rc.right;
  381. lppict->yExt = rc.bottom;
  382. GlobalUnlock (hpict);
  383. return hpict;
  384. }
  385. /* GetEnhMetafile
  386. * ---------------
  387. *
  388. * Return a handle to an object's picture data in metafile format.
  389. *
  390. * LPOBJ lpobj - The object
  391. *
  392. * RETURNS: A handle to the object's data in metafile format.
  393. *
  394. * CUSTOMIZATION: Re-implement
  395. *
  396. */
  397. static HANDLE GetEnhMetafile (LPOBJ lpobj)
  398. {
  399. LPMETAFILEPICT lppict = NULL;
  400. HANDLE hemf = NULL;
  401. HANDLE hMF = NULL;
  402. RECT rc;
  403. HDC hdc, hdc2;
  404. GetClientRect (lpobj->hwnd, (LPRECT)&rc);
  405. rc.right -= rc.left;
  406. rc.bottom -= rc.top;
  407. rc.left = rc.top = 0;
  408. DeviceToHiMetric ( (LPPOINT) &rc.right );
  409. hdc = CreateEnhMetaFile ( NULL, NULL, &rc, NULL );
  410. //* this is necessary because
  411. //* we need to draw the object
  412. //* in device coordinates that are
  413. //* the same physical size as the HIMETRIC
  414. //* logical space used in CreateEnhMetaFile.
  415. //* In this case we have scaled the HIMETRIC
  416. //* units down in order to use the logical
  417. //* pixel ratio (which is recommended UI)
  418. //* so we therefore have to convert the
  419. //* scaled HIMETRIC units back to Device.
  420. hdc2 = GetDC(NULL);
  421. SetMapMode(hdc2, MM_HIMETRIC);
  422. LPtoDP (hdc2, (LPPOINT)&rc.right, 1);
  423. if (rc.bottom < 0) rc.bottom *= -1;
  424. ReleaseDC(NULL,hdc2);
  425. DrawObj (hdc, lpobj, rc, dctypeMetafile);
  426. if ((hemf = (HANDLE)CloseEnhMetaFile (hdc)) == NULL)
  427. return NULL;
  428. return hemf;
  429. }
  430. /* GetNative
  431. * ---------
  432. *
  433. * Return a handle to an object's native data.
  434. *
  435. * LPOBJ lpobj - The object whose native data is to be retrieved.
  436. *
  437. * RETURNS: a handle to the object's native data.
  438. *
  439. * CUSTOMIZATION: The line "*lpnative = lpobj->native;" will change to
  440. * whatever code is necessary to copy an object's native data.
  441. *
  442. */
  443. static HANDLE GetNative (LPOBJ lpobj)
  444. {
  445. LPNATIVE lpnative = NULL;
  446. HANDLE hNative = NULL;
  447. hNative = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, sizeof (NATIVE));
  448. if (hNative == NULL)
  449. return NULL;
  450. if ((lpnative = (LPNATIVE) GlobalLock (hNative)) == NULL)
  451. {
  452. GlobalFree (hNative);
  453. return NULL;
  454. }
  455. // Copy the native data.
  456. *lpnative = lpobj->native;
  457. GlobalUnlock (hNative);
  458. return hNative;
  459. }
  460. /* GetObjNum
  461. * ---------
  462. *
  463. * LPSTR lpobj - The object whose number is desired
  464. *
  465. * RETURNS: The number of the object, i.e., the numerical portion of its name.
  466. *
  467. * CUSTOMIZATION: Server Demo specific
  468. */
  469. static INT GetObjNum (LPOBJ lpobj)
  470. {
  471. LPSTR lpsz;
  472. INT n=0;
  473. lpsz = lpobj->native.szName + 7;
  474. while (*lpsz && *lpsz>='0' && *lpsz<='9')
  475. n = 10*n + *lpsz++ - '0';
  476. return n;
  477. }
  478. /* GetText
  479. * -------
  480. *
  481. * Return a handle to an object's data in text form.
  482. * This function simply returns the name of the object.
  483. *
  484. * LPOBJ lpobj - The object
  485. *
  486. * RETURNS: A handle to the object's text.
  487. *
  488. * CUSTOMIZATION: Re-implement, if your application supports CF_TEXT as a
  489. * presentation format.
  490. *
  491. */
  492. static HANDLE GetText (LPOBJ lpobj)
  493. {
  494. HANDLE hText = NULL;
  495. LPSTR lpszText = NULL;
  496. if(!(hText = GlobalAlloc (GMEM_DDESHARE, sizeof (lpobj->native.szName))))
  497. return NULL;
  498. if (!(lpszText = GlobalLock (hText)))
  499. return NULL;
  500. lstrcpy (lpszText, lpobj->native.szName);
  501. GlobalUnlock (hText);
  502. return hText;
  503. }
  504. /* ObjDoVerb OBJECT "DoVerb" METHOD
  505. * ---------
  506. *
  507. * This method is called by the client, through the library, to either
  508. * PLAY, or EDIT the object. PLAY is implemented as a beep, and
  509. * EDIT will bring up the server and show the object for editing.
  510. *
  511. * LPOLEOBJECT lpoleobject - The OLE object
  512. * WORD wVerb - The verb acting on the object: PLAY or EDIT
  513. * BOOL fShow - Should the object be shown?
  514. * BOOL fTakeFocus - Should the object window get the focus?
  515. *
  516. * RETURNS: OLE_OK
  517. *
  518. * CUSTOMIZATION: Add any more verbs your application supports.
  519. * Implement verbPlay if your application supports it.
  520. *
  521. */
  522. OLESTATUS APIENTRY ObjDoVerb
  523. (LPOLEOBJECT lpoleobject, UINT wVerb, BOOL fShow, BOOL fTakeFocus)
  524. {
  525. switch (wVerb)
  526. {
  527. case verbPlay:
  528. { // The application can do whatever is appropriate for the object.
  529. INT i;
  530. for (i=0; i<25;i++) MessageBeep (0);
  531. return OLE_OK;
  532. }
  533. case verbEdit:
  534. if (fShow)
  535. return objvtbl.Show (lpoleobject, fTakeFocus);
  536. else
  537. return OLE_OK;
  538. default:
  539. // Unknown verb.
  540. return OLE_ERROR_DOVERB;
  541. }
  542. }
  543. /* ObjEnumFormats OBJECT "EnumFormats" METHOD
  544. * ---------------
  545. *
  546. * This method is used to enumerate all supported clipboard formats.
  547. * Terminate by returning NULL.
  548. *
  549. * LPOLEOBJECT lpoleobject - The OLE object
  550. * OLECLIPFORMAT cfFormat - The 'current' clipboard format
  551. *
  552. * RETURNS: The 'next' clipboard format which is supported.
  553. *
  554. * CUSTOMIZATION: Verify that the list of formats this function
  555. * returns matches the list of formats your application
  556. * supports.
  557. *
  558. */
  559. OLECLIPFORMAT APIENTRY ObjEnumFormats
  560. (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat)
  561. {
  562. if (cfFormat == 0)
  563. return cfNative;
  564. if (cfFormat == cfNative)
  565. return cfOwnerLink;
  566. if (cfFormat == cfOwnerLink)
  567. return CF_ENHMETAFILE;
  568. if (cfFormat == CF_ENHMETAFILE)
  569. return CF_METAFILEPICT;
  570. if (cfFormat == CF_METAFILEPICT)
  571. return CF_BITMAP;
  572. if (cfFormat == CF_BITMAP)
  573. return cfObjectLink;
  574. if (cfFormat == cfObjectLink)
  575. return 0;
  576. return 0;
  577. }
  578. /* ObjGetData OBJECT "GetData" METHOD
  579. * -----------
  580. *
  581. * Return the data requested for the specified object in the specified format.
  582. *
  583. * LPOLEOBJECT lpoleobject - The OLE object
  584. * WORD cfFormat - The data type requested in standard
  585. * clipboard format
  586. * LPHANDLE lphandle - Pointer to handle to memory where data
  587. * will be stored
  588. *
  589. * RETURNS: OLE_OK if successful
  590. * OLE_ERROR_MEMORY if there was an error getting the data.
  591. * OLE_ERROR_FORMAT if the requested format is unknown.
  592. *
  593. *
  594. * CUSTOMIZATION: Add any additional formats your application supports, and
  595. * remove any formats it does not support.
  596. *
  597. */
  598. OLESTATUS APIENTRY ObjGetData
  599. (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, LPHANDLE lphandle)
  600. {
  601. LPOBJ lpobj;
  602. lpobj = (LPOBJ) lpoleobject;
  603. if (cfFormat == cfNative)
  604. {
  605. if (!(*lphandle = GetNative (lpobj)))
  606. return OLE_ERROR_MEMORY;
  607. // The client has requested the data in native format, therefore
  608. // the data in the client and server are in sync.
  609. fDocChanged = FALSE;
  610. return OLE_OK;
  611. }
  612. if (cfFormat == CF_ENHMETAFILE)
  613. {
  614. if (!(*lphandle = GetEnhMetafile (lpobj)))
  615. return OLE_ERROR_MEMORY;
  616. return OLE_OK;
  617. }
  618. if (cfFormat == CF_METAFILEPICT)
  619. {
  620. if (!(*lphandle = GetMetafilePict (lpobj)))
  621. return OLE_ERROR_MEMORY;
  622. return OLE_OK;
  623. }
  624. if (cfFormat == CF_BITMAP)
  625. {
  626. if (!(*lphandle = (HANDLE)GetBitmap (lpobj)))
  627. return OLE_ERROR_MEMORY;
  628. return OLE_OK;
  629. }
  630. if (cfFormat == CF_TEXT)
  631. {
  632. if (!(*lphandle = GetText (lpobj)))
  633. return OLE_ERROR_MEMORY;
  634. return OLE_OK;
  635. }
  636. if (cfFormat == cfObjectLink)
  637. {
  638. if (!(*lphandle = GetLink (lpobj)))
  639. return OLE_ERROR_MEMORY;
  640. return OLE_OK;
  641. }
  642. if (cfFormat == cfOwnerLink)
  643. {
  644. if (!(*lphandle = GetLink (lpobj)))
  645. return OLE_ERROR_MEMORY;
  646. return OLE_OK;
  647. }
  648. return OLE_ERROR_FORMAT;
  649. }
  650. /* ObjQueryProtocol OBJECT "QueryProtocol" METHOD
  651. * ----------------
  652. *
  653. * LPOLEOBJECT lpoleobject - The OLE object
  654. * OLE_LPCSTR lpszProtocol - The protocol name, either "StdFileEditing"
  655. * or "StdExecute"
  656. *
  657. * RETURNS: If lpszProtocol is supported, return a pointer to an OLEOBJECT
  658. * structure with an appropriate method table for that protocol.
  659. * Otherwise, return NULL.
  660. *
  661. * CUSTOMIZATION: Allow any additional protocols your application supports.
  662. *
  663. *
  664. */
  665. LPVOID APIENTRY ObjQueryProtocol
  666. (LPOLEOBJECT lpoleobject, OLE_LPCSTR lpszProtocol)
  667. {
  668. return lstrcmp (lpszProtocol, "StdFileEditing") ? NULL : lpoleobject ;
  669. }
  670. /* ObjRelease OBJECT "Release" METHOD
  671. * -----------
  672. *
  673. * The server application should not destroy data when the library calls the
  674. * ReleaseObj method.
  675. * The library calls the ReleaseObj method when no clients are connected
  676. * to the object.
  677. *
  678. * LPOLEOBJECT lpoleobject - The OLE object
  679. *
  680. * RETURNS: OLE_OK
  681. *
  682. * CUSTOMIZATION: Re-implement. Do whatever needs to be done, if anything,
  683. * when no clients are connected to an object.
  684. *
  685. */
  686. OLESTATUS APIENTRY ObjRelease (LPOLEOBJECT lpoleobject)
  687. {
  688. INT i;
  689. /* No client is connected to the object so break all assocaiations
  690. between clients and the object. */
  691. for (i=0; i < clpoleclient; i++)
  692. ((LPOBJ)lpoleobject)->lpoleclient[i] = NULL;
  693. return OLE_OK;
  694. }
  695. /* ObjSetBounds OBJECT "SetBounds" METHOD
  696. * ------------
  697. *
  698. * This method is called to set new bounds for an object.
  699. * The bounds are in HIMETRIC units.
  700. * A call to this method is ignored for linked objects because the size of
  701. * a linked object depends only on the source file.
  702. *
  703. * LPOLEOBJECT lpoleobject - The OLE object
  704. * OLE_CONST RECT FAR* lprect - The new bounds
  705. *
  706. * RETURNS: OLE_OK
  707. *
  708. * CUSTOMIZATION: Re-implement
  709. * How an object is sized is application-specific. (Server Demo
  710. * uses MoveWindow.)
  711. *
  712. */
  713. OLESTATUS APIENTRY ObjSetBounds (LPOLEOBJECT lpoleobj, OLE_CONST RECT FAR * lprect)
  714. {
  715. if (docMain.doctype == doctypeEmbedded)
  716. {
  717. RECT rect = *lprect;
  718. LPOBJ lpobj = (LPOBJ) lpoleobj;
  719. // the units are in HIMETRIC
  720. rect.right = rect.right - rect.left;
  721. rect.bottom = rect.top - rect.bottom;
  722. HiMetricToDevice ( (LPPOINT) &rect.right);
  723. MoveWindow (lpobj->hwnd, lpobj->native.nX, lpobj->native.nY,
  724. rect.right + 2 * GetSystemMetrics(SM_CXFRAME),
  725. rect.bottom + 2 * GetSystemMetrics(SM_CYFRAME),
  726. TRUE);
  727. }
  728. return OLE_OK;
  729. }
  730. /* ObjSetColorScheme OBJECT "SetColorScheme" METHOD
  731. * -----------------
  732. *
  733. * The client calls this method to suggest a color scheme (palette) for
  734. * the server to use for the object.
  735. *
  736. * LPOLEOBJECT lpoleobject - The OLE object
  737. * OLE_CONST LOGPALETTE FAR * lppal - Suggested palette
  738. *
  739. * RETURNS: OLE_ERROR_PALETTE if CreatePalette fails,
  740. * OLE_OK otherwise
  741. *
  742. *
  743. * CUSTOMIZATION: If your application supports color schemes, then this
  744. * function is a good example of how to create and store
  745. * a palette.
  746. *
  747. */
  748. OLESTATUS APIENTRY ObjSetColorScheme
  749. (LPOLEOBJECT lpoleobject, OLE_CONST LOGPALETTE FAR *lppal)
  750. {
  751. HPALETTE hpal = CreatePalette (lppal);
  752. LPOBJ lpobj = (LPOBJ) lpoleobject;
  753. if (hpal==NULL)
  754. return OLE_ERROR_PALETTE;
  755. if (lpobj->hpal)
  756. DeleteObject (lpobj->hpal);
  757. lpobj->hpal = hpal;
  758. return OLE_OK;
  759. }
  760. /* ObjSetData OBJECT "SetData" METHOD
  761. * ----------
  762. *
  763. * This method is used to store data into the object in the specified
  764. * format. This will be called with Native format after an embedded
  765. * object has been opened by the Edit method.
  766. *
  767. * LPOLEOBJECT lpoleobject - The OLE object
  768. * WORD cfFormat - Data type, i.e., clipboard format
  769. * HANDLE hdata - Handle to the data.
  770. *
  771. * RETURNS: OLE_OK if the data was stored properly
  772. * OLE_ERROR_FORMAT if format was not cfNative.
  773. * OLE_ERROR_MEMORY if memory could not be locked.
  774. *
  775. * CUSTOMIZATION: The large then-clause will need to be re-implemented for
  776. * your application. You may wish to support additional
  777. * formats besides cfNative.
  778. *
  779. */
  780. OLESTATUS APIENTRY ObjSetData
  781. (LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata)
  782. {
  783. LPNATIVE lpnative;
  784. LPOBJ lpobj;
  785. lpobj = (LPOBJ)lpoleobject;
  786. if (cfFormat != cfNative)
  787. {
  788. return OLE_ERROR_FORMAT;
  789. }
  790. lpnative = (LPNATIVE) GlobalLock (hdata);
  791. if (lpnative)
  792. {
  793. lpobj->native = *lpnative;
  794. if (lpobj->aName)
  795. GlobalDeleteAtom (lpobj->aName);
  796. lpobj->aName = GlobalAddAtom (lpnative->szName);
  797. // CreateNewObj made an "Object 1" but we may be changing its number.
  798. docMain.rgfObjNums[1] = FALSE;
  799. docMain.rgfObjNums [GetObjNum(lpobj)] = TRUE;
  800. MoveWindow (lpobj->hwnd, 0, 0,
  801. // lpobj->native.nWidth + 2 * GetSystemMetrics(SM_CXFRAME),
  802. // lpobj->native.nHeight+ 2 * GetSystemMetrics(SM_CYFRAME),
  803. lpobj->native.nWidth,
  804. lpobj->native.nHeight,
  805. FALSE);
  806. GlobalUnlock (hdata);
  807. }
  808. // Server is responsible for deleting the data.
  809. GlobalFree(hdata);
  810. return lpnative ? OLE_OK : OLE_ERROR_MEMORY;
  811. }
  812. /* ObjSetTargetDevice OBJECT "SetTargetDevice" METHOD
  813. * -------------------
  814. *
  815. * This method is used to indicate the device type that an object
  816. * will be rendered on. It is the server's responsibility to free hdata.
  817. *
  818. * LPOLEOBJECT lpoleobject - The OLE object
  819. * HANDLE hdata - Handle to memory containing
  820. * a StdTargetDevice structure
  821. *
  822. * RETURNS: OLE_OK
  823. *
  824. * CUSTOMIZATION: Implement. Server Demo currently does not do anything.
  825. *
  826. */
  827. OLESTATUS APIENTRY ObjSetTargetDevice (LPOLEOBJECT lpoleobject, HANDLE hdata)
  828. {
  829. if (hdata == NULL)
  830. {
  831. // Rendering for the screen is requested.
  832. }
  833. else
  834. {
  835. LPSTR lpstd = (LPSTR) GlobalLock (hdata);
  836. // lpstd points to a StdTargetDevice structure.
  837. // Use it to do whatever is appropriate to generate the best results
  838. // on the specified target device.
  839. GlobalUnlock (hdata);
  840. // Server is responsible for freeing the data.
  841. GlobalFree (hdata);
  842. }
  843. return OLE_OK;
  844. }
  845. /* ObjShow OBJECT "Show" METHOD
  846. * --------
  847. *
  848. * This method is used to display the object.
  849. * The server application should be activated and brought to the top.
  850. * Also, in a REAL server application, the object should be scrolled
  851. * into view. The object should be selected.
  852. *
  853. * LPOLEOBJECT lpoleobject - Pointer to the OLE object
  854. * BOOL fTakeFocus - Should server window get the focus?
  855. *
  856. * RETURNS: OLE_OK
  857. *
  858. *
  859. * CUSTOMIZATION: In your application, the document should be scrolled
  860. * to bring the object into view. Server Demo brings the
  861. * object to the front, in case it is a linked object inside a
  862. * document with other objects obscuring it.
  863. *
  864. */
  865. OLESTATUS APIENTRY ObjShow (LPOLEOBJECT lpoleobject, BOOL fTakeFocus)
  866. {
  867. LPOBJ lpobj;
  868. HWND hwndOldFocus;
  869. hwndOldFocus = GetFocus();
  870. lpobj = (LPOBJ) lpoleobject;
  871. if (fTakeFocus)
  872. SetForegroundWindow (lpobj->hwnd);
  873. ShowWindow(hwndMain, SW_SHOWNORMAL);
  874. SetFocus (fTakeFocus ? lpobj->hwnd : hwndOldFocus);
  875. return OLE_OK;
  876. }
  877. /* PaintObj
  878. * ---------
  879. *
  880. * This function is called by the WM_PAINT message to paint an object
  881. * on the screen.
  882. *
  883. * HWND hwnd - The object window in which to paint the object
  884. *
  885. * CUSTOMIZATION: Server Demo specific
  886. *
  887. */
  888. VOID PaintObj (HWND hwnd)
  889. {
  890. LPOBJ lpobj;
  891. RECT rc;
  892. HDC hdc;
  893. PAINTSTRUCT paintstruct;
  894. BeginPaint (hwnd, &paintstruct);
  895. hdc = GetDC (hwnd);
  896. lpobj = HwndToLpobj (hwnd);
  897. GetClientRect (hwnd, (LPRECT) &rc);
  898. DrawObj (hdc, lpobj, rc, dctypeScreen);
  899. ReleaseDC (hwnd, hdc);
  900. EndPaint (hwnd, &paintstruct);
  901. }
  902. /* RevokeObj
  903. * ---------
  904. *
  905. * Call OleRevokeObject because the user has destroyed the object.
  906. *
  907. * LPOBJ lpobj - The object which has been destroyed
  908. *
  909. *
  910. * CUSTOMIZATION: You will only need to call OleRevokeObject once if there
  911. * is only one LPOLECLIENT in your OBJ structure, which there
  912. * should be.
  913. *
  914. */
  915. VOID RevokeObj (LPOBJ lpobj)
  916. {
  917. INT i;
  918. for (i=0; i< clpoleclient; i++)
  919. {
  920. if (lpobj->lpoleclient[i])
  921. OleRevokeObject (lpobj->lpoleclient[i]);
  922. else
  923. /* if lpobj->lpoleclient[i]==NULL then there are no more non-NULLs
  924. in the array. */
  925. break;
  926. }
  927. }
  928. /* SendObjMsg
  929. * ----------
  930. *
  931. * This function sends a message to a specific object.
  932. *
  933. * LPOBJ lpobj - The object
  934. * WORD wMessage - The message to send
  935. *
  936. * CUSTOMIZATION: You will only need to call CallBack once if there
  937. * is only one LPOLECLIENT in your OBJ structure, which there
  938. * should be.
  939. *
  940. */
  941. VOID SendObjMsg (LPOBJ lpobj, WORD wMessage)
  942. {
  943. INT i;
  944. for (i=0; i < clpoleclient; i++)
  945. {
  946. if (lpobj->lpoleclient[i])
  947. {
  948. // Call the object's Callback function.
  949. lpobj->lpoleclient[i]->lpvtbl->CallBack
  950. (lpobj->lpoleclient[i], wMessage, (LPOLEOBJECT) lpobj);
  951. }
  952. else
  953. break;
  954. }
  955. }
  956. /* SizeObj
  957. * -------
  958. *
  959. * Change the size of an object.
  960. *
  961. * HWND hwnd - The object's window
  962. * RECT rect - The requested new size in device units
  963. * BOOL fMove - Should the object be moved? (or just resized?)
  964. *
  965. * CUSTOMIZATION: Server Demo specific
  966. *
  967. */
  968. VOID SizeObj (HWND hwnd, RECT rect, BOOL fMove)
  969. {
  970. LPOBJ lpobj;
  971. lpobj = HwndToLpobj (hwnd);
  972. if (fMove)
  973. {
  974. lpobj->native.nX = rect.left;
  975. lpobj->native.nY = rect.top;
  976. }
  977. lpobj->native.nWidth = rect.right - rect.left;
  978. lpobj->native.nHeight = rect.bottom - rect.top ;
  979. SetHiMetricFields (lpobj);
  980. InvalidateRect (hwnd, (LPRECT)NULL, TRUE);
  981. fDocChanged = TRUE;
  982. if (docMain.doctype == doctypeFromFile)
  983. {
  984. // If object is linked, update it in client now.
  985. SendObjMsg (lpobj, OLE_CHANGED);
  986. }
  987. }