|
|
1.1 ! root 1: Microsoft Foundation Classes Microsoft Corporation ! 2: Technical Notes ! 3: ! 4: #10 : Writing an OLE Server Application ! 5: ! 6: This note describes the classes and steps involved in creating ! 7: an OLE server application. ! 8: ! 9: Please be sure to read the general MFC OLE overview (TN008.TXT). ! 10: ! 11: ============================================================================= ! 12: Features of an OLE Server Application ! 13: ===================================== ! 14: ! 15: User Interface Features ! 16: ----------------------- ! 17: ! 18: The following briefly describes some of the end-user features of a ! 19: typical OLE Server application. How the MFC OLE classes are used to ! 20: provide this support is described later. ! 21: ! 22: 1) Editing Embedded Data ! 23: OLE Servers will support editing of embedded data. That is, data stored ! 24: in a client document which is given to the server to edit or display. ! 25: The data is given back to the client document to be saved when closed. ! 26: In the case of editing an embedded document, the "File" menu should ! 27: have an "Update" menuitem instead of "Save". ! 28: ! 29: 2) Editing Linked Data ! 30: A server may optionally provide linking to server documents. ! 31: In this case the server will provide in addition to the embedded ! 32: data editing features, the ability to open normal files and copy ! 33: data to the clipboard. ! 34: ! 35: Additional features of linked data is that data updated the server ! 36: can automatically be updated in the client. The client may turn ! 37: of automatic updates if desired. ! 38: ! 39: 3) SDI vs MDI user interface ! 40: Since multiple client applications may be using embedded or linked ! 41: data at the same time, we need to support multiple servers. ! 42: There are two ways this can be done. With a single document interface ! 43: (SDI) the application must support multiple instances (i.e. a new ! 44: instance of the server application will be launched for each edited ! 45: document). For server applications that support links, or an MDI ! 46: interface, one instance of the application will responding to all ! 47: OLE client requests (i.e. create an new CMDIChildWnd for each document). ! 48: ! 49: 4) Additional Verbs ! 50: All OLE client apps provide access to the primary verb for an embedded ! 51: or linked object. This primary verb is usually "edit". Additional ! 52: verbs may be defined, and will be presented in the OLE client's Edit ! 53: menu when the embedded (or linked) object is selected. ! 54: These additional verbs can be added by registering the server ! 55: using the AfxOleRegisterServerName() function, or by using a ! 56: setup program. ! 57: ! 58: Additional Features ! 59: ------------------- ! 60: There are many other advanced features of an OLE Server you may wish ! 61: to consider. ! 62: ! 63: * the ability to support multiple data formats. MFC OLE defaults ! 64: to supporting "native" format and drawing as a meta-file. ! 65: ! 66: * OLE servers do not have to be visual and have a complete user ! 67: interface. Note-it and sound players are examples of these ! 68: simple servers that support embedding. ! 69: ! 70: * OLE servers can support multiple types. For example the MS Excel ! 71: application supports charts and spreadsheets. ! 72: ! 73: * OLE servers may also support execution of generic DDE execute ! 74: commands. Refer to the 'OnExecute' member functions. ! 75: ! 76: * it is possible to support links but not embedding. This is not ! 77: very typical but it is possible. ! 78: ! 79: * MFC OLE does not support OLE Handlers (i.e. DLLs for doing more ! 80: efficient server operations). OLE Handlers can be written ! 81: using the OLE API and may talk to an OLE server application ! 82: written with MFC OLE. ! 83: ! 84: ============================================================================= ! 85: Tasks of an OLE Server Developer ! 86: ================================ ! 87: ! 88: The Classes ! 89: ------------ ! 90: As mentioned in the overview, the MFC OLE classes require that you ! 91: derive your own classes from the MFC OLE base classes. You must ! 92: provide at least three derived classes, one for the server ! 93: application, one for the server document and one for the server ! 94: items. ! 95: ! 96: The server is used for managing server docs and is notified when clients ! 97: want to open or edit server documents. ! 98: ! 99: The server document class defines the structure of how items are managed. ! 100: The server item class defines the structure of how linked and/or embedded ! 101: OLE items fit into your application. ! 102: ! 103: There will typically only be one server object in your application. Having ! 104: more than one is necessary only if you want to support multiple OLE types. ! 105: There will one server document object per document. For an SDI multi-instance ! 106: application this will be one document per application. For an MDI ! 107: single-instance application, this will be one document for each MDI Child ! 108: window. ! 109: ! 110: Each document may have zero or more server items. ! 111: ! 112: ! 113: Creating the server class ! 114: ------------------------- ! 115: Class 'COleServer' provides a base class that is used for all global ! 116: server management. You must derive your own server class from ! 117: 'COleServer' and override several member functions: ! 118: ! 119: OnCreateDoc - create a new server document ! 120: OnEditDoc - edit an existing server document ! 121: ! 122: For servers that support links, you must also implement: ! 123: OnOpenDoc - open an existing document ! 124: ! 125: ! 126: In all of these cases you should create a new object of your ! 127: server document class (derived from COleServerDoc) and return ! 128: it. Do not register this server document. ! 129: ! 130: ! 131: Creating the document class ! 132: --------------------------- ! 133: Class 'COleServerDoc' provides a base class that is used to contain ! 134: server items. You must derive your own document class from ! 135: 'COleServerDoc' and override several member functions: ! 136: ! 137: OnGetDocument - return a new item representing the entire document ! 138: OnGetItem - return a new item representing the named part of ! 139: the document. ! 140: ! 141: In both of these cases, you should create a new object of your server ! 142: item class (derived from COleServerItem) and return it. ! 143: ! 144: For applications that support links, a server document should be created ! 145: for every named file. If the server document is not opened as a ! 146: result of a COleServer request (eg: OnCreateDoc or OnOpenDoc above) you must ! 147: explicitly register the document (eg: when the user directly opens an ! 148: existing file from the File/Open menu item). The 'Register' ! 149: member function is used for this registering. 'Revoke' can be used ! 150: to revoke the document. ! 151: ! 152: When the server document changes, there are specific notification routines ! 153: that must be called: ! 154: NotifyRename - call after document has been renamed by user ! 155: NotifyRevert - call after document has been reverted to original ! 156: (i.e. re-opened ignoring recent changes) ! 157: NotifySaved - call after document has been saved to disk ! 158: ! 159: Additional notifications include: ! 160: NotifyClosed - closed notification for old OLE servers ! 161: (usually NotifySaved and Revoke is enough) ! 162: NotifyChanged - notify of some global document change ! 163: ! 164: ! 165: Creating the item class ! 166: ----------------------- ! 167: Your server item is the server-side view of the linked or embedded ! 168: OLE object. Class 'COleServerItem' provides a base class that is used ! 169: to keep all the native data required to manage the server data as well ! 170: as any additional user interface data. ! 171: A COleServerItem must always be contained in a COleServerDoc. If the ! 172: server item is created as a result of a COleServerDoc callback ! 173: (i.e. OnGetDocument or OnGetItem) than no extra work must be done. ! 174: ! 175: Do not create server items outside these callbacks. ! 176: ! 177: You must override several member functions: ! 178: OnShow is called when the item is to be shown. It should scroll ! 179: the specific item into view and set the focus to it if appropriate. ! 180: OnDraw is called when the item is to be drawn (NOTE: it is drawn ! 181: into metafile DC, not a screen DC). ! 182: Serialize is part of the normal CObject serialization. ! 183: ! 184: Serialize is the means for getting the native data. You must implement ! 185: Serialize in your item class to load and store all important ! 186: native data for your server item. ! 187: COleServerItem::Serialize is a pure virtual function so you should ! 188: not call this as part of your serialize operation. ! 189: ! 190: ! 191: Flow of control ! 192: --------------- ! 193: Scenario for creating a new embedded object: (from Insert-New-Object ! 194: on the client app) ! 195: * the server is asked to create a new document (OnCreateDoc) ! 196: * the server document is asked to get an item representing ! 197: the entire document (OnGetDocument) ! 198: * the server item will be shown - but the client will still have ! 199: a "blank" item. ! 200: * when the server document is saved (eg: File/Update) then the client ! 201: will be updated. ! 202: ! 203: Scenario for editing an existing embedded object: ! 204: * the server is asked to create a new document (OnCreateDoc) ! 205: * the server document is asked to get an item representing ! 206: the entire document (OnGetDocument) ! 207: * the server item is de-serialized from the data provided by the client. ! 208: This will be the data from a previous serialization. ! 209: * the server item will be shown. ! 210: * when the server document is saved (eg: File/Update) then the client ! 211: will be updated. ! 212: ! 213: Scenario for editing an linked object: ! 214: * the server is asked to open an existing document (OnOpenDoc) ! 215: * the server document is asked to get an item representing ! 216: the entire document (OnGetDocument) or just a part of the ! 217: document (OnGetItem) depending on how the link was stored. ! 218: * the server item will be shown. ! 219: ! 220: ! 221: Checking errors and catching exceptions ! 222: --------------------------------------- ! 223: Some callbacks from the server or server document or server ! 224: items will return OLESTATUS codes. These should follow the conventions ! 225: of the OLE API (i.e. return OLE_OK if ok, some other OLESTATUS code ! 226: on error, eg: OLE_ERROR_GENERIC). ! 227: Other callbacks that return more useful information may throw exceptions ! 228: in the server or if possible just return a NULL value (eg: for OnCreateDoc ! 229: in the COleServer). ! 230: ! 231: Asynchronous Requests ! 232: --------------------- ! 233: When inside a callback from a server or server document or server item ! 234: you should not do any modal operation or anything that will cause your ! 235: application to call GetMessage or PeekMessage. The debugging version ! 236: of the MFC CWinApp class has special asserts that will catch scenarios ! 237: where server code is calling the main message pump when it shouldn't. ! 238: ! 239: Implementing the UI features ! 240: ---------------------------- ! 241: The following gives a brief overview of what you must do to implement ! 242: the major User Interface features of OLE for your server application. ! 243: See above for the list of 4 major UI features. See the OSERVER and ! 244: TESTSERV sample program for a working examples (OSERVER just supports ! 245: embedding, TESTSERV supports linking and embedding). ! 246: ! 247: 1) Editing Embedded Data ! 248: When your program is executed, you should examine the command ! 249: line argument in InitInstance. Check for the special "-Embedding" ! 250: or "/Embedding" flag, which determines if this application was ! 251: launched for embedding or not. ! 252: When constructing a server object (i.e. an object of your class ! 253: derived from COleServer) pass TRUE to the constructor if the ! 254: application was launched embedded. If launched embedded, the ! 255: server application will automatically shutdown when no more ! 256: client applications are connected to it. ! 257: ! 258: The basic structure of the server/server document/server item ! 259: provides most of what is needed for editing embedded data. ! 260: If your application also supports links to files, be sure to ! 261: change the file menu to "Update" instead of "Save". ! 262: ! 263: 2) Editing Linked Data ! 264: There are additional ways of accessing data when passed links. ! 265: In addition to the "/Embedding" flag, server applications that ! 266: support links should also look for a filename after the embedding ! 267: command line argument. If found, this is the first file that ! 268: should be opened. ! 269: ! 270: In order for a client to paste a link to your server application, ! 271: you must copy a link to the clipboard. See the TESTSERV program ! 272: for an example of this. ! 273: ! 274: Lastly, since clients may want immediate updates, the NotifyChanged ! 275: operation in COleServerItem can be used to notify the client that ! 276: this one specific change has occured. In general changes to all ! 277: server items (embedded and linked) will be notified when the ! 278: server document is saved (i.e. NotifySaved is called). ! 279: ! 280: 3) SDI vs MDI user interface ! 281: Building an SDI vs MDI app is just like a normal MFC windows app. ! 282: The additional work you must do is to register your server ! 283: (i.e. an object of your class derived from COleServer). Call ! 284: the Register function with the OLE class name (non-localized) ! 285: and a BOOL indicating if your app is multiple instance or not: ! 286: ! 287: SDI <=> multiple instance ! 288: (one CFrameWnd per document usually) ! 289: MDI <=> single instance ! 290: (one CMDIChildWnd per document usually) ! 291: ! 292: 4) Additional Verbs ! 293: Additional verbs must be defined in the registration database. ! 294: See below for the steps involved in creating a .REG file. ! 295: Additional verbs may be handled by overriding COleServerItem::OnExtraVerb ! 296: and doing a switch on the passed verb number). You should ! 297: return OLE_ERROR_DOVERB for verbs you don't understand. ! 298: ! 299: The primary verb of 0 is handled automatically by the default OnShow ! 300: member function. ! 301: ! 302: ============================================================================= ! 303: Creating a REG file ! 304: =================== ! 305: ! 306: In order to provide the OLE system functionality with enough information ! 307: about your OLE server, you must add this information to the system ! 308: registration database. ! 309: ! 310: The sample OSERVER.REG provides a registration file with the ! 311: basic structure which you can start with. Follow the additional ! 312: steps below. ! 313: ! 314: To actually place the information in the registration database, you ! 315: can use the AfxOleRegisterServerName() function to automatically ! 316: register the server when running it from the program manager, file ! 317: manager, or from an Icon. The AfxOleRegisterServerName() function ! 318: will also keep up with any changes in the server location. To use ! 319: this function, simply call it within your application's ! 320: InitInstance() function. It takes a class name and human readable ! 321: name as parameters (see steps 2 and 3 below). ! 322: ! 323: Steps for writing/customizing a .REG file: ! 324: ! 325: 1) start from an existing .REG file, it's easier that way. The OLE ! 326: sample programs have sample .REG files in their source directories. ! 327: ! 328: 2) pick a OLE class name for each of your OLE object types ! 329: This is an implementation name so it should be designed ! 330: to avoid collisions - so use your company's name or your ! 331: initials at the start of the class name. This name should not ! 332: contain spaces. eg: "MSGraph" or "JOE_CHART". ! 333: ! 334: 3) provide a human readable form of that OLE class name. This ! 335: is what people will see in the "Insert New Object" dialog box ! 336: and other user interfaces. This name may contain spaces. ! 337: eg: "Microsoft Graph" or "Joe's Cool Chart Thing" ! 338: ! 339: 4) provide the path name for where your server application will ! 340: be installed. The standard for this is to place each server ! 341: in a sub-directory of the Windows system directory ! 342: (usually C:\WINDOWS\OLEAPPS\MYSERVER). ! 343: If the server is going to be on the search path when Windows ! 344: is running, you do not have to specify an absolute path. ! 345: ! 346: 5) if you have a standard suffix for all your data files, add that ! 347: to the registration file. ! 348: ! 349: 6) if you have additional verbs for your server data, add them starting ! 350: with index 0. You will usually want to use verb index 0 as the ! 351: standard "Edit" verb. ! 352: ! 353: 7) save the registration file with the same name as your server ! 354: (eg: if you are building MYSERVER.EXE, name the file MYSERVER.REG). ! 355: ! 356: ============================================================================= ! 357: Other Issues: ! 358: ============= ! 359: ! 360: Building ! 361: -------- ! 362: Assuming you are already building a normal MFC windows application, ! 363: you must do the following additional steps: ! 364: ! 365: * include 'afxole.h' in those source files using MFC OLE (this will ! 366: include 'afxwin.h' if not included already). ! 367: * Link with the appropriate MFC library as usual. ! 368: * You will also need to link with two additional libraries: ! 369: OLESVR.LIB - interfaces to the server side OLE APIs ! 370: SHELL.LIB - interfaces to the system registration database ! 371: ! 372: Debugging and Testing ! 373: --------------------- ! 374: See TN007.TXT and TN009.TXT for general tips on debugging OLE applications. ! 375: ! 376: ! 377: ============================================================================= ! 378:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.