Российский Государственный Технологический Университет им. К.Э. Циолковского
Опубликован: 02.03.2007 | Доступ: свободный | Студентов: 5636 / 790 | Оценка: 3.96 / 3.45 | Длительность: 27:04:00
ISBN: 978-5-9556-0086-4
Лекция 16:

Форма

Extender providers. Провайдеры дополнительных свойств

Провайдер дополнительных свойств – компонент (не элемент управления, а именно компонент!), который "предоставляет" свойства другим компонентам. Провайдеры дополнительных свойств обеспечивают дополнительные возможности при реализации элементов управления.

К числу провайдеров относятся:

  • ToolTipProvider ;
  • HelpProvider ;
  • ErrorProvider.

Когда ToolTip Component на этапе разработки добавляется к форме, все остальные компоненты, размещенные на этой форме, получают новое свойство, которое даже можно просматривать и устанавливать (редактировать) в окне Properties непосредственно в процессе разработки формы. И это новое свойство, называемое ToolTip, может быть предоставлено для каждого элемента управления данной формы. Однако не надо обольщаться. Множество свойств элементов управления при этом не изменяется. При выполнении приложения дополнительное свойство остается недоступным через данный конкретный элемент управления.

В следующем примере кода форма была построена с кнопочкой, которая была названа MyButton, и элементом управления ToolTip, названным MyToolTip и "представляющим" кнопочке свойство ToolTip.

// И вот так просто и наивно значение свойства кнопочки не получить,
 // поскольку это свойство для данного элемента управления – не родное! 
 string myString;
 myString = MyButton.ToolTip;

Подобное обращение приведет к ошибке еще на стадии компиляции. А вот как надо обращаться к этому самому дополнительному свойству, установленному для кнопочки MyButton, для получения ранее назначенного этому элементу управления совета (просто форменное надувательство):

string myString;
 myString = MyToolTip.GetToolTip(MyButton); // Объект MyToolTip предоставляет
 // ToolTip (совет!) для элемента управления MyButton.

Провайдеры дополнительных свойств являются классами, а это означает, что у них имеются собственные свойства, методы и даже события.

Следующий программный код демонстрирует использование провайдеров.

using System;
 using System.Drawing;
 using System.Collections;
 using System.ComponentModel;
 using System.Windows.Forms;

 namespace Rolls01
 {

 // Summary description for numPointsForm.

 public class numPointsForm : System.Windows.Forms.Form
 {
  Form1 f1;
  int nPoints;
  private System.Windows.Forms.TextBox numBox;
  private System.Windows.Forms.Button button1;
  private System.ComponentModel.IContainer components;
 		
  private System.Windows.Forms.ToolTip toolTip;
  // Ссылка на объект - представитель класса ErrorProvider
  private System.Windows.Forms.ErrorProvider errorProvider;
 		
  private string[] errMess;

  public numPointsForm(Form1 f1Key)
  {
   f1 = f1Key;
   InitializeComponent();
   errMess = new string[] {
                             "Больше двух тараканов!",
                             "Целое и больше двух!"
                          };
  }


 // Clean up any resources being used.

 protected override void Dispose( bool disposing )
 {
  if( disposing )
  {
  if(components != null)
  {
  components.Dispose();
  }
 }
  base.Dispose( disposing );
 }

 #region Windows Form Designer generated code

 // Required method for Designer support – do not modify
 // the contents of this method with the code editor.

 private void InitializeComponent()
 {
  this.components = new System.ComponentModel.Container();
  this.numBox = new System.Windows.Forms.TextBox();
  this.button1 = new System.Windows.Forms.Button();
  this.toolTip = new System.Windows.Forms.ToolTip(this.components);
  this.SuspendLayout();
  // 
  // numBox
  // 
  this.numBox.Location = new System.Drawing.Point(8, 11);
  this.numBox.Name = "numBox";
  this.numBox.Size = new System.Drawing.Size(184, 20);
  this.numBox.TabIndex = 0;
  this.numBox.Text = "";
  this.numBox.Validating +=
  new System.ComponentModel.CancelEventHandler(this.numBox_Validating);
  // 
  // button1
  // 
  this.button1.Location = new System.Drawing.Point(208, 8);
  this.button1.Name = "button1";
  this.button1.TabIndex = 1;
  this.button1.Text = "OK";
  this.button1.Click += new System.EventHandler(this.button1_Click);
  // 
  // numPointsForm
  // 
  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
  this.ClientSize = new System.Drawing.Size(288, 45);
  this.Controls.Add(this.button1);
  this.Controls.Add(this.numBox);
  this.MaximizeBox = false;
  this.MinimizeBox = false;
  this.Name = "numPointsForm";
  this.Text = "numPointsForm";
  this.Load += new System.EventHandler(this.numPointsForm_Load);
  this.ResumeLayout(false);
  }
  #endregion

 private void numBox_Validating
            (object sender, System.ComponentModel.CancelEventArgs e)
 {
 int x;
 try
 {
  x = int.Parse(numBox.Text);
  if (x <= 1) 
  {
  numBox.Text = nPoints.ToString();
  e.Cancel = true;
  // Обращение к Error-провайдеру.
  errorProvider.SetError(numBox, this.errMess[0]);
  }
 else
 {
  nPoints = x;
 }
 }
 catch (Exception e2)
 {
 numBox.Text = nPoints.ToString();
 e.Cancel = true;
 // Обращение к Error-провайдеру.
 errorProvider.SetError(numBox, this.errMess[1]);
 }
 }

 private void numPointsForm_Load(object sender, System.EventArgs e)
 {
 nPoints = f1.nPoints;
 numBox.Text = nPoints.ToString();
 toolTip.SetToolTip(numBox,"Количество тараканчиков. Больше двух.");
 errorProvider = new ErrorProvider();
 }

 private void button1_Click(object sender, System.EventArgs e)
 {
 f1.nPoints = nPoints;
 this.Close();
 }
 }
 }
