使用各种博客和论坛帖子,我创建了一个扩展 ComboBox 控件并实现适用于 Windows 7 和 XP 的 CueText 属性的类。我在这里找到了最相关的信息:
- 如何在 XP 中设置提示文本:http ://www.ageektrapped.com/blog/the-missing-net-1-cue-banners-in-windows-forms-em_setcuebanner-text-prompt/
- 如何在 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 = &H1703
Windows 7。如果应用程序在 XP 上运行,您还需要单独选择组合框的文本部分。您可以在下面的代码中查看详细信息。要确定正在运行的操作系统,请参阅 MS 知识库文章 304289 (VB) 或 304283 (C#)。(我会发布链接,但我没有足够的声誉点来发布两个以上的链接。)
一个警告是,如果组合框是只读的(DropDownStyle = DropDownList),这将不适用于 XP。无论哪种方式,Windows 7 似乎都可以正常工作。如果您的应用程序需要在 XP 上运行,并且您需要组合框为只读但仍显示提示文本,您可以执行以下操作:
- 创建一个组合框并使用默认的 DropDownStyle,“DropDown”
- 处理组合框的 KeyPress 事件,并在该方法中告诉它该事件已按如下方式处理:
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