Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет: Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.
Как активировать код? |
Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1446 / 158 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Тема: Программирование
Специальности: Программист, Архитектор программного обеспечения
Теги:
Лекция 17:
Пользовательские элементы управления
Комбинирование готовых элементов управления
Всегда пользовательский элемент управления лучше создавать на основе уже существующих, преимущественно библиотечных, элементов управления, которые хорошо отлажены и работают привычным образом. В предыдущих примерах мы усовершенствовали библиотечный класс Button, приспосабливая его к нашим задачам путем расширения в другом классе.
Теперь мы разработаем свой элемент управления на основе нескольких библиотечных элементов. Применим прием многоэтапного последовательного расширения классов на основе наследования.
using System; using System.Drawing; using System.Windows.Forms; namespace Test { //****************************************************** // Кнопка, генерирующая множество событий Click // При нажатии и удержании на ней курсора мыши class ClickmaticButton : Button { // Определяем поля класса // Создаем таймер Timer timer = new Timer(); // Задержка срабатывания кнопки Button после нажатия мыши int iDelay = 250 * (1 + SystemInformation.KeyboardDelay); // Скорость для срабатывания таймера, генерирующего события повторных // нажатий кнопки компонента при удержании нажатой левой кнопки мыши int iSpeed = 405 - 12 * SystemInformation.KeyboardSpeed; // Конструктор public ClickmaticButton() { timer.Tick += TimerOnTick;// Подписались на тики } // Перехватываем нажатие левой кнопки мыши и запускаем таймер // для генерации событий Click кнопки Button protected override void OnMouseDown(MouseEventArgs args) { base.OnMouseDown(args); // Если нажата левая кнопка мыши if ((args.Button & MouseButtons.Left) != 0) { timer.Interval = iDelay;// Задержка до первого тика timer.Start();// Включили таймер } } // Отработка тиков void TimerOnTick(object sender, EventArgs e) { // Программно генерируем повторное // нажатие Button при каждом тике this.OnClick(EventArgs.Empty); // Меняем скорость таймера timer.Interval = iSpeed; } // Контролируем, находится ли нажатый курсор мыши // над кнопкой и управляем приостановкой таймера protected override void OnMouseMove(MouseEventArgs args) { base.OnMouseMove(args); // Приостанавливаем таймер timer.Enabled = this.Capture && this.ClientRectangle.Contains(args.Location); } // При отпускании кнопки таймер останавливаем protected override void OnMouseUp(MouseEventArgs args) { base.OnMouseUp(args); timer.Stop(); } } //****************************************************** // Рисование на генерирующей событие Click кнопке // изображения стрелки class ArrowButton : ClickmaticButton { // Поле для хранения ориентации кнопки // По умолчанию острый угол треугольника направлен вправо ScrollButton scrollButton = ScrollButton.Right; // Конструктор public ArrowButton() { // Задание стиля кнопки как не получающей фокус ввода this.SetStyle(ControlStyles.Selectable, false); } // Свойство для поддержки переменной перечисления public ScrollButton ScrollButton { get { return scrollButton; } set { scrollButton = value; this.Invalidate();// Перерисовать } } // Переопределяем метод отрисовки кнопки protected override void OnPaint(PaintEventArgs args) { Point point = PointToClient(Control.MousePosition); bool mouseInButton = this.Capture && this.ClientRectangle.Contains(point); ButtonState state = mouseInButton ? ButtonState.Pushed : ButtonState.Normal; state = !this.Enabled ? ButtonState.Inactive : state; Graphics gr = args.Graphics; // Рисуем кнопку с треугольником внутри ControlPaint.DrawScrollButton( gr, this.ClientRectangle, scrollButton, state); } protected override void OnMouseCaptureChanged(EventArgs args) { base.OnMouseCaptureChanged(args); this.Invalidate();// Перерисовать } } //****************************************************** // Самодельный элемент управления - поле с кнопками public class NumericScan : UserControl { // Объявили событие public event EventHandler ValueChanged; // Объявили ссылки-поля для видимости объектов TextBox txtBox; ArrowButton btn1, btn2; // Объявили базовые закрытые поля для открытых свойств int iDecimalPlaces = 0; decimal mValue = 0; decimal mIncrement = 1; decimal mMinimum = 0; decimal mMaximum = 100; // Доступные свойства-обертки полей public int DecimalPlaces { get { return iDecimalPlaces; } set { iDecimalPlaces = value; } } public decimal Value { get { return mValue; } set { txtBox.Text = ValueToText(mValue = value); } } public decimal Increment { get { return mIncrement; } set { mIncrement = value; } } public decimal Minimum { get { return mMinimum; } set { // Заодно отслеживаем диапазон Value if (Value < (mMinimum = value)) Value = mMinimum; } } public decimal Maximum { get { return mMaximum; } set { // Заодно отслеживаем диапазон Value if (Value > (mMaximum = value)) Value = mMaximum; } } // Конструктор public NumericScan() { txtBox = new TextBox(); txtBox.Parent = this; // Текст у правой границы поля txtBox.TextAlign = HorizontalAlignment.Right; txtBox.Text = ValueToText(mValue);// Инициализируем txtBox.TextChanged += TextBoxOnTextChanged; // При вводе Enter обновить Value элемента txtBox.KeyDown += TextBoxOnKeyDown; // Не принимать лишние символы txtBox.KeyPress += new KeyPressEventHandler(txtBox_KeyPress); btn1 = new ArrowButton(); btn1.Parent = this; // Ориентация треугольничка влево btn1.ScrollButton = ScrollButton.Left; btn1.Click += ButtonOnClick; btn2 = new ArrowButton(); btn2.Parent = this; // Ориентация треугольничка вправо btn2.ScrollButton = ScrollButton.Right;// По умолчанию btn2.Click += ButtonOnClick; } string ValueToText(decimal mValue) { // Возвращаем с форматированием return mValue.ToString("F" + iDecimalPlaces); } // Обработчик события изменения содержимого текстового поля void TextBoxOnTextChanged(object sender, EventArgs args) { try { // Преобразуем текст в число mValue = Decimal.Parse(txtBox.Text); } catch { }// На исключения не реагируем } // Обрабатывает каждую клавишу, но ждет клавишу Enter void TextBoxOnKeyDown(object sender, KeyEventArgs args) { switch (args.KeyCode) { // При нажатии Enter генерируем наше событие ValueChanged case Keys.Enter: OnValueChanged(EventArgs.Empty); break; } // Обнаруживаем цифру isNumeric = // Основная клавиатура args.KeyCode >= Keys.D0 && args.KeyCode <= Keys.D9 // Дополнительная клавиатура || args.KeyCode >= Keys.NumPad0 && args.KeyCode <= Keys.NumPad9 // Клавиша BackSpace || args.KeyCode == Keys.Back; } // Отфильтровываем лишние символы из поля ввода bool isNumeric;// Видимое поле void txtBox_KeyPress(object sender, KeyPressEventArgs args) { if (isNumeric != true)// Пропускаем только цифры args.Handled = true;// Не принимаем в TextBox } // Срабатывает автоматически и устанавливает // размеры компонента this.Width, this.Height public override Size GetPreferredSize(Size proposedSize) { const float weight = 1.2f;// Вес ширины // Высота компонента int height = txtBox.PreferredHeight + SystemInformation.HorizontalScrollBarHeight; // Устанавливаем размеры компонента return new Size((int)(weight * height), height); } // Срабатывает автоматически, позиционирует // кнопки и устанавливает их размеры protected override void OnResize(EventArgs args) { base.OnResize(args); txtBox.Height = txtBox.PreferredHeight; txtBox.Width = this.Width;// Текстовое поле по ширине компонента btn1.Location = new Point(0, txtBox.Height);// Слева снизу btn2.Location = new Point (this.Width / 2, txtBox.Height);// Середина низ // Приравниваем значения полей структур btn1.Size = btn2.Size = new Size(txtBox.Width / 2, this.Height - txtBox.Height); } // Когда элемент управления уходит из фокуса ввода, надо // проверить введенное и сгенерировать событие ValueChanged protected override void OnLeave(EventArgs args) { base.OnLeave(args); this.OnValueChanged(EventArgs.Empty);// Аргумент не используется } // Изменения величины пользователем по щелчкам мыши void ButtonOnClick(object sender, EventArgs e) { // Если не было, то дать фокус тексовому полю if (!txtBox.Focused) txtBox.Focus(); // Повышаем полномочия ссылки ArrowButton btn = sender as ArrowButton; // Пробная величина для изменения значения на шаге decimal mNewValue = Value; // Выявляем кнопку и проверяем выход за границу if (btn == btn1) if ((mNewValue -= Increment) < Minimum) return; if (btn == btn2) if ((mNewValue += Increment) > Maximum) return; // Принимаем изменение и вызываем обработчик, // который сгенерирует событие ValueChanged Value = mNewValue; OnValueChanged(EventArgs.Empty); } // Ввели свою дополнительную функцию // Изменение величины прямым вводом в текстовое поле protected virtual void OnValueChanged(EventArgs args) { // Последовательно проверяем выход величины за левую и правую // границы, и если выходит за границу, то обрезаем по границе Value = Math.Min(Maximum, Value); Value = Math.Max(Minimum, Value); //Value = Decimal.Round(Value, DecimalPlaces); // Генерируем событие if (ValueChanged != null) ValueChanged(this, args); } } //****************************************************** // Тест для проверки нашего элемента управления class MyClass : Form { // Внутренние поля для видимости в методах Label lbl1, lbl2;// Заполняются обработчиком события ValueChanged NumericScan numscan1, numscan2;// Ссылки на компоненты public MyClass() { this.Text = "Тест пользовательского компонента"; // Размеры формы this.Width = (int)(1.3f * this.Width); this.Height = (int)(.8f * this.Height); FlowLayoutPanel flow = new FlowLayoutPanel(); flow.Parent = this;// Привязали к форме // Размещение по столбцам flow.FlowDirection = FlowDirection.TopDown; // Внутреннее обрамление в пикселах flow.Padding = new Padding(20); // Растянули по форме flow.Dock = DockStyle.Fill; numscan1 = new NumericScan(); numscan1.Parent = flow; numscan1.AutoSize = true; // Элементы между собой выравнивать по центру numscan1.Anchor = AnchorStyles.None; numscan1.ValueChanged += NumericScanOnValueChanged; lbl1 = new Label(); lbl1.Parent = flow; lbl1.AutoSize = true; // Элементы между собой выравнивать по центру lbl1.Anchor = AnchorStyles.None; // Пустая текстовая метка для отступа элементов (new Label()).Parent = flow; numscan2 = new NumericScan(); numscan2.Parent = flow; numscan2.AutoSize = true; // Элементы между собой выравнивать по центру numscan2.Anchor = AnchorStyles.None; numscan2.ValueChanged += NumericScanOnValueChanged; lbl2 = new Label(); lbl2.Parent = flow; lbl2.AutoSize = true; // Элементы между собой выравнивать по центру lbl2.Anchor = AnchorStyles.None; // Сами принудительно выполняем обработчик // для начальной инициализации текстовых меток NumericScanOnValueChanged(numscan1, EventArgs.Empty); NumericScanOnValueChanged(numscan2, EventArgs.Empty); } void NumericScanOnValueChanged(object sender, EventArgs args) { NumericScan ob = sender as NumericScan;// Приводим ссылку if (ob == numscan1) lbl1.Text = "Первый: " + numscan1.Value; else if (ob == numscan2) lbl2.Text = "Второй: " + numscan2.Value; } } //****************************************************** // Запуск class Program { static void Main() { Application.EnableVisualStyles(); // Создали форму и запустили цикл сообщений Windows Application.Run(new MyClass()); } } }Листинг 17.13 . Пример разработки пользовательского элемента управления