|
Программирование >> Вывод графики
if (position.X > margin + theLine.Width) return -1; все в порядке, можно вернуть номер строки return index; И, наконец, при случае нам также понадобится выполнить преобразование между индексом строки и страничными, а не мировыми координатами. Сделать это позволят следующие методы: private Point LineIndexToPageCoordinates(int index) return LineIndexToWorldCoordinates(index) + new Size(AutoScrollPosition); private int PageCoordinatesToLineIndex(Point position) return WorldCoordinatesToLineIndex(position - new Size(AutoScrollPosition)); private Point LineIndexToPageCoordinates(int index) return LineIndexToWorldCoordinates(index) + new Size(AutoScrollPosition); private int PageCoordinatesToLineIndex(Point position) return WorldCoordinatesToLineIndex(position - new Size(AutoScrollPosition)); Обратите внимание, что для преобразования к страничным координатам добавляется значение AutoScrollPosition, которое отрицательно. Хотя эти методы сами по себе выглядят не особенно интересными, они иллюстрируют общую технику, которую, возможно, вам придется часто использовать. Работая с GDI+, вы часто попадаете в ситуацию, когда у вас есть определенные координаты (например, координаты пользовательского щелчка кнопкой мыши), и нужно найти, какой именно элемент расположен в этой точке. Или наоборот - имея определенный отображаемый элемент, нужно узнать, где он должен быть отображен. Поэтому, если вы пишете приложение GDI+, то всегда удобно иметь методы, выполняющие трансформации, подобные тем, что представлены здесь. Реакция на пользовательский ввод До сих пор все, что мы делали с этой главе с примером CapsEditor, за исключением меню File (Файл), делалось одним способом: приложение взаимодействовало с пользователем, отображая информацию на экране. Но почти все программы работают в двух направлениях: пользователь также может общаться с программой. Теперь мы добавим такую возможность в CapsEditor. Заставить приложение GDI+ реагировать на ввод пользователя в действительности намного проще, чем написать код рисования экрана (в главе 31 описано, как обрабатывать пользовательский ввод). По сути, для этого необходимо переопределить методы из класса Form, которые вызываются из обработчиков событий, подобно тому, как вызывается OnPaint() при возникновении события Paint. В табл. 33.5 перечислены методы, которые, возможно, потребуется переопределить, чтобы отреагировать на щелчки или перемещения мыши пользователем. Таблица 33.5. Методы, работающие с мышью
Если нужно обнаружить, что пользователь вводит некоторый текст, возможно, потребуется переопределить методы, перечисленные в табл. 33.6. Таблица 33.6. Методы, работающие с клавиатурой Метод Вызывается, когда OnKeyDown(KeyEventArgs e) Клавиша нажата. OnKeyPress(KeyPressEventArgs e) Клавиша нажата и отпущена. OnKeyUp(KeyEventArgs e) Нажатая клавиша отпущена. Обратите внимание, что некоторые из этих событий перекрываются. Например, если пользователь нажимает кнопку мыши, возбуждается событие MouseDown. Если кнопка немедленно отпущена, возбуждаются событие MouseUp и событие Click. К тому же некоторые из этих методов принимают аргумент, унаследованный от EventArgs, вместо экземпляра самого EventArgs. Экземпляры классов-наследников могут быть использованы для получения дополнительной информации об определенном событии. MouseEventArgs включает два свойства - X и Y, - которые сообщают координата: указателя мыши в момент нажатия ее кнопки. Как KeyEventArgs, так и KeyPressEventArgs имеют свойства, указывающие клавишу, к которой относится событие. Об этом достаточно. Нам остается тщательно продумать логику, которую мы хотим реализовать. Единственное, что следует отметить - работая с приложениями GDI+, приходится реализовывать больше логики самостоятельно, чем в обычных приложениях Windows Forms. Это потому, что приложения Windows Forms обычно реагируют на более высокоуровневые события (например, TextChanged - для текстовых полей). В отличие от этого, события GDI+ более элементарны - пользователь щелкает кнопкой мыши или нажимает какую-то клавишу. Действия, предпринимаемые приложением, зависят, скорее, от последовательности событий, нежели от одного события. Например, если ваше приложение работает подобно Microsoft Word, где пользователь, чтобы выделить некоторый текст, нажимает левую кнопку мыши, затем перемещает мышь и отпускает кнопку мыши. Приложение принимает событие MouseDown, но с ним ничего нельзя сделать, кроме как запомнить, что кнопка была нажата с курсором в определенной позиции. Затем, когда принимается событие MouseMove, нужно проверить, где теперь находится курсор, и выделить текст, отмеченный пользователем, начиная с позиции нажатия кнопки. Когда пользователь отпускает левую кнопку мыши, то должно быть предпринято соответствующее действие (в методе OnMouseUp()), чтобы проверить, не было ли выполнено перетаскивание, пока кнопка мыши была нажата, и соответствующим образом отреагировать. И только в этот момент последовательность завершается. Другой момент, который необходимо отметить - это то, что поскольку некоторые события перекрываются, часто приходится делать выбор, на какое из них должен реагировать ваш код. Золотое правило гласит, что нужно тщательно продумать логику каждой комбинации перемещения и щелчков мыши или событий клавиатуры, которые может инициировать пользователь, и гарантировать, чтобы ваше приложение реагировало так, чтобы обеспечивалось интуитивно ожидаемое поведение в любой ситуации. Большая часть работы здесь будет состоять в обдумывании, а не в кодировании, потому что нужно принимать во внимание большое число возможных комбинаций пользовательского ввода. Например, что должно делать приложение, если пользователь начнет вводить текст, пока нажата кнопка мыши? Это может показаться маловероятным, но рано или поздно какой-нибудь пользователь обязательно это попробует! Пример CapsEditor ограничивается очень простыми случаями, поэтому нам не приходится обдумывать никакие комбинации подобного рода. Единственное, что нужно сделать - обеспечить реакцию на двойной щелчок мыши, и в этом случае перевести в верхний регистр все символы строки, на которой будет находиться в этот момент указатель мыши. Это должно быть достаточно простой задачей, однако есть одна заминка. Необходимо перехватить событие DoubleClick, но приведенная выше табл. 33.5 сообщает, что это событие принимает параметр EventArgs, а не MouseEventArgs. Проблема в том, что нужно знать, где находится указатель мыши, когда пользователь выполняет двойной щелчок, чтобы правильно идентифицировать строку текста, которая должна быть переведена в верхний регистр - т.е. необходим параметр MouseEventArgs. Существует два обходных пути. Один заключается в использовании статического метода, реализованного объектом Form1 - Control.MousePosition - чтобы найти позицию указателя мыши: protected override void OnDoubleClick(EventArgs e) Point MouseLocation = Control.MousePosition; обработать двойной щелчок В большинстве случаев это будет работать. Однако может возникнуть проблема, связанная с тем, что наше приложение (или даже какое-нибудь другое приложение с высоким приоритетом) будет выполнять некоторую интенсивную вычислительную работу в тот момент, когда пользователь выполнит двойной щелчок. И тогда может случиться так, что OnDoubleClick() будет вызван через полсекунды или около того после реального двойного щелчка пользователя. Конечно, нам не нужны такие задержки, потому что они очень досаждают пользователям, а они иногда случаются по причинам, от нас не зависящим (на медленном компьютере, например). Полсекунды - достаточное время для того, чтобы указатель мыши был передвинут на пол-экрана, и в этом случае вызов Control.MousePosition вернет совершенно неверную позицию! Лучше положиться на одно из многих перекрытий событий, связанных с мышью. Первая часть двойного щелчка - это нажатие левой кнопки мыши. Это значит, что если вызывается OnDoubleClick() , точно известно, что перед этим вызывается OnMouseDown() с указателем мыши, находящимся в той же позиции. Можно воспользоваться переопределенным методом OnMouseDown() , чтобы сохранить позицию мыши, подготовив ее для OnDoubleClick() . Именно такой подход мы используем в CapsEditor:
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |