Листинг 2.3. Элементарное приложение

program WinAPI;

uses

Windows, Messages;

{$R *.res}

begin

MessageBox(0, 'This is a test', 'Little application', MB_OK);

end.


Зачастую полностью отказываться от классов, реализованных Borland, неоправданно, но для чистоты эксперимента в этой главе будут рассмотрены радикальные примеры, построенные на использовании только Windows API.

Создание окна вручную

Раз уж речь зашла о приложениях с оконным интерфейсом, то самое время приступить к его реализации средствами Windows API. Итак, чтобы создать и заставить работать окно приложения, нужно выполнить следующие операции.

1. Зарегистрировать класс окна с использованием функции RegisterClass или RegisterClassEx.

2. Создать экземпляр окна зарегистрированного ранее класса.

3. Организовать обработку сообщений, поступающих в очередь сообщений.

Пример того, как можно организовать регистрацию класса окна, приведен в листинге 2.4.

Листинг 2.4. Регистрация класса окна

function RegisterWindow():Boolean;

var

wcx: WNDCLASSEX;

begin

ZeroMemory(Addr(wcx), SizeOf(wcx));

//Формирование информации о классе окна

wcx.cbSize:= SizeOf(wcx);

wcx.hInstance:= GetModuleHandle(nil);

wcx.hIcon:= LoadIcon(0, IDI_ASTERISK); //Стандартный значок

wcx.hIconSm:= wcx.hIcon;

wcx.hCursor:= LoadCursor(0, IDC_ARROW); //Стандартный указатель

wcx.hb rBackground:= GetStockObject(WHITE_BRUSH); //Серый цвет фона

wcx.style:= 0;

//..самые важные параметры

wcx.lpszClassName:= 'MyWindowClass'; //Название класса

wcx.lpfnWndProc:= Addr(WindowFunc); //Адрес функции обработки сообщений

//Регистрация класса окна

RegisterWindow:= RegisterClassEx(wcx) <> 0;

end;


Здесь существенным моментом является обязательное заполнение структуры WNDCLASSEX информацией о классе окна. Наиболее необычной вам должна показаться следующая строка:


wcx.lpfnWndProc:= Addr(WindowFunc); //Адрес функции обработки сообщений


Здесь сохранен адрес функции WindowFunc (листинг 2.5) – обработчика оконных сообщений (называемый также оконной процедурой). После вызова функции RegisterClassEx система запомнит этот адрес и будет вызывать указанную функцию-обработчик каждый раз при необходимости обработать сообщение, пришедшее окну. Код простейшей реализации функции WindowFunc приведен в листинге 2.5.

Листинг 2.5. Функция обработки сообщений

//Функция обработки сообщений

function WindowFunc(hWnd:HWND; msg:UINT; wParam:WPARAM; lParam:LPARAM):LRESULT; stdcall;

var

ps: PAINTSTRUCT;

begin

case msg of

WM_CLOSE:

if (hWnd = hMainWnd) then

PostQuit Message(0); //При закрытии окна – выход

WM_PAINT:

begin

//Перерисовка содержимого окна

BeginPaint(hWnd, ps);

Text Out(ps.hdc, 10, 10, 'Текст в окне', 12);

EndPaint(hWnd, ps);

end;

else

begin

//Обработка по умолчанию

WindowFunc:= DefWindowProc(hWnd, msg, wParam, lParam);

Exit;

end;

end;

WindowFunc:= S_OK; //Сообщение обработано

end;


В этой функции реализована обработка сообщения WM_PAINT – запроса на перерисовку содержимого окна. Обработка сообщения WM_CLOSE предусмотрена для того, чтобы при закрытии главного окна происходил выход из приложения. Для всех остальных сообщений выполняется обработка по умолчанию.

Обратите особое внимание на прототип этой функции: типы возвращаемых значений, типы параметров и способ вызова функции (stdcall) должны быть именно такими, как в листинге 2.5. Возвращаемое значение зависит от конкретного сообщения. Чаще всего это S_OK (константа, равная 0) в случае успешной обработки сообщения.

В листинге 2.6 приведена часть программы, использующая регистрацию, создание окна, а также организующая обработку сообщений для созданного окна.

Листинг 2.6. Регистрация и создание окна. Цикл обработки сообщений