форма windows Как добавить значок справа или слева от текстового поля
Я создаю приложение Windows form, и у меня есть текстовое поле для поиска.
Я хотел бы поместить значок поиска внутри текстового поля, справа или слева
Вот так:
Я бы предпочел справа
Обновление 1
Я спрашиваю о Windows forms не ASP.net или MVC
6 ответов:
Можно использовать a
Panel
, aTextBox
и APictureBox
.Текстовое поле должно быть помещено в панель, чтобы вы не могли писать поверх изображения поиска.
Вы можете создать новый 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; } } }