.net - 如何在 VB.NET 中创建命令链接按钮(具有多行文本)?

标签 .net vb.net winforms winapi button

我知道如何使用默认按钮项,但是有什么方法可以实现多行按钮的样式(或者更确切地说,“可点击文本”?),如下所示?

情况是,我有一个界面供用户选择他希望建立的文件类型,并且在较大的主文本行下必须有一个简短的描述。

我只打算在 Windows 7 上运行此程序,因此我无需担心与旧版本 Windows 的向后兼容性

最佳答案

屏幕截图中显示的按钮实际上是整个 Aero UI 中使用的按钮。它是一种称为“命令链接”的自定义样式按钮,可以轻松应用于标准 Button 控件。

不幸的是,WinForms 库不通过简单的属性公开此功能,但可以通过一些 P/Invoke 轻松修复。

您要查找的样式称为BS_COMMANDLINK。根据the documentation ,这种风格:

Creates a command link button that behaves like a BS_PUSHBUTTON style button, but the command link button has a green arrow on the left pointing to the button text. A caption for the button text can be set by sending the BCM_SETNOTE message to the button.

这里有一个小的自定义按钮控件类,它扩展了标准 WinForms Button 控件,并将“命令链接”样式实现为可以在设计器中或通过代码进行配置的属性。

关于代码需要注意的几点:

  1. FlatStyle 属性必须始终设置为 FlatStyle.System,这会强制使用标准 Windows API 按钮控件,而不是由 WinForms 绘制的控件代码。这是 BS_COMMANDLINK 样式工作所必需的(因为它仅受 native 控件支持),并且无论如何它都会生成更好看的按钮控件(具有跳动效果等)。为了强制执行此操作,我重写了 FlatStyle 属性并设置了默认值。

  2. CommandLink 属性是您打开和关闭“命令链接”样式的方式。默认情况下它是关闭的,为您提供一个标准按钮控件,因此您可以根据需要用此控件替换应用程序中的所有按钮控件,只是为了方便。当您打开该属性(将其设置为 True)时,您会得到一个精美的多行命令链接按钮。

  3. 命令链接按钮的标题与标准按钮上显示的标题相同。不过,标题按钮支持第二行的“描述”。这可以通过 WinAPI 消息 BCM_SETNOTE 之后的另一个名为 CommandLinkNote 的属性进行配置。当您将按钮配置为标准按钮控件 (CommandLink = False) 时,该属性的值将被忽略。

Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Runtime.InteropServices

Public Class ButtonEx : Inherits Button

    Private _commandLink As Boolean
    Private _commandLinkNote As String

    Public Sub New() : MyBase.New()
        'Set default property values on the base class to avoid the Obsolete warning
        MyBase.FlatStyle = FlatStyle.System
    End Sub

    <Category("Appearance")> _
    <DefaultValue(False)> _
    <Description("Specifies this button should use the command link style. " & _
                 "(Only applies under Windows Vista and later.)")> _
    Public Property CommandLink As Boolean
        Get
            Return _commandLink
        End Get
        Set(ByVal value As Boolean)
            If _commandLink <> value Then
                _commandLink = value
                Me.UpdateCommandLink()
            End If
        End Set
    End Property

    <Category("Appearance")> _
    <DefaultValue("")> _
    <Description("Sets the description text for a command link button. " & _
                 "(Only applies under Windows Vista and later.)")> _
    Public Property CommandLinkNote As String
        Get
            Return _commandLinkNote
        End Get
        Set(value As String)
            If _commandLinkNote <> value Then
                _commandLinkNote = value
                Me.UpdateCommandLink()
            End If
        End Set
    End Property

    <Browsable(False)> <EditorBrowsable(EditorBrowsableState.Never)> _
    <DebuggerBrowsable(DebuggerBrowsableState.Never)> _
    <Obsolete("This property is not supported on the ButtonEx control.")> _
    <DefaultValue(GetType(FlatStyle), "System")> _
    Public Shadows Property FlatStyle As FlatStyle
        'Set the default flat style to "System", and hide this property because
        'none of the custom properties will work without it set to "System"
        Get
            Return MyBase.FlatStyle
        End Get
        Set(ByVal value As FlatStyle)
            MyBase.FlatStyle = value
        End Set
    End Property

#Region "P/Invoke Stuff"
    Private Const BS_COMMANDLINK As Integer = &HE
    Private Const BCM_SETNOTE As Integer = &H1609

    <DllImport("user32.dll", CharSet:=CharSet.Unicode, SetLastError:=False)> _
    Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, _
                                        <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As IntPtr
    End Function

    Private Sub UpdateCommandLink()
        Me.RecreateHandle()
        SendMessage(Me.Handle, BCM_SETNOTE, IntPtr.Zero, _commandLinkNote)
    End Sub

    Protected Overrides ReadOnly Property CreateParams As CreateParams
        Get
            Dim cp As CreateParams = MyBase.CreateParams

            If Me.CommandLink Then
                cp.Style = cp.Style Or BS_COMMANDLINK
            End If

            Return cp
        End Get
    End Property
#End Region

End Class

关于.net - 如何在 VB.NET 中创建命令链接按钮(具有多行文本)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10469968/

相关文章:

.net - 如何使用AutoMapper.ForMember?

c# - 我应该如何设置用户控件来触发其子项的事件,就好像它们是它自己的一样?

mysql - SQL 数据库关系和 VB.Net 应用程序

vb.net - 更改列表框中包含绘制项目上特定字符串的特定项目的颜色

c# - 从 datetimepicker 获取起始日期和截止日期之间的值

c# - 无法编辑填充有 LINQ 查询结果的 DataGridView

.net - 当 Directory.GetFiles() 发现文件名不是 "like"时抛出异常时如何处理异常?

.net - 窗体转图片

vb.net - 创建从系统托盘运行的程序

c# - 表格之间的连接