0

我正在更新一个需要将提示横幅添加到文本框和只读组合框 (DropDownStyle=DropDownList) 的 VB.net 项目。我正在开发的机器是 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 上工作。

有没有人得到提示横幅组合框在 XP 上工作?

4

1 回答 1

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/

简而言之,Windows 7 和 XP 对提示横幅文本的设置略有不同,因此您需要检查程序在哪个操作系统上运行,然后适当地处理提示文本。您需要EM_SETCUEBANNER As Integer = &H1501用于 XP 和CB_SETCUEBANNER As UInteger = &H1703Windows 7。如果应用程序在 XP 上运行,您还需要单独选择组合框的文本部分。您可以在下面的代码中查看详细信息。要确定正在运行的操作系统,请参阅 MS 知识库文章 304289 (VB) 或 304283 (C#)。(我会发布链接,但我没有足够的声誉点来发布两个以上的链接。)

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

  1. 创建一个组合框并使用默认的 DropDownStyle,“DropDown”
  2. 处理组合框的 KeyPress 事件,并在该方法中告诉它该事件已按如下方式处理:e.Handled = True. 这将防止输入文本。
  3. 使用设计视图中的工具箱创建一个空白 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
于 2013-07-25T21:53:54.197 回答