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