# External Toolbar Layout Negotiation Mechanism

Last updated: 29 September 1996 -- satona

This document describes two interfaces we've introduced in the IE 3.0 (Internet Explorer 3.0) to share the "Internet Toolbar" implementation between two browser frames, IE 3.0 (a stand-alone web browser) and IE 4.0 (the windows shell). Although I describe this interface in this particular context, there is nothing specific to this particular application or implementation in these interfaces.

> Notes: IE 3.0 hosted only one toolbar, but IE 4.0 is going to host more than one (including the tree pane). The (private) interfaces we've introduced in IE 3.0 is not efficient for it. It requires to allocate a site for each toolbar. To avoid that inefficiency, we are changing the interface. All the member function calls to IDockingWindowSite takes an additiona parameter punkOuter, which identifies the toolbar. All the changes are marked in italic fonts.

When the browser frame is created, it CoCreateInstance an instance of the "Internet Toolbar" and attach it the frame window. The browser frame implements the IDockingWindowSite interface and the toolbar implements the IDockingWindow interface. Those interfaces are used only for layout negotiation and accelerators and actual navigation commands (that's what this particular toolbar does) is sent via the OLE automation interface (IWebBrowserApp in this particular case).

The idea is very similar to the toolbar layout negotiation between in-place active object and in-place frame, but uses different set of interfaces which are specific to the negotiation between the frame and the toolbar that is not provided by the active object.

In IE 4.0, we added another interface, IDockingWindowFrame, which provides a way to add or remove toolbars programatically. Both the WebBar and the DesktopChannel (a vertical toolbar with channel change UI buttons) will use this mechanism.

- IDockingWindowFrame interface
- IDockingWindowSite interface
- IDockingWindow interface
- Notes
- Interface Definitions

### IDockingWindowFrame interface (New IE 4.0)

In addition to the standard "Internet Toolbar", ISVs (or ICPs) can add any toolbars (any COM objects which supports IDockingWindow interface) to browser windows (including browser window OCs, sub-frames in frame sets and the desktop window) programatically. It will be done by (1) obtaining the IDockingWindowFrame inteface via IServiceProvider::QueryService (sid = SID_SShellBrowser for the immediate parent or SID_STopLevelBrowser for the top-level browser), (2) then calling AddToolbar member with a COM object, which supports IDockingWindow interface. Member functions of IDockingWindowFrame are described below:

- The AddToolbar member will attach the specified toolbar to the toolbar frame (e.g., IE browser window). When successfully attached, SetToolbarSite and ShowST member functions (of its IDockingWindow) will be called. It's important to note that the IDockingWindowSite object may or may not be the same as the IDockingWindowFrame object. Therefore, toolbars must establish the communication with the browser by the IDockingWindowSite interface passed via SetToolbarSite.
- The RemoveToolbar member will detach the specified toolbar from the site. CloseST and SetToolbarSite(NULL) will be called by the toolbar site.

### IDockingWindowSite interface

This interface is implemented by a frame window object, which typically implements the IOleInPlaceUIWindow as well It inherits IOleWindow, and it has four additional member functions, GetBorderST, RequestBorderSpaceST, SetBorderSpaceST and OnFocusChange. These member functions are always called by one of associated toolbars.

- GetBorderST/RequestBorderSpaceST/SetBorderSpaceST: The definitions are exactly the same as corresponding methods in IOleInPlaceUIWindow. The prefix "ST" is added to allow C++ programmers to implement both interfaces in a single frame object.
- [New IE 4.0] The OnFocusChangeST member will be called by the toolbar that is either getting or loosing the input focus. The frame will use this event to keep track of which toolbar has the focus.

### IDockingWindow interface

This interface is implemented by a toolbar object, which displays some tools within the border space of the frame window, with which it is associated. This interface also inherits IOleWindow. It has six additional member functions, SetToolbarSite, ShowST, CloseST, ResizeBorderST, TranslateAcceleratorST and HasFocus.

- SetToolbarSite is called by the frame to establish the relationship between the frame and the toolbar object. The frame also calls SetToolbarSite with NULL when it is disconnecting the toolbar (typically when the frame is being closed). When SetToolbarSite(NULL) is called, the toolbar object must release all interface pointers obtained from the site (or frame).
- ShowST is called by the frame with a Boolean parameter, indicating whether it should be shown or not. When being shown, the toolbar should get an appropriate border space (by calling IDockingWindowSite members) and make it visible filling the entire border space it acquired. When being hidden, it should make it invisible and return the border space by calling SetBorderSpaceST with 0s.
- CloseST is called by the frame (before calling SetToolbarSite with NULL) when it is about disconnect the toolbar from the frame. If the toolbar has some global state to be persisted (to a registry or something), this is a good time to do it.
- ResizeBorderST is called by the frame when the border space has to be re-negotiated. It typically happens when the user changes the size of the entire frame window or another border space negotiation (which happens outside of the border rectangle for this toolbar) changed the border rectangle for this toolbar.
- TranslateAcceleratorST is called by the frame only if the toolbar has the input focus.
- HasFocus is called by the frame (typically from its message loop) to determine if it should call its TranslateAcceleratorST or not.

### Notes

TranslateAcceleratorST and HasFocus might need some improvement if we are going to use these interfaces widely.

Not calling TranslateAcceleratorST at all when it does not have the input focus simplifies the issue but there is a restriction. There might be some cases where a toolbar wants to process a certain set of accelerators even though it does not have the input focus (of course, we need to worry about conflicts -- that's a general problem with multiple UI components).

We found a case where the browser frame needs to be notified when its toolbar (of one of its toolbars) gets the input focus (to redirect OLECMDID_CUT/COPY/PASET commands via IOleCommandTarget -- see another document "DocObject: Edit Menu command dispatching" for further discussion). We probably needs to add OnSetFocus member for IDockingWindowSite for this particular purpose.

IE 4.0 frame (the shell explorer) will probably support multiple toolbars (the tree pane will be added as a toolbar). To implement it under the current interfaces, the frame needs to have a IDockingWindowSite for each toolbar, which is not efficient. We can avoid it by adding a parameter to its member functions, which identifies the toolbar. It can be an object pointer or a DWORD identifier (which will be set by the frame via SetOwner).

### Interface Definitions

    //==========================================================================
    // IDockingWindowSite/IDockingWindow interfaces
    //
    //  These interfaces allows us (or ISVs) to install/update external Internet
    // Toolbar for IE and the shell. The frame will simply get the CLSID from
    // registry (to be defined) and CoCreateInstance it.
    //
    //==========================================================================

    #undef  INTERFACE
    #define INTERFACE   IDockingWindowSite

    DECLARE_INTERFACE_(IDockingWindowSite, IOleWindow)
    {
        // *** IUnknown methods ***
        STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
        STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
        STDMETHOD_(ULONG,Release) (THIS) PURE;

        // *** IOleWindow methods ***
        STDMETHOD(GetWindow) (THIS_ HWND * lphwnd) PURE;
        STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;

        // *** IDockingWindowSite methods ***
        STDMETHOD(GetBorderST) (THIS_ IUnkown* punkSrc, LPRECT prcBorder) PURE;
        STDMETHOD(RequestBorderSpaceST) (THIS_ IUnkown* punkSrc, LPCBORDERWIDTHS pbw) PURE;
        STDMETHOD(SetBorderSpaceST) (THIS_ IUnkown* punkSrc, LPCBORDERWIDTHS pbw) PURE;
        STDMETHOD(OnFocusChangeST) (THIS_ IUnknown* punkSrc, BOOL fSetFocus) PURE;
    };

    #undef  INTERFACE
    #define INTERFACE   IDockingWindowFrame

    DECLARE_INTERFACE_(IDockingWindowFrame, IOleWindow)
    {
        // *** IUnknown methods ***
        STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
        STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
        STDMETHOD_(ULONG,Release) (THIS) PURE;

        // *** IOleWindow methods ***
        STDMETHOD(GetWindow) (THIS_ HWND * lphwnd) PURE;
        STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;

        // *** IDockingWindowFrame methods ***
        STDMETHOD(AddToolbar) (THIS_ IUnkown* punkSrc, DWORD dwReserved) PURE;
        STDMETHOD(RemoveToolbar) (THIS_ IUnkown* punkSrc) PURE;
    };

    #undef  INTERFACE
    #define INTERFACE   IDockingWindow

    DECLARE_INTERFACE_(IDockingWindow, IOleWindow)
    {
        // *** IUnknown methods ***
        STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
        STDMETHOD_(ULONG,AddRef) (THIS)  PURE;
        STDMETHOD_(ULONG,Release) (THIS) PURE;

        // *** IOleWindow methods ***
        STDMETHOD(GetWindow) (THIS_ HWND * lphwnd) PURE;
        STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;

        // *** IDockingWindow methods ***
        STDMETHOD(SetToolbarSite) (THIS_ IUnknown* punkSite) PURE;
        STDMETHOD(ShowST)         (THIS_ BOOL fShow) PURE;
        STDMETHOD(CloseST)        (THIS_ DWORD dwReserved) PURE;
        STDMETHOD(ResizeBorderST) (THIS_ LPCRECT   prcBorder,
                                         IUnknown* punkToolbarSite,
                                         BOOL      fReserved) PURE;
        STDMETHOD(TranslateAcceleratorST) (THIS_ LPMSG lpmsg) PURE;
        STDMETHOD(HasFocus)       (THIS) PURE;
    };

Go to the home page