Combobox 在Windows XP中设置组合框提示横幅

Combobox 在Windows XP中设置组合框提示横幅,combobox,windows-xp,watermark,cue,Combobox,Windows Xp,Watermark,Cue,我正在更新一个VB.net项目,该项目需要将提示横幅添加到文本框和只读组合框(DropDownStyle=DropDownList)。我正在开发的机器是Windows7。我在扩展组合框并添加提示文本属性的类中添加提示文本。以下是将提示文本添加到组合框的方式: '"Me" refers to a combobox that has been extended to include a Cue Text property SendMessage(New HandleRef(Me, Me.Hand

我正在更新一个VB.net项目,该项目需要将提示横幅添加到文本框和只读组合框(DropDownStyle=DropDownList)。我正在开发的机器是Windows7。我在扩展组合框并添加提示文本属性的类中添加提示文本。以下是将提示文本添加到组合框的方式:

 '"Me" refers to a combobox that has been extended to include a Cue Text property
 SendMessage(New HandleRef(Me, Me.Handle), CB_SETCUEBANNER, IntPtr.Zero, _cueText)
上面的代码来自这个博客bost:,它是用C#编写的;我把它翻译成VB。我尝试了我在别处发现的其他类似的变体,都得到了相同的结果:当我在Windows7中运行程序时,它对文本框和组合框非常有效;它仅适用于Windows XP中的文本框

我在不同的论坛上读到了很多关于确保视觉风格被选中以及禁用东亚语言和复杂脚本的评论。我已经做了所有这些,但仍然没有让它在XP上工作


是否有人获得了组合框在XP上工作的提示横幅?

