DEVTOME.COM HOSTING COSTS HAVE BEGUN TO EXCEED 115$ MONTHLY. THE ADMINISTRATION IS NO LONGER ABLE TO HANDLE THE COST WITHOUT ASSISTANCE DUE TO THE RISING COST. THIS HAS BEEN OCCURRING FOR ALMOST A YEAR, BUT WE HAVE BEEN HANDLING IT FROM OUR OWN POCKETS. HOWEVER, WITH LITERALLY NO DONATIONS FOR THE PAST 2+ YEARS IT HAS DEPLETED THE BUDGET IN SHORT ORDER WITH THE INCREASE IN ACTIVITY ON THE SITE IN THE PAST 6 MONTHS. OUR CPU USAGE HAS BECOME TOO HIGH TO REMAIN ON A REASONABLE COSTING PLAN THAT WE COULD MAINTAIN. IF YOU WOULD LIKE TO SUPPORT THE DEVTOME PROJECT AND KEEP THE SITE UP/ALIVE PLEASE DONATE (EVEN IF ITS A SATOSHI) TO OUR DEVCOIN 1M4PCuMXvpWX6LHPkBEf3LJ2z1boZv4EQa OR OUR BTC WALLET 16eqEcqfw4zHUh2znvMcmRzGVwCn7CJLxR TO ALLOW US TO AFFORD THE HOSTING.

THE DEVCOIN AND DEVTOME PROJECTS ARE BOTH VERY IMPORTANT TO THE COMMUNITY. PLEASE CONTRIBUTE TO ITS FURTHER SUCCESS FOR ANOTHER 5 OR MORE YEARS!

Programming Microsoft Word - 12 - Working with WPF

What are we going to do in this tutorial?

In the preceding tutorials, we worked on Visual Basic programs as a 'Windows Form' project. Microsoft is steadily moving ahead with support for devices other than regular PCs. Phones, tablets etc are increasingly important when it comes to deploying software and the use of WPF (Windows Presentation Foundation) is part of that. In the next series of tutorials, we are going to work on a WPF project instead of a Windows Form project. Some things are easier in WPF but others really require more of your hard work. In this tutorial, you will code a WPF program that starts from the tray, similar to the one from tutorial 3. The code is a bit different, but you will get used to that. This tray application will be the basis of the program. You will add several features later on. Let's get to work on the basic program: the tray application.

Step 1

