Button inside a WinForms textbox
Getting the button inside the TextBox just requires adding it to the box' Controls collection. You'll also need to do something reasonable to prevent the text inside the box disappearing underneath the button; that requires a wee bit of pinvoke. Like this:
protected override void OnLoad(EventArgs e) {
var btn = new Button();
btn.Size = new Size(25, textBox1.ClientSize.Height + 2);
btn.Location = new Point(textBox1.ClientSize.Width - btn.Width, -1);
btn.Cursor = Cursors.Default;
btn.Image = Properties.Resources.star;
textBox1.Controls.Add(btn);
// Send EM_SETMARGINS to prevent text from disappearing underneath the button
SendMessage(textBox1.Handle, 0xd3, (IntPtr)2, (IntPtr)(btn.Width << 16));
base.OnLoad(e);
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
Looked like this while I tested the right margin (should have picked a prettier bitmap):
Button inside a winforms textbox vb.net
It looks like some of the code related to Size
and Location
is wrong. Try this:
btn.Size = New Size(25, textBox1.ClientSize.Height + 2)
btn.Location = New Point(textBox1.ClientSize.Width - btn.Width - 1, -1)
btn.FlatStyle = FlatStyle.Flat
btn.Cursor = Cursors.Default
btn.Image = Image.FromFile("C:\ansoft\Soljica\texture\tone.png")
btn.FlatAppearance.BorderSize = 0
textBox1.Controls.Add(btn)
SendMessage(textBox1.Handle, &HD3, CType(2, IntPtr), CType((btn.Width << 16), IntPtr))
How to add button to textbox?
You have to tell the designer that it should also serialize the properties of the button:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Button Button {
//...
}
The default is Hidden so none of the button properties would be written to the Designer.cs file. Setting, say, the Text property works in the designer but the property value is lost after you start the app or reload the form.
How to set focus on textbox and button simultaneously in WinForm
This is a fundamental Windows principle. It's not possible to have 2 controls (windows) focused at the same time.
So the focus should be inside the text box. But you can get the visual indication needed by setting the ok button as AcceptButton
of the form (you might also want to set cancel button as CancelButton
).
In the form constructor, load event or using designer:
this.AcceptButton = okButton;
There is no need to handle KeyDown
event - as soon as the text box is not multiline, pressing Enter
while the focus is inside it will generate ok button click. The same applies for the button set as CancelButton
when you press ESC
.
Winform copy button text to textbox using universal method
You can use this which is more universal as the Control class contains the Text property. Also, using the best practice $"".
private void btn_A_Click(object sender, EventArgs e)
{
box_UserInput.Text = $"{box_UserInput.Text}{((Control)sender).Text}";
}
You can also assign the same event to each button. Create an event, say addControlTextOnClick and assign the same event to each button.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void addControlTextOnClick(object sender, EventArgs e)
{
box_UserInput.Text = $"{box_UserInput.Text}{((Control)sender).Text}";
}
}
You can even shorten this more using this C# construct:
private void addControlTextOnClick(object sender, EventArgs e) =>
box_UserInput.Text = $"{box_UserInput.Text}{((Control)sender).Text}";
Focusing on textBox after clicking a button
Instead of just using .Focus()
go for this combination:
// Set focus to control
txtbox.Focus();
// Set text-selection to end
txtbox.SelectionStart = txtbox.Text.Length == 0 ? 0 : txtbox.Text.Length -1;
// Set text-selection length (in your case 0 = no blue text)
txtbox.SelectionLength = 0
OR
// Set focus to control
txtbox.Focus();
// Check if text is longer then 0
if(txtbox.Text.Length > 0)
{
// Set text-selection to end
txtbox.SelectionStart = txtbox.Text.Length -1;
// Set text-selection length (in your case 0 = no blue text)
txtbox.SelectionLength = 0
}
Both ways are the same. In the first one, I check for text-length == 0
in-place in the second line.
In the second one, I use a classical if
statement.
how to add ellipse button and textbox in current cell of datagridview in winforms
You need to create custom EditingControl
, Cell
and Column
classes as described here: http://msdn.microsoft.com/en-us/library/aa730881(v=vs.80).aspx
I've created sample application for you. See download link below.
Contents:
TextButton control
UserControl containing TextBox without border and simple button.Simple Edit Form
Any simple dialog form, returningDialogResult
.DataGridViewTextButtonEditingControl class
We need to inherit from ourTextButton
control and to implementIDataGridViewEditingControl
interface here.internal class DataGridViewTextButtonEditingControl : TextButton, IDataGridViewEditingControl
{
public DataGridViewTextButtonEditingControl()
{
InnerTextBox.TextChanged += (o, e) => NotifyDataGridViewOfValueChange();
}
public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
{
Font = dataGridViewCellStyle.Font;
if (dataGridViewCellStyle.BackColor.A < 255)
{
Color opaqueBackColor = Color.FromArgb(255, dataGridViewCellStyle.BackColor);
BackColor = opaqueBackColor;
EditingControlDataGridView.EditingPanel.BackColor = opaqueBackColor;
}
else
{
BackColor = dataGridViewCellStyle.BackColor;
}
ForeColor = dataGridViewCellStyle.ForeColor;
}
public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
TextBox textBox = InnerTextBox;
switch (keyData & Keys.KeyCode)
{
case Keys.Right:
{
if (textBox != null)
{
// If the end of the selection is at the end of the string,
// let the DataGridView treat the key message
if ((RightToLeft == RightToLeft.No && !(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length)) ||
(RightToLeft == RightToLeft.Yes && !(textBox.SelectionLength == 0 && textBox.SelectionStart == 0)))
{
return true;
}
}
break;
}
case Keys.Left:
{
if (textBox != null)
{
// If the end of the selection is at the begining of the string
// or if the entire text is selected and we did not start editing,
// send this character to the dataGridView, else process the key message
if ((RightToLeft == RightToLeft.No && !(textBox.SelectionLength == 0 && textBox.SelectionStart == 0)) ||
(RightToLeft == RightToLeft.Yes && !(textBox.SelectionLength == 0 && textBox.SelectionStart == textBox.Text.Length)))
{
return true;
}
}
break;
}
case Keys.Home:
case Keys.End:
{
// Let the grid handle the key if the entire text is selected.
if (textBox != null)
{
if (textBox.SelectionLength != textBox.Text.Length)
{
return true;
}
}
break;
}
case Keys.Delete:
{
// Let the grid handle the key if the carret is at the end of the text.
if (textBox != null)
{
if (textBox.SelectionLength > 0 ||
textBox.SelectionStart < textBox.Text.Length)
{
return true;
}
}
break;
}
}
return !dataGridViewWantsInputKey;
}
public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
{
return Text; // Convert.ChangeType(Text, typeof(int));
}
public void PrepareEditingControlForEdit(bool selectAll)
{
if (selectAll)
{
InnerTextBox.SelectAll();
}
else
{
// Do not select all the text, but
// position the caret at the end of the text
InnerTextBox.SelectionStart = InnerTextBox.Text.Length;
}
}
public DataGridView EditingControlDataGridView { get; set; }
public object EditingControlFormattedValue { get; set; }
public int EditingControlRowIndex { get; set; }
public bool EditingControlValueChanged { get; set; }
public Cursor EditingPanelCursor { get; private set; }
public bool RepositionEditingControlOnValueChange { get; private set; }
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
NotifyDataGridViewOfValueChange();
}
private void NotifyDataGridViewOfValueChange()
{
if (!EditingControlValueChanged)
{
EditingControlValueChanged = true;
EditingControlDataGridView.NotifyCurrentCellDirty(true);
}
}
}DataGridViewTextButtonCell class
We need to inherit from theDataGridViewCell
to implementDataGridViewTextButtonEditingControl
initialization, cell painting and (important!) cloning.
Without overriding theClone()
method, we will not be able to set properties of a newly created instances.internal sealed class DataGridViewTextButtonCell : DataGridViewCell
{
private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextOffsetLeft = 3;
private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextOffsetRight = 4;
private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft = 0;
private const byte DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginRight = 0;
private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextOffsetTop = 2;
private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextOffsetBottom = 1;
private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithWrapping = 1;
private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithoutWrapping = 2;
private const byte DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginBottom = 1;
// Type of this cell's editing control
private static readonly Type defaultEditType = typeof(DataGridViewTextButtonEditingControl);
// Type of this cell's value. The formatted value type is string, the same as the base class DataGridViewTextBoxCell
private static readonly Type defaultValueType = typeof(string);
public override object Clone()
{
DataGridViewTextButtonCell cell = base.Clone() as DataGridViewTextButtonCell;
if (cell != null)
{
cell.ButtonClickHandler = ButtonClickHandler;
}
return cell;
}
/// <summary>
/// Adjusts the location and size of the editing control given the alignment characteristics of the cell
/// </summary>
private Rectangle GetAdjustedEditingControlBounds(Rectangle editingControlBounds, DataGridViewCellStyle cellStyle)
{
// Add a 1 pixel padding on the left and right of the editing control
editingControlBounds.X += 1;
editingControlBounds.Width = Math.Max(0, editingControlBounds.Width - 2);
// Adjust the vertical location of the editing control:
int preferredHeight = cellStyle.Font.Height + 3;
if (preferredHeight < editingControlBounds.Height)
{
switch (cellStyle.Alignment)
{
case DataGridViewContentAlignment.MiddleLeft:
case DataGridViewContentAlignment.MiddleCenter:
case DataGridViewContentAlignment.MiddleRight:
editingControlBounds.Y += (editingControlBounds.Height - preferredHeight) / 2;
break;
case DataGridViewContentAlignment.BottomLeft:
case DataGridViewContentAlignment.BottomCenter:
case DataGridViewContentAlignment.BottomRight:
editingControlBounds.Y += editingControlBounds.Height - preferredHeight;
break;
}
}
return editingControlBounds;
}
public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
TextButton textButton = DataGridView.EditingControl as TextButton;
if (textButton != null)
{
//textButton.BorderStyle = BorderStyle.None;
string initialFormattedValueStr = initialFormattedValue as string;
textButton.Text = initialFormattedValueStr;
if (ButtonClickHandler != null)
textButton.ButtonClick += ButtonClickHandler;
}
}
public override void DetachEditingControl()
{
base.DetachEditingControl();
TextButton textButton = DataGridView.EditingControl as TextButton;
if (textButton != null)
{
textButton.ClearUndo();
if (ButtonClickHandler != null)
textButton.ButtonClick -= ButtonClickHandler;
}
}
public override void PositionEditingControl(bool setLocation, bool setSize, Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
{
Rectangle editingControlBounds = PositionEditingPanel(cellBounds,
cellClip,
cellStyle,
singleVerticalBorderAdded,
singleHorizontalBorderAdded,
isFirstDisplayedColumn,
isFirstDisplayedRow);
editingControlBounds = GetAdjustedEditingControlBounds(editingControlBounds, cellStyle);
DataGridView.EditingControl.Location = new Point(editingControlBounds.X, editingControlBounds.Y);
DataGridView.EditingControl.Size = new Size(editingControlBounds.Width, editingControlBounds.Height);
}
public DataGridViewTextButtonEditingControl EditingControl
{
get { return DataGridView == null ? null : DataGridView.EditingControl as DataGridViewTextButtonEditingControl; }
}
public override Type EditType
{
get { return defaultEditType; }
}
public override Type ValueType
{
get { return base.ValueType ?? defaultValueType; }
}
public override Type FormattedValueType
{
get { return defaultValueType; }
}
protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
{
if (DataGridView == null)
{
return;
}
// First paint the borders and background of the cell.
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle,
paintParts & ~(DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.ContentForeground));
//if (PartPainted(paintParts, DataGridViewPaintParts.Border))
// PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle);
Point ptCurrentCell = DataGridView.CurrentCellAddress;
bool cellCurrent = ptCurrentCell.X == ColumnIndex && ptCurrentCell.Y == rowIndex;
bool cellEdited = cellCurrent && DataGridView.EditingControl != null;
// If the cell is in editing mode, there is nothing else to paint
if (cellEdited)
{
if (PartPainted(paintParts, DataGridViewPaintParts.Background))
{
//graphics.FillRectangle(br, cellBounds);
PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle);
}
}
else
{
if (PartPainted(paintParts, DataGridViewPaintParts.ContentForeground))
{
// Take the borders into account
Rectangle borderWidths = BorderWidths(advancedBorderStyle);
Rectangle valBounds = cellBounds;
valBounds.Offset(borderWidths.X, borderWidths.Y);
valBounds.Width -= borderWidths.Right;
valBounds.Height -= borderWidths.Bottom;
// Also take the padding into account
if (cellStyle.Padding != Padding.Empty)
{
if (DataGridView.RightToLeft == RightToLeft.Yes)
{
valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top);
}
else
{
valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top);
}
valBounds.Width -= cellStyle.Padding.Horizontal;
valBounds.Height -= cellStyle.Padding.Vertical;
}
valBounds = GetAdjustedEditingControlBounds(valBounds, cellStyle);
TextFormatFlags horAlign = TextFormatFlags.Left;
switch (cellStyle.Alignment)
{
case DataGridViewContentAlignment.BottomLeft:
case DataGridViewContentAlignment.MiddleLeft:
case DataGridViewContentAlignment.TopLeft:
horAlign = TextFormatFlags.Left;
break;
case DataGridViewContentAlignment.BottomCenter:
case DataGridViewContentAlignment.MiddleCenter:
case DataGridViewContentAlignment.TopCenter:
horAlign = TextFormatFlags.HorizontalCenter;
break;
case DataGridViewContentAlignment.BottomRight:
case DataGridViewContentAlignment.MiddleRight:
case DataGridViewContentAlignment.TopRight:
horAlign = TextFormatFlags.Right;
break;
}
bool cellSelected = (cellState & DataGridViewElementStates.Selected) != 0;
SolidBrush br = new SolidBrush(cellSelected ? cellStyle.SelectionBackColor : cellStyle.BackColor);
if (PartPainted(paintParts, DataGridViewPaintParts.Background))
{
graphics.FillRectangle(br, cellBounds);
PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle);
}
if (cellStyle.Padding != Padding.Empty)
{
valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top);
valBounds.Width -= cellStyle.Padding.Horizontal;
valBounds.Height -= cellStyle.Padding.Vertical;
}
if (cellCurrent)
{
// Draw focus rectangle
if (DataGridView.Focused && valBounds.Width > 0 && valBounds.Height > 0)
{
ControlPaint.DrawFocusRectangle(graphics, valBounds, Color.Empty, br.Color);
}
}
int verticalTextMarginTop = cellStyle.WrapMode == DataGridViewTriState.True ? DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithWrapping : DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginTopWithoutWrapping;
valBounds.Offset(DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft, verticalTextMarginTop);
valBounds.Width -= DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginLeft + DATAGRIDVIEWTEXTBOXCELL_horizontalTextMarginRight;
valBounds.Height -= verticalTextMarginTop + DATAGRIDVIEWTEXTBOXCELL_verticalTextMarginBottom;
TextRenderer.DrawText(graphics, formattedValue as string, cellStyle.Font,
valBounds,
cellSelected ? cellStyle.SelectionForeColor : cellStyle.ForeColor, TextFormatFlags.Default | horAlign | TextFormatFlags.Top);
}
if (PartPainted(paintParts, DataGridViewPaintParts.ErrorIcon))
{
// Paint the potential error icon on top of the NumericUpDown control
base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText,
cellStyle, advancedBorderStyle, DataGridViewPaintParts.ErrorIcon);
}
}
}
/// <summary>
/// Little utility function called by the Paint function to see if a particular part needs to be painted.
/// </summary>
private static bool PartPainted(DataGridViewPaintParts paintParts, DataGridViewPaintParts paintPart)
{
return (paintParts & paintPart) != 0;
}
public EventHandler<TextButton.TextButtonEventArgs> ButtonClickHandler { get; set; }
}DataGridViewTextButtonColumn class
Simply inherit from theDataGridViewColumn
and provide several properties that should be passed to the our underlyingTextButton
control.internal sealed class DataGridViewTextButtonColumn : DataGridViewColumn
{
private EventHandler<TextButton.TextButtonEventArgs> buttonClickHandler;
public DataGridViewTextButtonColumn()
: base(new DataGridViewTextButtonCell())
{
}
public EventHandler<TextButton.TextButtonEventArgs> ButtonClickHandler
{
get
{
return buttonClickHandler;
}
set
{
DataGridViewTextButtonCell cell = CellTemplate as DataGridViewTextButtonCell;
if (cell != null)
{
if (value != null)
cell.ButtonClickHandler += value;
else if (buttonClickHandler != null)
cell.ButtonClickHandler -= buttonClickHandler;
}
buttonClickHandler = value;
}
}
public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
base.CellTemplate = value;
DataGridViewTextButtonCell cell = CellTemplate as DataGridViewTextButtonCell;
if (cell != null)
cell.ButtonClickHandler = ButtonClickHandler;
}
}
}Usage example
Assuming thatgrid
isDataGridView
.grid.Columns.AddRange(new DataGridViewColumn[]
{
new DataGridViewTextBoxColumn
{
ValueType = typeof (string),
HeaderText = "Name"
},
new DataGridViewTextButtonColumn
{
ValueType = typeof (int),
HeaderText = "Count",
ButtonClickHandler = (o, e) =>
{
grid.EndEdit();
using (EditForm frm = new EditForm { Value = e.Text })
if (frm.ShowDialog(this) == DialogResult.OK)
{
e.Text = frm.Value;
e.Handled = true;
}
grid.BeginEdit(false);
}
}
});
Download Link: Full project (Zip-Archive, Target Framework: v.3.5)
UPDATE (10 oct 21): link fixed.
Related Topics
Convert Datatable to Generic List
Could We Save Delegates in a File (C#)
Deserialize JSON in a "Tryparse" Way
C# Guid and SQL Uniqueidentifier
How to Read Single Excel Cell Value
Memory Efficiency and Performance of String.Replace .Net Framework
Best Way to Find All Factors of a Given Number
What Is the Correct Way to Read from Networkstream in .Net
How to Print Webview Content in a Windows Store App
Number of Occurrences of a Character in a String
Is There Any Valid Reason to Ever Ignore a Caught Exception