WinForms 文本框的自定义插入符号

发布于 2024-07-14 02:51:55 字数 198 浏览 6 评论 0原文

我正在 WinForms .Net 2.0 应用程序中开发一个类似自定义超级终端的应用程序。 我在面板中有一个多行文本框,您可以在其中与硬件设备交互。

我的客户想要一个自定义插入符,一个大小为一个字符空间的填充矩形,而不是默认的垂直线。

我知道 .Net 默认情况下不提供执行此操作的选项,但必须有一些 Windows 函数来执行此操作。

I'm developing a custom HyperTerminal like application in a WinForms .Net 2.0 application. I have a multiline TextBox in a Panel in which you can interact with a hardware device.

My customer wants to have a custom Caret, a filled rectangle the size of one character space instead of the vertical line that is by default.

I know .Net does not provide an option to do this by default, but there must some Windows function to do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

固执像三岁 2024-07-21 02:51:55

这些是 Windows 提供的 Native Caret 函数列表,您可以将它们用于您的应用程序。

    [DllImport("User32.dll")]
    static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);

    [DllImport("User32.dll")]
    static extern bool SetCaretPos(int x, int y);

    [DllImport("User32.dll")]
    static extern bool DestroyCaret();

    [DllImport("User32.dll")]
    static extern bool ShowCaret(IntPtr hWnd);

    [DllImport("User32.dll")]
    static extern bool HideCaret(IntPtr hWnd);

参考 SharpDevelop,源代码 @ src\Libraries\ICSharpCode.TextEditor\Project\Src\Gui\Caret.cs

These are the list of Native Caret functions provided by Windows you can use them for you application.

    [DllImport("User32.dll")]
    static extern bool CreateCaret(IntPtr hWnd, int hBitmap, int nWidth, int nHeight);

    [DllImport("User32.dll")]
    static extern bool SetCaretPos(int x, int y);

    [DllImport("User32.dll")]
    static extern bool DestroyCaret();

    [DllImport("User32.dll")]
    static extern bool ShowCaret(IntPtr hWnd);

    [DllImport("User32.dll")]
    static extern bool HideCaret(IntPtr hWnd);

Refer SharpDevelop, Source Code @ src\Libraries\ICSharpCode.TextEditor\Project\Src\Gui\Caret.cs

悲欢浪云 2024-07-21 02:51:55

假设有一个带有文本框的表单:

public partial class Form1 : Form
{
    [DllImport("user32.dll")]
    static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);
    [DllImport("user32.dll")]
    static extern bool ShowCaret(IntPtr hWnd);

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        CreateCaret(textBox1.Handle, IntPtr.Zero, 10, textBox1.Height);
        ShowCaret(textBox1.Handle);
    }
}

Assume a form with a textbox on it:

public partial class Form1 : Form
{
    [DllImport("user32.dll")]
    static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);
    [DllImport("user32.dll")]
    static extern bool ShowCaret(IntPtr hWnd);

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        CreateCaret(textBox1.Handle, IntPtr.Zero, 10, textBox1.Height);
        ShowCaret(textBox1.Handle);
    }
}
在梵高的星空下 2024-07-21 02:51:55

我会使用 System.Drawing 绘制自定义光标(位图),也许使用计时器让它像另一个光标一样闪烁。

获取光标的当前位置(以像素为单位)并在该光标上绘制位图。 找到正确的位置可能很棘手,但应该是可行的。

看看这里 所有者在 winforms 中绘制的文本框。

I would use System.Drawing to draw a custom cursor (bitmap), maybe with a timer to let it blink like another cursor.

Get the current position of the Cursor in pixels and draw a bitmap over that cursor. Can be tricky to find the correct position, but should be doable.

Have a look here for Owner drawn textbox in winforms.

铜锣湾横着走 2024-07-21 02:51:55

使用:

richTextBoxConsole.GetPositionFromCharIndex(cursorPos)

隐藏普通插入符并绘制自己的插入符? 未经测试,但我认为应该可以工作。

Use:

richTextBoxConsole.GetPositionFromCharIndex(cursorPos)

Hide the normal caret and draw your own? Not tested, but should work I think.