Fire up Visual Studio (I am using Visual Community 2015 for this tutorial; it's a free download) and start a new project (Ctrl + N).

Add references to System.Windows.Forms.dll and System.Drawing.dll as follows: → go to the top menu and choose Project → Add reference

The search box (as indicated in the picture below) is a useful tool to find the relevant references. Add references to the two dll's as mentioned above. Be sure to check the box before the reference before clicking Ok in the 'Add reference' window.

Step 3

After adding the references, you can delete the Main Window. This file 'MainWindow.xaml' is visible in the Solution Explorer (see picture below). Delete it by right clicking it in the Solution Explorer and choose 'Delete'.

After that, the program needs to be told how to start. By default, your program points to the 'MainWindow.xaml' as startup. The particular line of code that points the program to starting with opening this windows is included in the xaml code of the Application.xaml file. Double click this file ' Application.xaml ' in the Solution Explorer to reveal the xaml code.

The following line of code tells your program to start with opening the MainWindow:

StartupUri="MainWindow.xaml" 

Change this as follows:

Startup="Tray_Loaded"

This changes two things: 1. Instead of pointing to a window with 'StartupUri', you point to a specific sub routine with the line 'Startup' 2. The startup routine will be the sub routine 'Tray Loaded' which will be a code written in Visual Basic.

Step 4

In the Solution Explorer, expand the 'Application.xaml' file so that the file 'Application.xaml.vb' becomes visible. Double clicking this file opens a code window in which you can type Visual Basic code.

Place the following code between 'Class Application' and 'End Class':

Private m_NotifyIcon As System.Windows.Forms.NotifyIcon
    Private m_ContextMenu As System.Windows.Controls.ContextMenu

    Private Sub Tray_Loaded(sender As System.Object, e As StartupEventArgs)

        m_NotifyIcon = New System.Windows.Forms.NotifyIcon()
        m_NotifyIcon.Icon = System.Drawing.SystemIcons.Information
        AddHandler m_NotifyIcon.MouseClick, AddressOf MyNotifyIcon_MouseClick
        m_NotifyIcon.Visible = True



        m_ContextMenu = New System.Windows.Controls.ContextMenu()
        m_ContextMenu.Items.Add("1")
        m_ContextMenu.Items.Add("2")
        m_ContextMenu.Items.Add("3")
    End Sub

    Private Sub MyNotifyIcon_MouseClick()
        m_ContextMenu.IsOpen = True
    End Sub

The code does the following: 1. the first two lines create two objects: your icon and a context menu. 2. the sub routine 'Tray_Loaded' is the routine that is used as startup routine. 3. the code in the 'Tray_Loaded' routine creates an instance of the icon object (a NotifyIcon) and attaches a standard icon graphic from Windows' own collection (the Information incon). 4. The 'Addhandler' creates a hook to catch a mouse click on the icon by the user. The icon is set as Visible so that the icon will be visible in the tray when the program is started. 5. the next lines create an instance of the m_ContextMenu object and add three items to this menu. 6. the sub routine 'MyNotifyIcon_MouseClick ' runs if the user clicks on the icon. Upon clicking the icon, the code of this subroutine ensures that the menu is shown.

This code is still very rudimentary. You will notice that the menu will not disappear if you click the mouse outside of the menu. This is non-intuitive behaviour that needs to be corrected somehow. Unfortunately, WPF does not have easy tricks to do this, so we settle for an quick and dirty solution here in the next step.

Step 5

Clicking the tray icon opens the menu. We want the user to be able to make the menu disappear if necessary. One option would be to add a menu item 'hide' and have appropriate code executed to hide the menu if the user selects this 'hide' menu item. Another quick and dirty method is enabling the user to have the menu disappear with a double click of the mouse. It's not ideal, but works sufficiently in practice.

in the Visual Basic code in 'Application.xaml.vb' in the Private Sub Tray_Loaded below the line 'AddHandler m_NotifyIcon.MouseClick, AddressOf …', add the following additional line of code:

AddHandler m_NotifyIcon.MouseDoubleClick, AddressOf MyNotifyIcon_MouseDoubleClick

Ignore the error that Visual Studio throws. This line of code is quite similar to the line of code directly above it. The difference is that this code looks for a double click of the mouse instead of a single click.

To make the solution work, add a new subroutine in the Visual Basic code:

Private Sub MyNotifyIcon_MouseDoubleClick()
        m_ContextMenu.IsOpen = False
    End Sub

This code runs if the user double clicks the icon: the menu will disappear. It is not an ideal solution, but sufficiently intuitive for a user to work with. Other solutions are quite technical and beyond the scope and level of this tutorial.

Step 6

The final step is to make the menu items operational. Something must happen (code must be executed) if a user clicks a menu item. This is done by adding so-called 'handlers' to the three menu items, which menu items are created by our current code.

To effect this, the way of adding menu items must be changed. Instead of adding items to the menu by adding times as a text (1,2 and 3), we are going to specify menu items as object, give those menu items names and headers and subsequently add these object to the context menu as menu items. By doing so, we create menu items that we can refer to, for instance when adding a 'handler' to such object.

Replace the following code with the subsequent block of code . code that must be replaced:

        m_ContextMenu = New System.Windows.Controls.ContextMenu()
        m_ContextMenu.Items.Add("1")
        m_ContextMenu.Items.Add("2")
        m_ContextMenu.Items.Add("3")

code that replaces code above

m_ContextMenu = New System.Windows.Controls.ContextMenu()

        Dim mySubMenu1 As New System.Windows.Controls.MenuItem
        mySubMenu1.Name = "Item_1"
        mySubMenu1.Header = "Item 1"

        Dim mySubMenu2 As New System.Windows.Controls.MenuItem
        mySubMenu2.Name = "Item_2"
        mySubMenu2.Header = "Item 2"

        Dim mySubMenu3 As New System.Windows.Controls.MenuItem
        mySubMenu3.Name = "Item_3"
        mySubMenu3.Header = "Item 3"

        m_ContextMenu.Items.Add(mySubMenu1)
        m_ContextMenu.Items.Add(mySubMenu2)
        m_ContextMenu.Items.Add(mySubMenu3)

        AddHandler(mySubMenu1.Click), AddressOf mySubMenu1_Click
        AddHandler(mySubMenu2.Click), AddressOf mySubMenu2_Click
        AddHandler(mySubMenu3.Click), AddressOf mySubMenu3_Click

The new code does the following: 1. the first line creates an instance of the m_ContextMenu object. 2. next, there are three blocks of code that each (i) create a menu item, (ii) give the menu item a name (note: the name cannot have spaces in it. Doing so will cause an error when running the program) and (iii) give the menu item a header (the text visible in the menu when the program runs). 3. consequently, all three menu items are added to the context menu. 4. the 'Addhandler' lines create a handler for each menu item added. The line specifies (in layman's terms) that when the menu item is clicked (referred to in the code with the name of the menu item ending with '.Click'), the sub routine specified should run (referred to in the code with the name of the menu item ending with '_Click').

To finalise this code, add three subroutines to the code as follows:

Private Sub mySubMenu1_Click()
        MessageBox.Show("You clicked Item 1")
End Sub


Private Sub mySubMenu2_Click()
        MessageBox.Show("You clicked Item 2")
End Sub

Private Sub mySubMenu3_Click()
        MessageBox.Show("You clicked Item 3")
End Sub

You will note that the name of the subroutines align to the 'AddressOf' naming as added to the code. The relevant of these subroutines fire when the relevant menu item is clicked. Instead of showing a message box with text, the action could also be showing a form with certain functionality in your program.

So there it is. Your tray context menu with working menu items:

For reference purposes, the entire code of the class is listed below:

Class Application

    ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
    ' can be handled in this file.

    Private m_NotifyIcon As System.Windows.Forms.NotifyIcon
    Private m_ContextMenu As System.Windows.Controls.ContextMenu


    Private Sub Tray_Loaded(sender As System.Object, e As StartupEventArgs)

        m_NotifyIcon = New System.Windows.Forms.NotifyIcon()
        m_NotifyIcon.Icon = System.Drawing.SystemIcons.Information

        AddHandler m_NotifyIcon.MouseClick, AddressOf MyNotifyIcon_MouseClick
        AddHandler m_NotifyIcon.MouseDoubleClick, AddressOf MyNotifyIcon_MouseDoubleClick

        m_NotifyIcon.Visible = True

        m_ContextMenu = New System.Windows.Controls.ContextMenu()

        Dim mySubMenu1 As New System.Windows.Controls.MenuItem
        mySubMenu1.Name = "Item_1"
        mySubMenu1.Header = "Item 1"

        Dim mySubMenu2 As New System.Windows.Controls.MenuItem
        mySubMenu2.Name = "Item_2"
        mySubMenu2.Header = "Item 2"

        Dim mySubMenu3 As New System.Windows.Controls.MenuItem
        mySubMenu3.Name = "Item_3"
        mySubMenu3.Header = "Item 3"

        m_ContextMenu.Items.Add(mySubMenu1)
        m_ContextMenu.Items.Add(mySubMenu2)
        m_ContextMenu.Items.Add(mySubMenu3)

        AddHandler(mySubMenu1.Click), AddressOf mySubMenu1_Click
        AddHandler(mySubMenu2.Click), AddressOf mySubMenu2_Click
        AddHandler(mySubMenu3.Click), AddressOf mySubMenu3_Click

    End Sub

    Private Sub mySubMenu1_Click()
        MessageBox.Show("You clicked Item 1")
    End Sub


    Private Sub mySubMenu2_Click()
        MessageBox.Show("You clicked Item 2")
    End Sub

    Private Sub mySubMenu3_Click()
        MessageBox.Show("You clicked Item 3")
    End Sub

    Private Sub MyNotifyIcon_MouseClick()
        m_ContextMenu.IsOpen = True

    End Sub

    Private Sub MyNotifyIcon_MouseDoubleClick()
        m_ContextMenu.IsOpen = False
    End Sub

End Class

Conclusion

In this tutorial, you created a tray context menu in WPF with items that fire an action when clicked upon. This is done purely in code instead of built-in functionality when working with WinForms. Of course, reality requires more flexibility in context menus, for instance by creating sub menus. Furthermore, creation of sizable menus (and sub menus) in code can be streamlined by building specific subroutines to that effect, avoiding copy/pasting similar blocks of code. These things will be explored in the next tutorial.

Computing A-Z | Programming | Software


QR Code
QR Code programming_microsoft_word_-_12_-_working_with_wpf (generated for current page)
 

Advertise with Anonymous Ads