winforms文本框是否有任何属性可以在框的末尾创建一个嵌入式按钮?
类似Chrome地址框中的收藏夹按钮:

我在一些Excel表单中也看到过如下内容:

编辑
我跟随Hans Passant的回答添加了一个click事件处理程序,它似乎工作正常:
protected override void OnLoad(EventArgs e) {
var btn = new Button();
btn.Size = new Size(25, textBoxFolder.ClientSize.Height + 2);
btn.Location = new Point(textBoxFolder.ClientSize.Width - btn.Width, -1);
btn.Cursor = Cursors.Default;
btn.Image = Properties.Resources.arrow_diagright;
btn.Click += btn_Click;
textBoxFolder.Controls.Add(btn);
// Send EM_SETMARGINS to prevent text from disappearing underneath the button
SendMessage(textBoxFolder.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);
private void btn_Click(object sender, EventArgs e) {
MessageBox.Show("hello world");
}
Run Code Online (Sandbox Code Playgroud)
Han*_*ant 54
获取TextBox中的按钮只需将其添加到"控件集合"框中.你还需要做一些合理的事情来防止盒子里面的文字消失在按钮下面; 这需要一点点的pinvoke.像这样:
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);
Run Code Online (Sandbox Code Playgroud)
当我测试右边距时应该看起来像这样(应该选择一个更漂亮的位图):

这是TextBox子类中包含的答案.
public class ButtonTextBox : TextBox {
private readonly Button _button;
public event EventHandler ButtonClick { add { _button.Click += value; } remove { _button.Click -= value; } }
public ButtonTextBox() {
_button = new Button {Cursor = Cursors.Default};
_button.SizeChanged += (o, e) => OnResize(e);
this.Controls.Add(_button);
}
public Button Button {
get {
return _button;
}
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
_button.Size = new Size(_button.Width, this.ClientSize.Height + 2);
_button.Location = new Point(this.ClientSize.Width - _button.Width, -1);
// Send EM_SETMARGINS to prevent text from disappearing underneath the button
SendMessage(this.Handle, 0xd3, (IntPtr)2, (IntPtr)(_button.Width << 16));
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
Run Code Online (Sandbox Code Playgroud)
我在Reflector中看到控件包含“ SendMessage(int,int,int)”方法,我发现了另一种方法。
using System;
using System.Reflection;
using System.Windows.Forms;
static class ControlExtensions
{
static BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
static Type[] SendMessageSig = new Type[] { typeof(int), typeof(int), typeof(int) };
internal static IntPtr SendMessage(this Control control, int msg, int wparam, int lparam)
{
MethodInfo MethodInfo = control.GetType().GetMethod("SendMessage", flags, null, SendMessageSig, null);
return (IntPtr)MethodInfo.Invoke(control, new object[] { msg, wparam, lparam });
}
}
Run Code Online (Sandbox Code Playgroud)
现在,通过在ButtonTextBox中重写WndProc,我们可以实现所需的效果。
public class ButtonTextBox : TextBox
{
Button button;
public ButtonTextBox()
{
this.button = new Button();
this.button.Dock = DockStyle.Right;
this.button.BackColor = SystemColors.Control;
this.button.Width = 21;
this.Controls.Add(this.button);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case 0x30:
int num = this.button.Width + 3;
this.SendMessage(0xd3, 2, num << 16);
return;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为这是更安全的方法。
| 归档时间: |
|
| 查看次数: |
32229 次 |
| 最近记录: |