PNRT
asked on
vb.net programming the Windows7 taskbar icons
Hi experts. Without using WPF or Windows-API-Code-Pack-1.1, can anyone please advise if it is possible to add right click commands to the VB programs icons on the taskbar? Sort of like the system tray but using the taskbar icons? If so please point me in the right direction for sample code. The only thing I can find is Windows-API-Code-Pack-1.1 which is unsupported and may not last past Windows 7. Many Thanks
ASKER
Hi - Thanks for the reply. Apologies and please correct me if I'm wrong but doesn't this just pin to the taskbar?
I was looking for the ability to add commands to the right click function of the icon in the taskbar
I was looking for the ability to add commands to the right click function of the icon in the taskbar
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Many thanks indeed, this is an excellent response. Just one thing. You mentioned the API Code pack. This looked perfect for what I needed but I was worried about the fact that it was not supported and that it seemed to be very Windows 7 oriented. What is your view on it? Would it be OK with Windows 8.1, Is it stable? I am mainly interested in Windows 7 and Windows 8
Many Thanks again for your help
Many Thanks again for your help
I'm not finding anywhere that indicates that the Windows API Pack is not supported. As for it's availability beyond Windows 7. Looking at the latest version of Windows (Windows 10), the GUI still supports the same functionality and features as Windows 7. Also, yes there is the Metro Interface on Windows 8/8.1 but that only accounts for a part of the user experience. The desktop still uses the same elements introduced in Windows 7.That being said, while you may design this for Windows 7 (and for the time being, 8, 8.1 and 10), this should not preclude you from considering the kernels that were used for Vista, XP, 2000 and 2003. You can essentially have your cake and eat it too.
Here is one method (using the SendMessage API to send a Registered Message based on the Code Project by Ahmed Said):
Here is one method (using the SendMessage API to send a Registered Message based on the Code Project by Ahmed Said):
1. Using the [url="https://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c
NuGet Package Manager extension[/url] I installed the WindowsAPIPack Core and Extensions."]2. Make your project a 'Single Instance' application.
3. Add the Native Methods for this example.
Add a class called 'NativeMethods.vb' to your project and place the following into the code file:Imports System.Runtime.InteropServices
Public Class NativeMethods
''' Define our Constants we will use
Public Const WM_SYSCOMMAND As Int32 = &H112
Public Const MF_SEPARATOR As Int32 = &H800
Public Const MF_BYPOSITION As Int32 = &H400
Public Const MF_STRING As Int32 = &H0
Public Const MF_SETTINGS As Int32 = 1000
Public Const MF_ABOUT As Int32 = 1001
<DllImport("user32.dll")> _
Public Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function GetSystemMenu(ByVal hWnd As IntPtr, ByVal bRevert As Boolean) As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function InsertMenu(ByVal hMenu As IntPtr, ByVal wPosition As Int32, ByVal wFlags As Int32, ByVal wIDNewItem As Int32, ByVal lpNewItem As String) As Boolean
End Function
<DllImport("user32.dll")> _
Public Shared Function RegisterWindowMessage(ByVal msgName As String) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
End Class
4. Create the Global settings for this example.
Add a module to your project named 'Globals.vb' and add the following to the code file:Imports Microsoft.WindowsAPICodePack.Shell
Imports Microsoft.WindowsAPICodePack.Taskbar
Imports System.IO
Module Globals
Public Property IsUsingStandardAPIMenu() As Boolean = False
Public Property Windows7APIMenu() As JumpList
Public ShowAboutArg As Integer = NativeMethods.RegisterWindowMessage("JumpList.ShowAboutArg")
Public ShowSettingsArg As Integer = NativeMethods.RegisterWindowMessage("JumpList.ShowSettingsArg")
Public Sub LoadStandardAPIMenu(ByVal Handle As IntPtr)
' Get the Handle for the Forms System Menu
Dim hMenu As IntPtr = NativeMethods.GetSystemMenu(Handle, False)
' Create our new System Menu items just before the Close menu item
NativeMethods.InsertMenu(hMenu, 5, NativeMethods.MF_BYPOSITION Or NativeMethods.MF_SEPARATOR, 0, String.Empty)
' <-- Add a menu seperator
NativeMethods.InsertMenu(hMenu, 6, NativeMethods.MF_BYPOSITION, NativeMethods.MF_SETTINGS, "Settings...")
NativeMethods.InsertMenu(hMenu, 7, NativeMethods.MF_BYPOSITION, NativeMethods.MF_ABOUT, "About...")
IsUsingStandardAPIMenu = True
End Sub
Public Sub LoadWindows7APIMenu(ByVal Handle As IntPtr)
Dim list As JumpList = JumpList.CreateJumpListForIndividualWindow(TaskbarManager.Instance.ApplicationId, Handle)
Dim current As FileInfo = New FileInfo(Application.ExecutablePath())
list.ClearAllUserTasks()
list.AddCustomCategories(New JumpListCustomCategory("Actions"))
list.AddUserTasks(New JumpListLink(current.FullName, "Settings...") With {.Arguments = String.Format("Handle={0}|Command={1}", Handle, ShowSettingsArg), .IconReference = New IconReference(current.FullName, 0)})
list.AddUserTasks(New JumpListLink(current.FullName, "About...") With {.Arguments = String.Format("Handle={0}|Command={1}", Handle, ShowAboutArg), .IconReference = New IconReference(current.FullName, 0)})
list.AddUserTasks(New JumpListSeparator())
list.Refresh()
Windows7APIMenu = list
End Sub
Public Function RegisterMessage(ByVal MessageName As String) As Integer
Return NativeMethods.RegisterWindowMessage(MessageName)
End Function
Public Sub SendMessage(ByVal Handle As IntPtr, ByVal MessageID As Integer)
SendMessage(Handle, MessageID, IntPtr.Zero, IntPtr.Zero)
End Sub
Public Function SendMessage(ByVal Handle As IntPtr, ByVal MessageID As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean
Dim result As Long = NativeMethods.SendMessage(Handle, MessageID, wParam, lParam)
Return result = 0
End Function
End Module
5. Setup the main form to create the menu and overload the WndProc method.
Add the following to your main form code file (generally Form1.vb): Private Sub OnLoad(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
If Environment.OSVersion.Platform = PlatformID.Win32NT Then
If Environment.OSVersion.Version.Major < 6 Then
LoadStandardAPIMenu(Handle)
ElseIf Environment.OSVersion.Version.Major >= 6 Then
If Environment.OSVersion.Version.Minor < 1 Then
LoadStandardAPIMenu(Handle)
ElseIf Environment.OSVersion.Version.Minor >= 1 Then
LoadWindows7APIMenu(Handle)
End If
End If
End If
End Sub
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
If IsUsingStandardAPIMenu Then
' Check if a System Command has been executed
If m.Msg = NativeMethods.WM_SYSCOMMAND Then
' Execute the appropriate code for the System Menu item that was clicked
Select Case m.WParam.ToInt32()
Case NativeMethods.MF_SETTINGS
MessageBox.Show("Settings menu was clicked")
Exit Select
Case NativeMethods.MF_ABOUT
MessageBox.Show("About menu was clicked")
Exit Select
End Select
End If
Else
If m.Msg = ShowSettingsArg Then
MessageBox.Show("Settings task list menu was clicked")
ElseIf m.Msg = ShowAboutArg Then
MessageBox.Show("About task list menu was clicked")
End If
End If
MyBase.WndProc(m)
End Sub
6. Handle your Application events for Startup and StartupNextInstance.
In the ApplicationEvents.vb add the following code: Public Sub OnStartup(ByVal sender As Object, ByVal e As StartupEventArgs) Handles Me.Startup
For Each arg As String In e.CommandLine
If arg.ToUpper().Contains("HANDLE=") Then
Dim message = arg.ToUpper().Split(New String() {"|"c}, StringSplitOptions.RemoveEmptyEntries).Select(Function(pairs) pairs.Split("="c)).ToDictionary(Function(key) key(0).ToUpper(), Function(val) If(val.Length = 1, String.Empty, val(1)))
Dim handle As Integer = -1
Dim command As Integer = -1
If Not message.TryGetValue("HANDLE", handle) Then handle = -1
If Not message.TryGetValue("COMMAND", command) Then command = -1
If handle <> -1 AndAlso command <> -1 Then
SendMessage(handle, command)
End If
End If
Next
End Sub
Public Sub OnStartupNextInstance(ByVal sender As Object, ByVal e As StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
e.BringToForeground = True
For Each arg As String In e.CommandLine
If arg.ToUpper().Contains("HANDLE=") Then
Dim message = arg.ToUpper().Split(New String() {"|"c}, StringSplitOptions.RemoveEmptyEntries).Select(Function(pairs) pairs.Split("="c)).ToDictionary(Function(key) key(0).ToUpper(), Function(val) If(val.Length = 1, String.Empty, val(1)))
Dim handle As Integer = -1
Dim command As Integer = -1
If Not message.TryGetValue("HANDLE", handle) Then handle = -1
If Not message.TryGetValue("COMMAND", command) Then command = -1
If handle <> -1 AndAlso command <> -1 Then
SendMessage(handle, command)
End If
End If
Next
End Sub
If done correctly, when you run the application on a Windows Vista or lower computer, you should see the standard menu as presented in the examples above. Running on Windows 7/8/8.1/10 should give you the following:Clicking on either the Settings or About task list item should give you a message box:Proof of Concept on Windows 8.1:Proof of Concept on Windows 2003:-saige-
ASKER
Many thanks for you help. Have closed the question and awarded the points (I should have been able to give you double for the excellent answer), but I just wondered if this is the same API Code pack that you were referring to?
http://channel9.msdn.com/coding4fun/articles/Coding-4-Fun-Windows-7-Taskbar
I ask only because there are many articles stating that this has been retired and is no longer supported
http://archive.msdn.microsoft.com/
http://channel9.msdn.com/coding4fun/articles/Coding-4-Fun-Windows-7-Taskbar
I ask only because there are many articles stating that this has been retired and is no longer supported
http://archive.msdn.microsoft.com/
Open in new window
vbs code though\
but you may be a starting point