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

Форма

Метод WndProc

В классах-наследниках класса Control (в классах Form, "Кнопка", "Список", ...) объявляется виртуальный метод WndProc, который обеспечивает обработку передаваемых приложению сообщений Windows. Переопределение этого метода позволяет задавать специфику поведения создаваемого элемента управления, включая и саму форму.

protected virtual void WndProc(ref Message m);
 Parameters
 m 
 The Windows Message to process.

Все сообщения после PreProcessMessage метода поступают к WndProc -методу. В сущности, ничего не изменилось! WndProc -метод соответствует WindowProc -функции.

Пример переопределения WndProc

Реакция приложения на передаваемые в оконную процедуру WndProc сообщения Windows определяет поведение приложения. Метод WndProc в приложении может быть переопределен. При его переопределении следует иметь в виду, что для адекватного поведения приложения в среде Windows необходимо обеспечить вызов базовой версии метода WndProc. Все, что не было обработано в рамках переопределенного метода WndProc, должно обрабатываться в методе базового класса.

Ниже демонстрируется пример переопределения метода WndProc. В результате переопределения приложение "научилось" идентифицировать и реагировать на системное сообщение WM_ACTIVATEAPP, которое передается каждому приложению при переводе приложения из активного состояния в пассивное и обратно:

using System;
 using System.Drawing;
 using System.Windows.Forms;

 namespace csTempWindowsApplication1
 {
 public class Form1 : System.Windows.Forms.Form
 {
 // Здесь определяется константа, которая содержится в "windows.h" 
 // header file.
 private const int WM_ACTIVATEAPP = 0x001C;
 // Флаг активности приложения. 
 private bool appActive = true;

 static void Main() 
 {
 Application.Run(new Form1());
 }
 public Form1()
 { 
 // Задание свойств формы.
 this.Size = new System.Drawing.Size(300,300);
 this.Text = "Form1";
 this.Font = new System.Drawing.Font("Microsoft Sans Serif",
                                      18F,
                                      System.Drawing.FontStyle.Bold,
                                      System.Drawing.GraphicsUnit.Point,
                                      ((System.Byte)(0))
                                     );
 }

 // Вот переопределенная оконная процедура. 
 protected override void WndProc(ref Message m) 
 {
 // Listen for operating system messages.
 switch (m.Msg)
 {
 // Сообщение под кодовым названием WM_ACTIVATEAPP occurs when the application
 // becomes the active application or becomes inactive.
 case WM_ACTIVATEAPP:
 // The WParam value identifies what is occurring.
 appActive = (((int)m.WParam != 0));

 // Invalidate to get new text painted.
 this.Invalidate(); 
 break; 
 }
 base.WndProc(ref m);
 }

 protected override void OnPaint(PaintEventArgs e) 
 {
 // Стиль отрисовки текста определяется состоянием приложения.
 if (appActive) 
 {
 e.Graphics.FillRectangle(SystemBrushes.ActiveCaption,20,20,260,50);
 e.Graphics.DrawString("Application is active",
                            this.Font, SystemBrushes.ActiveCaptionText, 20,20);
 }
 else 
 {
 e.Graphics.FillRectangle(SystemBrushes.InactiveCaption,20,20,260,50);
 e.Graphics.DrawString("Application is Inactive",
                            this.Font, SystemBrushes.ActiveCaptionText, 20,20);
 }
 }

 }
 }
Листинг 16.8.

Контекст приложения

Создается простейшее Windows-приложение с единственной формой. Точка входа в приложение – статическая функция Main – располагается непосредственно в классе формы. Здесь форма создается, инициализируется, показывается:

// Этот явно избыточный набор пространств имен формируется
 // Visual Studio по умолчанию.
 using System;
 using System.Drawing;
 using System.Collections;
 using System.ComponentModel;
 using System.Windows.Forms;
 using System.Data;

 namespace xForm
 {

 // Summary description for Form1.

 public class Form1 : System.Windows.Forms.Form
 {

 // Required designer variable.

 private System.ComponentModel.Container components = null;

 public Form1()
 {
 //
 // Required for Windows Form Designer support
 //
 InitializeComponent();

 //
 // TODO: Add any constructor code after InitializeComponent call
 //
 }


 // 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.Size = new System.Drawing.Size(300,300);
 this.Text = "Form1";
 }
 #endregion

 // The main entry Point for the application.

 static void Main() 
 {
 Application.Run(new Form1());
 }
 }
 }
Листинг 16.9.

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

ApplicationContext (контекст приложения) специфицирует и объединяет контекстную информацию о потоках приложения.

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

  • Пара конструкторов, которые обеспечивают инициализацию объекта. Один из них в качестве параметра использует ссылку на объект – представитель класса формы.
  • Свойство MainForm, определяющее главную форму данного контекста приложения.
  • Общедоступные методы Dispose (Overloaded. Releases the resources used by the ApplicationContext), Equals (inherited from Object ), ExitThread (Terminates the message loop of the thread), GetHashCode (inherited from Object ), GetType (inherited from Object), ToString (inherited from Object ).
  • Событие ThreadExit, которое происходит, когда в результате выполнение метода ExitThread прекращает выполнение цикл обработки сообщений.
  • Protected методы Dispose (Releases the resources used by the ApplicationContext), ExitThreadCore (Terminates the message loop of the thread), Finalize, MemberwiseClone, OnMainFormClosed.

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

// По сравнению с предыдущим примером сократили количество
// используемых пространств имен. Оставили только необходимые. 
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace xApplicationContext
{
public class xForm : System.Windows.Forms.Form
{

private System.ComponentModel.Container components = null;
private MyApplicationContext appContext; 

// Модифицировали конструктор.
// 1. Формы украшены названиями.
// 2. В соответствии с замыслом, о факте закрытия формы
// должно быть известно объекту - контексту приложения,
// который осуществляет общее руководство приложением.
public xForm(string keyText, MyApplicationContext contextKey)
{
this.Text = keyText;
appContext = contextKey;
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.Size = new System.Drawing.Size(300,300);
// Объект - контекст приложения должен отреагировать на
// факт (событие) закрытия формы. Здесь производится 
// подписка объекта - контекста приложения на событие
// закрытия формы. 
this.Closed+=new EventHandler(appContext.OnFormClosed);
}
#endregion

// The main entry Point for the application. 
// Точка входа в приложение перенесена в класс
// контекста приложения.

//static void Main() 
//{
//	Application.Run(new xForm());
//}
}

// The class that handles the creation of the application windows
public class MyApplicationContext : ApplicationContext 
{

private int formCount;
private xForm form1;
private xForm form2;


// Конструктор Контекста приложения.
private MyApplicationContext() 
{
formCount = 0;
// Create both application forms and handle the Closed event
// to know when both forms are closed.
form1 = new xForm("Form 0",this);
formCount++;

form2 = new xForm("Form 1",this);
formCount++;
form1.Show();
form2.Show();
}

public void OnFormClosed(object sender, EventArgs e)
{
// Форма закрывается – счетчик открытых форм уменьшается.
// Приложение сохраняет работоспособность до тех пор,
// пока значение счетчика не окажется равным 0.
// После этого – Exit().
formCount––;
if (formCount == 0) 
{
Application.Exit(); 
}
}

static void Main(string[] args) 
{
// Создается объект – представитель класса MyApplicationContext,
// который берет на себя функции управления приложением.
MyApplicationContext context = new MyApplicationContext();
// Приложение запускается для объекта контекста приложения.
Application.Run(context);
}
}
}
Листинг 16.10.
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