在Windows XP中设置ComboBox提示横幅

时间:2013-07-24 20:56:25

标签: combobox windows-xp watermark cue

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

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

上面的代码来自这个博客:http://www.aaronlerch.com/blog/page/7/,它位于C#中;我把它翻译成VB。我尝试了其他类似的变种,我在其他地方找到了,都有相同的结果:当我在Windows 7中运行程序时,它适用于文本框和组合框;它仅适用于Windows XP中的文本框。

我在不同论坛上阅读了很多关于确保选择视觉样式并禁用东亚语言和复杂脚本的评论。我已经完成了所有这些,但仍然没有在XP上工作。

有没有人获得组合框的cue横幅才能在XP上工作?

1 个答案:

答案 0 :(得分:2)

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

  1. 如何在XP中设置提示文字:http://www.ageektrapped.com/blog/the-missing-net-1-cue-banners-in-windows-forms-em_setcuebanner-text-prompt/
  2. 如何在Windows 7中设置提示文字:http://www.aaronlerch.com/blog/2007/12/01/watermarked-edit-controls/
  3. 简而言之,Windows 7和XP设置cue横幅文本的方式略有不同,因此您需要检查程序运行的操作系统,然后适当地处理提示文本。对于Windows 7,您需要使用EM_SETCUEBANNER As Integer = &H1501,对于Windows 7,您需要使用CB_SETCUEBANNER As UInteger = &H1703。如果应用程序在XP上运行,您还需要单击组合框的文本部分。您可以在下面的代码中查看详细信息。要确定正在运行的操作系统,请参阅MS知识库文章304289(VB)或304283(C#)。 (我会发布链接,但我没有足够的声望点来发布超过两个。)

    有一点需要注意,如果组合框是只读的(DropDownStyle = DropDownList),这将无法在XP上运行。 Windows 7似乎无论如何都可以正常工作。如果您的应用程序需要在XP上运行,并且您需要只读取组合框但仍显示提示文本,那么您可以执行以下操作:

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

      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