| 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 | < Назад | Оглавление | Далее > |