65.9K
CodeProject 正在变化。 阅读更多。
Home

Wobbly Menu - 受 iPhone 启发

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (29投票s)

2010年3月9日

CPOL

3分钟阅读

viewsIcon

77778

downloadIcon

2522

类似 iPhone 的菜单系统和抖动重排技术,带有实用的示例应用程序。

引言

几年前 Windows 7 发布时,我曾期望 Microsoft 对 Windows 95 中引入的菜单系统进行彻底的改造。但令我失望的是,它并没有发生根本性的改变。但是多点触控操作系统是我的想法(我看到人们在 Win 7 电视广告中将许多奇怪的事情称为他们的想法,所以我也想将其称为我的想法)。另一方面,我受到了 iPhone 用户界面的启发,它的设计非常适合手指操作,我认为我也应该为 Windows 实现类似的功能。结果,这个简单的应用程序就变成了现实。

Screen.jpg

这是什么?

这是一个控件,它为添加到菜单项集合中的每个项目创建按钮,并将按钮设置为半透明。当鼠标悬停在按钮上时,按钮会“缓慢地”变得完全可见,当鼠标移开时,按钮会恢复为半透明。

它还允许您重新排列按钮。当双击标题栏时,按钮开始摇摆,用户可以拖放并重新排列顺序。

这个示例是什么?

我在这里提供的示例非常简单,它允许用户将 Windows 文件夹中的任何文件拖放到标题栏中,并且应用程序会为您拖放的每个文件创建一个快捷方式。它提取图标和文件名来创建按钮,然后当单击该按钮时,它将在其注册的应用程序中启动该文件。

我使用了哪些技术?

这里使用了许多简单的技术来实现所有这些功能。

可调光按钮数组

据我所知,除了Form对象之外,没有任何 Windows Form 控件支持允许设置透明度级别的 opacity 属性。因此,我创建了一个类似按钮的窗体数组。

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

摇摆按钮

当双击标题栏时,按钮会变得摇摆不定。我一直在想如何实现这一点。但这是最简单的。

'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))

弯曲按钮

我想让按钮看起来像带有弯曲角的 iPhone 按钮。一个简单的几何形状帮助我实现了这一点。

''' <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

注册文件图标提取

在我的示例应用程序中,我正在创建带有图标的按钮。这是我发现的一件有趣的事情。我一直想知道如何在不进行可怕的 Windows API 调用的情况下提取文件扩展名的注册图标。最后,我在 .NET Framework 的Icon类本身中找到了一个简单的功能。

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. 

您如何使用它?

这是我自己出于兴趣而开发的,任何人都可以免费将其用于个人用途。但是,如果有人试图将其用于商业目的,我希望得到一些分成是合理的。

正如我之前提到的,我将其创建为一个控件,以便它可以重复用于不同的目的。以下 2 张图片显示了 2 个简单的应用程序。

horizontal.jpg

一个示例展示了如何使用默认设置创建按钮。

MultiColor.jpg

一个示例展示了如何创建彩色按钮。

下一步?

  1. 下载代码并编译WobblyMenu.Control项目
  2. 创建一个新项目并添加对WobblyMenu.Control程序集的引用
  3. 创建一个实例到
    WobblyMenu.Control.DimmableMenu
  4. [可选]设置您的工作区的最大尺寸
    [control].Size = New Size(width, height)
  5. [可选]设置按钮大小
    [control].ItemSize = New Size(width, height)
  6. 添加菜单项并将它们分配给
    WobblyMenu.Control.MenuItem
    Dim WobblyMenu.Control.MenuItem Instance = _
    	[control] .MenuItems.AddMenuItem(Text, Image)
  7. 添加菜单项并将它们分配给
    AddHandler [menuitem].OnClick, AddressOf ItemClickHandler
  8. [可选]处理 OnClose 事件
    [control].OnClose, AddressOf CloseEventHandler
  9. 显示菜单
    [control].Show()

我发现这个控件非常有用,并且我正在许多不同的应用程序中使用它。我很高兴听到您的评论和改进建议。请密切关注历史记录部分,我可能会更新或修复错误。

历史

  • V 1.00 - 2010 年 3 月 9 日 11:39 - 首次提交
  • V 1.20 - 2010 年 3 月 17 日 10:19 - 添加了以下功能
    • 指定重新排列动画效果(摇摆/摆动/两者兼有)
    • 删除菜单项的能力
    • 重新排列后保存顺序
    • 工具提示
© . All rights reserved.