OWLNext 7.0
Borland's Object Windows Library for the modern age
|
The next set of adaptations provide standard OLE user interface features such as menu merging and drag and drop.
The following topics discuss programming the user interface.
The following topics discuss programming the user interface.
ObjectComponents notifies your application's windows of OLE-related events by sending the WM_OCEVENT message. The ObjectWindows OLE classes provide default handlers for the various WM_OCEVENT event notifications. Furthermore, the ObjectWindows classes also process a few standard Windows messages to add additional features of the standard OLE user interface. For example, if a user double-clicks within the client area of your container window, a handler in TOleWindow checks whether the click occurred over an embedded object and, if so, activates the object. Similarly, the TOleWindow::EvPaint method causes each embedded object to draw itself. The following table lists the methods implemented by the client window (TOleWindow) and frame window(TOleFrame, TOleMDIFrame) classes. If you override these handlers in your derived class you must invoke the base class version.
Method | Message | Class | Description |
EvSize | WM_SIZE | Frame | Notifies embedded servers of the size change. |
EvTimer | WM_TIMER | Frame | Invokes IdleAction so that DLL servers can carry out command enabling. |
EvActivateApp | WM_ACTIVATEAPP | Frame | Notifies embedded servers about being activated. |
EvLButtonDown | WM_LBUTTONDOWN | Client | Deactivates any in-place active object. |
EvRButtonDown | WM_RBUTTONDOWN | Client | Displays pop-up verb menu if cursor is on an embedded object. |
EvLButtonDblClk | WM_LBUTTONDBLCLK | Client | Activates any embedded object under the cursor. |
EvMouseMove | WM_MOUSEMOVE | Client | Allows user to move or resize an embedded object. |
EvLButtonUp | WM_LBUTTONUP | Client | Informs the selected object of position or size changes. |
EvSize | WM_SIZE | Client | Informs TOcView object that window has changed size. |
EvMdiActivate | WM_MDIACTIVATE | Client | Informs TOcView object that window has changed size. |
EvMouseActivate | WM_MOUSEACTIVATE | Client | Forwards the message to the top-level parent window and returns the code to activate the client window. |
EvSetFocus | WM_SETFOCUS | Client | Notifies any in-place server of focus change. |
EvSetCursor | WM_SETCURSOR | Client | Changes cursor shape if within an embedded object. |
EvDropFiles | WM_DROPFILES | Client | Embeds dropped file(s). |
EvPaint | WM_PAINT | Client | Causes embedded objects to paint. |
EvCommand | WM_COMMAND | Client | Processes command IDs of verbs. |
EvCommandEnable | WM_COMMANDENABLE | Client | Processes command IDs of verbs. |
In some cases, you might need to know what action the base class handler took before you decide what to do in your overriding handler. This is particularly true for mouse-related messages. If the base class handled a double-click action, for example, the user intended the action to activate an object and you probably don't want your code to reinterpret the double-click as a different command. The code that follows shows how to coordinate with a base class handler. These three procedures let the user draw on the surface of the client window with the mouse.
As an OLE container, however, the client window may contain embedded objects. Mouse events performed on these objects should not result in any drawing operation. This code shows the handlers updated to allow and check for OLE related processing. Boldface type highlights the changes.
The SelectEmbedded method is inherited from TOleWindow. It returns true if an embedded object is currently being moved. The client window calls it to determine whether a mouse message has already been processed by the OLE base class.
Typically, your derived class must call the base class handlers before processing any event or message. The EvLButtonUp handler, however, calls the base class last. Doing so allows the handler to rely on SelectEmbedded which is likely to be reset after TOleWindow processes the mouse-up message.
The menu bar of an OLE container with an active object is composed of individual pieces from the normal menus of both the container and server. The container contributes pop-up menus dealing with the application frame or with documents. The server, on the other hand, provides the Edit menu, the Help menu, and any menus that let the user manipulate the activated object.
OLE divides the top-level menus of a menu bar into six groups. Each group is a set of contiguous top-level drop-down menus. Each group is made up of zero or more pop-up menus. The menu groups are named File, Edit, Container, Object, Window, and Help. The group names are for convenience only. They suggest a common organization of related commands, but you can group the commands any way you like.
When operating on its own, a container or server provides the menus for all of the six groups. During an in-place edit session, however, the container retains control of the File, Container and Window groups while the server is responsible for the Edit, Object, and Help groups.
The TMenuDescr class automatically handles all menu negotiations between the server and the container. You simply identify the various menu groups within your menu resource, and ObjectWindows displays the right ones at the right times.
To indicate where groups begin and end in your menu resource, insert SEPARATOR menu items between them. Remember to mark all six groups even if some of them are empty. The TMenuDescr class scans for the separators when loading a menu from a resource. It removes the separators found between top-level entries and builds a structure which stores the number of pop-up menus assigned to each menu group. This information allows ObjectWindows to merge the server's menu into your container's menu bar.
The following menu resource script, taken from the ObjectWindows Tutorial, illustrates defining a simple application menu before it is divided into groups.
The File menu entry belongs to the OLE File menu group. The Tools menu allows the user to edit the application's document, so it belongs to the Edit group. This application does not contain any menus belonging to the Object, Container, or Window group. And finally, the Help menu belongs to the Help group. The following code is a modified version of the same menu resource with SEPARATOR dividers inserted to indicate where one group stops and the next begins.
Insert separators in your application's menu to indicate the various menu groups. Then modify your code to use the SetMenuDescr method when assigning your frame window's menu. This example shows the menu assignment before and after adding menu merging.
Before:
After including group indicators in the menu:
Instead of using separators to show which drop-down menus belong to each group, you can use the TMenuDescr constructor whose parameters accept a count for each group. For more details, see the description of the TMenuDescr constructors in the ObjectWindows Reference Guide.
An OLE container places OLE commands on its Edit menu. The TOleWindow class has default implementations for all of them. It invokes standard dialogs boxes where necessary and processes the user's response. All you have to do is add the commands to the Edit menu of your frame window. It's not necessary to support all six commands, but every container should support at least CM_EDITINSERTOBJECT, to let the user add new objects to the current document, and CM_EDITOBJECT, to let the user choose verbs for the currently selected object.
ObjectWindows defines standard identifiers for the OLE Edit menu commands in ocf/oleview.rh. Update your resource file to include the header file and use the standard identifiers to put OLE commands on the Edit menu.
If your OLE container has a tool bar, assign it the predefined identifier IDW_TOOLBAR. ObjectWindows must be able to find the container's tool bar if a server needs to display its own tool bar in the container's window. If ObjectWindows can identify the old tool bar, it temporarily replaces it with the new one taken from the server. For ObjectWindows to identify the container's tool bar, the container must use the IDW_TOOLBAR as its window ID.
The TOleFrame::EvAppBorderSpaceSet method uses the IDW_TOOLBAR for its default implementation. A container can provide its own implementation to handle more complex situations, such as merging with multiple tool bars.