一袭水袖舞倾城 2024-07-21 02:51:55

我不确定我是否理解问题...但下一步将帮助其他像我一样找不到答案的人。
所以你有一行文本,你需要找到插入符位置(单击键盘左或右)。 您有 TextRenderer.MeasureString() 和 TextRenderer.DrawText()。 想法很简单,我们需要 util 函数

private SizeF CalculateTextSize(String _text, int begin, int end) 

,它计算给定文本的 SizeF。 因此,如果需要找到 Caret 位置,

size = CalculateTextSize(text, 0, index)

而 voalia

caretPos = new Point(x + size.Width, y)

另外,您需要通过传递 (clickeX,clickedY) 来找到 index 的位置。

for(int i=0; i < text.Lenght; i++)
{
   SizeF size = CalculateTextSize(text, 0, i);
   Rectangle rect = new Rectangle(x, y, size.Width, lineHeight);
    
   if(rect.Contains(clickedX,clickedY))
   {
      index = i;
      break;
   }
}

IDEA 可以很好地处理多行自定义文本编辑

using MyDirectX;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MyRenderText2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            LoadFont();
            text = "Олександр Буханенко";
            location = new Point(100, 33);
        }

        String text;
        int index = 0;

        Font font;
        private void LoadFont()
        {
            font = new Font("Calibri", 12f);
        }

        Point location;

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(Color.AntiqueWhite);
            RenderRect();
            RenderText();
        }

        private void RenderText()
        {
            Graphics g = this.CreateGraphics();

            TextRenderer.DrawText(g, text, font, location, Color.Red, TextFormatFlags.NoPadding);

            g.Dispose();
        }

        private void RenderRect()
        {
            SizeF textSize = new SizeF(0, 0);
            textSize = CalculateTextSize(text, 0, text.Length);

            Graphics g = this.CreateGraphics();
            g.DrawRectangle(Pens.Blue, new Rectangle(location.X, location.Y, (int)textSize.Width, (int)textSize.Height));
            g.Dispose();
        }



        private SizeF CalculateTextSize(String _text, int begin, int end)
        {
            String text = _text.Substring(begin, end - begin);
            SizeF textSize = new SizeF(0, 0);

            Graphics g = this.CreateGraphics();
            textSize = TextRenderer.MeasureText(g, text, font, new Size(0, 0), TextFormatFlags.NoPadding);
            g.Dispose();

            return textSize;
        }



        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);

            Size size = new Size(0, 0);
            size = GetCaretSize();
            Point pos = new Point(0, 0);
            pos = GetCaretPos();

            Win32.CreateCaret(this.Handle, IntPtr.Zero, 1, size.Height);
            Win32.SetCaretPos(pos.X, pos.Y);
            Win32.ShowCaret(this.Handle);

        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);

            Win32.DestroyCaret();
        }



        private Size GetCaretSize()
        {
            Size caretSize = new Size(0, 0);

            String s = "1";
            SizeF sSize = new SizeF(0, 0);

            sSize = this.CalculateTextSize(s, 0, 1);

            caretSize.Width = 1;
            caretSize.Height = (int)sSize.Height;

            return caretSize;
        }

        private Point GetCaretPos()
        {
            Point pos = new Point(0, 0);

            String text1 = text.Substring(0, index);
            String text2 = text.Substring(index);
            String[] lines = text1.Split('\r');
            String lastLineText1 = lines[lines.Length - 1];

            //calculate x
            SizeF lastLineText1Size = new SizeF(0, 0);
            lastLineText1Size = CalculateTextSize(lastLineText1, 0, lastLineText1.Length);
            pos.X = location.X + (int)lastLineText1Size.Width;

            //calculate y
            pos.Y = location.Y;
            SizeF text1Size = new SizeF(0, 0);
            text1Size = CalculateTextSize(text1, 0, text1.Length);
            pos.Y += (int)text1Size.Height;

            String s = "1";
            SizeF sSize = new SizeF(0, 0);
            sSize = CalculateTextSize(s, 0, 1);
            pos.Y -= (text.Substring(0, index).Length != 0 ? 1 : 0) * (int)sSize.Height;

            return pos;
        }



        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Point pos = new Point(0, 0);
            String s1 = "", s2 = "";


            switch (e.KeyCode)
            {
                case Keys.Left:
                    index--;
                    index = Math.Max(index, 0);

                    //this.Invalidate();

                    pos = GetCaretPos();
                    Win32.HideCaret(this.Handle);
                    Win32.SetCaretPos(pos.X, pos.Y);
                    Win32.ShowCaret(this.Handle);
                    break;

                case Keys.Right:
                    index++;
                    index = Math.Min(index, text.Length);

                    //this.Invalidate();

                    pos = GetCaretPos();
                    Win32.HideCaret(this.Handle);
                    Win32.SetCaretPos(pos.X, pos.Y);
                    Win32.ShowCaret(this.Handle);
                    break;

                case Keys.Back:
                    s1 = text.Substring(0, Math.Max(index - 1, 0));
                    s2 = text.Substring(index);

                    text = s1 + s2;
                    index--;
                    index = Math.Max(0, index);

                    pos = GetCaretPos();
                    Win32.SetCaretPos(pos.X, pos.Y);

                    this.Invalidate();
                    break;

                case Keys.Delete:
                    s1 = text.Substring(0, index);
                    s2 = text.Substring(Math.Min(index + 1, text.Length));

                    text = s1 + s2;

                    this.Invalidate();
                    break;
            }
        }

        private void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (int)Keys.Back)
                return;

            String s1 = "", s2 = "";
            s1 = text.Substring(0, index);
            s2 = text.Substring(index);

            text = s1 + e.KeyChar + s2;
            index++;

            Point pos = new Point(0, 0);
            pos = GetCaretPos();
            Win32.SetCaretPos(pos.X, pos.Y);

            this.Invalidate();
        }



        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            

        }
    }
}

