|
|
1.1 ! root 1: Microsoft Foundation Classes Microsoft Corporation ! 2: Technical Notes ! 3: ! 4: #9 : Writing an OLE Client Application ! 5: ! 6: This note describes the classes and steps involved in creating ! 7: an OLE client application. ! 8: ! 9: Please be sure to read the general MFC OLE overview first (TN008.TXT). ! 10: ! 11: ============================================================================= ! 12: Features of an OLE Client Application ! 13: ===================================== ! 14: ! 15: User Interface Features ! 16: ----------------------- ! 17: The following list briefly describes some of the end-user features of a ! 18: typical OLE Client application. How the MFC OLE classes are used to provide ! 19: this support is described later. ! 20: ! 21: 1) Insert New Object dialog ! 22: The menu item "Insert &New Object" usually resides on the "Insert" ! 23: or "Edit" menu. This menu item will bring up a dialog showing all ! 24: the available class names (from the registered OLE Servers in the system). ! 25: The selected class name is used to create a new object of that type ! 26: and insert it into the client document. ! 27: The new object will start out in a blank state - which means ! 28: you must add data to it (by editing it in the server application) ! 29: before it becomes useable by the end user. ! 30: ! 31: 2) Paste, Paste Link menu items ! 32: The standard "Edit" menu will usually contain "Paste" and "Paste Link". ! 33: If the client app only supports embedding, there will be no "Paste Link". ! 34: These menu items will be enabled or disabled depending on the current ! 35: contents of the clipboard. ! 36: ! 37: 3) Object menu item ! 38: The bottom of the "Edit" menu will usually contain an "Object" menu item. ! 39: This is a dynamic menu item that changes depending on the current ! 40: selection. If more than one verb is possible it will change into ! 41: a popup menu listing all the verbs. ! 42: ! 43: 4) Links dialog ! 44: This is the standard dialog used to view, fix and otherwise manipulate ! 45: all the links in the current document. ! 46: ! 47: 5) Insitu features ! 48: The client document is reponsible for drawing the embedded/linked object ! 49: data in the appropriate location. Also supporting selection of items ! 50: and/or ranges of items as well as non-embedded document components. ! 51: Lastly double-clicking on an embedded/linked object should activate ! 52: that object. ! 53: ! 54: 6) OLE items as part of a document ! 55: The embedded/linked items are maintained as part of the document. ! 56: When the document is saved, so are the embedded items as well as the ! 57: links to the linked items. When the client document is loaded from disk ! 58: the reverse happens and the embedded/linked items are loaded as part of ! 59: the document. ! 60: If your current client application (or the one you are planning) does ! 61: not have documents, or "load" and "save" functionality - you may ! 62: want to implement an OLE server instead. ! 63: ! 64: Additional Features ! 65: ------------------- ! 66: There are many other advanced features of an OLE Client than you can ! 67: implement on top of MFC OLE. These features are minimally supported in ! 68: the MFC OLE classes and are not well documented or illustrated in the ! 69: existing sample programs. These will be added into future versions of ! 70: MFC OLE. ! 71: ! 72: Additional information on these features can be found in the Windows 3.1 ! 73: OLE documentation. ! 74: ! 75: Features not supported: ! 76: * Paste Special dialog (all the interfaces are there, but no canned ! 77: dialog to make this easy). ! 78: * Full support for UNDO (COleClientItem::CreateCloneFrom is provided, ! 79: but a client app must still do a lot of extra work). ! 80: * Full range of object creation options (for example creating from ! 81: template, or creating from file). Easy to add in your class derived ! 82: from COleClientItem if needed, but this functionality is ! 83: usually done with the MFC CFile and CArchive classes. ! 84: * Clients using the server data for more than pictures. In general ! 85: a client will create an embedded/linked object with the ! 86: standard draw option (olerender_draw). This means the ! 87: client will just draw the embedded/linked object in a ! 88: rectangle on the screen. Other render options are available. ! 89: * After loading a document which has manual links, the client app ! 90: should prompt the user to see if they want to update links now. ! 91: ! 92: ============================================================================= ! 93: Tasks of an OLE Client Developer ! 94: ================================ ! 95: ! 96: The Classes ! 97: ------------ ! 98: As mentioned in the overview, the MFC OLE classes require that you ! 99: derive your own document and item classes from the MFC OLE base ! 100: classes. ! 101: ! 102: The document class defines the structure of how items are managed. ! 103: The item class defines the structure of how linked and/or embedded ! 104: OLE items fit into your application. ! 105: ! 106: Creating the document class ! 107: --------------------------- ! 108: Your client document will typically contain both OLE and non-OLE data. ! 109: Presumably you already have a class or two to manage non-OLE data in ! 110: your application (i.e. to store, display, hit detect the contents ! 111: of a Window's client area). ! 112: You must decide how OLE data will mix with the non-OLE data. ! 113: If your non-OLE data is stored as a CObject* collection, then there is ! 114: no extra work needed (since an OLE item is a CObject as well). ! 115: If not, you will have to extend your data structures so that they can ! 116: contain a client item wherever you want to mix OLE and non-OLE data. ! 117: ! 118: Class 'COleClientDoc' provides a base class that is used to contain ! 119: embedded items. You must derive your own document class from ! 120: 'COleClientDoc'. Be sure to override the member function 'GetNextItem' ! 121: to iterate over all the OLE items in the document (the interface is ! 122: very similar to MFC lists). ! 123: ! 124: You must register your client document when it is created (using 'Register'). ! 125: Also there are specific notification routines that must be called: ! 126: NotifyRename - call after document has been renamed by user ! 127: NotifyRevert - call after document has been reverted to original ! 128: (i.e. re-opened ignoring recent changes) ! 129: NotifySaved - call after document has been saved to disk ! 130: ! 131: All of these steps are covered in the OCLIENT sample program. ! 132: The class CMainDocument is attached to CMainWnd and together they ! 133: serve as the main client document. ! 134: ! 135: Creating the item class ! 136: ----------------------- ! 137: Your client item is the client-side view of the linked or embedded ! 138: OLE object. Class 'COleClientItem' provides a base class that is used ! 139: to keep extra application specific information about each linked/embedded ! 140: item. The position of the item in the client document is an example of ! 141: extra member data you can add to your class derived from COleClientItem. ! 142: ! 143: Since a COleClientItem must always be contained in a COleClientDoc, the ! 144: containing document must be passed as a parameter to the constructor. ! 145: ! 146: Your client item objects (derived from COleClientItem) will be created ! 147: in several end-user scenarios: (see below for how to implement these) ! 148: * with the InsertNewObject dialog ! 149: * when pasted from the clipboard (paste or paste-link) ! 150: * when loaded from an existing file ! 151: ! 152: You must override the member function 'OnChange' which is a callback ! 153: that notifies the client that the server has changed. There are three ! 154: reasons the client item may change: a linked item is changed (with ! 155: automatic notification turned on), the document edited on the server ! 156: is saved or the document edited on the server is closed. ! 157: ! 158: In general do not redraw the client item when you get the 'OnChange' ! 159: callback, but instead post an update message (or use InvalidateRect ! 160: for the window). ! 161: ! 162: All of these steps are covered in the OCLIENT sample program. ! 163: The class CEmbeddedItem is attached to CItemWnd and together they ! 164: provide both the data and user interface to the client item. ! 165: ! 166: ! 167: Checking errors and catching exceptions ! 168: --------------------------------------- ! 169: Abnormal conditions, like out of memory, or can't launch server will ! 170: result in a COleException being thrown. A COleException object ! 171: can be examined to see what OLESTATUS error code caused the problem. ! 172: If a set of conditions are expected, the MFC OLE member function will ! 173: return a BOOL. If the BOOL returns FALSE, a more detailed error ! 174: report can be determined by COleClientItem::GetLastStatus which ! 175: returns the OLESTATUS of the last OLE API function call. ! 176: ! 177: Asynchronous Requests ! 178: --------------------- ! 179: The member function COleClientItem::WaitForServer is used ! 180: to synchronize the client with the server. If a server request can't ! 181: be finished immediately, the client application will wait inside of ! 182: 'WaitForServer' until the operation is complete (successful or not). ! 183: The client code calling this just sees a simple synchronous call. ! 184: ! 185: While the client app is waiting it will continue to dispatch windows ! 186: messages. The static member function 'COleClientItem::InWaitForServer' ! 187: can be used to see if the client application is already nested in ! 188: a server request. See the OCLIENT sample app for an example of the ! 189: use of 'InWaitForServer'. ! 190: ! 191: Advanced users may wish to override 'WaitForServer' and customize ! 192: it's behavior as appropriate. See the OCLIENT sample app for an ! 193: example of how to turn on the hourglass when a client operation ! 194: is going to take too long as the result of a server not being ready. ! 195: ! 196: Implementing the UI features ! 197: ---------------------------- ! 198: The following gives a brief overview of what you must do to implement ! 199: the major User Interface features of OLE for your client application. ! 200: See above for the list of 6 major UI features. See the OCLIENT sample ! 201: program for a working example of how to implement these features. ! 202: ! 203: 1) Insert New Object dialog ! 204: (a) call 'AfxOleInsertDialog' to prompt the user for class name ! 205: (b) create an object of your COleClientItem derived class using ! 206: 'COleClientItem::CreateNewObject'. ! 207: (c) insert it at the current document (eg: at the insertion point ! 208: if applicable to your application). ! 209: ! 210: 2) Paste, Paste Link menu items ! 211: (a) create menu items for "Paste" and, optionally, "Paste Link" ! 212: (b) override OnInitMenu or OnInitMenuPopup in your main frame window ! 213: (i) call 'COleClientItem::CanPaste' to determine if you ! 214: can paste or not and enable menu item accordinglly ! 215: (ii) call 'COleClientItem::CanPasteLink' to determine if you ! 216: can paste link or not and enable menu item accordinglly ! 217: ! 218: (c) when either is selected, use CreateFromClipboard or ! 219: CreateLinkFromClipboard to create the new object from clipboard. ! 220: ! 221: 3) Object menu item ! 222: This is a complicated UI which is provided for you in the standard ! 223: MFC OLE library. ! 224: (a) create menu items for "Object" with special ID value ! 225: (b) as with Paste, override OnInitMenu or OnInitMenuPopup in ! 226: your main frame window ! 227: (c) call 'AfxOleSetEditMenu' with the item, menu, and the position where ! 228: to store the 'Object' menu in the specific popup. ! 229: ! 230: 4) Links dialog ! 231: (a) add a "Links" menu item to the "Edit" menu popup ! 232: (b) when the user selects the "Links" menu item, call 'AfxOleLinksDialog' ! 233: (c) you can disable the menu item either if no linked items are ! 234: selected, or if the document does not contain linked items. ! 235: (by overriding OnInitMenu or OnInitMenuPopup in ! 236: your main frame window). ! 237: ! 238: 5) Insitu features ! 239: This is the most work. ! 240: (a) when your window gets an OnPaint request, it must draw the ! 241: COleClientItem by calling 'Draw'. This draw routine is passed ! 242: a DC and a bounds rectangle. ! 243: (b) depending on your model of selection - you probably want to support ! 244: selection of linked/embedded items ! 245: (c) perhaps support resizing of embedded items - call SetBounds to ! 246: change the size. ! 247: (d) lastly, when the user double-clicks on a client item, it should ! 248: be activated by calling 'Activate'. Overriding OnLButtonDblClk ! 249: in the appropriate window class. ! 250: ! 251: 6) Object as part of a document ! 252: (a) provide an implementation of Save/load that uses the CArchive ! 253: serialization mechanism. ! 254: (b) implement Serialize for your derived COleClientItem class, and ! 255: be sure to call the base class COleClientItem::Serialize, since ! 256: this will save the embedded/linked object information. ! 257: ! 258: ============================================================================= ! 259: Other Issues: ! 260: ============= ! 261: ! 262: Building ! 263: -------- ! 264: Assuming you are already building a normal MFC windows application, ! 265: you must do the following additional steps: ! 266: ! 267: * include 'afxole.h' in those source files using MFC OLE (this will ! 268: include 'afxwin.h' if not included already). ! 269: * Link with the appropriate MFC library as usual. ! 270: * You will also need to link with two additional libraries: ! 271: OLECLI.LIB - interfaces to the client side OLE APIs ! 272: SHELL.LIB - interfaces to the registration API ! 273: COMMDLG.LIB - interfaces to the common dialog API ! 274: * you must include the standard client resources by including ! 275: 'afxoleUI.h' and 'afxoleUI.rc' in your client application's ! 276: RC file. This includes the dialog templates and standard ! 277: strings for the UI parts of the OLE support. ! 278: ! 279: * Warning: the OLE Links dialog may call COMMDLG to prompt ! 280: the user for a new filename. This requires a reasonable ! 281: amount of stack space (8K or more). ! 282: ! 283: Testing ! 284: ------- ! 285: There are two test programs provided in source form in the MFC SAMPLE ! 286: directory. ! 287: ! 288: TESTCLNT - a test client (i.e. used to test servers) ! 289: TESTSERV - a test server (i.e. used to test clients) ! 290: ! 291: You will probably want to use 'TestServ' or some other OLE server ! 292: to test your application. See the contents of the sample source ! 293: directories for more details on these test programs. ! 294: ! 295: Debugging ! 296: --------- ! 297: See TN007.TXT for a description of the 'afxTraceFlags' options for ! 298: doing advanced debugging. The multi-application debugging option ! 299: (option 1) is extremely useful, especially if you are debugging a ! 300: client and a server at the same time. ! 301: ! 302: The main message pump reporting (option 2) is very useful when you ! 303: are trying to figure out which messages are being dispatched. ! 304: ! 305: Option 0x10 is provided specifically for OLE debugging, and ! 306: turns on some rather verbose reporting messages informing you what ! 307: is going on in the MFC OLE classes. ! 308: ! 309: Sample Code ! 310: ----------- ! 311: In addition to the test programs, the OCLIENT sample provides a simple ! 312: sample of a OLE Client application. It exploits all of the user interfaces ! 313: provided by MFC OLE. ! 314: It is a good example since it is relatively simple. ! 315: It is a poor example since each embedded/linked items is stored in a ! 316: CWnd (a CItemWnd). In general embedded/linked items are normally ! 317: drawn as part of your client area. ! 318: ! 319: =============================================================================
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.