Основные компоненты WINDOWS – программы (.Cpp, .H, .Res, .Rc, .Def), компиляция.
Основные компоненты WINDOWS – программы (.cpp, .h, .res, .rc, .def), компиляция.
Файл .cpp содержит исходный текст функций приложения.
Файл .h – заголовочный файл, содержит заголовки или прототипы функций. Файл windows.h должен включаться во все исходные файлы приложений Windows. Он содержит определение типов данных, символических имен констант и прототипы функций программного интерфейса Windows. Также в файле windows.h описаны типы данных, например BYTE, WORD, UINT и др и их производные. Структуры, например типа MSG. Коды сообщений определены в файле windows.h, например WM_CREATE.
Файл .def – файл определения модуля. Дает компоновщику сведения о работе многомодульной программы.
Файл определения модуля.
Первая строка необходима для 16-битных приложений, для 32-битных не нужна.
EXETYPE WINDOWS
Директива CODE имеет следующий синтаксис:
CODE
[FIXED | MOVEABLE]
[DISCARDABLE | NONDISCARDABLE]
[PRELOAD | LOADONCALL]
Опции означают: сегмент фиксированной длины, сегмент может быть перемещён в памяти, может быть выгружен, не может быть выгружен, загружается в память при запуске приложения, загружается при обращении к некоторому его элементу.
Директива DATA имеет следующий синтаксис:
DATA
[NONE | SINGLE | MULTIPLE]
[READONLY | READWRITE]
[PRELOAD | LOADONCALL]
[SHARED | NONSHARED]
Опции означают: сегмент данных отсутствует, 1 сегмент, разделяемый всеми процессами, несколько сегментов данных, данные в сегменте можно читать, но не изменять, можно читать и изменять, сегмент заранее автоматически загружается в память, загружается при обращении к нему, одна копия сегмента разделяется всеми процессами, отдельная копия сегмента загружается для каждого процесса.
Директивы HEAPSIZE и STACKSIZE устанавливают размер локальной динамической памяти и стека программы.
Директива STUB вставляет в файл .EXE кода для WINDOWS программу DOS.
Пример:
EXETYPE windows // для 16 битSTACKSIZE 5120 // Размер стека в байтахHEAPSIZE 1024 // Размер локальной динамической памяти в байтахCODE preload moveable discardable // Атрибуты сегмента кода (что делать с прогой)DATA preload moveable multiple // Атрибуты сегмента данныхзагружается в память при запуске приложения, сегмент может быть перемещён в памяти,
а) может быть выгружен, б) сегмент, разделяемый всеми процессами
Файлы .rc и .res. Файл описания ресурсов (кисти, пиктограммы, шрифты…) имеет расширение .rc. Его необходимо включить в проект приложения наряду с файлами исходных текстов и файлом определения модуля. В процессе сборки загрузочного модуля файл описания ресурсов компилируется и преобразуется в двоичный файл с расширением имени .res. На финальном этапе сборки загрузочного модуля компилятор ресурсов rc.exe вызывается еще раз для записи ресурсов в загрузочный модуль.
Схема создания Windows-программы:
Исходные файлы программы на языке Си компилируются в объектные файлы. Компоновщик собирает приложение и библиотечные файлы с помощью заголовочного файла, который служит для согласования типов и имён переменных и др. объектов.
Файл определения модуля определяет, какие операции разрешены с данными и кодом программы.
Последним шагом является связывание двоичного файла ресурсов (RES) и программного файла (ЕХЕ) в единый Windows - выполнимый файл (ЕХЕ). Для этого снова используется компилятор ресурсов. Эта команда является последней при создании Windows – программы.
Окна, классы и типы окон.
Окна – основной объект в Windows. С точки зрения пользователя Windows окном является прямоугольная область экрана, в которой приложение может что-либо рисовать или писать, а также выполнять все операции взаимодействия с пользователем. Любое приложение Windows можно рассматривать как совокупность окон, внутри которых можно что-либо рисовать или писать. Для каждого окна в приложении определены данные и методы, предназначенные для работы с этими данными (в частности, для рисования в окне).
В ООП используется понятие наследования. Объекты могут наследовать методы других объектов. В Windows также предусмотрен такой механизм, реализуемый с использованием, так называемых, классов окна.
Для каждого класса окна определяется функция окна. При создании окна необходимо указать, к какому классу оно будет принадлежать и, соответственно, какую функцию окна будет использовать для обработки сообщений. Приложения могут создавать собственные классы окна, определяя свои функции окна (и, следовательно, свои методы), либо использовать стандартные, определенные в Windows, классы окна.
Любое создаваемое окно может наследовать свойства уже созданных ранее окон, добавляя свои или переопределяя уже имеющиеся в базовом классе методы. В этом и заключается механизм наследования Windows.
Классы окон имеют стили. Вот ряд из них:
1) CS_DBLCLKS – функция окна будет получать сообщение по двойному щелчку мыши
2) CS_GLOBALCLASS – класс является глобальным и доступен другим приложениям
3) CS_HREDRAW И CS_VREDRAW – внутренняя часть окна будет перерисовываться при изменении ширины и высоты окна
4) CS_NOCLOSE – в системном меню запрещена функция ция закрытия окна
5) CS_CLASSDC – создается единый контекст отображения, который будет использоваться всеми окнами, создаваемыми на базе данного класса
6) CS_OWNDC – для каждого окна, создаваемого на базе данного класса, будет создаваться отдельный контекст отображения.
Определенный в классе окна стиль класса окна используется при создании на базе этого класса всех окон. Для дальнейшего уточнения внешнего вида и поведения окна используется другая характеристика - стиль окна. Стиль окна указывается при создании окна функцией CreateWindow.
Для определения стиля окна используются символические константы с префиксом WS_, определенные в файле windows.h. С помощью этих констант можно определить примерно два десятка стилей окна, однако чаще всего используются несколько основных стилей.
Мы рассмотрим три основных стиля (типа) окон - перекрывающиеся окна (overlapped window), временные окна (pop-up window) и дочерние окна (child window) – несовместимы между собой.
Стили окна:
1) Перекрывающиеся окна WS_OVERLAPPEDWINDOW – используются в качестве главного окна приложения, обязательно имеют заголовок, рамку, внутреннюю часть (клиентская область), рамку. Дополнительно могут иметь – системное меню, полосы прокрутки, кнопки свертки и т.д.
2) Временные окна WS_POPUP – для вывода сообщений, остаются на экране непродолжительное время. Может иметь или не иметь заголовок, системное меню.
Окно (временное, перекрывающееся) может быть окном–владельцем (если оно сворачивается в пиктограмму, все окна, которыми оно владеет, становятся невидимыми, если уничтожить – уничтожаться и подчиненные, подчиненные окна располагаются всегда над поверхностью окна-владельца, загораживая его). Оба типа окна используют экранные координаты.
3) Дочерние окна WS_CHILD – для создания органов управления, напр. кнопки, переключатели. Обычно не имеют рамок, заголовков и т.д. Всегда располагаются на поверхности окна-родителя, система координат – в верхнем левом углу окна-родителя. Только дочерние окна (9-й параметр CreateWindow), могут иметь родителей, перекрывающие и временные окна могут иметь окно-хозяина (8-й параметр CreateWindow).
Другие стили: WS_BORDER, WS_CAPTION, WS_HSCROLL, WS_MAXIMIZE, WS_VISIBLE, WS_MINIMIZE, WS_VSCROLL и другие.
Typedef struct tagWNDCLASS
{
UINT style; // 1. Стиль класса, задается в виде констант с префиксом CS_
// wc.style=0 – стиль по умолчанию
//определяет реакцию окна на изменение его размера, на двойной щелчок мыши и др.
WNDPROC lpfnWndProc;// 2. Адрес функции окна, выполняющей обработку всех сообщений
// поступающих во все окна, созданные на базе данного класса
Окна списка
Предназначены для выбора элемента из некоторого определенного списка. С помощью класса "listbox" можно создавать одноколоночные и многоколоночные списки, имеющие вертикальную (для одноколоночных списков) и горизонтальную (для многоколоночных списков) полосу просмотра.
А) Создание:
hListBox = CreateWindow("listbox", NULL,WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_WANTKEYBOARDINPUT, 30,30,200,100, hwnd, (HMENU) ID_LIST, hInst, NULL);2 – имя/заголовок (должен быть NULL)
8 – идентификатор родит окна, куда будет поступать сообщение WM_COMMAND
Б) Стили окон списка:
LBS_EXTENDEDSEL – Можно выделять несколько рядом расположенных строк
LBS_MULTICOLUMN – для мультиколоночного списка
LBS_MULTIPLESEL – выделять несколько любых строк
LBS_SORT – строки списка будут отсортированы и другие (LBS_NOINTEGRALHEIGHT, LBS_NOREDROW, LBS_OWNERDRAWFIXED)
Список посылает в родительское окно сообщение WM_COMMAND. wParam этого сообщения содержит идентификатор списка, Младшее слово параметра lParam содержит идентификатор окна списка, а старшее - код извещения.
LBN_DBLCLK – Двойной щелчок левой клавишей мыши по строке списка
LBN_KILLFOCUS – потерян фокус ввода
LBN_SELCHANGE – польз-ль выбрал другую строку.
В) Сообщения для списка:
Для управления списком приложение посылает ему сообщения, вызывая функцию SendMessage.
LB_ADDSTRING – добавление строки в список LB_DELETESTRING
LB_DIR – заполнение списка именами файлов и каталогов в текущем каталоге
LB_FINDSTRING – поиск строки в списке.
Окна редактирования
Редактор используется для ввода, редактирования текста и текстовых файлов + может использоваться выделение и работа с буфером.А) Создание (парметры аналогично комбобоксу):
hwndEdit = CreateWindow("edit",NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|ES_LEFT,30, 30, 300, 30, hwnd, (HMENU) ID_EDIT, hInst, NULL);Б) Стили:
ES_MULTILINE – многострочный редактор текста
ES_READONLY – орган управления только для чтения
ES_LOWERCASE (UPPER) – преобразование к строчным (заглавным) символам.
ES_AUTOV(H)SCROLL – автоматическая свертка по вертикали(горизонтали)
ES_CENTER/RIGHT/LEFT –выравнивание текста
ES_PASSWORS – отображение * (для пароля).
В) Коды извещения
Текстовый редактор посылает в родительское окно сообщение WM_COMMAND с параметром wParam, равным идентификатору редактора. Младшее слово параметра lParam содержит идентификатор окна, полученный от функции CreateWindow при создании редактора. Старшее слово параметра lParam содержит код извещения.
EN_CHANGE – изменилось содержимое текста в окне редактирования
EN_H(V)SCROLL – выполнена свертка текста по горизонтали (вертикали)
EN_KILLFOCUS (SETFOCUS)– потерян фокус ввода, получен фокус ввода.
Г) Сообщения (С помощью функции SendMessage) можно посылать различные сообщения редактору:
Пример: WORD nState; nState = (WORD) SendMessage(hEdit, EM_CANUNDO, 0, 0L);
EM_CANUNDO – проверка поддержки отмены последнего действия
Способы создания меню
Меню – важный элемент пользовательского интерфейса Windows. Существует несколько типов меню: 1) Меню приложения; 2) Временное меню; 3) Многоуровневое меню; 4) Плавающее меню.
Включение меню может быть произведено несколькими (тремя) методами:
1) С помощью текстового редактора (простой способ)
2) С помощью графического редактора
3) Непосредственно в оперативной памяти
Рассмотрим наиболее часто используемые способы создания меню.
1. Создание меню в файле ресурсов
а) Описание шаблона в файле ресурсов
nameID MENU [load] [mem] – необязательные параметрыBEGIN . . .ENDnameID – для идентификации шаблона меню (строка, число от 1 до 65535).
MENU – служебное слово
[load] – необязательный; определяет момент загрузки меню в память. (PRELOAD – загрузка сразу после запуска приложения LOADONCALL – загрузка только при отображении меню)
[mem] – необязательный; влияет на тип памяти, выделяемой для хранения шаблона (FIXED, MOVEABLE, DISCARDABLE – не перемещаемый, перемещаемый (по умолчю.), освобождаемый).
б) Описание операторов временных меню POPUP
POPUP text [, param]BEGIN . . .ENDв) Описание операторов строк MENUITEM
MENUITEM text, id [, param] // располагаются между BEGIN и END
text – имя строки, буква после & будет подчеркнута, \t – табуляция, \a – выравнивает по правой границе
id – определяет число, кот.идентиф-ет пункт меню. (приложение получит его с сообщением WM_COMMAND при выборе данного меню)
[param] – бывает CHECKED √, GRAYED, INACTIVE (не активная, но не серая) и другие (MENUBREAK, MENUBARBREAK, HELP – слева от текста вертикальная линия)
MENUITEM SEPARATOR // создание горизонтальной разделительной линии
г) Пример меню
#include "menu.hpp"APP_MENU MENU BEGIN POPUP "&File" BEGIN MENUITEM "&New", CM_FILENEW MENUITEM "&Open...", CM_FILEOPEN ENDENDКонстанты лучше описывать в отдельном файле "menu.hpp":
#define CM_FILEOPEN 24332#define CM_FILENEW 24331
д) Подключение меню к окну приложения
1) При регистрации класса:
Для подключения меню необходимо записать адрес текстовой строки "APP_MENU" в поле lpszMenuName структуры wc, имеющей тип WNDCLASS:
wc.lpszMenuName = "APP_MENU";2) При создании окна:hwnd = CreateWindow(…, APP_MENU, …) - девятый параметр – идентификатор меню. У дочерних окон нет меню.2. С помощью функций в теле программыПриведем перечень основных функций для работы с меню:1.HMENU WINAPI CreateMenu(void);//Создает пустое меню, возвращает ID меню в случае успеха,NULL - иначе2.HMENU WINAPI CreatePopupMenu(void); // Для создания пустого временного меню3.HMENU WINAPI DestroyMenu(void); // Для удаления меню (перед завершением работы)4. Для подключения к окну с идентификатором hwnd меню с идентификатором hmenu вы можете воспользоваться функцией: BOOL WINAPI SetMenu(HWND hwnd, HMENU hmenu);
Перед вызовом этой функции вы должны загрузить меню и получить его идентификатор, например, при помощи функции LoadMenu.
5. Для добавления строк в пустые меню можно воспользоваться функцией:
BOOL WINAPI AppendMenu(HMENU hmenu, UINT fuFlags, UINT idNewItem, LPCSTR lpszNewItem);UINT fuFlags определяет атрибуты элемента меню (MF_CHECKED – √, MF_GRAYED – строка серая, неактивная, MF_ENABLED – нормальный вид, MF_POPUP – с данным элементом связывается временное меню, MF_STRING – элемент является строкой символов).
idNewItem– указывается идентификатор создаваемой строки меню, если это не MF_POPUP
lpszNewItem – разные значения в зависимости от флага (подпись строки, как правило)
AppendMenu(hmenu, MF_ENABLED|MF_POPUP{или MF_STRING},(UINT)hmenuFile {или IDM_FOUR}, "File");
6. Для перерисовки полосы меню для hwnd окна: void WINAPI DrawMenuBar(HWND hwnd);
_______________________________________________________________________________
7. Вставка команды между имеющимися строками:
BOOL WINAPI InsertMenu(HMENU hmenu, UINT idItem, UINT fuFlags, UINT idNewItem, LPCSTR lpszNewItem);
Есть 2 флага (MF_BYCOMMAND и MF_BYPOSITION), в зависимости от которых idItem определит идентификатор или порядковый номер элемента, перед которым будет вставка). Для добавления в конец, необходимо написать -1.
8. Для изменения строк – функция (после нее нужна перерисовка):
BOOL WINAPI ModifyMenu(HMENU hmenu, UINT idItem, UINT fuFlags, UINT idNewItem, LPCSTR lpszNewItem);9. Удаление элементов меню: BOOL WINAPI DeleteMenu(HMENU hmenu, UINT idItem, UINT fuFlags);
10.Удаление элементов меню без освобождения занятых им ресурсов:
Общий контекст отображения.
Этот контекст используется чаще всего и поэтому для ускорения доступа к нему Windows использует кэширование (размер кэша достаточен для хранения только 5 контекстов отображения).
Для получения общего контекста отображения приложение должно вызвать функцию BeginPaint (при обработке сообщения WM_PAINT) или HDC WINAPI GetDC(HWND hwnd), int WINAPI ReleaseDC(HWND hwnd, HDC hdc) (при обработке других сообщений). При этом перед регистрацией класса окна в поле стиля класса окна в структуре WNDCLASS должно быть: wc.style = 0;
Функция BeginPaint возвращает указатель на структуру контекста отображения (HDC) для окнаhwnd:
HDC WINAPI BeginPaint(HWND hwnd, PAINTSTRUCT FAR* lpps);
Перед этим она подготавливает указанное окно для рисования, заполняя структуру типа PAINTSTRUCT (адрес которой передается через lpps) информацией, которую можно использовать в процессе рисования.
Контекст отображения, полученный при помощи функции BeginPaint, необходимо освободить перед завершением обработки сообщения WM_PAINT, вызвав функцию EndPaint: void WINAPI EndPaint (HWND hwnd, const PAINTSTRUCT FAR* lpps);
Каждый раз, когда приложение получает общий контекст отображения, его атрибуты принимают значения по умолчанию. Поэтому установка атрибутов должна выполняться каждый раз после получения общего контекста отображения.
HDC WINAPI CreateDC(
Typedef struct tagRECT
{ int left; х-коор-та верхнего левого угла
Int top; y-коор-та
Int bottom; y-коор-та
} RECT;
Если окно содержит несколько областей, подлежащих обновлению, приложение получает только одно сообщение WM_PAINT, в котором определена область, охватывающая все указанные выше области.
Рассмотрим некоторые функции, имеющие отношение к сообщению WM_PAINT.
1. Функция UpdateWindow имеет следующий прототип: void UpdateWindow(HWND hwnd);
Эта функция посылает сообщение WM_PAINT функции окна, идентификатор которого задан в качестве параметра hwnd, в обход очереди сообщений приложения, если для окна существует непустая область обновления.
2. При помощи функции InvalidateRectвы можете объявить любую область окна как требующую обновления.
void InvalidateRect(HWND hwnd, LPRECT lprc, BOOL fErase);
1 – идентификатор окна, для которого выполняется операция.
2 – дальний указатель на структуру типа RECT, определяющую прямоугольную область, подлежащую обновлению.
3 – необходимость стирания фона окна.
3. Функция ValidateRect удаляет прямоугольную область из списка областей, подлежащих обновлению:
void ValidateRect(HWND hwnd, LPRECT lprc);
Итоги:
А) Приложение должно выполнять вывод в окно "централизованно" в функции окна при получении сообщения WM_PAINT.
Б) При обработке сообщения WM_PAINT для увеличения скорости работы следует использовать координаты области окна, подлежащей обновлению, хотя можно обновить и все окно.
В) Используя специальные функции, приложение в любой момент времени может определить любую область окна как подлежащую (или не подлежащую) обновлению и послать самому себе в соответствующую функцию окна сообщение WM_PAINT.
Дополнительные темы.
Аппаратная независимость
Наряду с графическим приборным интерфейсом и многозадачной средой с обменом сообщениями, аппаратная независимость является третьей основной особенностью Windows, выделяющей ее среди всех графических оболочек.
Аппаратная независимость означает, что прикладная программа, работающая в среде Windows на некотором компьютере с определенным набором технических средств, будет работать на любом компьютере, на котором работает система Windows. Таким образом, в системе Windows программист свободен при создании программ от особенностей и ограничений, накладываемых конкретными техническими устройствами.
Windows обеспечивает аппаратную независимость путем определения минимально необходимых свойств, которыми должны обладать технические устройства. Этот набор свойств является минимально необходимым для функционирования процедур Windows.
1. Основные компоненты WINDOWS – программы (.cpp, .h, .res, .rc, .def), компиляция
2. Структура WINDOWS – программы
3. Сообщения. Источники сообщений,
4. Формирование сообщений, примеры. Очереди.
5. Сообщения. Цикл сообщений, основные компоненты
6. Сообщения. Структура сообщений на примере WM_COMMAND
7. Структура MSG. Обработка сообщений.
8. Средства обработки в приложении и WINDOWS
9. Окна, классы и типы окон.
10. Регистрация класса окна, основные элементы класса
11. Линейки прокрутки, переключатели, окна пометки, окна списка
12. Комбинированные списки, окна редактирования и статические текстовые объекты
13. Способы создания меню
14. Определение диалоговой панели, взаимодействие пользователя с панелью
15. Диалоговые панели, модальные панели.
16. Немодальные панели. Отличие циклов сообщений
17. Ресурсы. Файл ресурсов, текстовый, бинарный. Создание
18. Файл определения модуля. Назначение, основные директивы (относящиеся к коду и данным
19. Графический приборный интерфейс GDI. Состав, назначение
20. Контекст, содержание контекста
21. Общий контекст, родительский, личный, для класса окна, физический
22. Последовательность действий приложения при формир. рисунка
23. Преобразование логических координат в физические и наоборот, единицы измерений, масштабирование
24. Назначение и состав структуры PAINTSTRUCT. Сообщ.WM_PAINT
25. Управление памятью и аппаратная независимость
Основные компоненты WINDOWS – программы (.cpp, .h, .res, .rc, .def), компиляция.
Файл .cpp содержит исходный текст функций приложения.
Файл .h – заголовочный файл, содержит заголовки или прототипы функций. Файл windows.h должен включаться во все исходные файлы приложений Windows. Он содержит определение типов данных, символических имен констант и прототипы функций программного интерфейса Windows. Также в файле windows.h описаны типы данных, например BYTE, WORD, UINT и др и их производные. Структуры, например типа MSG. Коды сообщений определены в файле windows.h, например WM_CREATE.
Файл .def – файл определения модуля. Дает компоновщику сведения о работе многомодульной программы.
Файл определения модуля.
Первая строка необходима для 16-битных приложений, для 32-битных не нужна.
EXETYPE WINDOWS
Директива CODE имеет следующий синтаксис:
CODE
[FIXED | MOVEABLE]
[DISCARDABLE | NONDISCARDABLE]
[PRELOAD | LOADONCALL]
Опции означают: сегмент фиксированной длины, сегмент может быть перемещён в памяти, может быть выгружен, не может быть выгружен, загружается в память при запуске приложения, загружается при обращении к некоторому его элементу.
Директива DATA имеет следующий синтаксис:
DATA
[NONE | SINGLE | MULTIPLE]
[READONLY | READWRITE]
[PRELOAD | LOADONCALL]
[SHARED | NONSHARED]
Опции означают: сегмент данных отсутствует, 1 сегмент, разделяемый всеми процессами, несколько сегментов данных, данные в сегменте можно читать, но не изменять, можно читать и изменять, сегмент заранее автоматически загружается в память, загружается при обращении к нему, одна копия сегмента разделяется всеми процессами, отдельная копия сегмента загружается для каждого процесса.
Директивы HEAPSIZE и STACKSIZE устанавливают размер локальной динамической памяти и стека программы.
Директива STUB вставляет в файл .EXE кода для WINDOWS программу DOS.
Пример:
EXETYPE windows // для 16 битSTACKSIZE 5120 // Размер стека в байтахHEAPSIZE 1024 // Размер локальной динамической памяти в байтахCODE preload moveable discardable // Атрибуты сегмента кода (что делать с прогой)DATA preload moveable multiple // Атрибуты сегмента данныхзагружается в память при запуске приложения, сегмент может быть перемещён в памяти,
а) может быть выгружен, б) сегмент, разделяемый всеми процессами
Файлы .rc и .res. Файл описания ресурсов (кисти, пиктограммы, шрифты…) имеет расширение .rc. Его необходимо включить в проект приложения наряду с файлами исходных текстов и файлом определения модуля. В процессе сборки загрузочного модуля файл описания ресурсов компилируется и преобразуется в двоичный файл с расширением имени .res. На финальном этапе сборки загрузочного модуля компилятор ресурсов rc.exe вызывается еще раз для записи ресурсов в загрузочный модуль.
Схема создания Windows-программы:
Исходные файлы программы на языке Си компилируются в объектные файлы. Компоновщик собирает приложение и библиотечные файлы с помощью заголовочного файла, который служит для согласования типов и имён переменных и др. объектов.
Файл определения модуля определяет, какие операции разрешены с данными и кодом программы.
Последним шагом является связывание двоичного файла ресурсов (RES) и программного файла (ЕХЕ) в единый Windows - выполнимый файл (ЕХЕ). Для этого снова используется компилятор ресурсов. Эта команда является последней при создании Windows – программы.