Implementing Shell Desk Band and Internet Explorer Bars



Click here for a larger image.



Click here for a larger image.

Introduction

The Internet Explorer Bars are child windows within the main Explorer window, and Desk Band is a dockable window on the desktop/taskbar. Both can be used to display information or interact with the user. This article deals with the implementation of these Band objects.

Design

Creating an IE Bar or Desk Band requires you to implement several interfaces and a special registration procedure. To make life easier for you, I developed an ATL class, CDeskBand, which encapsulates all these boring things needed by COM and Windows Shell runtime. In addition, there is also a CShellModule class that serves to register/unregister COM objects.

New macros

BEGIN_TYPE_MAP(x)
Marks the beginning of the type map of Band ATL objects. The parameter x is an array holding _ATL_TYPEMAP_ENTRY structures that describe the objects' type.

END_TYPE_MAP()
Marks the end of the type map of Band ATL objects. When CShellModule::RegisterServer is called, it updates the system Registry for each object in the type map.

TYPE_ENTRY(clsid, type)
Enters the type of the Band object into the type map. Parameter clsid is a CLSID of the object to be entered into the map and type can be one of the following values:

  • DeskBand
  • VerticalExplorerBar
  • HorizontalExplorerBar

Using these macros is similar to the standard ATL BEGIN_OBJECT_MAP/OBJECT_ENTRY/END_OBJECT_MAP macros.

DECLARE_MENU_MAP(x)
Forward declaration of the menu map. Parameter x is the name of the map specific to one or more Band objects.

BEGIN_MENU_MAP(x)
Marks the beginning of the menu map. Parameter x is an array holding the _ATL_MENUMAP_ENTRY structures that describe menu items and must be the same as used in the previous macro.

END_MENU_MAP()
Marks the end of the menu map.

MENU_ENTRY(id,flags,item,help,verb)
Enters an item into the menu map. Parameter id should be unique within the map; for flags' parameter values you should look into the MSDN documentation for the InsertMenu function. Item parameter is a label displayed for a menu item; help parameter is a help string for an item; and verb a is language-independent command name (like open, save, ...).

MENU_ENTRY_SEPARATOR()
Enters a separator menu item into the menu map.

You should create the menu map only if you need special commands for your Band object (a typical usage may be the "Settings..." command). You can use one menu map for more Band objects.

CShellModule

class CShellModule : public CComModule

CShellModule implements a COM server module with extensions in the registration/unregistration procedure needed by Windows Shell.

HRESULT Init( _ATL_TYPEMAP_ENTRY *pdt, _ATL_OBJMAP_ENTRY *p, HINSTANCE h )
Initializes all data members. Parameter pdt is a pointer to the type map array; the other ones are the same as in the CComModule::Init method.

HRESULT RegisterServer( const CLSID *pCLSID = NULL )
Depending on the pCLSID parameter, updates the system Registry for a single class object or for all objects in the object map.

HRESULT UnregisterServer( const CLSID *pCLSID = NULL )
Depending on the pCLSID parameter, unregisters either a single class object or all objects in the object map.

CDeskBand

template < const CLSID *pclsid,const _ATL_MENUMAP_ENTRY *pMenu = NULL >
class ATL_NO_VTABLE CDeskBand : public CComObjectRootEx<CComSingleThreadModel>, IObjectWithSite, IPersistStream, IDeskBand, IContextMenu

CDeskBand implements Shell Desk Band and IE Bars objects. It provides five protected virtual methods you can override:

  • LRESULT OnCreate( LPCREATESTRUCT lpCreateStruct ) -- WM_CREATE message handler
  • LRESULT OnDestroy() -- WM_DESTROY message handler
  • LRESULT OnPaint() -- WM_PAINT message handler
  • LRESULT OnCommand( WPARAM wParam, LPARAM lParam ) -- WM_COMMAND message handler
  • LRESULT OnMsg( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam ) -- generic message handler excluding previous messages

For your Band object, you should derive your own class from CDeskBand. Let's see the example:

DECLARE_MENU_MAP(DeskBandMenu)
extern const CLSID CLSID_SampleDeskBand;

class CSampleDeskBand : public CComCoClass<CSampleDeskBand,
                            &CLSID_SampleDeskBand>,
   public CDeskBand<&CLSID_SampleDeskBand,DeskBandMenu>
{
public:
  CSampleDeskBand();
  ~CSampleDeskBand();

  DECLARE_REGISTRY_RESOURCEID(IDR_DESKBAND)
  DECLARE_PROTECT_FINAL_CONSTRUCT()

protected:
  virtual LRESULT OnPaint();

private:
  // your data data members
};

Downloads

Download demo project
Download source