更改

Win32.CreateCaret(...), Win32.ShowCaret(...), Win32.SetCaretPos(...), Win32.DestroyCaret(...) 

CreateCaret(...), ShowCaret(...)...
[DllImport("user32.dll")]
static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);
[DllImport("user32.dll")]
static extern bool ShowCaret(IntPtr hWnd);

完整项目

I'm not sure I understand question... But next will help others who like me not found answer.
So you have one line text, you need find Caret position (click keybord LEFT or RIGHT). You have TextRenderer.MeasureString() and have TextRenderer.DrawText(). Idea simple, we need util function

private SizeF CalculateTextSize(String _text, int begin, int end) 

and it's calculate SizeF of given text. So if need find Caret position,

size = CalculateTextSize(text, 0, index)

and voalia

caretPos = new Point(x + size.Width, y)

Another, you need find position of index by passing (clickeX,clickedY).

for(int i=0; i < text.Lenght; i++)
{
   SizeF size = CalculateTextSize(text, 0, i);
   Rectangle rect = new Rectangle(x, y, size.Width, lineHeight);
    
   if(rect.Contains(clickedX,clickedY))
   {
      index = i;
      break;
   }
}

IDEA works fine with Multiline custom text edit

using MyDirectX;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MyRenderText2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            LoadFont();
            text = "Олександр Буханенко";
            location = new Point(100, 33);
        }

        String text;
        int index = 0;

        Font font;
        private void LoadFont()
        {
            font = new Font("Calibri", 12f);
        }

        Point location;

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(Color.AntiqueWhite);
            RenderRect();
            RenderText();
        }

        private void RenderText()
        {
            Graphics g = this.CreateGraphics();

            TextRenderer.DrawText(g, text, font, location, Color.Red, TextFormatFlags.NoPadding);

            g.Dispose();
        }

        private void RenderRect()
        {
            SizeF textSize = new SizeF(0, 0);
            textSize = CalculateTextSize(text, 0, text.Length);

            Graphics g = this.CreateGraphics();
            g.DrawRectangle(Pens.Blue, new Rectangle(location.X, location.Y, (int)textSize.Width, (int)textSize.Height));
            g.Dispose();
        }



        private SizeF CalculateTextSize(String _text, int begin, int end)
        {
            String text = _text.Substring(begin, end - begin);
            SizeF textSize = new SizeF(0, 0);

            Graphics g = this.CreateGraphics();
            textSize = TextRenderer.MeasureText(g, text, font, new Size(0, 0), TextFormatFlags.NoPadding);
            g.Dispose();

            return textSize;
        }



        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);

            Size size = new Size(0, 0);
            size = GetCaretSize();
            Point pos = new Point(0, 0);
            pos = GetCaretPos();

            Win32.CreateCaret(this.Handle, IntPtr.Zero, 1, size.Height);
            Win32.SetCaretPos(pos.X, pos.Y);
            Win32.ShowCaret(this.Handle);

        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);

            Win32.DestroyCaret();
        }



        private Size GetCaretSize()
        {
            Size caretSize = new Size(0, 0);

            String s = "1";
            SizeF sSize = new SizeF(0, 0);

            sSize = this.CalculateTextSize(s, 0, 1);

            caretSize.Width = 1;
            caretSize.Height = (int)sSize.Height;

            return caretSize;
        }

        private Point GetCaretPos()
        {
            Point pos = new Point(0, 0);

            String text1 = text.Substring(0, index);
            String text2 = text.Substring(index);
            String[] lines = text1.Split('\r');
            String lastLineText1 = lines[lines.Length - 1];

            //calculate x
            SizeF lastLineText1Size = new SizeF(0, 0);
            lastLineText1Size = CalculateTextSize(lastLineText1, 0, lastLineText1.Length);
            pos.X = location.X + (int)lastLineText1Size.Width;

            //calculate y
            pos.Y = location.Y;
            SizeF text1Size = new SizeF(0, 0);
            text1Size = CalculateTextSize(text1, 0, text1.Length);
            pos.Y += (int)text1Size.Height;

            String s = "1";
            SizeF sSize = new SizeF(0, 0);
            sSize = CalculateTextSize(s, 0, 1);
            pos.Y -= (text.Substring(0, index).Length != 0 ? 1 : 0) * (int)sSize.Height;

            return pos;
        }



        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Point pos = new Point(0, 0);
            String s1 = "", s2 = "";


            switch (e.KeyCode)
            {
                case Keys.Left:
                    index--;
                    index = Math.Max(index, 0);

                    //this.Invalidate();

                    pos = GetCaretPos();
                    Win32.HideCaret(this.Handle);
                    Win32.SetCaretPos(pos.X, pos.Y);
                    Win32.ShowCaret(this.Handle);
                    break;

                case Keys.Right:
                    index++;
                    index = Math.Min(index, text.Length);

                    //this.Invalidate();

                    pos = GetCaretPos();
                    Win32.HideCaret(this.Handle);
                    Win32.SetCaretPos(pos.X, pos.Y);
                    Win32.ShowCaret(this.Handle);
                    break;

                case Keys.Back:
                    s1 = text.Substring(0, Math.Max(index - 1, 0));
                    s2 = text.Substring(index);

                    text = s1 + s2;
                    index--;
                    index = Math.Max(0, index);

                    pos = GetCaretPos();
                    Win32.SetCaretPos(pos.X, pos.Y);

                    this.Invalidate();
                    break;

                case Keys.Delete:
                    s1 = text.Substring(0, index);
                    s2 = text.Substring(Math.Min(index + 1, text.Length));

                    text = s1 + s2;

                    this.Invalidate();
                    break;
            }
        }

        private void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (int)Keys.Back)
                return;

            String s1 = "", s2 = "";
            s1 = text.Substring(0, index);
            s2 = text.Substring(index);

            text = s1 + e.KeyChar + s2;
            index++;

            Point pos = new Point(0, 0);
            pos = GetCaretPos();
            Win32.SetCaretPos(pos.X, pos.Y);

            this.Invalidate();
        }



        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            

        }
    }
}

Change

Win32.CreateCaret(...), Win32.ShowCaret(...), Win32.SetCaretPos(...), Win32.DestroyCaret(...) 

to

CreateCaret(...), ShowCaret(...)...
[DllImport("user32.dll")]
static extern bool CreateCaret(IntPtr hWnd, IntPtr hBitmap, int nWidth, int nHeight);
[DllImport("user32.dll")]
static extern bool ShowCaret(IntPtr hWnd);

full project

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文