форма windows Как добавить значок справа или слева от текстового поля


Я создаю приложение Windows form, и у меня есть текстовое поле для поиска.

Я хотел бы поместить значок поиска внутри текстового поля, справа или слева

Вот так:

Введите описание изображения здесь

Я бы предпочел справа

Обновление 1

Я спрашиваю о Windows forms не ASP.net или MVC

6 3

6 ответов:

Можно использовать a Panel, a TextBox и A PictureBox.

Введите описание изображения здесь

Текстовое поле должно быть помещено в панель, чтобы вы не могли писать поверх изображения поиска.

Вы можете создать новый UserControl, который будет выполнять требуемую работу. Для этого необходимо расширить класс TextBox. Посмотрите на код ниже:

    public class IconTextBox : System.Windows.Forms.TextBox
    {
        public IconTextBox() : base() { SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true); this.Multiline = true; }

        public System.Drawing.Bitmap BitmapImage
        {
            set;
            get;
        }

        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            base.OnPaint(e);
            System.Drawing.Image img = BitmapImage as System.Drawing.Image;
            e.Graphics.DrawImage(img, new System.Drawing.Point(this.Width - (img.Width), 0));

        }

    }

И в методе OnPaint можно указать изображение. Кроме того, вы можете расширить его, чтобы иметь настраиваемое свойство, которое может быть путем к изображению. Ваш выбор.

Использование пользовательского элемента управления или добавление кода каждый раз, когда вы хотите сделать это, может стать очень громоздким. Способ, которым я справляюсь с этим, заключается в добавлении класса инициализатора, который может быть вызван из моей формы во время выполнения. Поведение этого кода заключается в том, что когда пользователь начинает печатать, изображение исчезает. Если текстовое поле не содержит содержимого, то отображается изображение. Я обрабатываю событие щелчка для окна изображения, чтобы установить фокус на текстовое поле, чтобы сохранить иллюзию, что оно является частью элемента управления, и смещение влево по порядку разрешить отображение|, показывающего, что текстовое поле имеет фокус и готово к приему ввода.

Написав контроллер вместо пользовательского элемента управления, я избегаю необходимости распространять все события и свойства из текстового поля через мой пользовательский элемент управления. Этот класс зависит от системы.Окна.Формы и могут быть включены непосредственно в приложение Windows Forms или добавлены в библиотеку элементов управления, которая может вызываться из нескольких приложений.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;

namespace WindowsFormsApplication1
{
    class TextBoxIcon
    {
        public static TextBoxIcon AddIcon(TextBox textbox, Image icon)
        {
            if (icon != null) {
                return new TextBoxIcon(textbox, icon);
            } else {
                return null;
            }
        }

        private TextBox _TextBox;
        private PictureBox _PictureBox;

        private TextBoxIcon(TextBox textbox, Image icon) {
            this._TextBox = textbox;
            this._PictureBox = new PictureBox();
            this._PictureBox.BackColor = textbox.BackColor;
            this._PictureBox.Image = ScaleImage(icon);
            this._TextBox.Parent.Controls.Add(_PictureBox);
            this._PictureBox.Location = new Point(textbox.Left + 5, textbox.Top + 2);
            this._PictureBox.Size = new Size(textbox.Width - 10, textbox.Height - 4);
            this._PictureBox.Anchor = textbox.Anchor;
            this._PictureBox.Visible = _TextBox.Visible;
            this._PictureBox.BringToFront();
            textbox.Resize += TextBox_Resize;
            textbox.TextChanged += TextBox_TextChanged;
            textbox.Leave += TextBox_Leave;
            _PictureBox.Click +=  PictureBox_Click;
            textbox.VisibleChanged += TextBox_VisibleChanged;
        }

        public static Image ScaleImage(Image img) {
            if (img.Height == 16) {
                return img;
            } else {
                return new Bitmap(img, new Size((int)((img.Height / 16.0) * img.Width), 16));
            }
        }

        private void TextBox_Resize(Object sender, EventArgs e) {
            _PictureBox.Size = new Size(_TextBox.Width - 10, _TextBox.Height - 4);
        }

        private void TextBox_VisibleChanged(Object sender, EventArgs e) {
            _PictureBox.Visible = _TextBox.Visible;
        }

        private void ShowPictureBox() {
            _PictureBox.Visible = String.IsNullOrEmpty(_TextBox.Text);
        }

        private void TextBox_TextChanged(Object sender, EventArgs e) {
            ShowPictureBox();
        }

        private void TextBox_Leave(Object sender, EventArgs e) {
            ShowPictureBox();
        }

        public void PictureBox_Click(object sender, EventArgs e) { 
            _TextBox.Focus();
        }
    }
}

Вот как выглядит класс будет использоваться из вида:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            TextBoxIcon.AddIcon(txtSearch, Properties.Resources.search);
        }
    }
}

Пока текстовое поле существует и добавлено в форму, вызов может произойти в любое время.

Предлагаю использовать RichTextBox вместо TextBox.И вы можете установить свойство BackgroundImage в нагрузке вида:

public Form1()
        {
            InitializeComponent();
            richTextBox1.BackgroundImage = Image.FromFile("image path");
        }

И вы должны добавить обработку событий, таких как TextChanged и leave, чтобы показать и скрыть фоновое изображение

