Annotation of mstools/mfc/doc/tn009.txt, revision 1.1.1.1

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: =============================================================================

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.