MZero #7 [сентябрь 2004]
Меню
  Главная
  Авторам
  Разделы
  Команда MZero
  Клуб ICQ
HiTech
  В Канаде хотят запретить дышать алкоголем .
  Пять машин и технологий готовы изменить наш мир.
  Плавающие ботинки превращают людей в водомерок.
Моддинг
  СветоНожки для компа своими руками.
  Светильник из шариковой ручки.
  Светильник из шариковой ручки 2.
Mobile
  Проба КПК Fujitsu-Siemens Pocket-LOOX 420.
  "Мобильное телевидение" .
  Электробабло-2. Теперь в телефонной трубке.
Windows
  Как создать загрузочную дискету в Windows NT/2000?
  Microsoft разработала защищенную Windows XP .
Пингвин'zzz
  Пингвинодизайн: Стань крутым *nix-дизайнером!
  Bluetooth и Linux на примере Nokia 7650.
  Проблемы русификации в Linux.
Delphi
  Создание графического интерфейса пользователя средствами Win32 API .
  Создание плагинов к Winamp.
Интернет - программинг
  Анатомия межсайтового скриптинга.
  Flash-навигатор.
  PHP Inside #0 [Журнал для начинающи и проффесионалов].
Web - desigN
  Книги по web-дизайну.
  Четыре правила профессионального дизайна. Часть I .
  Четыре правила профессионального дизайна. Часть II .
  Четыре правила профессионального дизайна. Часть III .
  Четыре правила профессионального дизайна. Часть IV .
Жизнь в сети
  И на Google есть пятна.
  МАСЯНЯ IS BACK!!!
Софт
  WebSubmitter— на пути к известности.
  Управляем цифровой фотографией.
  Оживление цвета.
Чтиво
  Пауло Коэльо - Алхимик.
  С любовью Алиса.
Games
  Sacred (Князь тьмы).
  The Matrix Online.
  Far Cry.
  Cheats.
Интервью
  Что нового у ReGet?
  С разработчиками файлового менеджера Фрегат.
  С хакером, взломавшим Lenta.ru
Музыка
  Моя музыка существует отдельно от меня.
  Осёл-меломан.
  Outkast.
Стиль
  Гламурная девушка.
  Женская мода. Осень: твид, плащи, метал и космический шик.
  Стильная одежда для маленьких модников.
Здоровье
  Как правильно загорать.
Это мы смотрим...
  Тупичок Гоблина - Ночной дозор.
  Россия наносит ответный удар, сняв свой первый блокбастер.
Наука
  Спутник сфотографировал эльфов и фей.
  Переведи меня!
Pick up
  Как познакомиться с девушкой.
  "15 никогда" для использования в общении со слабым полом. (смешно)
www.mzero.by.ru
Delphi

Создание графического интерфейса пользователя средствами 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)
    Разберемся с параметрами:
    • 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.

Скачать пример: createwnd.zip (архив содержит файлы windows.cpp и windows.dpr). Вот и все. Удачи.




наверх Автор: Бобаченко Максим Источник: http://www.delphikingdom.ru/


Copyright by MZero
Копирование и использование данных материалов разрешается
только в случае указания на журнал "
MZero", как на источник получения информации.
При этом во всех ссылках обязательно явное указание адреса вэб-сайта
www.mzero.by.ru.
Журнал тестировался на IE 5.0/6.0; Opera; Mozilla; MYIE 2.0; Netscape