14.1 How Docking Windows Work

only for RuBoard - do not distribute or recompile

14.1 How Docking Windows Work

It takes a least two objects to create a functional docking window. The first is the primary objectthe object that wants to display a docking window (a namespace extension, BHO, band , etc.). The second object is the docking window itself. It contains all of the implementation code specific to docking windows. In this way, the relationship between the primary object and the docking window is similar to the one between a shell folder and a view; it allows the possibility of a one-to-many relationship.

The docking window object is very much like a band object in that it implements IObjectWithSite and IDockingWindow . IDeskband , which is the primary interface for band objects, is derived from IDockingWindow . So essentially , a docking window must implement the same core functionality as a band object; it must be able to respond to the shell's requests to show, close, and resize the window. Additionally, it must also be able to provide a window handle (of the docking window) to Explorer. This behavior is no different from that of band objects. Well, actually, there is one difference, which we've already talked about: band objects do not have to provide resize information to the shell. Docking windows do.

In order for the primary object to create a docking window, it must first get its hands on an IServiceProvider interface. Depending on the circumstances, this is done in one of two ways. If the component implements IObjectWithSite , as is the case with BHOs, browser extensions, or band objects, all it has to do is query the site pointer passed in by the shell. (See the discussion of site pointers in Chapter 12.) If the component is a namespace extension, it can get to IServiceProvider by means of the IShellBrowser interface that is passed to the component in the IShellView::CreateViewWindow method.

Once the primary object has an IServiceProvider interface pointer, it can then call the QueryService method to get IDockingWindowFrame ; this contains a method called AddToolbar . AddToolbar is the method that is used to add a docking window to Explorer. When the component calls AddToolBar , it passes a reference to an object that implements IDockingWindow (and IObjectWithSite ). This object, of course, is the docking window. From this point, control is transferred from the primary component to the docking window.

Once the shell has access to the docking window object, it calls IObjectWithSite::SetSite . The docking window object uses the site pointer in order to obtain a reference to IDockingWindowSite . This interface will help the docking window negotiate its border space within the client area of Explorer.

After the docking window determines its position, it is displayed.

only for RuBoard - do not distribute or recompile
only for RuBoard - do not distribute or recompile

14.2 Docking Window Interfaces

Docking windows require the use of four interfaces: IObjectWithSite , IDockingWindow , IDockingWindowFrame , and IDockingWindowSite . In the remainder of this section, we'll discuss the four interfaces and their members that are relevant to developing docking windows.

14.2.1 IObjectWithSite

The shell provides a site pointer to the docking window via the IObjectWithSite interface in a manner similar to browser helper objects or band objects. The primary objectthat is, the object that will create the docking windowuses IObjectWithSite to obtain references to IServiceProvider and, optionally , IWebBrowser2 . The secondary component, which is the actual docking window implementation, uses IObjectWithSite to obtain IDockingWindowFrame . IObjectWithSite is summarized in Table 14.2, but for a more complete discussion, please refer to Chapter 12.

Table14.1. IObjectWithSite Methods

Method

Description

GetSite

Returns the last site set with SetSite .

SetSite

Provides the IUnknown site pointer of Explorer.

14.2.2 IDockingWindow

We have already discussed IDockingWindow . If you remember our discussion of band objects, the IDeskband interface is derived from IDockingWindow . There is nothing new that we need to discuss concerning this interface. Table 14.1 provides a refresher course on the interface and on IOleWindow , the interface from which it is derived, but if you would like more detail, see Chapter 13. Methods marked with an asterisk are not implemented.

Table14.2. IDockingWindow Methods

IOleWindow

GetWindow

Returns the window handle to one of the windows participating in in-place activation (frame, document, parent, or in-place object window).

ContextSensitiveHelp *

Determines whether context-sensitive help mode should be entered during an in-place activation session.

IDockingWindow

ShowDW

Called when the docking window is supposed to be shown or hidden.

CloseDW

Called when the docking window is about to be closed.

ResizeBorderDW

Notifies the docking window object that the frame's border space has changed. This method is not implemented for band objects, but for docking windows it is a must.

14.2.3 IDockingWindowFrame

This interface is implemented by Explorer and provides all the methods necessary to add docking windows to a frame (see Table 14.3). It too is derived from IOleWindow .

Table14.3. IDockingWindowFrame Methods

IOleWindow

(See Table 14.1 for IOleWindow methods)

IDockingWindowFrame

AddToolbar

Used to add a docking window to the frame.

FindToolbar *

Finds the specified docking window in the frame and returns a reference to it.

RemoveToolbar *

Removes a docking window from the frame.

14.2.3.1 AddToolbar

Adds a docking window to Explorer or Internet Explorer's frame. The docking window must implement IDockingWindow . The component that creates the docking window calls this method once it has retrieved a pointer to the IDockingWindowFrame interface by calling IServiceProvider::QueryService . The syntax of AddToolbar is as follows :

 HRESULT AddToolbar(IUnknown* punkSrc, LPCWSTR pwszItem, 
    DWORD dwAddFlags); 

with the following parameters:

punkSrc

