通过坐标查找字符串的索引

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

我正在为 Windows 控制台项目开发一个屏幕,并且一直在努力解决以下问题。

场景:

  • 我在控制台中打印了一个字符串(可以在任何起始位置打印)
  • 我有变量存储字符串开始的坐标(x,y)
  • 我有打印字符串的长度。

我试图猜测光标在字符串的哪个位置。

示例:

  • 字符串从位置 (Console.CursorLeft, Console.CursorTop) 开始,比方说 (30,14)
  • 每行的最大 X 是 Console.WindowWidth,假设为 50。
  • 字符串长度为 250 个字符,这意味着字符串在位置 (30,19) 结束

如果我将光标移动到随机位置(3,16),我希望能够计算出字符串相应的索引/位置。

我尝试了不同的公式,欧几里德距离在这里不起作用,因为字符串一行一行。 这个功能我已经从头开始好几次了,现在又要从0开始了

如果有人可以建议我应该使用的公式,我将不胜感激

public static int GetStringIndex(int startX, int startY, string text)
        {
            int index = -1;
            int currentX = Console.CursorLeft;
            int currentY = Console.CursorTop;


            return index;
        }
c# string console coordinates
2个回答
1
投票

如果我理解正确的话,这就是你想要的:

int current = currentX + currentY * Console.BufferWidth;
int start = startX + startY * Console.BufferWidth;

return start <= current && current < start + text.Length ? current - start : -1;

当您将控制台视为一个大的一维数组时,这很容易。


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.