Листинг 16.2.

ToolTipProvider, не имея собственного внешнего представления, тем не менее обеспечивает визуализацию дополнительной информации, которая в соответствии с замыслом разработчика формы предоставляется пользователю приложения. Поэтому среди свойств объекта-представителя ToolTipProvider имеются такие свойства, связанные с формой подачи дополнительной информации, как:

  • BackColor — задает цвет фона выводимой информации;
  • ForeColor — задает цвет текста выводимой информации;
  • ToolTipIcon — сопутствующая пиктограмма;
  • ToolTipTitle — дополнительный заголовок;
  • IsBalloon — совет размещается в рамочке, в стиле прямой речи в комиксах.

Для ToolTip провайдера объявляются два события:

  • Draw — это событие возникает при условии установления в "true" свойства OwnerDraw (особая тема для исследования),
  • Popup — возникает непосредственно в момент "появления" совета.

Следующий фрагмент программного кода демонстрирует вариант обработки события Popup:

using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
 using System.Text;
 using System.Windows.Forms;

 namespace WindowsApplication2
 {
 public partial class Form1 : Form
 {
 Random rnd;
 float rp;

 // Массив советов!
 string[] tipsForPlusButton = 
 {
   "Эта кнопочка используется для вычисления суммы пары слагаемых.",
   "Жми на эту кнопочку, дружок!",
   "Не робей, эта кнопочка специально для тебя...",
   "Нажимать с осторожностью.",
   "Кнопка ПЛЮС"
 };

 // Специально объявляемые заголовки для выдаваемых советов.
 string[] tipsTitles =
 {
  "Страшные случаи из жизни",
  "Совет по заполнению первого окна",
  "Совет по заполнению второго окна",
  "Сумма"
 }; 

 public Form1()
 {
     rnd = new Random();
     InitializeComponent();
 }


 // При загрузке формы элементы управления "получают" собственные советы. 
 private void Form1_Load(object sender, EventArgs e)
 {
     this.xToolTip.SetToolTip
         (this.plusButton, tipsForPlusButton[0]);
     this.xToolTip.SetToolTip
         (
          this.textBox1,
          "Текстовое окно для ввода значения первого слагаемого"
          );
     this.xToolTip.SetToolTip
         (
          this.textBox2,
          "Текстовое окно для ввода значения второго слагаемого"
         );
     this.xToolTip.SetToolTip
         (
          this.textBox3,
          "Текстовое окно для вывода значения суммы слагаемых"
         );

     this.textBox1.Text = "0";
     this.textBox2.Text = "0";
 }

 // При нажатии кнопочки в провайдере заменяется совет. 
 private void plusButton_Click(object sender, EventArgs e)
 {
     x = int.Parse(this.textBox1.Text) + int.Parse(this.textBox2.Text);
     this.textBox3.Text = x.ToString();
     this.xToolTip.SetToolTip
         (
          this.plusButton,
          tipsForPlusButton[rnd.Next(0, tipsForPlusButton.Length)]
         );
 }

 // В обработчике события можно определить элемент управления, 
 // для которого выдается совет. При этом изменяется заголовок совета.
 private void xToolTip_Popup(object sender, PopupEventArgs e)
 {
     if (e.AssociatedControl.Name.Equals("plusButton"))
     {
         xToolTip.ToolTipTitle = tipsTitles[0];
         this.Text = "tip for plusButton";
     }
     else if (e.AssociatedControl.Name.Equals("textBox1"))
     {
         xToolTip.ToolTipTitle = tipsTitles[1];
     }
     else if (e.AssociatedControl.Name.Equals("textBox2"))
     {
         xToolTip.ToolTipTitle = tipsTitles[2];
     }
     else if (e.AssociatedControl.Name.Equals("textBox3"))
     {
         xToolTip.ToolTipTitle = tipsTitles[3];
     }
 }
 }
 }
