Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WinForms文本框中的按钮_C#_.net_Winforms - Fatal编程技术网

C# WinForms文本框中的按钮

C# WinForms文本框中的按钮,c#,.net,winforms,C#,.net,Winforms,WinForms文本框是否有任何属性使框末端的嵌入式按钮成为可能 类似于Chrome地址框上的“收藏夹”按钮: 在一些Excel表格中,我还看到了如下内容: 编辑 我按照Hans Passant的回答添加了一个click事件处理程序,它似乎可以正常工作: protected override void OnLoad(EventArgs e) { var btn = new Button(); btn.Size = new Size(25, textBoxFolder.Cli

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");
}
protected override void OnLoad(事件参数e){
var btn=新按钮();
btn.Size=新尺寸(25,textBoxFolder.ClientSize.Height+2);
btn.Location=新点(textBoxFolder.ClientSize.Width-btn.Width,-1);
btn.Cursor=Cursors.Default;
btn.Image=Properties.Resources.arrow\u diagright;
点击+=btn\U点击;
textBoxFolder.Controls.Add(btn);
//发送EM_SETMARGINS以防止按钮下方的文本消失

SendMessage(textBoxFolder.Handle,0xd3,(IntPtr)2,(IntPtr)(btn.Width否。为了完成类似的操作,您需要创建自己的用户控件。它可以很容易地从文本框和按钮组合在一起。困难在于,如果您想要与文本框类似的属性,您需要创建所有属性。最后需要大量代码。

将按钮放在文本框中只需要res将其添加到框的控件集合中。您还需要采取一些合理的措施,以防止框中的文本在按钮下方消失;这需要一点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);
protected override void OnLoad(事件参数e){
var btn=新按钮();
btn.Size=新尺寸(25,textBox1.ClientSize.Height+2);
btn.Location=新点(textBox1.ClientSize.Width-btn.Width,-1);
btn.Cursor=Cursors.Default;
btn.Image=Properties.Resources.star;
textBox1.Controls.Add(btn);
//发送EM_SETMARGINS以防止按钮下方的文本消失

StEndoMeST(TrimBox x1句柄,0xD3,(ItpTR)2,(ItpTR)(BTN.Wrime

)。如果您愿意向另一个库添加引用,您可以考虑使用KrpToT工具包(可用AT)。您可以免费使用的基本工具包(不带色带、导航器或工作区功能)确实允许您添加“按钮规格”。各种控件(包括文本框),它们的视觉效果与您描述的一样。

下面是文本框子类中的答案

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

}
公共类按钮文本框:文本框{
专用只读按钮_按钮;
public event EventHandler按钮单击{add{{u button.Click+=value;}删除{{u button.Click-=value;}
公共按钮文本框(){
_按钮=新按钮{Cursor=Cursors.Default};
_button.SizeChanged+=(o,e)=>OnResize(e);
this.Controls.Add(_按钮);
}
公共按钮{
得到{
返回按钮;
}
}
受保护的覆盖void OnResize(事件参数e){
基数(e);
_button.Size=新尺寸(_button.Width,this.ClientSize.Height+2);
_button.Location=新点(this.ClientSize.Width-\u button.Width,-1);
//发送EM_SETMARGINS以防止按钮下方的文本消失

SendMessage(this.Handle,0xd3,(IntPtr)2,(IntPtr)(_button.Width是Hans Passant的一个不错的想法的一个小补充-如果文本框的大小可以调整,您可以添加一个绑定到基础按钮,以便它的位置也可以根据ClientSize的更改进行调整:

    //Adjust the Location of the button on Size Changes of the containing textBox.
    var binding = new Binding("Location", textBox1, "ClientSize");
    binding.Format += (s, e) => e.Value = e.Value is Size ? new Point(((Size)e.Value).Width - btn.Width, -1) : new Point(0, 0);
    btn.DataBindings.Add(binding);

只需对已接受的解决方案进行一小部分扩展,就可以使按钮看起来和操作正常,需要进行一些调整。以下是搜索框的调整:

    private static readonly int SEARCH_BUTTON_WIDTH = 25;

    private void ConfigureSearchBox()
    {
        var btn = new Button();
        btn.Size = new Size(SEARCH_BUTTON_WIDTH, searchBox.ClientSize.Height + 2);
        btn.Dock = DockStyle.Right;
        btn.Cursor = Cursors.Default;
        btn.Image = Properties.Resources.Find_5650;
        btn.FlatStyle = FlatStyle.Flat;
        btn.ForeColor = Color.White;
        btn.FlatAppearance.BorderSize = 0;
        btn.Click += btn_Click;
        searchBox.Controls.Add(btn);
        this.AcceptButton = btn;
        // Send EM_SETMARGINS to prevent text from disappearing underneath the button
        SendMessage(searchBox.Handle, 0xd3, (IntPtr)2, (IntPtr)(btn.Width << 16));
    }

    [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");
    }
private static readonly int SEARCH_BUTTON_WIDTH=25;
私有void配置搜索框()
{
var btn=新按钮();
btn.Size=新尺寸(搜索按钮宽度,searchBox.ClientSize.Height+2);
btn.Dock=DockStyle.Right;
btn.Cursor=Cursors.Default;
btn.Image=Properties.Resources.Find_5650;
btn.FlatStyle=FlatStyle.Flat;
btn.ForeColor=颜色。白色;
btn.FlatAppearance.BorderSize=0;
点击+=btn\U点击;
searchBox.Controls.Add(btn);
this.AcceptButton=btn;
//发送EM_SETMARGINS以防止按钮下方的文本消失

SendMessage(searchBox.Handle,0xd3,(IntPtr)2,(IntPtr)(btn.Width我在反射器中看到控件包含“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 });
    }
}
现在,通过覆盖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;
        }
    }
}
公共类按钮文本框:文本框
{
按钮;
公共按钮文本框()
{
this.button=新按钮();
this.button.Dock=DockStyle.Right;
this.button.BackColor=SystemColors.Control;
this.button.Width=21;
this.Controls.Add(this.button);
}
受保护的覆盖无效WndProc(参考消息m)
{
基准WndProc(参考m);
开关(m.Msg)
{
案例0x30:
int num=this.button.Width+3;

这是SendMessage(0xD3,2,num,我在OP中显示的第二个屏幕打印是从Excel表单中出来的,它必须在某处。我可以从Excel库继承它吗?@ WHYHEQ-Excel用C++ API和MFC编写的C++。它是一个自定义的控件。您可以在WINFALSE中做类似的事情,但是您需要创建自定义控件。.我建议学习WPF.这要容易得多this@thorkia-看起来excel的想法有点牵强,但请查看Hans solution+对OP的评论。@Highcore,你是一匹绝无仅有的单招小马。请添加[winforms]标记你被忽略的标记,我不想再看到你的wpf咆哮了。@HighCore我在Hans说的同样的话之前已经告诉过你。我强烈建议你从现在开始避免WinForms问题。@HansPassant…我刚从离开和catc回来