I need a toolbar to act like an Office Toolbar. How do I make a form resize and snap to the respective screen border as it moves outside of the bounds of the screen. I also need to relocate the buttons on the toolbar.
You would think this would be a simple task, and althought it is not rocket science, it does require some tricky code. If you do not get the code just right, you will get more "flash for the audience" than you want. For this reason, you will see a "Busy" flag being set that keeps the flash from happening. The Mosue_Move event will be firing so rapidily that you must protect the code that is moving the toolbar while it is in control. For this reason, if the truth were known, the Busy flag is causing me to ignore most of the Mouse_Move events. However, that will not be noticeable in the operation of moving the toolbar. This article will show you how to make a user designed toolbar automatically resize from a vertical to a horizontal position, relocate all of its tool buttons, and snap to the screen border as the toolbar is moved outside the bounds of the screen on any border.
First, you need to build a form like the one shown in Figure 1. The number of buttons is up to you. However they should all be the same size, including the lblMove Label, which has the move icon on it. The user must click on that control to move the form. Set the FormBorderStyle property to SizableToolWindow. If you use any one of the others, either it will not look good or it will not be able to be sized as narrow as I want it to be for a vertical toolbar.
Figure 1 - Docking Toolbar.

There are several sections of code that I will reproduce in the article so that you have all of the code, except for the Window Designer Code.
The declarations section of the form must have the variables shown below. I use the Enums so that I can get Intellisense and make the code more readable.
| Private formLoading As Boolean = True Private XPos As Long Private YPos As Long Private busy As Boolean Private vWidth As Single = 32 Private vHeight As Integer = 160 Private hWidth As Integer = 160 Private hHeight As Integer = 32 Private btnHeight As Integer = 25 Private btnWidth As Integer = 25 Private currDockStyle As Short Private Enum DockPosition Top Bottom Left Right End Enum Private Enum DockStyle NotSet Vertical Horizontal End Enum |
| Private Sub Form1_Resize(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Resize ' since only a few border styles will support a form as ' narrow as this one and sizable tool window is the best ' style to use, we must have a resize event in case the user ' has nothing else to do but to try to make the form look ' cruddy by resizing it, we force the size here... If currDockStyle = DockStyle.NotSet Then Exit Sub ElseIf currDockStyle = DockStyle.Vertical Then Me.Height = vHeight Me.Width = vWidth Else Me.Height = hHeight Me.Width = hWidth End If End Sub Private Sub Button4_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button4.Click Me.Dispose() End Sub Private Sub lblMove_MouseDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles lblMove.MouseDown XPos = e.X YPos = e.Y End Sub Private Sub lblMove_MouseMove(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles lblMove.MouseMove Dim computedLeft As Single = Me.Left Dim computedTop As Single = Me.Top Dim computedRight As Single = (Me.Left + Me.Width) Dim computedBottom As Single = (Me.Top + Me.Height) If e.Button = MouseButtons.Left Then If busy Then Exit Sub busy = True computedLeft = computedLeft - (XPos - e.X) computedTop = computedTop - (YPos - e.Y) computedRight = computedRight - (XPos - e.X) computedBottom = computedBottom - (YPos - e.Y) If computedLeft >= 1 And _ computedRight <= _<BR> Screen.PrimaryScreen.Bounds.Width - 1 Then Me.Left = Me.Left - (XPos - e.X) Else If Not computedLeft >= 1 Then DockToolBar(DockPosition.Left) Else DockToolBar(DockPosition.Right) End If busy = True Exit Sub End If If computedTop >= 1 And _ computedBottom <= _<BR> Screen.PrimaryScreen.Bounds.Height - 1 Then Me.Top = Me.Top - (YPos - e.Y) Else If Not computedTop >= 1 Then DockToolBar(DockPosition.Top) Else DockToolBar(DockPosition.Bottom) End If busy = True Exit Sub End If busy = False End If End Sub Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load currDockStyle = DockStyle.Horizontal End Sub Private Sub lblMove_MouseUp(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles lblMove.MouseUp busy = False End Sub |
| Private Sub DockToolBar(ByVal DockTo As DockPosition) Dim c As Control Dim s As Single = 0 Dim i As Integer = 0 With Me Dim pt As New System.Drawing.Point(Me.Left, Me.Top) Select Case DockTo Case DockPosition.Top, DockPosition.Bottom Me.currDockStyle = DockStyle.Horizontal ' make the toolbar a horizontal bar .Width = hWidth .Height = hHeight ' relocate all controls except the move label For Each c In Controls If Not c Is lblMove Then c.Top = 0 c.Left = (i * (btnWidth + 5)) i += 1 DoEvents() End If Next Me.lblMove.Left = Me.Width - (25 + 5) .lblMove.Top = 0 DoEvents() ' honor the taskbar if not auto hidden If DockTo = DockPosition.Top Then .Top = 1 Else .Top = Screen.PrimaryScreen.GetWorkingArea(pt).Height - _ (.Height + 1) End If .Left = Math.Min(.Left, _ Screen.PrimaryScreen.GetWorkingArea(pt).Width - _ (.Width + 1)) Case DockPosition.Left, DockPosition.Right currDockStyle = DockStyle.Vertical ' redraw the form as vertical toolbar .Width = vWidth .Height = vHeight ' relocate all of the controls except the move label For Each c In Controls If Not c Is lblMove Then c.Left = 0 c.Top = (i * (btnHeight + 5)) i += 1 DoEvents() End If Next ' relocate the move label .lblMove.Left = 0 .lblMove.Top = .Height - (25 + 5) ' this code honors any on top task bar if not auto hidden If DockTo = DockPosition.Left Then .Left = 1 Else .Left = Screen.PrimaryScreen.GetWorkingArea(pt).Width - _ (.Width + 1) End If .Top = Math.Min(.Top, _ Screen.PrimaryScreen.GetWorkingArea(pt).Height - _ (.Height + 1)) End Select End With End Sub |

