Windows shape how to add an icon to the right or left of the text field

I am creating a windows form application and I have a search text box.

I would like to put the search icon inside the textbox, right or left

like this:

enter image description here

I would prefer in the correct

Update 1

I am asking about Windows Forms, not ASP.net or MVC

+3


source to share


6 answers


You can use Panel

, a TextBox

and PictureBox

.

enter image description here



The TextBox needs to be placed in the panel so you can't write over your search image.

+6


source


You can create a new UserControl that will do the work you want. To do this, you need to extend the TextBox class. Take a look at the code below:

    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));

        }

    }

      



And in the OnPaint method, you can specify an image. Also you can extend this to have a custom property that can be image. Your choice.

+2


source


Using a custom control or adding code every time you want to do this can get very cumbersome. The way I handle this is to add an initializer class that can be called from my form at runtime. The behavior of this code happens when the user starts typing, the image disappears. If the text box has no content, the image appears. I am handling the click event for the image window to set focus to the textarea to maintain the illusion that it is part of the control and offsets the left to allow | to show that the textbox has focus and is ready to receive input.

By writing a controller instead of a custom control, I don't have to propagate all events and properties from the textbox through my custom control. This class depends on System.Windows.Forms and can be included directly in your Windows Forms application or added to a control library that can be called from multiple applications.

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();
        }
    }
}

      

This is how the class will be used from the form:

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);
        }
    }
}

      

As long as the text box exists and is added to the form, the call can occur at any time.

+1


source


I suggest using RichTextBox

instead TextBox

. And you can set the BackgroundImage property on form load:

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

      

And you have to add event handling like TextChanged

and leave

to show and hide the background image

0


source


Along the line of Atanas' answer, I found the following to work well.

Properties SearchImage

and CancelSearchImage

can be set to control the images used.

EM_SETMARGINS message is sent to prevent text under the button from disappearing.


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; }
    }
}

      

0


source


Along the line of Atanas' answer, I found the following to work well. Properties SearchImage

and CancelSearchImage

can be set to control the images used.

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; }
    }
}

      

0


source







All Articles