Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Wobbly Menu - An Inspiration from iPhone

4.87/5 (33 votes)
17 Mar 2010CPOL3 min read 1   2.5K  
iPhone like menu system and wobbly re-arrangement technique with a useful sample application

Introduction

When Windows 7 was announced, some years ago, I was expecting a total revamp of the menu system which Microsoft introduced with Windows 95. But to my disappointment, it hasn't changed anything drastically. But multi-touch enabled OS was my idea (I've seen people saying so many weird things as their idea in the Win 7 TV ads, so I wanted to call this as mine.) On the other hand, I was inspired by the iPhone’s UI which is really designed in a finger friendly manner and I though I should implement something like that for Windows too. As a result, this simple application came into reality.

Screen.jpg

What is it?

This is a control that creates buttons for each item added to the menu items collection and sets the buttons to semi transparent. When the mouse is hovered over, the button 'slowly' becomes fully visible and goes back to semi transparent when the mouse moves out.

It also let you re-arrange the buttons. When the title bar is double clicked, the buttons start wobbling and the user can drag-drop and re-arrange the order.

What is this Sample?

The sample what I have given here is a very simple one which allows the users to drag and drop any files from a Windows folder into the title bar and the application creates a shortcut for each file you dropped. It extracts the icons and file names to create the button and then when the button is clicked, it will launch the file in its registered application.

What Techniques Have I Used?

A number of simple techniques have been used here to achieve all these functionalities.

Dimmable Button Array

To my knowledge, none of the Windows Form controls other than Form object support the opacity property which allows setting transparency levels. Therefore, I have created an array of forms like buttons.

VB.NET
Private Sub MoveChildForms()
    Dim iY As Integer = Me.Bottom + m_DimmableMenu.Spacing
    Dim iX As Integer = Me.Left
    For Each oMenu As frmMenu In ChildMenus.Values
        'positioning the menu item form.
        oMenu.SetPosition(New Point(iX, iY))

        'setting the size of title bar
        Me.MaximumSize = New Size((iX - Me.Left) + m_DimmableMenu.ItemSize.Width, 20)
        Me.Size = Me.MaximumSize
        Me.MinimumSize = Me.MaximumSize

        'incrementing the y position first, and then x
        If iY < (Me.Top + m_DimmableMenu.Size.Height) Then
            iY = oMenu.Bottom + m_DimmableMenu.Spacing
        Else
            iY = Me.Bottom + m_DimmableMenu.Spacing
            iX = oMenu.Right + m_DimmableMenu.Spacing
        End If

        'animating?
        If oMenu.m_iAnimationId = 1 Then
            oMenu.StartAnimation()
        End If
    Next
    Dim r As Rectangle = Me.RectangleToScreen(Me.ClientRectangle)
    m_DimmableMenu.UpdateRect(r.X, r.Y, Me.Width, iY - Me.Top)
End Sub

Wobbly Buttons

When the title bar is double clicked, the buttons become wobbly. I've been wondering how to make this. But this is the simplest of all.

VB
'Set location, with a random variant to the original position.
'm_InitPos is the Initial Original Position of the Button
'm_oRnd is an Random Number generator
Me.Location = New Point(m_InitPos.X + m_oRnd.Next(-2, 2), _
	m_InitPos.Y + m_oRnd.Next(-2, 2))

Curvy Buttons

I wanted to make the buttons look like the iPhone buttons with the curvy corners. A simple geometry helped me in achieving this.

VB.NET
''' <summary>
''' Creates a Graphics Path with a rounded corner
''' </summary>
''' <param name="r">Rectangle region</param>
''' <param name="d">The rounded corner diameter</param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function GetRoundedRectanglePath(ByVal r As Rectangle, _
            ByVal d As Integer) As GraphicsPath
    Dim gp As New GraphicsPath()
    gp.AddArc(r.X, r.Y, d, d, 180, 90)
    gp.AddArc(r.X + r.Width - d, r.Y, d, d, 270, 90)
    gp.AddArc(r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90)
    gp.AddArc(r.X, r.Y + r.Height - d, d, d, 90, 90)
    gp.AddLine(r.X, r.Y + r.Height - d, r.X, CInt(r.Y + d / 2))
    gp.CloseFigure()
    Return gp
End Function

Registered File Icon Extraction

In my sample application, I am creating button with icons. This is an interesting thing I found. I always wanted to know how the registered icon for file extension can be extracted without making horrendous Windows API calls. Finally, I found a simple functionality in the .NET Framework's Icon class itself.

Public Shared Function ExtractAssociatedIcon(ByVal filePath As String) _
	As System.Drawing.Icon
Member of: System.Drawing.Icon
Summary:
Returns an icon representation of an image contained in the specified file.

Parameters:
filePath: The path to the file that contains an image.

Return Values:
The System.Drawing.Icon representation of the image contained in the specified file.

Exceptions:
System.ArgumentException: filePath does not indicate a 
valid file.-or-filePath indicates a Universal Naming Convention (UNC) path. 

How You Can Use It?

I've developed this on my own interest and it is free to be used by anyone for their personal use. But I think it is reasonable to expect a cut for myself, if anyone is trying to use this for commercial purposes.

As I mentioned earlier, I've created this as a control so that it can be re-used for different purposes. The following 2 images show 2 simple applications.

horizontal.jpg

An example shows how to create buttons with default settings.

MultiColor.jpg

An example shows how to create colourful buttons.

What's Next?

  1. Download the code and compile the WobblyMenu.Control project
  2. Create a new project and add reference to WobblyMenu.Control assembly
  3. Create an instance to:
    VB.NET
    WobblyMenu.Control.DimmableMenu
  4. [Optional] Set the maximum size of your work area
    VB.NET
    [control].Size = New Size(width, height)
  5. [Optional] Set the button size:
    VB.NET
    [control].ItemSize = New Size(width, height)
  6. Add menu items and assign them to
    VB.NET
    WobblyMenu.Control.MenuItem
    Dim WobblyMenu.Control.MenuItem Instance = _
    	[control] .MenuItems.AddMenuItem(Text, Image)
  7. Add menu items and assign them to
    VB.NET
    AddHandler [menuitem].OnClick, AddressOf ItemClickHandler
  8. [Optional] Handle OnClose event
    VB.NET
    [control].OnClose, AddressOf CloseEventHandler
  9. Display the menu
    VB.NET
    [control].Show()

I found this control very useful and I am using this in many different applications. I will be happy to hear your comments and suggestions for improvements. Please keep an eye on the history section and I might be updating or fixing bugs.

History

  • V 1.00 - 09/Mar/2010 11:39 - First submission
  • V 1.20 - 17/Mar/2010 10:19 - Added the following functionalities:
    • Specify Rearrangement Animation effect (Wobble / Wiggle / Both)
    • Ability to delete a menu item
    • Save the order after rearrangement
    • Tooltip

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)