Архитектура Windows приложения

April 26, 2010 by admin Комментировать »

Каждая Windows-программа (приложение) использует как минимум одно окно – это может быть стандартное окно, диалоговая панель, окно сообщения.

Весь жизненный цикл Windows-программы состоит из трех периодов:

? инициализации – регистрации класса окна, создания и отображения окна;

? выполнения – цикла обработки сообщений;

? завершения – закрытия окна и возврата в среду Windows.

В отличие от операционной системы MSDOS, где работающая программа монопольно владела всеми ресурсами ПК и обращалась к системным ресурсам по мере необходимости, в Windows ситуация другая. Здесь не только приложение обращается к ОС, но и сама ОС, при возникновении каких-либо событий, посылает окну приложения сообщения, вызывая связанную с этим окном специальную функцию для обработки этих сообщений.

Практически каждая Windows-программа состоит из следующих обязательных частей:

? основной вызывающей программы (для Pascal-программ это то, что находится между ключевыми словами Begin и End головной программы);

? создания и описания атрибутов класса окна программы;

? создания экземпляра окна данного класса;

? цикла обработки сообщений;

? оконной функции, обрабатывающей сообщения.

clip_image002

В качестве примера рассмотрим простейшее приложение, состоящее из одного пустого стандартного окна. Вид этого окна приведен здесь. С ним можно манипулировать (перемещать за заголовок, изменять размеры протягиванием мышью за границы или с помощью кнопок) как с обычным окном Windows. Код программы (создан в среде Delphi) приведен ниже. Чтобы в Delphi получить такую программу, следует выполнить, например, следующую последовательность действий:

? вызвать среду программирования Delphi;

? исключить форму Form1 из вашего нового приложения; для этого следует перейти в меню – Project?Remove from Project . В появившемся одноименном диалоговом окне указать на строку Unit1 и нажать на клавишу OK. Тем самым из проекта удаляется модуль Unit1, а вместе с ним и соответствующая форма Form1;

? визуализировать редактор кода Delphi вместе с листингом основной программы (Project1). Это проще всего сделать через меню – Project?View Source. После этого, удалив все лишнее, начать работать с этим кодом как с обычным кодом в Turbo Pascal.

Следует напомнить, что файл с исходным текстом этой программы будет иметь расширение dpr, т.к. мы работаем в Delphi.

Простейшее Windows?приложение

{1} program Win_API_Metodich;

{2} uses Windows, Messages;

{3} const

{4} MyClassName = ‘My_WinAPI_Prog’;

{5} function MyWindowProc(hWindow:HWND; iMsg:LongWord;

WParam, LParam:LongInt):LongInt; stdcall;

{6} begin

{7} MyWindowProc:=0;

{8} case iMsg of

{9} WM_DESTROY : begin

{10} PostQuitMessage(0);

{11} Halt(0);

{12} end;

{13} end;

{14} MyWindowProc:=DefWindowProc(hWindow,iMsg,WParam,LParam);

{15} end;

{16} var

{17} hWindow : HWND;

{18} Msg : TMsg;

{19} WindowClass : TWndClass;

{20} i : Integer;

{21} st : String;

{22} BEGIN

{23} with WindowClass do

{24} begin

{25} style:=CS_HREDRAW OR CS_VREDRAW;

{26} lpfnWndProc:=@MyWindowProc;

{27} cbClsExtra:=0;

{28} cbWndExtra:=0;

{29} hInstance:=SysInit.HInstance;

{30} hIcon:=LoadIcon(0,IDI_APPLICATION);

{31} hCursor:=LoadCursor(0,IDC_ARROW);;

{32} hbrBackground:=GetStockObject(LTGRAY_BRUSH);

{33} lpszMenuName:=”;

{34} lpszClassName:=MyClassName;

{35} end;

{36} if RegisterClass(WindowClass)=0 then

{37} begin

{38} MessageBox(0,’Плохо–RegisterClass’,’Error’,MB_OK);

{39} Halt;

{40} end;

{41} hWindow:=Windows.CreateWindow(MyClassName,’Hello VAK’,

{42} WS_OVERLAPPEDWINDOW OR WS_VISIBLE,

{43} CW_USEDEFAULT,CW_USEDEFAULT,

{44} CW_USEDEFAULT,CW_USEDEFAULT,

{45} 0,0,hInstance,Nil);

{46} if hWindow = 0 then

{47} begin

{48} MessageBox(0,’Плохо–CreateWindow’,’Error’,MB_OK);

{49} Halt;

{50} end;

{51} while GetMessage(Msg,hWindow,0,0) do

{52} begin

{53} TranslateMessage(Msg);

{54} DispatchMessage(Msg);

{55} end;

{56} Halt(Msg.WParam);

{57} END.

В программе используются только средства WinAPI и языка программирования Object Pascal. Все типы, константы и функции из системных библиотек Windows становятся доступными через интерфейс модулей windows.pas и messages.pas системы программирования Delphi.

