|
|
Win32 API
С появлением разнообразных визуальных средств разработки приложений,
написание графических интерфейсов программ превратилось в подобие детской
игры. Ткнул мышкой - появилась формочка, второй раз ткнул - кнопочка
нарисовалась. Как мне кажется, многие сейчас не помышляют об ином способе
программирования в графической среде. Безусловно, против прогресса не
попрешь, при написании больших проектов все эти удобства очень даже
кстати. Но разговор не об этом. Иногда дело доходит до абсурда, примитивное
приложение пишется с использованием MFC, VCL etc. Такие программы жрут
память, как термиты и занимают, своим жирным телом, лишнее дисковое
пространство. Как правило, MFC/VCL аналоги "весят" в десять
- двадцать раз больше, чем программы написанные на чистом API. А Visual
Basic (да простит меня бог за это словосочетание) с его msvbvmXX.dll?
Да и системных ресурсов расходуется значительно больше (в несколько
раз). Бедные пользователи, отказывая себе в пиве, копят ассигнации на
покупку нового железа. Разве не жалко - бедненьких? Не только же программерам
пиво пить? Есть еще один положительный момент в API кодинге, программист
становится ближе к операционной системе. Соответственно - лучше ее понимает
и контролирует. Да и просто - это очень увлекательное занятие. Повторюсь,
все вышесказанное относится именно к маленьким, простеньким программкам,
в больших проектах все обстоит совершенно иначе.
Надеюсь, убедил. Поехали.
Мы рассмотрим создание простенького оконного интерфейса с минимальной
функциональностью. Это будет простое окошко с двумя полями ввода и двумя
кнопочками. При нажатии на кнопку "Copy", текст из первого
поля ввода будет скопирован во второе. При нажатии на кнопку "Close",
программа завершит свою работу. В дальнейшем оно может послужить шаблоном
для написания других, более сложных, приложений. Будем общаться на языке
C/C++, хотя и Delphi не обидим. Общий принцип один и тот же, различается
только синтаксис. Чтобы работать с системными сообщениями и API-функциями,
необходимо к своему проекту подключить заголовочные файлы; в C/C++ это
windows.h, в Delphi это модули windows и messages.
Любая программа в ОС Windows состоит из трех основных частей: главной
функции, цикла обработки сообщений и оконной функции, которая обрабатывает
все сообщения, посылаемые окну.
Наша программа начинает выполняться с функции WinMain(). Это и есть
главная функция. Функция WinMain() выполняет, обычно, следующие задачи:
• Определяет класс окна. Не путать с классом ООП.
• Регистрирует данный класс в системе.
• Создает главное окно приложения и другие элементы управления.
• Отображает окно на экране.
• Запускает цикл обработки сообщений.
• Объявляется она вот каким образом:
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
• int APIENTRY WinMain(HINSTANCE hInstance,
• HINSTANCE hPrevInstance,
• LPSTR lpCmdLine,
int nCmdShow)
Разберемся с параметрами:
• hInstance - дескриптор текущего экземпляра приложения.
• hPrevInstance - дескриптор предыдущего экземпляра приложения, если
оно запущено.
• lpCmdLine - указатель на строку, содержащую параметры передаваемые
программе при запуске.
• nCmdShow - константа определяющая способ отображения окна. (Смотри
константы SW_).
В Delphi мы не увидим такой картины, в этой среде разработки главная
функция скрывается от программиста компилятором. Хотя, несомненно, она
присутствует в конечном коде. Для регистрации класса окна, необходимо
заполнить поля структуры типа WNDCLASS (в Delphi TWNDCLASS). У нас,
для этого, объявлена переменная wcl.
wcl.hInstance = hInstance;
Дескриптор текущего экземпляра приложения, переменная hInstance инициализируется
функцией WinMain(). В Delphi инициализируется неявным образом.
wcl.lpszClassName = szWinName;
Имя класса. Строковую переменную szWinName мы создали и инициализировали
предварительно.
wcl.lpfnWndProc = WindowFunc;
Указатель на оконную функцию.
wcl.style = 0;
Константа, задающая стиль окна. Для этого используется флаги CS_, я
просто обнулил. Можно задавать комбинацию флагов с помощью битовой операции
"или".
wcl.hIcon = LoadIcon(NULL, IDI_ASTERISK);
Дескриптор иконки приложения, возвращаемый функцией LoadIcon(). Я загрузил
стандартную иконку. Смотри константы IDI_.
wcl.hCursor = LoadCursor(NULL,IDC_ARROW);
Дескриптор курсора приложения, возвращаемый функцией LoadCursor(). Я
загрузил стандартную стрелочку. Смотри константы IDC_.
wcl.lpszMenuName = NULL;
Указатель на строку, задающую имя ресурса меню для данного оконного
класса. Нет меню, нет и указателя.
wcl.cbClsExtra = 0;
Зарезервированное поле. Обнуляем.
wcl.cbWndExtra = 0;
Зарезервированное поле. Обнуляем.
wcl.hbrBackground = (HBRUSH)COLOR_WINDOW;
Цвет окошка. Константа COLOR_WINDOW приводится к типу HBRUSH (в Delphi
приводить не нужно). Также, с помощью функции GetStockObject(), можно
задать цвет кисти окна или фоновый рисунок.
Теперь, смело, регистрируем класс окна.
RegisterClass(&wcl);
В качестве параметра функции RegisterClass передается указатель на структуру
wcl.
Следующей строкой мы создаем наше окно.
hMainWnd = CreateWindow(szWinName, "Простое
окно на API.",
WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ S_MAXIMIZEBOX, CW_USEDEFAULT,
CW_USEDEFAULT, 300, 170, HWND_DESKTOP, NULL, hInstance, NULL);
• Первый параметр - имя класса окна.
• Второй параметр - Заголовок окна.
• Третий параметр - стиль окна. Из стандартного WS_OVERLAPPEDWINDOW,
с помощью операции xor, я изъял возможность масштабирования окна и отключил
кнопку максимизации.
• Четвертый и пятый - положение окна от левого, верхнего угла экрана.
У меня CW_USEDEFAULT, при этом значении система выбирает положение окна
автоматически.
• Шестой и седьмой параметры - ширина и высота окна, соответственно.
• Восьмой параметр - окно владелец. У главного окна, владелец - рабочий
стол (0). У элементов управления - главное окно.
• Девятый - указатель на дескриптор меню. Нет меню, нет и указателя.
• Десятый параметр - Дескриптор текущего экземпляра приложения.
• Одиннадцатый - Используется при создании приложений с MDI-интерфейсом.
Нам не нужен.
Функция возвращает дескриптор созданного окна, который заносится в переменную
hMainWnd.
Дескриптор окна - уникальный номер в системе, по которому идентифицируется
окно или элемент управления.
Далее мы создадим необходимые элементы управления. Все элементы управления
- те же окна, просто они имеют другое имя класса. Классы элементов управления
регистрировать не нужно, они уже предопределены в системе. Кнопка -
класс button. Поле ввода - класс edit. Надпись - класс ststic. Существует
множество классов, которые соответствуют стандартным элементам управления.
Контролы создаем с помощью, знакомой нам, функции CreateWindow() и незнакомой
CreateWindowEx(). CreateWindowEx() позволяет создать окно с расширенным
стилем. Мы используем ее для создания полей ввода. В этой функции добавлен
первый параметр, который и задает этот самый расширенный стиль, остальные
параметры как у CreateWindow(). Элементы управления являются дочерними
окнами, их владелец главное окно.
Создавая контролы, в параметрах функции необходимо указать дескриптор
главного окна, а также стиль окна WS_CHILD. Внешним видом и функциональностью
элементов управления можно манипулировать с помощью флагов: WS_, ES_,
BS_, SS_, объединяя их битовой операцией "или". Создавая контролы,
мы инициализируем соответствующие переменные их дескрипторами, которые
возвращают функции CreateWindow() и CreateWindowEx(). Эти дескрипторы
понадобятся нам для дальнейшей работы с элементами управления. Отображаем,
созданное нами, окно на экране и перерисовываем его.
ShowWindow(hMainWnd, nCmdShow);
UpdateWindow(hMainWnd);
Создаем цикл обработки сообщений.
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Функция GetMessage выбирает очередное сообщение из очереди сообщений
приложения и отправляет его окну.
• Первый параметр - структура типа MSG (в Delphi типа TMSG)
• Второй параметр - дескриптор окна, которому предназначено сообщение.
Если NULL или 0, то все окна приложения.
• Третий и четвертый - позволяют задать диапазон принимаемых сообщений.
Если 0, то все сообщения, адресованные окну.
GetMessage
- возвращает FALSE при появлении сообщения WM_QUIT, в этом случае происходит
выход из цикла и приложение завершает работу.
TranslateMessage
- переводит виртуальные коды клавиш в клавиатурные сообщения.
DispatchMessage
- отправляет сообщение оконной функции, для обработки.
Оконная функция обеспечивает функциональность программы, путем обработки
системных сообщений. Оконная функция является CALLBACK - функцией, т.е.
вызывается операционной системой в ответ на поступившее, новое сообщение.
Оконная функция объявлена таким образом:
LRESULT CALLBACK WindowFunc(HWND hMainWnd, UINT iMsg, WPARAM wParam,
LPARAM lParam)
• HMainWnd - дескриптор главного окна.
• iMsg - номер сообщения. Смотри константы WM_.
• lParam и wParam - параметры сообщения.
При появлении сообщения, мы можем сравнить параметр iMsg с одной из
констант WM_ и запрограммировать соответствующую реакцию программы.
Например: при нажатии левой кнопки мыши, когда указатель мыши находится
над клиентской областью окна, возникает событие WM_LBUTTONDOWN. Вызывается
оконная функция, в параметр iMsg заносится значение константы WM_LBUTTONDOWN,
мы можем проверить условие и запрограммировать нужную нам реакцию программы.
Внутри оконной функции расположен оператор выбора, который и выполняет
вышеописанную задачу. В операторе выбора обязательно должен быть организован
обработчик по умолчанию, который реализуется функцией DefWindowProc(hMainWnd,
iMsg, wParam, lParam);
Если этого не сделать, наша программа издохнет так и не ожив. Множество
сообщений, обрабатывается самой системой, такие как: изменение размеров
окна, сворачивание/разворачивание окна, вызов системного меню etc. Для
этого и служит DefWindowProc().
При работе с оконными элементами управления, окну владельцу посылается
сообщение WM_COMMAND, при этом lParam содержит дескриптор элемента управления,
а старший байт параметра wParam - идентификатор события, вызванного
в элементе управления. Например: при нажатии на кнопку - BN_CLICKED.
Смотри константы BN_, WM_. Закрыть прогу мы можем использовав функцию
PostQuitMessage(0). Эта функция посылает окну сообщение WM_QUIT.
Несколько слов о том, как писать такие программы на Delphi. Создаем
новый проект, запускаем Project Manager, удаляем Unit1 вместе с формой.
Жмем Ctrl + F12 и открываем файл проекта. Удаляем из uses модуль forms,
добавляем туда windows и messages. Удаляем все между begin и end. Заготовка
готова. Можно кодить. Писать программы на чистом API невозможно без
справки, которая всегда должна быть под рукой. Будь ты самим Гейтсом
- все не запомнить. Рекомендую:
• прежде всего - MSDN;
• справочная система Delphi (файл MSTOOLS.HLP);
• на сайте http://www.soobcha.ru/rushelp
есть русская справка по Win32 API.
Вот и все.
Удачи.
Бобаченко Максим ( maxboroda@mail.ru
)
|
|
SOFT |
Анимация Flash
Вот, наконец, и добрались до анимации. Анимация и маленький
размер файла – это то, что сделало Flash таким популярным. |
|
Flash: урок 2
Учимся на примере учителя! Не пропустите второе занятие! |
|
Swift 3D часть 2
Продолжаем обзор основных функций Swift 3D и становимся
настоящими трехмерными художниками! |
|
Пароли
Вот, почитаешь вроде бы журналы, посмотришь, какие советы
полезные там дают. И посмотришь на людей, которые кивают
головой: «Да, да!!». А ведь все равно продолжают ставить
пароли, что-то типа «111», «qwerty» или еще лучше собственное
имя. |
| |
|