netlib.narod.ru< Назад | Оглавление | Далее >

Определение позиции курсора в тексте

Как замечено выше, одна из сложных задач включает определение позиции курсора в тексте, набранном пропорциональным шрифтом. В целом для решения этой задачи нужно несколько раз вызвать метод MeasureString, чтобы изучить текст, по которому щелкнул мышью пользователь (точнее, выяснить расстояние между символами этого текста).

В программе TypeAway из главы 6 я показал, как дублировать вводимые с клавиатуры символы в виде строки текста на экране. В ней была каретка, которую пользователь мог перемещать при помощи стрелок. Давайте добавим к TypeAway интерфейс, который бы позволил с помощью мыши устанавливать позицию каретки на основе значения свойства X объекта MouseEventArgs, передаваемого как аргумент метода OnMouseDown. (В случае обработки нескольких строк пришлось бы задействовать в программе и свойство Y, чтобы определить строку текста, которую указал пользователь.)

HitTestText.cs

  //--------------------------------------------
  // HitTestText.cs (C) 2001 by Charles Petzold
  //--------------------------------------------
  using System;
  using System.Drawing;
  using System.Windows.Forms;

  class HitTestText: TypeAway
  {
      public new static void Main()
      {
          Application.Run(new HitTestText());
      }
      public HitTestText()
      {
          Text += " with Hit-Testing";
          Cursor = Cursors.IBeam;
      }
      protected override void OnMouseDown(MouseEventArgs mea)
      {
          if (strText.Length == 0)
              return;

          Graphics grfx  = CreateGraphics();
          float    xPrev = 0;
          int      i;

          for (i = 0; i < strText.Length; i++)
          {
              SizeF sizef = grfx.MeasureString(strText.Substring(0, i + 1),
                                       Font, Point.Empty, 
                                       StringFormat.GenericTypographic);
 
              if (Math.Abs(mea.X - xPrev) < Math.Abs(mea.X - sizef.Width))
                  break;

              xPrev = sizef.Width;
          }
          iInsert = i;

          grfx.Dispose();
          PositionCaret();
      }
  }

Обратите внимание, что конструктор устанавливает свойство Cursor формы как Cursors.IBeam, чтобы сделать программу похожей на настоящий текстовый редактор.

Метод OnMouseDown включает цикл for, параметром которого является количество символов в строке текста. При сравнении используется вызов Math.Abs (вычисление модуля числа), который определяет расстояние между символами, ближайшими к курсору мыши по горизонтали. После этого метод заносит в поле iInsert новый индекс символа и вызывает PositionCaret, чтобы преобразовать этот новый индекс в новую позицию каретки, выраженную в пикселах.

К сожалению, как и исходная версия TypeAway, эта программа не может корректно работать с текстом, который читается (и пишется) справа налево.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz