Читайте также:
|
|
В Windows Forms термин "форма" - синоним окна верхнего уровня. Главное окно приложения - форма. Любые другие окна верхнего уровня, которые имеет приложение - также формы. Окна диалога также считаются формами. Несмотря на название, приложения, использующие Windows Forms, не выглядят как формы. Подобно традиционным Windows-приложениям приложения осуществляют полный контроль над событиями в собственных окнах.
Программисты видят Microsoft.NET через линзу.NET Framework class library. Представьте MFC на порядок больше и вы получите точную картину о ширине и глубине.NET Framework class library. Чтобы облегчить противоречия в обозначениях и придать организацию многим сотням классов,.NET Framework class library разбита на иерархические разделы по именам. Корневой раздел, System, определяет фундаментальные типы данных, используемые всеми приложениями.NET.
Приложения, использующие Windows Forms используют классы System.WinForms.
· Form, который моделирует поведение окон или форм;
· Menu, который представляет меню;
· Clipboard, который дает возможность приложениям Windows Forms использовать буфер обмена.
В основе почти каждого приложения, написанного с применением Windows Forms, - производный класс от System.WinForms.Form. Образец этого класса представляет главное окно приложения. System.WinForms.Form имеет множество свойств и методов, которые имеют богатый программный интерфейс к формам.
Приложения, основанные на Windows Forms, которые используют кнопки, списки и другие типы компонентов Windows, используют классы управления System.WinForms, значительно упрощающие программирование управления. \
Другой важный "строительный" блок приложения, который использует Windows Forms - класс System.WinForms.Application. Этот класс содержит статический метод Run, который загружает приложение и отображает окно.
Другая важная грань модели программирования Windows Forms - механизм, который формы используют для ответа на ввод в меню, средств управления и других элементов GUI приложения. Традиционные Windows-приложения обрабатывают сообщения WM_COMMAND и WM_NOTIFY используя события процесса Windows Forms. В C# и на других языках, которые поддерживают.NET Common Language Runtime (CLR), события - члены типа первого класса наравне с методами, полями и свойствами. Фактически все управляющие классы (control classes) Windows Forms (а также и многие неуправляющие классы) создают события. Например, кнопка (экземпляр System.WinForms.Button) после нажатия создает событие Click. Форма, которая должна ответить на нажатие кнопки может использовать следующий код, чтобы соединить кнопку на обработчиком события Click:
MyButton.Click += new EventHandler (OnButtonClicked);
...
private void OnButtonClicked (object sender, EventArgs e)
{
MessageBox.Show ("Click!");
}
EventHandler - специальный обработчик событий, который выполняет метод OnButtonClicked когда MyButton создает событие Click. Первый параметр OnButtonClicked идентифицирует объект, который вызвал событие. Второй параметр в основном бессмысленен для события Click, но используется некоторым другие типами событий, чтобы передать дополнительную информацию.
Приложение "Hello World" с Windows Forms
ЛИСТИНГ 1
using System;
using System.WinForms;
using System.Drawing;
public class MyForm: Form
{
public MyForm ()
{
Text = "Windows Forms Demo";
}
protected override void OnPaint (PaintEventArgs e)
{
e.Graphics.DrawString ("Hello, world", Font,
new SolidBrush (Color.Black), ClientRectangle);
}
public static void Main (string[] args)
{
Application.Run (new MyForm ());
}
}
20.Управляемый код и данные. Особенности создания приложений в среде Framework.Net - единый каркас среды разработки
В каркасе Framework.Net можно выделить два основных компонента:
● статический - FCL (Framework Class Library) - библиотеку классов каркаса;
● динамический - CLR (Common Language Runtime) - общеязыковую исполнительную среду.
Управляемый C++
Прежде всего, рассмотрим важные для нас особенности самой.NET Framework.
Среди основных задач подобных сред исполнения программ можно отметить следующие:
● автоматическая сборка мусора, избавляющая программиста от необходимости помнить о таких мелочах, как вызовы деструкторов и освобождение памяти, занимаемой объектами;
● гарантированная инициализация переменных, контроль типов и проверка допустимости значений аргументов во время исполнения, что, в свою очередь, позволяет защитить систему от неправильно работающих программ, тем самым, повышая её надёжность;
● сокрытие деталей работы с элементами операционной системы, включая многозадачность, пользовательский интерфейс, управление ресурсами и т.п., что позволяет абстрагироваться от деталей работы в конкретной ОС и, в некоторых случаях, создавать переносимые приложения.
C++ разрабатывался как универсальный язык, в том числе и для решения задач реального времени, низкоуровневого программирования и написания драйверов аппаратных устройств, в связи с чем применение в нём автоматической сборки мусора, неявной инициализации переменных и проверки допустимости значений аргументов является неоправданными из-за потери производительности.
Прямая работа с операционной системой и различными API, а также “мирное
C++ остался самим собой. Можно не инициализировать указатели, выходить за границы массивов, забывать освобождать выделенную память, и никакие CLR не могут нам в этом помешать. С другой стороны, C++ должен уметь работать с объектами CLR и позволять этим объектам работать со своим кодом, т.е. играть по правилам той среды, в которой он используется.
Для решения этих задач разработчики из Microsoft пошли по пути расширения возможностей языка, добавления в него ряда ключевых слов, директив и опций компилятора. Как раз это расширение и получило название Managed Extensions for C++.
Managed Extensions for C++ позволяет C++ программам использовать следующие объекты CLR:
● Управляемые типы, массивы и указатели
● Интерфейсы
● Строки
● Делегаты и события
● Свойства
● Метаданные
__gc
Идентификатор __gc применяется для объявления сложных типов, массивов и указателей, размещаемых в куче среды исполнения CLR. Сокращение gc, скорее всего, происходит от garbage collection. Рассмотрим пример:
__gc class Foo { public: ~Foo(); void Fun(); }; void test() { Foo *p = new Foo; p->Fun(); } |
__gc arrays
Так же, как и для объектов управляемых типов, память для управляемых массивов выделяется в куче CLR. Массивы могут содержать переменное число элементов и всегда инициализируются при создании. Для объявления управляемых массивов используется специальный синтаксис:
int ar __gc[] = new int __gc[10]; ar[0] = 1; ar = new int __gc[20]; |
Создать массив объектов Foo можно следующим образом
Foo *ar[] = new Foo*[10]; ar[0] = new Foo; |
Как вы можете заметить, в примере с объектом Foo мы не использовали ключевого слова __gc. В этом нет необходимости, так как компилятор уже знает, что имеет дело с управляемым типом.
Для возвращения массивов из функций и для объявления многомерных массивов в MC++ также применяется новый причудливый синтаксис:
int test()__gc[] { return new int __gc[10]; } void test() { int ar __gc[,] = new int __gc[10,20]; for (int i=0; i<ar->GetLength(0); i++) for (int j=0; j<ar->GetLength(1); j++) ar[i,j] = i + j; } |
Из последнего примера явно следует, что управляемые массивы не являются привычными для нас массивами C++. Скорее, это объекты со своим интерфейсом, и, к сожалению, мы не можем применять для них обычные в C++ методы работы с массивами. Это легко проверить на следующем примере:
void test() { int ar __gc[] = new int __gc[10]; int *p1 = ar; // ошибка int *p2 = &ar[0]; // ошибка } |
__pin
Тем не менее, было бы странным не иметь доступа к памяти управляемых объектов. И такая возможность есть. Managed Extensions for C++ включает ещё одно ключевое слово - __pin, позволяющее объявлять pinning pointers на управляемые объекты. Один из переводов этого термина мог бы звучать, как “прикольные указатели”, но боюсь, что это может быть неправильно понято. Поэтому мы будем пользоваться оригиналом или, в крайнем случае, транслитерацией.
Pin-указатели позволяют зафиксировать объект в памяти и сделать его неперемещаемым до тех пор, пока такой указатель существует как объект и его значение не равно нулю. Рассмотрим пример:
void test() { int ar __gc[] = new int __gc[10]; int __pin *p = &ar[0]; memset(p-100,-1,2000); // делаем, что хотим } |
__nogc
Как нетрудно догадаться, это ключевое слово обозначает обычный неуправляемый тип C++. Этот модификатор используется компилятором по умолчанию и приведён здесь лишь для полноты картины.
__value
Согласитесь, размещать абсолютно все переменные в управляемой куче расточительно, особенно если это просто байт или целое, использующиеся в качестве счётчика. Как известно, размещение переменных в стеке является наиболее эффективным для простых переменных с коротким жизненным циклом. Идентификатор __value позволяет объявлять управляемые типы, которые, в отличие от gc-типов, могут размещаться как в управляемой куче, так и в стеке программы. В таблице 1 приведено соответствие между примитивными типами C++ и управляемыми типами CLR.
С помощью модификатора __value можно объявлять как классы и структуры, так и управляемые перечислимые типы. Более того, это единственный способ объявлять перечисления, которые будет понимать CLR. Например:
__value class cl { int a; }; __value struct st { int a; }; __value enum en: int { En1, En2 }; |
__box
Ключевое слово __box создаёт обёртку для value-типов, после чего их можно использовать так же, как и gc-классы. Такие языки, как C# и VB.NET, создают обёртки для value-типов автоматически, в MC++ неявное преобразование запрещено из соображений производительности.
Дата добавления: 2015-10-13; просмотров: 280 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Особенности использования, преимущества и недостатки кроссплатформенной среды разработки QT creator. | | | Глава 1 |