|
|
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.