KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Симон Робинсон - C# для профессионалов. Том II

Симон Робинсон - C# для профессионалов. Том II

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Симон Робинсон, "C# для профессионалов. Том II" бесплатно, без регистрации.
Перейти на страницу:

 return index;

}

Наконец, иногда необходимо делать преобразование между индексом строки и координатами страницы, а не мировыми координатами. Это делает следующий метод:

private Point LineIndexToPageCoordinates(int index) {

 return LineIndexToWorldCoordinates(index) + new Size(AutoScrollPosition);

}


private int PageCoordinatesToLineIndex(Point position) {

 return WorldCoordinatesToLineIndex(position - new Size(AutoScrollPosition));

}

Эти методы сами по себе не кажутся особенно интересными, они иллюстрируют общую технику, которую, по всей видимости, вам придется часто использовать. Применяя GDI+, мы иногда оказываемся в ситуации где заданы некоторые координаты (например, координаты места, где пользователь щелкнул мышью) и требуется определить, какой элемент изображен в этом месте. Или наоборот, для заданного определенного элемента вывода необходимо приблизительно определить, где он должен быть выведен. Следовательно, при создании приложений GDI+ может оказаться полезным умение написать методы, эквивалентные методам преобразований координат, проиллюстрированным здесь.

Ответ на ввод пользователя

До сих пор, за исключением пеню File в примере CapsEditor, все, что делались в этой главе, было односторонним, так как приложение общалось с пользователем, выводя информацию на экране. Почти любое программное обеспечение работает в обоих направлениях — пользователь также может общаться с программным обеспечением. Мы собираемся теперь добавить эту возможность в CapsEditor.

Заставить приложение GDI+ ответить на пользовательский ввод в действительности значительно проще, чем писать код для рисования на экране, и мы в главе 9 уже рассмотрели, как обрабатывать ввод пользователя. По сути для этого необходимо переопределить методы из класса Form, которые вызываются из соответствующего обработчика событий почти так же, как вызывается OnPaint(), когда инициируется событие Paint.

Для случая обнаружения, когда пользователь щелкнул мышью или переместил мышь, функции которые можно будет переопределить включают следующие:

Метод Когда вызывается OnClick(EventArgs е) Сделан щелчок мышью OnDoublеСlick(EventArgs е) Сделан двойной щелчок мышью OnMouseDown(MouseEventArgs е) Нажата левая кнопка мыши OnMouseHover(MouseEventArgs е) Мышь остается неподвижной после перемещения OnMouseMove(MouseEventArgs е) Мышь перемещается OnMouseUp(MouseEventArgs e) Левая кнопка мыши отпущена

Если требуется определить, когда пользователь вводит с клавиатуры какой-то текст, то, вероятно, можно будет переопределить следующие методы.

OnKeyDown(KeyEventArgs е) Клавиша нажата OnKeyPress(KeyPressEventArgs е) Клавиша нажата и отпущена OnKeyUp(KeyEventArgs e) Нажатая клавиша отпущена

Отметим, что некоторые из этих событий перекрываются. Например, нажатие пользователем кнопки мыши порождает событие MouseDown. Если кнопка немедленно снова освобождается, то это порождает событие MouseUp и событие Click. Также некоторые из этих методов получают аргумент, который выводится из аргумента EventArgs и поэтому может использоваться для предоставления дополнительных данных об определенном событии. MouseEventArgs имеет два свойства — X и Y, которые задают координаты мыши во время нажатия кнопки. KeyEventArgs и KeyPressEventArgs имеют свойства, указывающие, какая клавиша или клавиши имеют отношение к событию.

