netlib.narod.ru | < Назад | Оглавление | Далее > |
Элементы управления или формы, получающие вводимую с клавиатуры информацию, обычно как-то показывают, что они находятся в фокусе. Например, текст кнопки, находящейся в фокусе, обводится точечной линией. Элементы управления и формы, позволяющие вводить текст, обычно отмечают место появления следующего символа на экране короткой горизонтальной (вертикальной) линией или квадратиком. Этот индикатор, может быть, знаком вам под названием курсор, но в Windows правильнее называть его кареткой. Слово курсор зарезервировано для растровой картинки, отражающей положение указателя мыши на экране.
Если вы создадите элемент управления TextBox или RichTextBox (как это делается, я покажу в главе 18), то за формирование и вывод каретки будет отвечать он. Во многих случаях функциональности этих элементов управления вполне хватает программе. В частности, RichTextBox построен на основе того же элемента управления Windows, что и Microsoft WordPad, и обладает достаточно широкими возможностями.
Если же эти элементы управления не соответствуют вашим задачам и нужно написать собственный код для ввода текста, возникает небольшая проблема. Среди функций, которых нет в библиотеках классов Windows Forms, пожалуй, самым загадочным образом пропала каретка.
Боюсь, чтобы решить нашу проблему, снова придется писать неуправляемый код, копающийся в DLL Windows. Если вы захотите использовать мой класс Caret в своих программах, учтите, что он определяется в моем собственном пространстве имен. Он основан на API каретки Windows и начинается объявлением пяти внешних функций, расположенных в библиотеке User32.dll.
Caret.cs
//-------------------------------------- // Caret.cs (C) 2001 by Charles Petzold //-------------------------------------- using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace Petzold.ProgrammingWindowsWithCSharp { class Caret { [DllImport("user32.dll")] public static extern int CreateCaret(IntPtr hwnd, IntPtr hbm, int cx, int cy); [DllImport("user32.dll")] public static extern int DestroyCaret(); [DllImport("user32.dll")] public static extern int SetCaretPos(int x, int y); [DllImport("user32.dll")] public static extern int ShowCaret(IntPtr hwnd); [DllImport("user32.dll")] public static extern int HideCaret(IntPtr hwnd); // Поля Control ctrl; Size size; Point ptPos; bool bVisible; // Конструкторы // Конструктор по умолчанию недоступен private Caret() { } // Доступен только конструктор с аргументом Control public Caret(Control ctrl) { this.ctrl = ctrl; Position = Point.Empty; Size = new Size(1, ctrl.Font.Height); Control.GotFocus += new EventHandler(ControlOnGotFocus); Control.LostFocus += new EventHandler(ControlOnLostFocus); // Если элемент управлениЯ имеет фокус, создаем каретку if (ctrl.Focused) ControlOnGotFocus(ctrl, new EventArgs()); } // Свойства public Control Control { get { return ctrl; } } public Size Size { get { return size; } set { size = value; } } public Point Position { get { return ptPos; } set { ptPos = value; SetCaretPos(ptPos.X, ptPos.Y); } } public bool Visibility { get { return bVisible; } set { if (bVisible = value) ShowCaret(Control.Handle); else HideCaret(Control.Handle); } } // Методы public void Show() { Visibility = true; } public void Hide() { Visibility = false; } public void Dispose() { // Если элемент управления имеет фокус, уничтожаем каретку if (ctrl.Focused) ControlOnLostFocus(ctrl, new EventArgs()); Control.GotFocus -= new EventHandler(ControlOnGotFocus); Control.LostFocus -= new EventHandler(ControlOnLostFocus); } // Обработчики событий void ControlOnGotFocus(object obj, EventArgs ea) { CreateCaret(Control.Handle, IntPtr.Zero, Size.Width, Size.Height); SetCaretPos(Position.X, Position.Y); Show(); } void ControlOnLostFocus(object obj, EventArgs ea) { Hide(); DestroyCaret(); } } }
Чтобы создать каретку в форме (или любом другом объекте, производном от Control), используйте конструктор:
Caret caret = new Caret(form);
Класс Caret определяет конструктор по умолчанию как закрытый, поэтому надо включить аргументы в конструктор. У Caret четыре свойства:
Свойства Caret
Тип | Свойство | Доступ | Описание |
Control | Control | Чтение | Объект Control, с которым связана каретка |
Size | Size | Чтение/запись | Размер каретки в пикселах |
Point | Position | Чтение/запись | Положение каретки относительно начала координат формы |
bool | Visibility | Чтение/запись | Видимость каретки |
В средах, функционирующих в текстовом режиме, каретка часто принимает вид символа подчеркивания или квадратика. Однако такие каретки не очень хорошо работают с текстом переменной ширины — здесь лучше использовать вертикальную линию. В общем случае программа, использующая класс Caret со шрифтом формы по умолчанию, может установить размер каретки так:
caret.Size = new Size(2, Font.Height);
Свойство Position указывает позицию каретки относительно левого верхнего угла клиентской области.
Свойство Visibility позволяет прятать и снова показывать каретку При рисовании на форме каретку нужно каждый раз скрывать. Это надо делать до или после, но не во время события Paint! В качестве альтернативы свойству Visibility годятся методы Hide и Show. Dispose — единственный открытый метод, поддерживаемый классом Caret:
Методы Caret
Метод | Описание |
void Hide() | Скрывает каретку |
void Show() | Показывает каретку |
void Dispose() | Деактивизирует каретку |
Вызывать метод Dispose обычно не требуется. Он нужен лишь для того, чтобы прекратить ввод текста с клавиатуры в форму, осуществляемый с использованием каретки.
Caret — хороший пример класса, который должен подключить обработчики событий к форме, с которой он связан. Caret устанавливает обработчики событий GotFocus и LostFocus. Он создает каретку, когда форма получает фокус, и уничтожает ее, когда форма теряет фокус, согласно рекомендациям по обработке каретки в программировании Win32. Метод Dispose просто отключает обработчики событий, после чего каретка больше не создается.
Но имейте в виду, что форма, использующая класс Caret и самостоятельно переопределяющая его методы OnGotFocus и OnLostFocus, рискует отключить обработчики событий в Caret! Если пришлось переопределить эти методы, обязательно вызывайте методы из базового класса:
protected override void OnGotFocus(EventArgs ea) { base.OnGotFocus(ea); ... } protected override void OnLostFocus(EventArgs ea) { base.OnLostFocus(ea); ... }
Методы OnGotFocus и OnLostFocus из базового класса вызывают установленные обработчики событий так же, как методы Caret.
netlib.narod.ru | < Назад | Оглавление | Далее > |