通过各种博客和论坛帖子,我创建了一个类,该类扩展了组合框控件,并实现了适用于Windows 7和XP的CueText属性。我在这里找到了最相关的信息:

  • 如何在XP中设置提示文本:
  • 如何在Windows 7中设置提示文本:
  • 简而言之,Windows7和XP设置提示横幅文本的方式略有不同,因此您需要检查程序运行在哪个操作系统上,然后适当地处理提示文本。对于XP,您需要使用
    EM_SETCUEBANNER作为整数=&H1501
    ,对于Windows 7,您需要使用
    CB_SETCUEBANNER作为UInteger=&H1703
    。如果应用程序在XP上运行,您还需要挑出组合框的文本部分。您可以在下面的代码中看到详细信息。要了解哪个操作系统正在运行,请参阅MS KB文章304289(VB)或304283(C)。(我会发布链接,但我没有足够的信誉点数发布两个以上的链接。)

    一个警告是,如果组合框是只读的(DropDownStyle=DropDownList),这在XP上不起作用。无论哪种方式,Windows7似乎都能正常工作。如果您的应用程序需要在XP上运行,并且您需要组合框为只读,但仍然显示提示文本,那么您可以执行以下操作:

  • 创建一个组合框并使用默认的下拉样式“DropDown”
  • 处理组合框的按键事件,并在该方法中告诉它事件已按如下方式处理:
    e.handled=True。
    这将阻止键入文本
  • 使用“设计”视图中的工具箱创建一个空白ContextMenuStrip,单击组合框,查看其属性,并将其ContextMenuStrip设置为刚才创建的。当用户右键单击组合框时,这将不会导致任何情况发生,因此他们无法将文本粘贴到组合框中 下面是继承ComboBox控件并添加适用于XP和7的CueText属性的类的VB代码。您唯一需要做的就是找出正在运行的操作系统:

    Imports System.ComponentModel
    Imports System.Runtime.InteropServices
    
    Public Class CueComboBox
    Inherits ComboBox
    
    ' Occurs when the CueText property value changes.
    Public Event CueTextChanged As EventHandler
    
    'Windows XP
    Private Shared EM_SETCUEBANNER As Integer = &H1501
    'Windows 7
    Private Shared CB_SETCUEBANNER As UInteger = &H1703
    
    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal        wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As Int32
    End Function
    
    <DllImport("user32.dll")> _
    Private Shared Function GetComboBoxInfo(ByVal hwnd As IntPtr, ByRef pcbi As COMBOBOXINFO) As Boolean
    End Function
    
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure COMBOBOXINFO
        Public cbSize As Integer
        Public rcItem As RECT
        Public rcButton As RECT
        Public stateButton As IntPtr
        Public hwndCombo As IntPtr
        Public hwndItem As IntPtr
        Public hwndList As IntPtr
    End Structure
    
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure RECT
        Public left As Integer
        Public top As Integer
        Public right As Integer
        Public bottom As Integer
    End Structure
    
    Private Shared Function GetComboBoxInfo(ByVal control As Control) As COMBOBOXINFO
        Dim info As New COMBOBOXINFO()
        'a combobox is made up of three controls, a button, a list and textbox;
        'we want the textbox
        info.cbSize = Marshal.SizeOf(info)
        GetComboBoxInfo(control.Handle, info)
        Return info
    End Function
    
    
    Private _cueText As String = [String].Empty
    
    ' Gets or sets the text that will display as a cue to the user.
    <Description("The text value to be displayed as a cue to the user.")> _
    <Category("Appearance")> <DefaultValue("")> <Localizable(True)> _
    Public Property CueText() As String
        Get
            Return _cueText
        End Get
        Set(ByVal value As String)
            If value Is Nothing Then
                value = [String].Empty
            End If
    
            If Not _cueText.Equals(value, StringComparison.CurrentCulture) Then
                _cueText = value
                UpdateCue()
                OnCueTextChanged(EventArgs.Empty)
            End If
        End Set
    End Property
    
    <EditorBrowsable(EditorBrowsableState.Advanced)> _
    Protected Overridable Sub OnCueTextChanged(ByVal e As EventArgs)
        RaiseEvent CueTextChanged(Me, e)
    End Sub
    
    
    Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
        UpdateCue()
        MyBase.OnHandleCreated(e)
    End Sub
    
    
    Private Sub UpdateCue()
        ' If the handle isn't yet created, this will be called when it is created
        If Me.IsHandleCreated Then
            ' Windows XP sets the cue banner differently than Windows 7
            If Form1.OPERATING_SYSTEM = "Windows XP" Then
                Dim info As COMBOBOXINFO = GetComboBoxInfo(Me)
                SendMessage(info.hwndItem, EM_SETCUEBANNER, 0, _cueText)
            Else
                SendMessage(New HandleRef(Me, Me.Handle), CB_SETCUEBANNER, IntPtr.Zero, _cueText)
            End If
        End If
    End Sub
    
    End Class
    
    导入System.ComponentModel
    导入System.Runtime.InteropServices
    公共类组合框
    继承组合框
    '在CueText属性值更改时发生。
    公共事件提示文本已更改为EventHandler
    “Windows XP
    私有共享EM_SETCUEBANNER为整数=&H1501
    “Windows 7
    私有共享CB_SETCUEBANNER作为UInteger=&H1703
    _
    私有共享函数SendMessage(ByVal hWnd作为IntPtr,ByVal msg作为Integer,ByVal wParam作为Integer,ByVal lParam作为String)作为Int32
    端函数
    _
    作为布尔值的私有共享函数getComboxInfo(ByVal hwnd作为IntPtr,ByRef pcbi作为ComboxInfo)
    端函数
    _
    私有结构ComboxInfo
    公共cbSize为整数
    公共rcItem作为RECT
    公共按钮为RECT
    公共状态按钮作为IntPtr
    公共hwndCombo作为IntPtr
    作为IntPtr的公共HwnItem
    作为IntPtr的公共hwndList
    端部结构
    _
    私有结构
    公共左整数
    作为整数的公共top
    作为整数的公权
    公共底部为整数
    端部结构
    私有共享函数GetComboBoxInfo(ByVal控件作为控件)作为ComboxInfo
    作为新COMBOBOXINFO()的尺寸信息
    '组合框由三个控件组成,一个按钮、一个列表和文本框;
    “我们想要文本框
    info.cbSize=Marshal.SizeOf(info)
    GetComboBoxInfo(control.Handle,info)
    返回信息
    端函数
    Private _cuetextas String=[String]。空
    '获取或设置将作为提示显示给用户的文本。
    _
    _
    公共属性CueText()作为字符串
    得到
    返回提示文本
    结束
    设置(ByVal值作为字符串)
    如果值为零,那么
    值=[String]。为空
    如果结束
    如果不是_cueText.Equals(value,StringComparison.CurrentCulture),则
    _提示文本=值
    updatece()
    OnCueTextChanged(EventArgs.Empty)
    如果结束
    端集
    端属性
    _
    受保护的可重写子OnCueTextChanged(ByVal e作为EventArgs)
    RaiseEvent CueTextChanged(Me,e)
    端接头
    已创建受保护的重写子OnHandleCreated(ByVal e作为EventArgs)
    updatece()
    MyBase.OnHandleCreated(e)
    端接头
    私有子更新()
    '如果尚未创建句柄,则在创建句柄时将调用它
    如果我是山德勒创造的那么
    “Windows XP设置提示横幅的方式与Windows 7不同
    如果Form1.OPERATING_SYSTEM=“Windows XP”,则
    尺寸信息作为COMBOBOXINFO=GetComboBoxInfo(Me)
    SendMessage(info.hwnItem,EM_SETCUEBANNER,0,_cueText)
    其他的
    SendMessage(新HandleRef(Me,Me.Handle),CB_SETCUEBANNER,IntPtr.Zero,_cueText)
    如果结束
    如果结束
    端接头
    末级