Затем разработчик должен продумать логику последующих действий. Только одно замечание. Вполне вероятно, что приложение GDI+ потребует создания большего объема логики, чем приложение Windows.Forms. Это связано с тем, что в приложении Windows.Forms приходится отвечать на высокоуровневые события (например, TextChanged для текстового поля). При использовании GDI+ события являются более базовыми — пользователь щелкает мышью или нажимает клавишу h. Действие, которое предпринимает приложение, скорее всего зависит от последовательности событий, а не от одного события. Например, в Word for Windows, чтобы выбрать некоторый текст, пользователь обычно щелкает левой кнопкой мыши, перемещает мышь и освобождает левую кнопку мыши. Если пользователь просто нажмет, а затем освободит левую кнопку мыши, Word не выделит никакой текст, он просто переместит курсор текста в место, где был курсор мыши. Поэтому в точке, где пользователь нажимает левую кнопку мыши, нельзя еще сказать, что пользователь собирается делать. Приложение будет получать событие MouseDown, но, предположим, что требуется, чтобы приложение вело себя так же, как это делает Word for Windows. Нам ничего не остается, кроме как записать, что произошел щелчок мыши с курсором в определенной позиции. Когда будет получено событие MouseMove, вы захотите проверить в только что сделанных записях, не нажата ли в данный момент левая кнопка, и если это так, то выделить текст, поскольку пользователь его выбрал. Когда пользователь освобождает левую кнопку мыши (в методе OnMouseUp()), происходит проверка, было ли выполнено какое-либо перемещение, пока мышь была нажата, а далее нужно действовать соответственно. Только в этой точке последовательность завершается.

Другой момент нашего рассмотрения связан с перекрытием некоторых событий, так как в этой ситуации возникает необходимость выбора события, на которое должен ответить код.

Золотое правило состоит в тщательном продумывании логики каждой комбинации движения мыши или щелчка и события клавиатуры, которое может инициировать пользователь, а также обеспечении того, чтобы приложение отвечало способом, который интуитивно понятен и согласован с обычно ожидаемым поведением приложений в каждом случае. Большая часть работы здесь будет состоять в обдумывании, а не в кодировании, хотя кодирование потребуется достаточно кропотливое, поэтому может понадобиться принять во внимание множество комбинаций ввода пользователя. Например, что должно делать приложение, если пользователь начинает вводить текст, когда одна из кнопок мыши нажата? Это покажется невероятной комбинацией, но рано или поздно какой-то пользователь попробует так сделать.

Для примера CapsEditor все сделано очень простым, по сути нет никаких комбинаций для рассмотрения. Необходимо ответить только на двойной щелчок пользователя мышью, и в этом случае строку текста, над которой находится курсор мыши, необходимо перевести в символы верхнего регистра.

Это несложная задача, но имеется одна заминка. Необходимо перехватить событие Doubleclick, но приведенная выше таблица показывает, что это событие имеет параметр EventArgs, а не параметр MouseEventArgs. Проблема в том, что необходимо знать, где находится мышь, когда пользователь делает двойной щелчок, если требуется правильно определить строку текста, которая будет переводиться в верхний регистр, и для этого требуется параметр MouseEventArgs. Существует два способа обойти эту проблему. Один состоит в использовании статического метода Control.MousePosition, который реализован объектом Form1, чтобы найти положение мыши, как в следующем коде:

protected override void OnDoubleClick(EventArgs e) {

 Point MouseLocation = Control.MousePosition;

 // обработать двойной щелчок

В большинстве случаев это срабатывает. Однако могут быть сложности, если приложение (или даже некоторое другое приложение с более высоким приоритетом) выполняет некоторые интенсивные вычисления в момент двойного щелчка пользователя. В таком случае возможно, что обработчик событий OnDoubleClick() не будет вызван в течение полсекунды. Задержки такого рода вряд ли желательны, так как они начинают раздражать пользователей достаточно быстро. Половины секунды вполне достаточно для перемещения мыши на половину экрана, — и в этом случае выполнение OnDoubleClick() может произойти в совершенно другом месте.

Лучший подход состоит в использовании одного из многих наложений между значениями событий мыши. Первая часть двойного щелчка мыши включает нажатие левой кнопки. Это означает, что если вызывается OnDoubleClick(), то мы знаем, что также был вызван OnMouseDown() с курсором мыши в том же месте. Можно использовать перезагружаемую версию OnMouseDown() для записи положения мыши при использовании в OnDoubleClick(). Этот подход используется в CapsEditor:

protected override void OnMouseDown(MouseEventArgs e) {

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*