Implementation of required COM interfaces

Implementation of required COM interfaces
The toolbar band object implements the following interfaces in addition to IUnknown and IClassFactory.
IObjectWithSite: The IObjectWithSite interface is implemented to support direct communication between the band object and its site in the container i.e. Internet Explorer’s rebar control.
IObjectWithSite has two methods namely SetSite () and GetSite (). The container calls the SetSite method on this interface to provide the toolbar object with an interface pointer to its site.
When the user selects the band object, the container calls the IObjectWithSite::SetSite method. The IUnknown pointer is passed to the method as input parameter.
In the SetSite method, we generally obtain the handle to the parent window i.e. Internet Explorer’s rebar control. Then we register and create an invisible window as a child of the rebar control.
The GetSite method’s implementation simply wraps a call to the QueryInterface method using the site pointer saved by the SetSite.
IPersistStream: Internet Explorer will call the toolbar's IPersistStream interface to allow the toolbar to load or save persistent data. If there is no persistent data, the methods must still return a success code. The IPersistStream interface inherits from IPersist, so five methods must be implemented: GetClassID, IsDirty, Load, Save, GetSizeMax.
The toolbar does not persist any data. So the above methods return a success code except for the GetClassID method, which returns the toolbar object’s CLSID.
IDeskBand: The IDeskBand interface is specific to band objects. In addition to its one method, it inherits from IDockingWindow, which in turn inherits from IOleWindow.
There are two IOleWindow methods: GetWindow and ContextSensitiveHelp. The toolbar object's implementation of GetWindow returns the toolbar's child window handle. Context-sensitive help is not implemented, so ContextSensitiveHelp returns E_NOTIMPL.
The IDockingWindow interface has three methods: ShowDW, CloseDW, and ResizeBorder. The ResizeBorder method is not used with any type of band object and should always return E_NOTIMPL. The ShowDW method either shows or hides the toolbar's window, depending on the value of its parameter. The CloseDW method destroys the toolbar's window.
The method that is specific to IDeskBand is GetBandInfo (). Internet Explorer uses it to specify toolbar’s identifier and viewing mode. Internet Explorer also may request one or more pieces of information from the toolbar by filling the dwMask member of the DESKBANDINFO structure that is passed as the third parameter. GetBandInfo should store the identifier and viewing mode, and fill the DESKBANDINFO structure with the requested data.
Implementation of Optional COM interfaces
Apart from the above requisite interfaces, toolbar also implements the following optional interface.
IInputObject: The IInputObject interface must be implemented if a band object accepts user input. Internet Explorer implements IInputObjectSite and uses IInputObject to maintain proper user input focus when it has more than one contained window. There are three methods that need to be implemented. They are UIActivateIO, HasFocusIO, and TranslateAcceleratorIO.
Internet Explorer calls UIActivateIO to inform the toolbar that it is being activated or deactivated. When activated, the toolbar sample calls SetFocus to set the focus to its window.
Internet Explorer calls HasFocusIO when it is attempting to determine which window has focus. If the toolbar's window or one of its descendants has focus, HasFocusIO should return S_OK. If not, it should return S_FALSE.
TranslateAcceleratorIO allows the object to process keyboard accelerators. The toolbar sample processes the VK_BACK, VK_END, VK_DOWN, and VK_DELETE messages before dispatching the message to its parent window.
Registration of CLSID
The registration of LoginSoft toolbar’s CLSID, which is a 128bit GUID (Globally Unique ID), is done in the following root keys. The registry entries for LoginSoft toolbar look something like this.
HKEY_CLASSES_ROOT
CLSID
{18CEE64E-24C0-11D5-9525-0050BA8B648D} = "&LoginSoft"
InprocServer32 =
\Mfctolband.dll
ThreadingModel = “Apartment”
ProgID = “Toolband.band.1”
TypeLib = “{18CEE64E-24C0-11D5-9525-0050BA8B648D}”
VersionIndependentProgID = “Toolband.band”
The toolbar is also registered in HKEY_LOCAL_MACHINE with the following path.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Toolbar
The registration process is a must for COM objects. The Registration entries for the toolbar object are written in an “. RGS” file. The ATL registrar loads .RGS files that not only add but can also delete registry entries. So, the same file is used to both register and un-register the toolbar object.
Window Creation
The window creation is handled in SetSite method of IObjectWithSite interface. An invisible window is created between the toolbar and Internet Explorer’s rebar to get the window messages sent from the toolbar to its parent. When a method call is made to RegisterAndCreateWindow function IObjectWithSite::SetSite method, two messages are sent to the window viz. WM_NCCREATE and WM_CREATE.
WM_NCCREATE is called prior to WM_CREATE message when a window is first created. Then, in the WM_CREATE message, the toolbar is constructed and added to the reflection window.
Toolbar Construction
This section completely deals with the construction of toolbar by walking you through the making of Login soft toolbar.
Many hurdles had to be crossed to reach the goal. Being very new to Win32 programming, I had no idea how to add a button to a band we had just created. A lot of experiments were carried out to achieve the desired result. Being only one program old in experience with WINAPI programming, the first approach was to add the windows user interface controls like button, combo box etc. directly onto the reflection window. But the interface was very bad with the edges being very ugly. The first hurdle was to build a bar, which is similar to already existing toolbars in IE. Several days and a few mind blocks later, toolbar under Windows Common Controls was discovered.
First of all let me explain what a common control is. A common control is a child window, implemented by the common control library (comctl32.dll) that can be used by any Windows-based application to perform a common I/O routine. Toolbar is one of the common controls which supports features like transparent flat look, Hot tracking of buttons, dropdown buttons, setting different images to normal, hot and disabled buttons etc. The basic functionality of Windows toolbar control is to hold one or more buttons. Each button when clicked by a user sends WM_COMMAND message to the parent. The toolbar supports a set of global common control styles.
|
|
|
Figure 4: Flat and List style Toolbar
|
Another feature, which is extensively used in building this toolbar, is dropdown button feature. An attached down arrow usually indicates this type of button. This button is designed to present users with a list of options. When the user clicks the arrow; a popup menu is displayed below the button. To display the arrow on the button, TBSTYLE_EX_DRAWDDARROWS style is set to the toolbar.
|
|
|
Figure 5: Drop down Buttons
|
Another feature supported by the toolbar control is hot tracking of buttons. Hot tracking means, when the mouse hovers over the buttons, the button becomes hot i.e. the button under the mouse is highlighted by drawing a box around the button as shown in the figure below. A toolbar created with the TBSTYLE_FLAT style supports hot-tracking by default.
|
|
|
Figure 6: Hot Tracking of Toolbar Button
|
Second hurdle to cross was to provide customization facility to the user. Meaning, the user can register with the toolbar to choose the buttons that can be placed on the toolbar. This was achieved with the help of ASP, XML technologies. To render the toolbar as per the users’ preferences, the user needs to be authenticated and then the preferences of that user are fetched from the permanent storage. This was achieved by storing the user details as well as the preferences against that user in a database.
Customization also includes configuring the mail server to show mail alerts in the form of image on the Mail button. The user enters the mal server name, user id, password etc in the preferences page, which gets stored in the database. The ASP application uses a class built with Java Mail API, which connects to the specified server logs in with the help of user id and password. The java class returns the number of new/unread mails present in the user’s inbox. This data is stored in one of the mail attributes in XML file. The toolbar application, based on this attribute, displays the appropriate image on “Mail” button on the toolbar.
The third hurdle came in the form of chevron on the toolbar. A chevron is a button with “>>” sign on it and appears whenever a portion of the toolbar is hidden as a result of reducing the size of the Internet Explorer window. This chevron can be obtained by setting the style of the band holding the toolbar to RBBS_USECHEVRON in the REBARBANDINFO structure. Later, this new modified structure is set to the band holding the toolbar.
-
Figure 7: Chevron on a Toolbar
|
|
|
Chevron
|
Here, the solution was available, but the problem faced was, where to set the structure of the method. The best way to do this is to set the structure at the time of toolbar creation i.e. during WM_CREATE window message. But, this threw access violation, as the band was not yet identified with the Internet Explorer. So an alternative had to be searched to set the style. Next approach was to set the style when the window sends WM_NOTIFY message to the window procedure. This resulted in more than one band being constructed. Finally, the style was set in IdockingWindow::ShowDW method to obtain a chevron with a dropdown menu of hidden toolbar buttons.
Window Procedure
Because a band object uses a child window for its display, it must implement a window procedure to handle Windows messaging. So the toolbar’s window procedure handles the following messages: WM_NCCREATE, WM_CREATE, WM_PAINT, WM_COMMAND, WM_NOTIFY, WM_SETFOCUS, and WM_KILLFOCUS.
WM_NCCREATE: This message is sent prior to WM_CREATE message when a window is first created. A window receives this message through window procedure.
WM_CREATE: This message is sent when an application requests that a window be created by calling CreateWindow or CreateWindowEx function. This message is sent before the function returns. Here, the toolbar is created and returns a handle to the reflection window.
WM_PAINT: Handles painting of the window.
WM_COMMAND: This message is sent when the user selects a command item from a menu, a button click or when an accelerator keystroke is translated. Here, the toolbar mainly processes button clicks and menu item selection form the dropdown buttons. The action performed on clicking a button or selecting menu could be navigating to a web site or launching an application or re-rendering toolbar etc.
WM_NOTIFY: This message is sent by a common control to its parent window when an event has occurred or the control requires some information. The toolbar mainly processes one message under WM_NOTIFY. They are TBN_DROPDOWN message, which is sent by the dropdown button on the toolbar. When this message is sent by the toolbar, the application obtains the position of the button and loads a popup menu and displays under that button.
WM_SETFOCUS & WM_KILLFOCUS: This message is sent to a window after it has gained or about to lose the keyboard focus. Here, these inform the site of a focus change by calling the sites IInputObjectSite::OnFocusChangeIS method.
Browsing Capability
The WebBrowser control adds browsing, document viewing, and data downloading capabilities to the application. Applications using this control will allow the user to browse sites on the Internet's World Wide Web, as well as folders in the local file system and on a network.
Here WebBrowser control is used to add the Internet browsing functionality to the toolbar. This control is made available in the form of IWebBrowser2 interface. The first task was to obtain a pointer to the IWebBrowser2 interface, which provides the capability to navigate to the required sites on button click or menu selections etc.
This is achieved with the help of IServiceProvider interface. This interface has one method by name QueryService that returns the IWebBrowser2 pointer, which is made use of to navigate to the required URL.
Working around the Keyboard
The keyboard is used primarily for entering and editing textual information. However, the Windows interface also supports the use of the keyboard to navigate, toggle modes, modify input, and, as a shortcut, invoke certain operations.
In Internet Explorer, the backspace is mapped to “Back button in the Standard Toolbar” which takes the user to previous page in history. Due to this, the toolbar’s edit box was not responding to backspace key in the keyboard. So to work around the problem i.e. to make the edit box respond to backspace key (VK_BACK) as long as the focus is in the edit box, this keyboard message was handled in the IInputObject::TranslateAcceleratorIO method before dispatching the message to the parent.
Miscellaneous Errors
Sudden disappearance of IE application: This was happening due to the size of the array, which holds the URL. As the size of the array was not sufficient to hold the complete URL of the site, the application overwrote memory which resulted in the IE window disappearing or it throw an access violation when running inside the debugger. This was sorted out by increasing the size of the array.
Obtaining Web browser pointer: The earlier approach taken to obtain the pointer to IWebBrowser2 interface was by registering the toolbar as a Browser Helper Object also.
In its simplest form, a BHO is a COM in-process server registered under a certain registry's key. Upon startup, Internet Explorer looks up that key and loads all the objects that’s CLSID is stored there. The browser initializes the object and asks it for a certain interface. Here, the BHO should implement IObjectWithSite interface. If that interface is found, Internet Explorer uses the methods provided to pass its IUnknown pointer down to the helper object
Through the IObjectWithSite interface’s SetSite method, the IWebBrowser2 pointer is obtained and stored in Queue. This pointer is used to navigate through the toolbar to the required websites.
This was dropped, as the whole process was tedious involving registering the object as Browser Helper Object and storing the pointer in a Queue.
Summary |
Band objects provide a flexible and powerful way to extend the capabilities of Internet Explorer. LoginSoft’s toolbar is a toolbar, which resides in the rebar control of the Internet Explorer and provides services like quick access to sites, mail settings, customizing toolbar buttons etc. It has links to LoginSoft home page along with its partner sites, few news sites and search option. The user can register and set the preferences. These preferences are used to render the toolbar elements. This toolbar is built using COM and windows programming.
References |
http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/Bands.asp
http://msdn.microsoft.com/library/en-us/dnmind99/html/cutting1199.asp
http://msdn.microsoft.com/library/en-us/dnctrl/html/msdn_rebar.asp
http://msdn.microsoft.com/library/en-us/vccore98/HTML/_core_rebar_controls_and_bands.asp
http://www.codeguru.com/ieprogram/bands.shtml
http://www.codeguru.com/ieprogram/CGBand.html
|