Сначала (строки 23..35) заполняется данными структура (запись) типа TWndClass – тем самым получает содержание переменная WindowClass – главное окно приложения. Несколько слов об атрибутах этого окна. Строка 25 – задается стиль окна – окно будет автоматически перерисовываться при изменении горизонтального и/или вертикального размеров. Следующее поле (строка 26) – здесь указан адрес оконной функции MyWindowProc, которая будет обрабатывать сообщения, получаемые окном от операционной системы. Строка 29 – указатель (handle) на экземпляр приложения (на программу). В строках 30 и 31 загружаются иконка окна и указатель мыши для окна; с таким набором параметров для функций LoadIcon и LoadCursor эти атрибуты будут стандартными. Если вам необходимо сопоставить окну свою иконку, то делается это следующим образом. Создается файл ресурсов, в котором размещается иконка (это можно сделать, например, с помощью встроенного в Delphi редактора Image Editor). Директивой компилятора {$R filename} этот файл подключается к проекту. Строка 30 в этом случае может быть записана так – hIcon:=LoadIcon(hInstance,’ICON_0′); – здесь ‘ICON_0’ имя иконки в файле ресурсов. Аналогично можно работать и с указателем мыши. Строка 32 определяет параметры кисти, которой будет "закрашена" поверхность окна (у нас это сплошной светло-серый фон). Так как у нашего окна нет меню, то поле записи в строке 33 остается пустым. И последнее, поле в строке 34 – здесь указывается имя класса нашего окна.

После заполнения полей переменной WindowClass, эта переменная передается в качестве параметра в функцию RegisterClass (строка 36) для регистрации операционной системой Windows класса нашего окна. При успешной регистрации (функция RegisterClass возвращает не 0, сразу проверяем данный факт в операторе if), этот класс становится известным операционной системе, и мы можем создавать объекты (экземпляры) этого класса, т.е., собственно, окна.

Далее (строка 41) – создаем экземпляр окна функцией CreateWindow. Первые два параметра – имя класса окна и строка заголовка окна. Третий параметр уточняет стиль окна. Здесь это стиль рамки, наличие кнопок в строке заголовка, факт видимости на экране самого окна и т.п. Следующие четыре параметра задают положение и размеры окна (в данном случае все отдается на "усмотрение" Windows). После этого идут: описатель окна родителя или владельца; указатель на меню окна или идентификатор дочернего окна; описатель нашего приложения; указатель на дополнительные данные для окна. В строках 46..50 проверяется факт создания окна. Если окно создано, то наша переменная hWindow (описатель (handle) окна) получает ненулевое значение. Через эту переменную в дальнейшем будет происходить обращение к окну (аналогия с файловой переменной в Pascal‘е).

В результате действий предыдущих операторов программы на экране появится окно. Теперь программу следует "оживить" – заставить ее реагировать на события. Для этого формируется цикл обработки сообщений – строки 51..55. Функция GetMessage выбирает из очереди окна (hWindow) приложения сообщения (Msg) и, либо передает их на обработку (и возвращает значение true) в тело цикла, либо программа заканчивает свое функционирование (false). Два последних параметра функции указывают, что любые сообщения для программы передаются в этот цикл. Функция GetMessage возвращает false только в случае получения сообщения WM_QUIT – закрыть окно и, т.к. это главное окно приложения, завершить программу. Функция TranslateMessage преобразует сообщения Msg (в основном вызванные клавиатурными действиями пользователя) в иную форму для дальнейшей обработки. Далее, функция DispatchMessage передает сообщение Msg на обработку в функцию окна (в нашем случае в функцию MyWindowProc). В этом месте и происходит вызов функции нашей программы через операционную систему Windows. Этот факт получил в программировании название обратного вызова функции – CallBack – вызов "позади (за спиной)" программы. Сообщение Msg – это структура типа записи, которая содержит информацию о том, кому передано сообщение, какое это сообщение, некоторые детали сообщения, системное время наступления соответствующего события и координаты мыши в момент отправления сообщения.

Сообщения, получаемые приложением, отправляются на обработку в функцию окна – MyWindowProc. Эта функция описана в нашей программе в строках 5..15.

Всего в Windows зарезервировано 1024 номера (0..1023) под различные системные сообщения. Функция окна должна реагировать на любое сообщение ОС, поступающее в приложение. Программист описывает специфические реакции только на те сообщения, которые необходимы по смыслу программы. Для остальных сообщений предусмотрена обработка по умолчанию. Поэтому получается, что вся функциональность приложения сосредоточена в программном коде, описывающем нестандартную (специфическую) реакцию на то или иное сообщение ОС.

В нашем случае функция окна минимальная. Этот минимум определен следующими требованиями:

? обязательно обрабатывается сообщение WM_DESTROY;

? необрабатываемые сообщения передаются назад на обработку ОС.

В функцию окна (строка 5) передаются через параметры: описатель окна (hWindow); код (номер) сообщения (iMsg); дополнительная информация о сообщении (WParam, LParam). Имя функции окна может быть произвольным, однако параметрыстрого фиксированы и задан способ их передачи (stdcall). Явное указание способа передачи параметров функции окна в нашем случае обязательно – мы работаем на языке Pascal в Delphi, а ОС Windows написана на языке C. Еще раз отметим, что функция окна вызывается только ОС при поступлении сообщения окну.

Само тело функции окна имеет простую структуру (строки 7..14). Здесь организован обычный оператор выбора на множестве целочисленных значений кодов (номеров) сообщений. Значения кодов сообщений определены в системных библиотеках (соответственно, в модулях Delphi) как константы. Поэтому код сообщения (строка 9) целесообразно указывать константой, а не числом. В нашем случае обрабатывается только сообщение WM_DESTROY. Это сообщение поступает приложению перед его закрытием. Специфическая обработка данного сообщения позволяет программисту провести здесь операции по закрытию своих рабочих файлов, очистить память от динамических данных и т.п. Мы ничего подобного в нашей программе не делаем, т.к. в этом нет необходимости. После подобных действий вызывается специальная функция PostQuitMessage, которая посылает окну программы сообщение WM_QUIT, что приводит к выходу из цикла обработки сообщений и завершению программы.

Строка 14 предназначена для передачи назад в ОС необработанного функцией окна сообщения для его обработки по умолчанию.

Оставить комментарий

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