38

WinForms テキストボックスには、ボックスの最後に埋め込みボタンを可能にするプロパティがありますか?

Chrome アドレス ボックスのお気に入りボタンのようなもの:

ここに画像の説明を入力

また、いくつかの Excel フォームで次のようなものを見てきました。

ここに画像の説明を入力


編集

Hans Passant の回答に従って、クリック イベント ハンドラーを追加しましたが、問題なく動作しているようです。

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

7 に答える 7

11

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

}
于 2013-08-05T04:07:31.717 に答える
6

コントロールに "SendMessage(int,int,int)" メソッドが含まれていることを Reflector で確認し、別の方法を見つけました。

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

そして、これははるかに安全な方法だと思います。

于 2016-12-23T03:52:35.640 に答える
4

別のライブラリへの参照を追加する場合は、Krypton Toolkit ( https://github.com/ComponentFactory/Kryptonで入手可能) の使用を検討できます。無料で使用できる基本的なツールキット (リボン、ナビゲーター、またはワークスペース機能なし) を使用すると、説明どおりに視覚的に表示されるさまざまなコントロール (テキスト ボックスを含む) に「ボタン仕様」を追加できます。

于 2013-04-09T17:24:12.270 に答える
1

いいえ。そのようなことを行うには、独自のユーザー コントロールを作成する必要があります。テキストボックスとボタンから簡単にまとめることができます。問題は、テキスト ボックスと同様のプロパティが必要な場合、それらすべてを作成する必要があることです。結局のところ、それは多くのコードです。

于 2013-04-07T22:57:32.243 に答える