Corrected Demonstration projects
Added note about IDE error when undocking
vbAccelerator Office Docking Bar Control
Office XP style docking support for toolbars and controls
This control provides a new container for the vbAccelerator Toolbar and CoolMenu control which allows controls to be docked and undocked to the side of any form. It emulates the style of the Office XP toolbars and provides full support for saving and restoring the layout of the toolbars. It can also be used as a more flexible alternative to the Rebar control.
Before You Start
The demonstration project requires that you have the following controls installed and registered on your computer. The Toolbar and Popup Menu must be the versions posted 23rd April 2003 or later:
About the Office Docking Bar Control
The docking bar control is an alignable control which can be sited on any edge of a form. Once sited, you can specify if the control has a non-docking area (which can be used, for example, to hold a status bar at the bottom of a form) and then you can start adding bars to the control. Each bar can contain as single captured child-window, which would normally be a toolbar (although any control with a hWnd property can be added).
The docking bar can be locked so that none of the child windows can be rearranged or undocked by the user. This is the same as the "Lock Toolbars" mode offered by Explorer under Windows XP. It can also be set so bars cannot be undocked, in which case it operates in a similar way to a Rebar control.
For each bar that's added, you specify its correct size when docked horizontally and vertically and a key to identify the bar. Optionally, you can determine whether the bar should be added to an existing row or whether it should be inserted at the beginning or the end. You can also configure whether the bar should always fill an entire row, whether it can be closed when undocked, and whether it cannot be docked horizontally or vertically.
Once the initial configuration of bars has been created, you can Save the current layout and restore it back again at any time. This allows you to persist the state of the bars when your application shuts down and to restore them to exactly the same positions when the application is restarted.
The Control and The IDE
For reasons which I do not understand, you can only perform undocking once your application has been compiled into an executable. If you try to undock a toolbar whilst you are running in the IDE, you will get this error followed by a nasty crash:
There is no workaround for this at the moment. Just don't undock any toolbars in the IDE!
Using the Office Docking Bar Control
Using the docking bar control is fairly simple as you'll see from the demonstration, however, this article provides a detailed view of what's going on to provide a fuller understanding of how to configure your own application with the control.
There are six areas to cover:
1. Configuring the Docking Controls
The first thing to do to use the control is to add a docking container to each side of the form you want to allow docking on. Note that if you don't set the Align property of the control, it will not work properly - this is only an issue for SDI forms, since on an MDI form the control will automatically align itself.
Once you have a docking control at each edge you want to allow docking, consider whether you want to have a non-docking area in each. The non-docking area is a space closest to the edge of the window into which you can place other controls. An example of using the non-docking area is for a status bar at the bottom of a form. Obviously you can align a normal status bar to the bottom of the form separately, but it is difficult in VB to determine which order controls aligned to the edges of a form appear in. To set the non-docking area, set the NonDockingArea property of the control to True and then specify the NonDockingAreaSize in pixels. Once you've set this, you can drop any control onto the docking control to show in the non-docking area.
You can now determine if you want the control to draw in the Office XP style (the default) or using the older border style by setting the OfficeXpStyle property.
Now you are ready to add some bars to the docking container.
2. Adding Bars
Adding bars is achieved using the Add and Capture methods. The Add method creates a new bar, whilst the Capture method associates a child window with the bar. The Add method has a number of parameters so these will be covered here.
Once you've added a bar, you can specify the control to be added to it. The Capture method takes the Key to a bar and the window handle (hWnd) of the control to be captured into the bar.
3. Specifying the cXAHorz, cYAHorz, cYAVert and cYAHorz Parameters for Toolbars
When adding toolbars to the control, there are two ways to specify these parameters, depending on whether the toolbar contains a control that can be stretched (such as a combo box) or not. If the toolbar can't be stretched, then this code is used:
ctlDock.Add _ "MYTOOLBAR", _ tbrStandard.ToolbarWidth, tbrStandard.ToolbarHeight, _ getVerticalHeight(tbrStandard), getVerticalWidth(tbrStandard)
Where the getVerticalHeight and getVerticalWidth functions are the ones provided in the demonstration:
Private Function getVerticalHeight(tbrThis As cToolbar) As Long Dim l As Long Dim lHeight As Long Dim lMaxWidth As Long Dim lRowHeight As Long Dim lRowWidth As Long lMaxWidth = getVerticalWidth(tbrThis) For l = 0 To tbrThis.ButtonCount - 1 If tbrThis.ButtonVisible(l) Then If tbrThis.ButtonControl(l) = 0 Then If tbrThis.ButtonStyle(l) = CTBSeparator Then ' we'll start a new row for the next one lHeight = lHeight + lRowHeight lRowHeight = 0 lRowWidth = 0 Else If (lRowWidth + tbrThis.ButtonWidth(l) > lMaxWidth) Then ' This button needs to go on a new row: lHeight = lHeight + lRowHeight lRowHeight = 0 lRowWidth = lRowWidth + tbrThis.ButtonWidth(l) If (tbrThis.ButtonHeight(l) > lRowHeight) Then lRowHeight = tbrThis.ButtonHeight(l) End If Else ' This button goes on this row: If (tbrThis.ButtonHeight(l) > lRowHeight) Then lRowHeight = tbrThis.ButtonHeight(l) End If lRowWidth = lRowWidth + tbrThis.ButtonWidth(l) End If End If End If End If Next l lHeight = lHeight + lRowHeight getVerticalHeight = lHeight End Function Private Function getVerticalWidth(tbrThis As cToolbar) As Long Dim l As Long Dim lMaxWidth As Long For l = 0 To tbrThis.ButtonCount - 1 If tbrThis.ButtonVisible(l) Then If tbrThis.ButtonControl(l) = 0 Then If (tbrThis.ButtonWidth(l) > lMaxWidth) Then lMaxWidth = tbrThis.ButtonWidth(l) End If End If End If Next l getVerticalWidth = lMaxWidth End Function
Note that toolbar buttons containing controls such as Combo Boxes are hidden when the toolbar is docked vertically, like the Office XP docking toolbars.
3. Responding to Events from the Docking Container
Once you've added the bars, you can start responding to events from the dock container. There are five events; the ChevronPress event is the one you are most likely to want to respond to.
4. Saving and Restoring Layouts
Saving and restoring a layout associated with any docking bar is achieved using XML. The Microsoft MSXML 3 parser (supplied with IE5.5 and above, downloadable otherwise) is used for XML serialisation and deserialisation.
To persist a layout to XML, you use the SaveLayout function of the docking bar control. This returns an XML string containing all the information needed to restore the layout of a bar. (Note: you should not modify the contents of this XML stream in any way since it represents the entire internal state of the control. Making changes to any of the data may have unpredictable results). If you have more than one docking bar control, you can place the results of more than SaveLayout call into the same XML document. Here is a code snippet from the demonstration which shows how to save the state of all the docking bars in the form and persist it to a file:
Dim sMsg As String Dim ctl As Control Dim ctlDock As vbalDockContainer ' Get the XML: sMsg = "<Layout>" For Each ctl In Me.Controls If TypeName(ctl) = "vbalDockContainer" Then Set ctlDock = ctl sMsg = sMsg & vbCrLf & ctlDock.SaveLayout() End If Next sMsg = sMsg & vbCrLf & "</Layout>" ' Persist to a file Dim sFile As String sFile = App.Path & "\layout.xml" On Error Resume Next Kill sFile On Error GoTo errorHandler Dim iFile As Integer iFile = FreeFile Open sFile For Binary Access Write As #iFile Put #iFile, , sMsg Close #iFile
To restore a layout, you essentially reverse the process by reading a previously stored XML layout and asking each dock control to restore itself using the RestoreLayout method. This method will take any XML string and search for the correct sub-tag to restore from.
The main difference is that you must also tell the docking controls about the toolbars and controls which should be captured into the new layout. To do this you pass in two arrays. The first array contains the keys which identify the bars, and the second contains the window handles to the toolbar or control you want to capture into the bar for each key. The two arrays must have exactly the same dimensions.
Here's a snippet of code from the demonstration project for restoring the layout from a previously saved file:
' Read the saved XML Layout: Dim sFile As String sFile = App.Path & "\layout.xml" Dim iFile As Integer iFile = FreeFile Open sFile For Binary Access Read As #iFile Dim sXml As String sXml = String(LOF(iFile), " ") Get #iFile, , sXml Close #iFile ' Set up an array of Keys and their associated ' window handles: ReDim sKey(1 To 6) As String Dim hwnd(1 To 6) As Long sKey(1) = "MENU": hwnd(1) = tbrMenu.hwnd sKey(2) = "STANDARD": hwnd(2) = tbrStandard.hwnd sKey(3) = "UTILITY": hwnd(3) = tbrAddress.hwnd sKey(4) = "DRAWING": hwnd(4) = 0 sKey(5) = "TABLES": hwnd(5) = 0 sKey(6) = "HELP": hwnd(6) = 0 ' Restore the layout on every docking container ' on the form: Dim ctl As Control Dim ctlDock As vbalDockContainer For Each ctl In Me.Controls If TypeName(ctl) = "vbalDockContainer" Then Set ctlDock = ctl ctlDock.RestoreLayout sXml, sKey(), hwnd() End If Next
5. Other Properties and Methods
There are a number of methods to adjust bars and their positions as well as properties you can use to examine the state of the docking controls.
6. MDI and SDI Considerations
The control can be used in either MDI or SDI applications. However, note the following:
There are a few things missing from this version of the control which are under research for the next release. These do not prevent the control from being usable in its current state. A .NET version is also under preparation.
The Office Docking Bar control provides you with a way to create an Office XP/Visual Studio.NET style interface using the existing Toolbar and CoolMenu controls. The interface is similar to the Office XP one with only some minor omissions. I've been using this control in a reasonably large project for two or three months without problems.