[in] A reference to the object implementing IDockingWindow (i.e., a reference to the docking window).

pwszItem

[in] The address of a null- terminated UNICODE string that will be used to identify the docking window. This string can be used later, if necessary, to locate a docking window by calling FindToolbar .

dwAddFlags

[in] A flag that defines the visibility of the docking window being added. This should either be zero, which specifies that the docking window should be visible, or DWFAF_HIDDEN .

14.2.3.2 FindToolbar

Finds a docking window in the frame. The method is declared as follows:

 HRESULT FindToolbar(LPCWSTR pwszItem, REFIID riid, 
                    LPVOID* ppvObj); 

Its parameters are:

pwszItem

[in] This is a pointer to the same string that was passed to AddToolbar .

riid

[in] This is a pointer to the GUID that identifies IDockingWindow .

ppvOut

[in, out] If the call is successful, this will contain the IDockingWindow interface of the requested docking window.

This method is not necessary for implementing docking windows. The primary component should keep all references to docking windows cached as private member variables ; it would never need to call this method in that circumstance. Presumably, an object that implements a docking window might provide the name of the window (as specified in the call to AddToolbar ) by means of a Public property. Additional components having an interest in the docking window could then locate it in the frame by calling FindToolbar .

14.2.3.3 RemoveToolbar

Removes the specified docking window from the frame. Its syntax is as follows:

 HRESULT RemoveToolbar(IUnknown*   punkSrc   , DWORD   dwRemoveFlags   ); 

Its parameters are as follows:

punkSrc

[in] This is the address of the docking window object. The shell will call IDockingWindow::CloseDW in response to this call.

dwRemoveFlags

[in] Option flags for removing the docking window object. These flags have no meaning in terms of implementing a docking window. Because the Platform SDK does not document the meaning of these flags, it is assumed they are used by internal Microsoft implementations of the interface. This parameter can be one or more of the following values:

Constant

Description

DWFRF_NORMAL

The default delete processing is performed.

DWFRF_DELETECONFIGDATA

In addition to deleting the toolbar, any configuration data is removed as well.

Most likely, this method would not be called under normal circumstances. That's because the docking window itself should have access to the information that the primary component does; it should be able to remove itself. This method is used when the docking window is not your own (well, most likely).

14.2.4 IDockingWindowSite

This interface, which is implemented by Explorer, is used to manage the border space for one or more docking windows. A docking window component can use this interface to obtain its real estate within Explorer's client area. IDockingWindowSite is derived from IOleWindow ; its members are listed in Table 14.4.

Table14.4. IDockingWindowSite

IOleWindow

(See Table 14.1 for IOleWindow methods)

IDockingWindowSite

GetBorderDW

Gets the border space that has been allocated for the docking window. Note, that this method is in no way tied to SetBorderSpaceDW . The two methods operate independently of each other. The only requirement is that this method is only valid after an initial call to RequestBorderSpaceDW .

RequestBorderSpaceDW

Requests border space for the docking window. The space is not actually allocated until SetBorderSpaceDW is called. The space returned might be different from the requested amount. The request can also be refused altogether. After calling this method, GetBorderDW should be called to get the actual space that was allocated.

SetBorderSpaceDW

Allocates space for the docking window. Usually, this method is called immediately after RequestBorderSpaceDW to finalize the request for space.

14.2.4.1 GetBorderDW

Retrieves the border space that has been requested by the docking window. RequestBorderSpaceDW must be called first. After a request is made, this method gets the actual space allotted to the docking window. It is important to note that the space requested may be different than the space that is actually reserved. The syntax of GetBorderDW is:

 HRESULT GetBorderDW(IUnknown*   punkSrc   , LPRECT   prcBorder   ); 

with the following parameters:

punkSrc

[in] Address of the docking window interface for the object that has requested space (that is, for the docking window).

prcBorder

[in] Address of a RECT structure that will contain border coordinates to be used by the docking window upon the successful return of this method.

14.2.4.2 RequestBorderSpaceDW

This method is called to request border space for the docking window; it is either approved, denied , or adjusted to accommodate the shell. If the request is approved or modified the method will return zero. Otherwise, an OLE error will be raised.

The actual space is not allocated until SetBorderSpaceDW is called. Here is the syntax for this method:

 HRESULT RequestBorderSpaceDW(IUnknown*   punkSrc   , LPCBORDERWIDTHS   pbw   ); 

with the following parameters:

punkSrc

[in] The address of the docking window interface for the object that is requesting space.

pbw

[in] A pointer to a BORDERWIDTHS structure (which is the same thing as a RECT structure) that contains the requested border space.

14.2.4.3 SetBorderSpaceDW

Allocates border space for the docking window. Its syntax is:

 HRESULT SetBorderSpaceDW(IUnknown*   punkSrc   , LPCBORDERWIDTHS   pbw   ); 

with the following parameters:

punkSrc

[in] Address of the docking window interface for which border space is being assigned.

pbw

[in] Address of a BORDERWITHS ( RECT ) structure containing the coordinates for the space that is being allocated.

only for RuBoard - do not distribute or recompile