WinForms TextBox 的自定义插入符

问题描述 投票:0回答:5

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

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

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

c# .net winforms caret
5个回答
16
投票

这些是 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


8
投票

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

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

1
投票

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

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

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


0
投票

用途:

richTextBoxConsole.GetPositionFromCharIndex(cursorPos)

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


0
投票

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

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

计算给定文本的SizeF。所以如果需要找到插入符位置,

size = CalculateTextSize(text, 0, index)

和沃利亚

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);
© www.soinside.com 2019 - 2024. All rights reserved.