Листинг 16.3.

Validating и Validated элементов управления

Предполагается, что свойство CausesValidation элементов управления, для которых будет проводиться проверка, установлено в true. Это позволяет отработать обработчику событие Validating, которое возникает в момент потери фокуса элементом управления. У обработчика события Validating имеется аргументобъект – представитель класса CancelEventArgs, обычно с именем e. У него есть поле Cancel, которое в случае ошибки можно установить в true, что приводит к возвращению фокуса.

Validated генерируется после Validating. Разница между ними заключается в следующем.

Validating активизируется для данного элемента управления непосредственно после потери фокуса. Перехват этого события позволяет, например, оперативно проверить правильность заполнения данного поля ввода и в случае некорректного заполнения вернуть фокус в это поле. При этом можно предпринять некоторые шаги по коррекции неправильного значения. Например, если в поле ввода должна располагаться последовательность символов, преобразуемая к целочисленному значению, а туда была записана " qwerty ", то можно восстановить последнее корректное значение или вписать туда строку " 0 ".

Validated активизируется при попытке закрытия формы. В обработчике этого события обычно располагается код, который позволяет осуществить проверку корректности заполнения всей формы в целом — например, отследить отсутствие значений в текстовых полях, которые обязательно должны быть заполнены:

using System;
 using System.Drawing;
 using System.Collections;
 using System.ComponentModel;
 using System.Windows.Forms;
 using System.Data;

 namespace PropertiesProviders
 {
 public class Form1 : System.Windows.Forms.Form
  {
 private System.Windows.Forms.Button BigButton;
 private System.Windows.Forms.ToolTip toolTip01;
 private System.ComponentModel.IContainer components;

 private System.Windows.Forms.Button RedButton;
 private System.Windows.Forms.ErrorProvider errorProvider1;
 int nTip = 0;
 string[] Tips = {
 "Не торопись...",
 "Попробуй еще раз... " ,
 "Зри в корень... "
 };

 int nErr = 0;
 private System.Windows.Forms.TextBox textBox1;
 private System.Windows.Forms.HelpProvider helpProvider1;
 string[] ErrMess = {
 "Не надо было этого делать... ",
 "Какого хрена... ",
 "Ну все... ",
  "" 
  };


 public Form1()
 {
 InitializeComponent();
 }

 protected override void Dispose( bool disposing )
 {
 if( disposing )
 {
 if (components != null) 
 {
 components.Dispose();
 }
 }
 base.Dispose( disposing );
 }

 #region Windows Form Designer generated code

 // Required method for Designer support – do not modify
 // the contents of this method with the code editor.

 private void InitializeComponent()
 {
 this.components = new System.ComponentModel.Container();
 this.BigButton = new System.Windows.Forms.Button();
 this.toolTip01 = new System.Windows.Forms.ToolTip(this.components);
 this.RedButton = new System.Windows.Forms.Button();
 this.errorProvider1 = new System.Windows.Forms.ErrorProvider();
 this.textBox1 = new System.Windows.Forms.TextBox();
 this.helpProvider1 = new System.Windows.Forms.HelpProvider();
 this.SuspendLayout();
 // 
 // BigButton
 // 
 this.BigButton.Location = new System.Drawing.Point(8, 40);
 this.BigButton.Name = "BigButton";
 this.BigButton.TabIndex = 0;
 this.BigButton.Text = "BigButton";
 this.toolTip01.SetToolTip(this.BigButton, "Жми на эту кнопку, дружок!");
 this.BigButton.Click += new System.EventHandler(this.BigButton_Click);
 // 
 // RedButton
 // 
 this.RedButton.Location = new System.Drawing.Point(112, 40);
 this.RedButton.Name = "RedButton";
 this.RedButton.Size = new System.Drawing.Size(80, 23);
 this.RedButton.TabIndex = 1;
 this.RedButton.Text = "RedButton";
 this.toolTip01.SetToolTip(this.RedButton,"А на эту кнопку нажимать не надо!");
 this.RedButton.Click += new System.EventHandler(this.RedButton_Click);
 // 
 // errorProvider1
 // 
 this.errorProvider1.ContainerControl = this;
 // 
 // textBox1
 // 
 this.helpProvider1.SetHelpString(this.textBox1, "int values only...");
 this.textBox1.Location = new System.Drawing.Point(272, 40);
 this.textBox1.Name = "textBox1";
 this.helpProvider1.SetShowHelp(this.textBox1, true);
 this.textBox1.TabIndex = 2;
 this.textBox1.Text = "";
 this.textBox1.Validating += new

System.ComponentModel.CancelEventHandler(this.textBox1_Validating);
 // 
 // Form1
 // 
 this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
 this.ClientSize = new System.Drawing.Size(536, 168);
 this.Controls.Add(this.textBox1);
 this.Controls.Add(this.RedButton);
 this.Controls.Add(this.BigButton);
 this.Name = "Form1";
 this.Text = "Form1";
 this.ResumeLayout(false);
 }
 #endregion

 static void Main() 
 {
 Application.Run(new Form1());
 }
 private void BigButton_Click(object sender, System.EventArgs e)
  {
 this.toolTip01.SetToolTip(this.BigButton, Tips[nTip]);
 if (nTip < 2) nTip++;
 else nTip = 0;
  }

 private void RedButton_Click(object sender, System.EventArgs e)
  {
 errorProvider1.SetError(RedButton, ErrMess[nErr]);
 if (nErr < 3) nErr++;
 else nErr=0;
  }
 private void textBox1_Validating
                      (object sender, System.ComponentModel.CancelEventArgs e)
 {
 int val = 0;
 try
 {
 if (this.textBox1.Text != "")
 val = int.Parse(textBox1.Text);
 errorProvider1.SetError(textBox1, ""); 
 }
 catch
 {
 e.Cancel = true;
 errorProvider1.SetError(textBox1, "Ну целое же...");
 }
 }
 }
 }
