Tutorial: Creating a desktop band object
Language: VB.Net 03, 05
Level: Advanced
Step 1: The very first thing that we must do when creating a deskband object is to get some API stuff out of the way. Below is a list of API commands and there enum/structures.
Lets put all of the following in a module named modSidebar.vb.
- Code: Select all
Module modSidebar
SHAppBarMessage
- Used to send a message to register a bar
- Code: Select all
Public Declare Function SHAppBarMessage Lib "shell32.dll" Alias _
"SHAppBarMessage" ( _
ByVal dwMessage As Integer, _
ByRef pData As APPBARDATA) As System.UInt32
MoveWindow
- Used to move windows or placement on desktop
- Code: Select all
Public Declare Function MoveWindow Lib "User32.dll" Alias _
"MoveWindow" ( _
ByVal hWnd As IntPtr, _
ByVal x As Integer, _
ByVal y As Integer, _
ByVal cx As Integer, _
ByVal cy As Integer, _
ByVal repaint As Boolean) As Boolean
RegisterWindow
- Used to register a window with Windows
- Code: Select all
Public Declare Auto Function RegisterWindowMessage Lib _
"User32.dll" ( _
ByVal msg As String) As Integer
FindWindow
- Used to find a window that has been registered
- Code: Select all
Public Declare Function FindWindowA Lib "user32" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
SetWindowPos
- Used to set the position of the registered window
- Code: Select all
Public Declare Function SetWindowPos Lib "user32" ( _
ByVal hwnd As Integer, _
ByVal hWndInsertAfter As Integer, _
ByVal x As Integer, _
ByVal y As Integer, _
ByVal cx As Integer, _
ByVal cy As Integer, _
ByVal wFlags As Integer) As Integer
And now lets define our structures.
APPBARDATA
- This is where the information for the bar is created/stored
- Code: Select all
Structure APPBARDATA
Public cbSize As Integer
Public hWnd As IntPtr
Public uCallbackMessage As Integer
Public uEdge As Integer
Public rc As RECT
Public lParam As IntPtr
End Structure
RECT
- This is basically a structure for drawing
- Code: Select all
Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
End Structure
Now lets move on to enumerations.
ABMsg
- This is used to send a specific message on what type of bar we want.
- Code: Select all
Enum ABMsg
ABM_NEW = 0
ABM_REMOVE = 1
ABM_QUERYPOS = 2
ABM_SETPOS = 3
ABM_GETSTATE = 4
ABM_GETTASKBARPOS = 5
ABM_ACTIVATE = 6
ABM_GETAUTOHIDEBAR = 7
ABM_SETAUTOHIDEBAR = 8
ABM_WINDOWPOSCHANGED = 9
ABM_SETSTATE = 10
End Enum
ABNotify
- Used to send a message to a window
- Code: Select all
Enum ABNotify
ABN_STATECHANGE = 0
ABN_POSCHANGED = 1
ABN_FULLSCREENAPP = 2
ABN_WINDOWARRANGE = 3
End Enum
ABEdge
- This is used to say where we want the bar docked
- Code: Select all
Enum ABEdge
ABE_LEFT = 0
ABE_TOP = 1
ABE_RIGHT = 2
ABE_BOTTOM = 3
End Enum
Now lets setup some variables
- Code: Select all
Public fBarRegistered As Boolean = False
Public uCallBack As Integer
Now end the module.
- Code: Select all
End Module
Note: The rest of this information goes into Form1 or whatever your main form name is called. Also, you need to import the following.
- Code: Select all
Imports System.Runtime.InteropServices
Step 2: Now that we have our module setup we need to go into our main form and do some extra steps to make sure that we are able to receive window messages.
So the first thing we are going to do here is to do whats called subclassing. Here we are going to subclass window messages with a function called WndProc.
WndProc
- Used to catch window messages
- Code: Select all
Protected Overloads Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = uCallBack Then
Select Case m.WParam.ToInt32
Case CType(ABNotify.ABN_POSCHANGED, Integer)
ABSetPos()
' break
End Select
End If
Try
MyBase.WndProc(m)
Catch ex As Exception
'
End Try
End Sub
Step 3: After we have our message function setup we now need to create a param option for making sure our form is displayed properly.
CreateParams
- Used to setup the display of our form.
- Code: Select all
Protected Overloads Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.Style = cp.Style And ((Not 12582912))
cp.Style = cp.Style And ((Not 8388608))
cp.ExStyle = 128 Or 8
Return cp
End Get
End Property
Step 4: Okay. Now that we have those setup next we need to get into the nitty gritty of our code. The next sub procedure we are going to make is ABSetPos which actually does all of the work for us.
ABSetPos
- Docks/Registers our bar
- Code: Select all
Private Sub ABSetPos()
Dim abd As APPBARDATA = New APPBARDATA
abd.cbSize = Marshal.SizeOf(abd)
abd.hWnd = Me.Handle
abd.uEdge = CType(ABEdge.ABE_TOP, Integer)
If abd.uEdge = CType(ABEdge.ABE_LEFT, Integer) OrElse abd.uEdge = CType(ABEdge.ABE_RIGHT, Integer) Then
abd.rc.top = 0
abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height
If abd.uEdge = CType(ABEdge.ABE_LEFT, Integer) Then
abd.rc.left = 0
abd.rc.right = Size.Width
Else
abd.rc.right = SystemInformation.PrimaryMonitorSize.Width
abd.rc.left = abd.rc.right - Size.Width
End If
Else
abd.rc.left = 0
abd.rc.right = SystemInformation.PrimaryMonitorSize.Width
If abd.uEdge = CType(ABEdge.ABE_TOP, Integer) Then
abd.rc.top = 0
abd.rc.bottom = Size.Height
Else
abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height
abd.rc.top = abd.rc.bottom - Size.Height
End If
End If
SHAppBarMessage(CType(ABMsg.ABM_QUERYPOS, Integer), abd)
Select Case abd.uEdge
Case CType(ABEdge.ABE_LEFT, Integer)
abd.rc.right = abd.rc.left + Size.Width
' break
Case CType(ABEdge.ABE_RIGHT, Integer)
abd.rc.left = abd.rc.right - Size.Width
' break
Case CType(ABEdge.ABE_TOP, Integer)
abd.rc.bottom = abd.rc.top + Size.Height
' break
Case CType(ABEdge.ABE_BOTTOM, Integer)
abd.rc.top = abd.rc.bottom - Size.Height
' break
End Select
SHAppBarMessage(CType(ABMsg.ABM_SETPOS, Integer), abd)
MoveWindow(abd.hWnd, abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, True)
End Sub
Step 5: Now that we have our main code we need to setup a procedure for checking to see if our bar is registered or not. To do this we simply create another sub procedure. RegisterBar simply does the work for us to see if the bar needs to be registered or unregistered.
Registerbar
- Used to register/unregister our bar
- Code: Select all
Private Sub RegisterBar()
Dim abd As APPBARDATA = New APPBARDATA
abd.cbSize = Marshal.SizeOf(abd)
abd.hWnd = Me.Handle
If Not fBarRegistered Then
uCallBack = RegisterWindowMessage("MyDesktopBar")
abd.uCallbackMessage = uCallBack
Dim ret As System.UInt32 = SHAppBarMessage(CType(ABMsg.ABM_NEW, Integer), abd)
fBarRegistered = True
ABSetPos()
Else
SHAppBarMessage(CType(ABMsg.ABM_REMOVE, Integer), abd)
fBarRegistered = False
End If
End Sub
Step 6: So now you are done coding the features and now we can put them to use. To do this we simply call registerbar() in our form load event and registerbar() again in our button close event.
So on your form go a head and create a button. Doesn't matter the name but for this reason I am going to leave it Button1.
- Code: Select all
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
RegisterBar()
Me.Close()
End Sub
- Code: Select all
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
RegisterBar()
End Sub
Now you are done.
Run your application and watch it register.
Well, if you have any problems with this or would actually like a breakdown of something that you found here please just post here and I will reply. And as always Happy Coding.
Jason

If you need help with it let me know.