В соответствии с ответом Атанаса я нашел, что хорошо работает следующее.

Свойства SearchImage и CancelSearchImage можно задать для управления используемыми изображениями.

Сообщение EM_SETMARGINS отправляется для предотвращения исчезновения текста под кнопкой.


public class SearchTextBox : TextBox
{
    private const int EM_SETMARGINS = 0xd3;

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

    private PictureBox searchPictureBox;

    private Button cancelSearchButton;

    public SearchTextBox()
    {
        cancelSearchButton = new Button();
        cancelSearchButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
        cancelSearchButton.Size = new Size(16, 16);
        cancelSearchButton.TabIndex = 0;
        cancelSearchButton.TabStop = false;
        cancelSearchButton.FlatStyle = FlatStyle.Flat;
        cancelSearchButton.FlatAppearance.BorderSize = 0;
        cancelSearchButton.Text = "";
        cancelSearchButton.Cursor = Cursors.Arrow;

        Controls.Add(cancelSearchButton);

        cancelSearchButton.Click += delegate
        {
            Text = "";
            Focus();
        };

        searchPictureBox = new PictureBox();
        searchPictureBox.Anchor = AnchorStyles.Top | AnchorStyles.Right;
        searchPictureBox.Size = new Size(16, 16);
        searchPictureBox.TabIndex = 0;
        searchPictureBox.TabStop = false;
        Controls.Add(searchPictureBox);

        // Send EM_SETMARGINS to prevent text from disappearing underneath the button
        SendMessage(Handle, EM_SETMARGINS, (IntPtr)2, (IntPtr)(16 << 16));

        UpdateControlsVisibility();
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        UpdateControlsVisibility();
    }

    private void UpdateControlsVisibility()
    {
        if (string.IsNullOrEmpty(Text))
        {
            cancelSearchButton.Visible = false;
            searchPictureBox.Visible = true;
        }
        else
        {
            cancelSearchButton.Visible = true;
            searchPictureBox.Visible = false;
        }
    }

    [Browsable(true)]
    public Image SearchImage
    {
        set
        {
            searchPictureBox.Image = value;
            searchPictureBox.Left = Width - searchPictureBox.Size.Width - 4;
            searchPictureBox.Top = Height - searchPictureBox.Size.Height - 4;
        }

        get { return searchPictureBox.Image; }
    }

    [Browsable(true)]
    public Image CancelSearchImage
    {
        set
        {
            cancelSearchButton.Image = value;
            cancelSearchButton.Left = Width - searchPictureBox.Size.Width - 4;
            cancelSearchButton.Top = Height - searchPictureBox.Size.Height - 4;
        }

        get { return cancelSearchButton.Image; }
    }
}

В соответствии с ответом Атанаса я нашел, что хорошо работает следующее. Свойства SearchImage и CancelSearchImage можно задать для управления используемыми изображениями.

public class SearchTextBox : TextBox
{
    private const int EM_SETMARGINS = 0xd3;

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

    private PictureBox searchPictureBox;

    private Button cancelSearchButton;

    public SearchTextBox()
    {
        cancelSearchButton = new Button();
        cancelSearchButton.Anchor = AnchorStyles.Top | AnchorStyles.Right;
        cancelSearchButton.Size = new Size(16, 16);
        cancelSearchButton.TabIndex = 0;
        cancelSearchButton.TabStop = false;
        cancelSearchButton.FlatStyle = FlatStyle.Flat;
        cancelSearchButton.FlatAppearance.BorderSize = 0;
        cancelSearchButton.Text = "";
        cancelSearchButton.Cursor = Cursors.Arrow;

        Controls.Add(cancelSearchButton);

        cancelSearchButton.Click += delegate
        {
            Text = "";
            Focus();
        };

        searchPictureBox = new PictureBox();
        searchPictureBox.Anchor = AnchorStyles.Top | AnchorStyles.Right;
        searchPictureBox.Size = new Size(16, 16);
        searchPictureBox.TabIndex = 0;
        searchPictureBox.TabStop = false;
        Controls.Add(searchPictureBox);

        // Send EM_SETMARGINS to prevent text from disappearing underneath the button
        SendMessage(Handle, EM_SETMARGINS, (IntPtr)2, (IntPtr)(16 << 16));

        UpdateControlsVisibility();
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        UpdateControlsVisibility();
    }

    private void UpdateControlsVisibility()
    {
        if (string.IsNullOrEmpty(Text))
        {
            cancelSearchButton.Visible = false;
            searchPictureBox.Visible = true;
        }
        else
        {
            cancelSearchButton.Visible = true;
            searchPictureBox.Visible = false;
        }
    }

    [Browsable(true)]
    public Image SearchImage
    {
        set
        {
            searchPictureBox.Image = value;
            searchPictureBox.Left = Width - searchPictureBox.Size.Width - 4;
            searchPictureBox.Top = Height - searchPictureBox.Size.Height - 4;
        }

        get { return searchPictureBox.Image; }
    }

    [Browsable(true)]
    public Image CancelSearchImage
    {
        set
        {
            cancelSearchButton.Image = value;
            cancelSearchButton.Left = Width - searchPictureBox.Size.Width - 4;
            cancelSearchButton.Top = Height - searchPictureBox.Size.Height - 4;
        }

        get { return cancelSearchButton.Image; }
    }
}