Wobbly Menu - 受 iPhone 启发






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

这是什么?
这是一个控件,它为添加到菜单项集合中的每个项目创建按钮,并将按钮设置为半透明。当鼠标悬停在按钮上时,按钮会“缓慢地”变得完全可见,当鼠标移开时,按钮会恢复为半透明。
它还允许您重新排列按钮。当双击标题栏时,按钮开始摇摆,用户可以拖放并重新排列顺序。
这个示例是什么?
我在这里提供的示例非常简单,它允许用户将 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 个简单的应用程序。
下一步?
- 下载代码并编译
WobblyMenu.Control
项目 - 创建一个新项目并添加对
WobblyMenu.Control
程序集的引用 - 创建一个实例到
WobblyMenu.Control.DimmableMenu
- [可选]设置您的工作区的最大尺寸
[control].Size = New Size(width, height)
- [可选]设置按钮大小
[control].ItemSize = New Size(width, height)
- 添加菜单项并将它们分配给
WobblyMenu.Control.MenuItem Dim WobblyMenu.Control.MenuItem Instance = _ [control] .MenuItems.AddMenuItem(Text, Image)
- 添加菜单项并将它们分配给
AddHandler [menuitem].OnClick, AddressOf ItemClickHandler
- [可选]处理 OnClose 事件
[control].OnClose, AddressOf CloseEventHandler
- 显示菜单
[control].Show()
我发现这个控件非常有用,并且我正在许多不同的应用程序中使用它。我很高兴听到您的评论和改进建议。请密切关注历史记录部分,我可能会更新或修复错误。
历史
- V 1.00 - 2010 年 3 月 9 日 11:39 - 首次提交
- V 1.20 - 2010 年 3 月 17 日 10:19 - 添加了以下功能
- 指定重新排列动画效果(摇摆/摆动/两者兼有)
- 删除菜单项的能力
- 重新排列后保存顺序
- 工具提示