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.

722 lines
17 KiB

  1. //**********************************************************************
  2. // File name: DOC.CPP
  3. //
  4. // Implementation file for CSimpleDoc.
  5. //
  6. // Functions:
  7. //
  8. // See DOC.H for Class Definition
  9. //
  10. // Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved.
  11. //**********************************************************************
  12. #include "pre.h"
  13. #include "iocs.h"
  14. #include "ias.h"
  15. #include "app.h"
  16. #include "site.h"
  17. #include "doc.h"
  18. #include "idt.h"
  19. #include "dxferobj.h"
  20. //**********************************************************************
  21. //
  22. // CSimpleDoc::Create
  23. //
  24. // Purpose:
  25. //
  26. // Creation for the CSimpleDoc Class
  27. //
  28. // Parameters:
  29. //
  30. // CSimpleApp FAR * lpApp - Pointer to the CSimpleApp Class
  31. //
  32. // LPRECT lpRect - Client area rect of "frame" window
  33. //
  34. // HWND hWnd - Window Handle of "frame" window
  35. //
  36. // Return Value:
  37. //
  38. // None
  39. //
  40. // Function Calls:
  41. // Function Location
  42. //
  43. // StgCreateDocfile OLE API
  44. // RegisterDragDrop OLE API
  45. // CoLockObjectExternal OLE API
  46. // CreateWindow Windows API
  47. // ShowWindow Windows API
  48. // UpdateWindow Windows API
  49. //
  50. // Comments:
  51. //
  52. // This routine was added so that failure could be returned
  53. // from object creation.
  54. //
  55. //********************************************************************
  56. CSimpleDoc FAR * CSimpleDoc::Create(CSimpleApp FAR *lpApp, LPRECT lpRect,HWND hWnd)
  57. {
  58. CSimpleDoc FAR * lpTemp = new CSimpleDoc(lpApp, hWnd);
  59. if (!lpTemp)
  60. return NULL;
  61. // create storage for the doc.
  62. HRESULT hErr = StgCreateDocfile (
  63. NULL, // generate temp name
  64. STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE,
  65. 0, &lpTemp->m_lpStorage);
  66. if (hErr != NOERROR)
  67. goto error;
  68. // create the document Window
  69. lpTemp->m_hDocWnd = CreateWindow(
  70. "SimpDndDocWClass",
  71. NULL,
  72. WS_CHILD | WS_CLIPCHILDREN,
  73. lpRect->left,
  74. lpRect->top,
  75. lpRect->right,
  76. lpRect->bottom,
  77. hWnd,
  78. NULL,
  79. lpApp->m_hInst,
  80. NULL);
  81. if (!lpTemp->m_hDocWnd)
  82. goto error;
  83. ShowWindow(lpTemp->m_hDocWnd, SW_SHOWNORMAL); // Show the window
  84. UpdateWindow(lpTemp->m_hDocWnd); // Sends WM_PAINT message
  85. // Ensable InsertObject menu choice
  86. EnableMenuItem( lpApp->m_hEditMenu, 1, MF_BYPOSITION | MF_ENABLED);
  87. // Disable Copy menu choice
  88. EnableMenuItem( lpApp->m_hEditMenu, 0, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  89. // It is *REQUIRED* to hold a strong LOCK on the object that is
  90. // registered as drop target. this call will result in at least one
  91. // ref count held on our document. later in CSimpleDoc::Close we will
  92. // unlock this lock which will make our document's ref count go to 0.
  93. // when the document's ref count goes to 0, it will be deleted.
  94. CoLockObjectExternal (&lpTemp->m_DropTarget, TRUE, 0);
  95. // Register our window as a DropTarget
  96. RegisterDragDrop(lpTemp->m_hDocWnd, &lpTemp->m_DropTarget);
  97. lpTemp->m_fRegDragDrop = TRUE;
  98. return (lpTemp);
  99. error:
  100. delete (lpTemp);
  101. return NULL;
  102. }
  103. //**********************************************************************
  104. //
  105. // CSimpleDoc::Close
  106. //
  107. // Purpose:
  108. //
  109. // Close CSimpleDoc object.
  110. // when the document's reference count goes to 0, the document
  111. // will be destroyed.
  112. //
  113. // Parameters:
  114. //
  115. //
  116. // Return Value:
  117. //
  118. // None
  119. //
  120. // Function Calls:
  121. // Function Location
  122. //
  123. // RevokeDragDrop OLE API
  124. // CoLockObjectExternal OLE API
  125. // OleFlushClipboard OLE API
  126. // ShowWindow Windows API
  127. //
  128. // Comments:
  129. //
  130. //********************************************************************
  131. void CSimpleDoc::Close(void)
  132. {
  133. TestDebugOut("In CSimpleDoc::Close\r\n");
  134. ShowWindow(m_hDocWnd, SW_HIDE); // Hide the window
  135. // Remove our data transfer object from clipboard if it is there.
  136. // this will leave HGLOBAL based data behind on the clipboard
  137. // including OLE 1.0 compatibility formats.
  138. OleFlushClipboard();
  139. // Revoke our window as a DropTarget
  140. if (m_fRegDragDrop) {
  141. RevokeDragDrop(m_hDocWnd);
  142. m_fRegDragDrop = FALSE;
  143. }
  144. // Close the OLE object in our document
  145. if (m_lpSite)
  146. m_lpSite->CloseOleObject();
  147. // Unlock the lock added in CSimpleDoc::Create. this will make
  148. // the document's ref count go to 0, and the document will be deleted.
  149. CoLockObjectExternal (&m_DropTarget, FALSE, TRUE);
  150. }
  151. //**********************************************************************
  152. //
  153. // CSimpleDoc::CSimpleDoc
  154. //
  155. // Purpose:
  156. //
  157. // Constructor for the CSimpleDoc Class
  158. //
  159. // Parameters:
  160. //
  161. // CSimpleApp FAR * lpApp - Pointer to the CSimpleApp Class
  162. //
  163. // HWND hWnd - Window Handle of "frame" window
  164. //
  165. // Return Value:
  166. //
  167. // None
  168. //
  169. // Function Calls:
  170. // Function Location
  171. //
  172. // TestDebugOut Windows API
  173. // GetMenu Windows API
  174. // GetSubMenu Windows API
  175. //
  176. // Comments:
  177. //
  178. //********************************************************************
  179. #pragma warning(disable : 4355) // turn off this warning. This warning
  180. // tells us that we are passing this in
  181. // an initializer, before "this" is through
  182. // initializing. This is ok, because
  183. // we just store the ptr in the other
  184. // constructor
  185. CSimpleDoc::CSimpleDoc(CSimpleApp FAR * lpApp,HWND hWnd)
  186. : m_DropTarget(this), m_DropSource(this)
  187. #pragma warning (default : 4355) // Turn the warning back on
  188. {
  189. TestDebugOut("In CSimpleDoc's Constructor\r\n");
  190. m_lpApp = lpApp;
  191. m_lpSite = NULL;
  192. m_nCount = 0;
  193. // set up menu handles
  194. lpApp->m_hMainMenu = GetMenu(hWnd);
  195. lpApp->m_hFileMenu = GetSubMenu(lpApp->m_hMainMenu, 0);
  196. lpApp->m_hEditMenu = GetSubMenu(lpApp->m_hMainMenu, 1);
  197. lpApp->m_hHelpMenu = GetSubMenu(lpApp->m_hMainMenu, 2);
  198. lpApp->m_hCascadeMenu = NULL;
  199. m_fModifiedMenu = FALSE;
  200. // drag/drop related stuff
  201. m_fRegDragDrop = FALSE; // is doc registered as drop target?
  202. m_fLocalDrag = FALSE; // is doc source of the drag
  203. m_fLocalDrop = FALSE; // was doc target of the drop
  204. m_fCanDropCopy = FALSE; // is Drag/Drop copy/move possible?
  205. m_fCanDropLink = FALSE; // is Drag/Drop link possible?
  206. m_fDragLeave = FALSE; // has drag left
  207. m_fPendingDrag = FALSE; // LButtonDown--possible drag pending
  208. m_ptButDown.x = m_ptButDown.y = 0; // LButtonDown coordinates
  209. }
  210. //**********************************************************************
  211. //
  212. // CSimpleDoc::~CSimpleDoc
  213. //
  214. // Purpose:
  215. //
  216. // Destructor for CSimpleDoc
  217. //
  218. // Parameters:
  219. //
  220. // None
  221. //
  222. // Return Value:
  223. //
  224. // None
  225. //
  226. // Function Calls:
  227. // Function Location
  228. //
  229. // TestDebugOut Windows API
  230. // CSimpleSite::Release SITE.CPP
  231. // IStorage::Release OLE API
  232. //
  233. // Comments:
  234. //
  235. //********************************************************************
  236. CSimpleDoc::~CSimpleDoc()
  237. {
  238. TestDebugOut("In CSimpleDoc's Destructor\r\n");
  239. // Release all pointers we hold to the OLE object. also release
  240. // the ref count added in CSimpleSite::Create. this will make
  241. // the Site's ref count go to 0, and the Site will be deleted.
  242. if (m_lpSite) {
  243. m_lpSite->UnloadOleObject();
  244. m_lpSite->Release();
  245. m_lpSite = NULL;
  246. }
  247. // Release the Storage
  248. if (m_lpStorage) {
  249. m_lpStorage->Release();
  250. m_lpStorage = NULL;
  251. }
  252. // if the edit menu was modified, remove the menu item and
  253. // destroy the popup if it exists
  254. if (m_fModifiedMenu)
  255. {
  256. int nCount = GetMenuItemCount(m_lpApp->m_hEditMenu);
  257. RemoveMenu(m_lpApp->m_hEditMenu, nCount-1, MF_BYPOSITION);
  258. if (m_lpApp->m_hCascadeMenu)
  259. DestroyMenu(m_lpApp->m_hCascadeMenu);
  260. }
  261. DestroyWindow(m_hDocWnd);
  262. }
  263. //**********************************************************************
  264. //
  265. // CSimpleDoc::QueryInterface
  266. //
  267. // Purpose:
  268. //
  269. // Return a pointer to a requested interface
  270. //
  271. // Parameters:
  272. //
  273. // REFIID riid - ID of interface to be returned
  274. // LPVOID FAR* ppvObj - Location to return the interface
  275. //
  276. // Return Value:
  277. //
  278. // S_OK - Interface supported
  279. // E_NOINTERFACE - Interface NOT supported
  280. //
  281. // Function Calls:
  282. // Function Location
  283. //
  284. // TestDebugOut Windows API
  285. // ResultFromScode OLE API
  286. //
  287. // Comments:
  288. //
  289. //********************************************************************
  290. STDMETHODIMP CSimpleDoc::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  291. {
  292. TestDebugOut("In CSimpleDoc::QueryInterface\r\n");
  293. *ppvObj = NULL; // must set out pointer parameters to NULL
  294. // looking for IUnknown
  295. if ( riid == IID_IUnknown)
  296. {
  297. AddRef();
  298. *ppvObj = this;
  299. return ResultFromScode(S_OK);
  300. }
  301. // looking for IDropTarget
  302. if ( riid == IID_IDropTarget)
  303. {
  304. m_DropTarget.AddRef();
  305. *ppvObj=&m_DropTarget;
  306. return ResultFromScode(S_OK);
  307. }
  308. // looking for IDropSource
  309. if ( riid == IID_IDropSource)
  310. {
  311. m_DropSource.AddRef();
  312. *ppvObj=&m_DropSource;
  313. return ResultFromScode(S_OK);
  314. }
  315. // Not a supported interface
  316. return ResultFromScode(E_NOINTERFACE);
  317. }
  318. //**********************************************************************
  319. //
  320. // CSimpleDoc::AddRef
  321. //
  322. // Purpose:
  323. //
  324. // Increments the document reference count
  325. //
  326. // Parameters:
  327. //
  328. // None
  329. //
  330. // Return Value:
  331. //
  332. // UINT - The current reference count on the document
  333. //
  334. // Function Calls:
  335. // Function Location
  336. //
  337. // TestDebugOut Windows API
  338. // CSimpleApp::AddRef APP.CPP
  339. //
  340. // Comments:
  341. //
  342. //********************************************************************
  343. STDMETHODIMP_(ULONG) CSimpleDoc::AddRef()
  344. {
  345. TestDebugOut("In CSimpleDoc::AddRef\r\n");
  346. return ++m_nCount;
  347. }
  348. //**********************************************************************
  349. //
  350. // CSimpleDoc::Release
  351. //
  352. // Purpose:
  353. //
  354. // Decrements the document reference count
  355. //
  356. // Parameters:
  357. //
  358. // None
  359. //
  360. // Return Value:
  361. //
  362. // UINT - The current reference count on the document
  363. //
  364. // Function Calls:
  365. // Function Location
  366. //
  367. // TestDebugOut Windows API
  368. //
  369. // Comments:
  370. //
  371. //********************************************************************
  372. STDMETHODIMP_(ULONG) CSimpleDoc::Release()
  373. {
  374. TestDebugOut("In CSimpleDoc::Release\r\n");
  375. if (--m_nCount == 0) {
  376. delete this;
  377. return 0;
  378. }
  379. return m_nCount;
  380. }
  381. //**********************************************************************
  382. //
  383. // CSimpleDoc::InsertObject
  384. //
  385. // Purpose:
  386. //
  387. // Inserts a new object to this document
  388. //
  389. // Parameters:
  390. //
  391. // None
  392. //
  393. // Return Value:
  394. //
  395. // None
  396. //
  397. // Function Calls:
  398. // Function Location
  399. //
  400. // CSimpleSite::CSimpleSite SITE.CPP
  401. // CSimpleSite::InitObject SITE.CPP
  402. // memset C Runtime
  403. // OleUIInsertObject OUTLUI function
  404. // CSimpleDoc::DisableInsertObject DOC.CPP
  405. //
  406. // Comments:
  407. //
  408. // This implementation only allows one object to be inserted
  409. // into a document. Once the object has been inserted, then
  410. // the Insert Object menu choice is greyed out, to prevent
  411. // the user from inserting another.
  412. //
  413. //********************************************************************
  414. void CSimpleDoc::InsertObject()
  415. {
  416. OLEUIINSERTOBJECT io;
  417. UINT iret;
  418. char szFile[OLEUI_CCHPATHMAX];
  419. m_lpSite = CSimpleSite::Create(this);
  420. // clear the structure
  421. _fmemset(&io, 0, sizeof(OLEUIINSERTOBJECT));
  422. // fill the structure
  423. io.cbStruct = sizeof(OLEUIINSERTOBJECT);
  424. io.dwFlags = IOF_SELECTCREATENEW |
  425. IOF_DISABLELINK | IOF_DISABLEDISPLAYASICON |
  426. IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT;
  427. io.hWndOwner = m_hDocWnd;
  428. io.lpszCaption = (LPSTR)"Insert Object";
  429. io.iid = IID_IOleObject;
  430. io.oleRender = OLERENDER_DRAW;
  431. io.lpIOleClientSite = &m_lpSite->m_OleClientSite;
  432. io.lpIStorage = m_lpSite->m_lpObjStorage;
  433. io.ppvObj = (LPVOID FAR *)&m_lpSite->m_lpOleObject;
  434. io.lpszFile = szFile;
  435. io.cchFile = sizeof(szFile);
  436. _fmemset((LPSTR)szFile, 0, sizeof(szFile));
  437. // call OUTLUI to do all the hard work
  438. iret = OleUIInsertObject(&io);
  439. if (iret == OLEUI_OK)
  440. {
  441. m_lpSite->InitObject((BOOL)(io.dwFlags & IOF_SELECTCREATENEW));
  442. // disable Insert Object menu item
  443. DisableInsertObject();
  444. }
  445. else
  446. {
  447. m_lpSite->Release();
  448. m_lpSite = NULL;
  449. m_lpStorage->Revert();
  450. }
  451. }
  452. //**********************************************************************
  453. //
  454. // CSimpleDoc::lResizeDoc
  455. //
  456. // Purpose:
  457. //
  458. // Resizes the document
  459. //
  460. // Parameters:
  461. //
  462. // LPRECT lpRect - The size of the client are of the "frame"
  463. // Window.
  464. //
  465. // Return Value:
  466. //
  467. // NULL
  468. //
  469. // Function Calls:
  470. // Function Location
  471. //
  472. // MoveWindow Windows API
  473. //
  474. // Comments:
  475. //
  476. //********************************************************************
  477. long CSimpleDoc::lResizeDoc(LPRECT lpRect)
  478. {
  479. MoveWindow(
  480. m_hDocWnd,
  481. lpRect->left, lpRect->top,
  482. lpRect->right, lpRect->bottom, TRUE);
  483. return NULL;
  484. }
  485. //**********************************************************************
  486. //
  487. // CSimpleDoc::lAddVerbs
  488. //
  489. // Purpose:
  490. //
  491. // Adds the objects verbs to the edit menu.
  492. //
  493. // Parameters:
  494. //
  495. // None
  496. //
  497. // Return Value:
  498. //
  499. // NULL
  500. //
  501. // Function Calls:
  502. // Function Location
  503. //
  504. // GetMenuItemCount Windows API
  505. // OleUIAddVerbMenu OUTLUI function
  506. //
  507. // Comments:
  508. //
  509. //********************************************************************
  510. long CSimpleDoc::lAddVerbs(void)
  511. {
  512. // m_fModifiedMenu is TRUE if the menu has already been modified
  513. // once. Since we only support one obect every time the application
  514. // is run, then once the menu is modified, it doesn't have
  515. // to be done again.
  516. if (m_lpSite && !m_fModifiedMenu)
  517. {
  518. int nCount = GetMenuItemCount(m_lpApp->m_hEditMenu);
  519. OleUIAddVerbMenu ( m_lpSite->m_lpOleObject,
  520. NULL,
  521. m_lpApp->m_hEditMenu,
  522. nCount + 1,
  523. IDM_VERB0,
  524. 0, // no maximum verb IDM enforced
  525. FALSE,
  526. 1,
  527. &m_lpApp->m_hCascadeMenu);
  528. m_fModifiedMenu = TRUE;
  529. }
  530. return (NULL);
  531. }
  532. //**********************************************************************
  533. //
  534. // CSimpleDoc::PaintDoc
  535. //
  536. // Purpose:
  537. //
  538. // Paints the Document
  539. //
  540. // Parameters:
  541. //
  542. // HDC hDC - hDC of the document Window
  543. //
  544. // Return Value:
  545. //
  546. // None
  547. //
  548. // Function Calls:
  549. // Function Location
  550. //
  551. // CSimpleSite::PaintObj SITE.CPP
  552. //
  553. // Comments:
  554. //
  555. //********************************************************************
  556. void CSimpleDoc::PaintDoc (HDC hDC)
  557. {
  558. // if we supported multiple objects, then we would enumerate
  559. // the objects and call paint on each of them from here.
  560. if (m_lpSite)
  561. m_lpSite->PaintObj(hDC);
  562. }
  563. //**********************************************************************
  564. //
  565. // CSimpleDoc::DisableInsertObject
  566. //
  567. // Purpose:
  568. //
  569. // Disable the ability to insert a new object in this document.
  570. //
  571. // Parameters:
  572. //
  573. // None
  574. //
  575. // Return Value:
  576. //
  577. // None
  578. //
  579. // Function Calls:
  580. // Function Location
  581. //
  582. // RevokeDragDrop OLE API
  583. // EnableMenuItem Windows API
  584. //
  585. // Comments:
  586. //
  587. // This implementation only allows one object to be inserted
  588. // into a document. Once the object has been inserted, then
  589. // the Insert Object menu choice is greyed out, to prevent
  590. // the user from inserting another. Also we revoke ourself as
  591. // a potential drop target.
  592. //
  593. //********************************************************************
  594. void CSimpleDoc::DisableInsertObject(void)
  595. {
  596. // Disable InsertObject menu choice
  597. EnableMenuItem( m_lpApp->m_hEditMenu, 1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  598. // Enable Copy menu choice
  599. EnableMenuItem( m_lpApp->m_hEditMenu, 0, MF_BYPOSITION | MF_ENABLED);
  600. // We no longer accept dropping of objects
  601. if (m_fRegDragDrop) {
  602. RevokeDragDrop(m_hDocWnd);
  603. m_fRegDragDrop = FALSE;
  604. }
  605. }
  606. //**********************************************************************
  607. //
  608. // CSimpleDoc::CopyObjectToClip
  609. //
  610. // Purpose:
  611. //
  612. // Copy the embedded OLE object to the clipboard
  613. //
  614. // Parameters:
  615. //
  616. // None
  617. //
  618. // Return Value:
  619. //
  620. // None
  621. //
  622. // Function Calls:
  623. // Function Location
  624. //
  625. // CDataXferObj::Create DXFEROBJ.CPP
  626. // CDataXferObj::QueryInterface DXFEROBJ.CPP
  627. // OleSetClipboard OLE API
  628. //
  629. // Comments:
  630. //
  631. // This implementation only allows one object to be inserted
  632. // into a document. Once the object has been inserted, then
  633. // the Copy menu choice is enabled.
  634. //
  635. //********************************************************************
  636. void CSimpleDoc::CopyObjectToClip(void)
  637. {
  638. LPDATAOBJECT lpDataObj;
  639. // Create a data transfer object by cloning the existing OLE object
  640. CDataXferObj FAR* pDataXferObj = CDataXferObj::Create(m_lpSite,NULL);
  641. if (! pDataXferObj) {
  642. MessageBox(NULL,"Out-of-memory","SimpDnD",MB_SYSTEMMODAL|MB_ICONHAND);
  643. return;
  644. }
  645. // initially obj is created with 0 refcnt. this QI will make it go to 1.
  646. pDataXferObj->QueryInterface(IID_IDataObject, (LPVOID FAR*)&lpDataObj);
  647. // put out data transfer object on the clipboard. this API will AddRef.
  648. OleSetClipboard(lpDataObj);
  649. // Give ownership of data transfer object to clipboard
  650. pDataXferObj->Release();
  651. }