显示一个 C# WinForms 编辑控件的提示

9

我正在开发一个 C# WinForms 应用程序 (VS.NET 2008, .NET 3.5 sp 1)。在一个表单上,我有一个搜索字段,而不是在搜索字段旁边放置标签,我想在搜索字段本身的背景中显示一些灰色文字(例如“搜索术语”)。当用户开始在搜索字段中输入文本时,文字应该消失。我该如何实现这个效果?

4个回答

9

您需要使用一些P/Invoke互操作代码来完成此操作。查找Win32 API SendMessage函数和EM_SETCUEBANNER消息。


5

最好发布代码而不是链接。我从这里发布此内容。

            //Copyright (c) 2008 Jason Kemp

            //Permission is hereby granted, free of charge, to any person obtaining a copy
            //of this software and associated documentation files (the "Software"), to deal
            //in the Software without restriction, including without limitation the rights
            //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
            //copies of the Software, and to permit persons to whom the Software is
            //furnished to do so, subject to the following conditions:

            //The above copyright notice and this permission notice shall be included in
            //all copies or substantial portions of the Software.

            //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
            //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
            //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
            //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
            //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
            //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
            //THE SOFTWARE.

            using System;
            using System.Runtime.InteropServices;
            using System.Windows.Forms;
            using System.Text;


            public static class Win32Utility
            {
                [DllImport("user32.dll", CharSet = CharSet.Auto)]
                private static extern Int32 SendMessage(IntPtr hWnd, int msg,
                    int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);

                [DllImport("user32.dll")]
                private static extern bool SendMessage(IntPtr hwnd, int msg, int wParam, StringBuilder lParam);

                [DllImport("user32.dll")]
                private static extern bool GetComboBoxInfo(IntPtr hwnd, ref COMBOBOXINFO pcbi);

                [StructLayout(LayoutKind.Sequential)]
                private struct COMBOBOXINFO
                {
                    public int cbSize;
                    public RECT rcItem;
                    public RECT rcButton;
                    public IntPtr stateButton;
                    public IntPtr hwndCombo;
                    public IntPtr hwndItem;
                    public IntPtr hwndList;
                }

                [StructLayout(LayoutKind.Sequential)]
                private struct RECT
                {
                    public int left;
                    public int top;
                    public int right;
                    public int bottom;
                }

                private const int EM_SETCUEBANNER = 0x1501;
                private const int EM_GETCUEBANNER = 0x1502;

                public static void SetCueText(Control control, string text)
                {
                    if (control is ComboBox)
                    {
                        COMBOBOXINFO info = GetComboBoxInfo(control);
                        SendMessage(info.hwndItem, EM_SETCUEBANNER, 0, text);
                    }
                    else
                    {
                        SendMessage(control.Handle, EM_SETCUEBANNER, 0, text);
                    }
                }

                private static COMBOBOXINFO GetComboBoxInfo(Control control)
                {
                    COMBOBOXINFO info = 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, ref info);
                    return info;
                }

                public static string GetCueText(Control control)
                {
                    StringBuilder builder = new StringBuilder();
                    if (control is ComboBox)
                    {
                        COMBOBOXINFO info = new COMBOBOXINFO();
                        //a combobox is made up of two controls, a list and textbox;
                        //we want the textbox
                        info.cbSize = Marshal.SizeOf(info);
                        GetComboBoxInfo(control.Handle, ref info);
                        SendMessage(info.hwndItem, EM_GETCUEBANNER, 0, builder);
                    }
                    else
                    {
                        SendMessage(control.Handle, EM_GETCUEBANNER, 0, builder);
                    }
                    return builder.ToString();
                }
            }

2

我认为通常做法是将文本的颜色设置为灰色,并填充提示文本。然后,编写文本字段焦点事件的处理程序,在获得和失去焦点时基于修改字段内容和颜色。以下是一些伪代码(抱歉,这完全不是C#代码。我现在在想Actionscript):

TextInput myInput;
boolean showingHint = true;

myInput.text = "Search Terms";
myInput.color = 0xcccccc;

myInput.onFocusGained = function() {
  if(showingHint) {
    myInput.text = "";
    myInput.color = 0x000000;
    showingHint = false;
  }
}

myInput.onFocusLost = function() {
  if(!showingHint && myInput.text.length == 0) {
    myInput.text = "Search Terms";
    myInput.color = 0xcccccc;
    showingHint = true;
  }
}

记住,只有在用户没有手动更改文本时,您才希望在失去焦点时更改文本。使用一个单独的布尔值来跟踪您是否正在显示提示,这样您就可以区分用户手动键入您的“提示”文本和实际内容。同样,如果正在显示提示,则只想清除输入框的内容,以避免意外删除用户输入。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接