Листинг 16.4.

Управление посредством сообщений

Когда при программировании Windows-приложений еще не использовались элементы MFC, когда еще не было карт сообщений, оконная процедура WinMain определялась явным образом, и в ней содержался ЦИКЛ, и можно было наблюдать устройство механизма непрерывного "прослушивания" и интерпретациии перехватываемых сообщений системы, передаваемых данному Windows-приложению.

При этом становилось очевидным, что вся работа приложения фактически сводится к установлению соответствия (с использованием простого оператора выбора) между распознанным в этом цикле сообщением и соответствующей функцией-обработчиком.

Естественно, при этом производился вызов соответствующей функции с возможной передачей этой функции параметров. А попадание в этот цикл обеспечивалось достаточно тривиальной стандартной последовательностью операторов.

С появлением MFC этот цикл при помощи достаточно простой стандартной серии макроопределений скрывался от разработчика приложения за картой сообщений. Обсуждение реальных механизмов работы приложения рядовыми программистами не предполагалось.

Обеспечить реакцию приложения на одно из множества стандартных сообщений (событие), приходящих от операционной системы, можно было путем простой модификации соответствующего макроопределения, добавляя к этому макроопределению указатель (ссылку, делегат, событие) на функцию – обработчик события.

kewezok kewezok
kewezok kewezok
Елена Шляхт
Елена Шляхт
Объясните плиз в чем отличие а++ от ++а
Почему результат разный?
int a=0, b=0;
Console.WriteLine(a++); //0
Console.WriteLine(++b); //1
a++;
++b;
Console.WriteLine(a); //2
Console.WriteLine(b); //2