Александр Чиртик - Программирование в Delphi. Трюки и эффекты Страница 8
- Категория: Компьютеры и Интернет / Программирование
- Автор: Александр Чиртик
- Год выпуска: -
- ISBN: -
- Издательство: -
- Страниц: 15
- Добавлено: 2019-05-29 10:56:59
Александр Чиртик - Программирование в Delphi. Трюки и эффекты краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «Александр Чиртик - Программирование в Delphi. Трюки и эффекты» бесплатно полную версию:Как и все издания данной серии, эта книга адресована тем, кто хочет научиться делать с помощью уже знакомых программных пакетов новые интересные вещи. Издание будет полезно и новичкам, и опытным программистам. Автор описывает удивительные возможности, скрытые в языке, и на примерах учит читателя программистским фокусам – от «мышек-невидимок» и «непослушных окон» до воспроизведения MP3 и управления офисными программами Word и Excel из приложений Delphi. Купив эту книгу, вы пройдете непростой путь к вершинам программистского мастерства весело и интересно.
Александр Чиртик - Программирование в Delphi. Трюки и эффекты читать онлайн бесплатно
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas'{Form1};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Теперь обратите внимание на модули Windows и Messages. В первом определены константы, структуры данных, необходимые для работы с функциями Windows API, и, конечно же, объявлены импортируемые из системных библиотек API-функции. В модуле Messages можно найти определения констант и структур, предназначенных для работы с Windows-сообщениями (подробнее об этом смотрите в подразделе «Реакция на сообщения элементов управления» гл. 2 (стр. 66)).
Собственно, этих двух модулей должно хватить для того, чтобы реализовать оконное приложение, использующее, правда, только стандартные функции Windows API и стандартные элементы управления. В листинге 2.3 приведен пример элементарного Windows-приложения. Главное, на что сейчас стоит обратить внимание, – это размер приложения: всего 15 Кбайт.
Листинг 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. Регистрация и создание окна. Цикл обработки сообщенийprogram Window;
uses
Windows, Messages;
{$R *.res}
var
hMainWnd: HWND;
mess: MSG;
...
begin
//Создание окна
if not RegisterWindow() then Exit;
hMainWnd:= CreateWindow(
'MyWindowClass', //Имя класса окна
'Главное окно', //Заголовок окна
WS_VISIBLE or WS_OVERLAPPEDWINDOW,//Стиль окна (перекрывающееся, видимое)
CW_USEDEFAULT, //Координата X по умолчанию
CW_USEDEFAULT, //Координата Y по умолчанию
CW_USEDEFAULT, //Ширина по умолчанию
CW_USEDEFAULT, //Высота по умолчанию
HWND(nil), //Нет родительского окна
HMENU(nil), //Нетменю
GetModuleHandle(nil),
nil);
//Запуск цикла обработки сообщений
while (Longint(GetMessage(mess, HWND(nil), 0, 0)) <> 0)
do begin
TranslateMessage(mess);
DispatchMessage(mess);
end;
end.
В листинге 2.6 на месте многоточия должны находиться коды функций WindowFunc и Regis terWindow. При создании окна использовались только стили WS_VI SIBLE и WS_OVERLAPPEDWINDOWS. Но это далеко не все возможные стили окон. В приложении 2 приведен список всех стилей окон (если другого не сказано, то стили можно комбинировать с помощью оператора Or). Кроме функции CreateWindow, для создания окон можно использовать функцию CreateWindowEx. При этом появится возможность указать дополнительный (расширенный) стиль окна (первый параметр функции CreateWindowEx). Список расширенных стилей также приведен в приложении 2.
В конце листинга 2.6 записан цикл обработки сообщений:
while (Longint(GetMessage(mess, hMainWnd, 0, 0)) > 0)
do begin
TranslateMessage(mess);
DispatchMessage(mess);
end;
Здесь API-функция GetMessage возвращает значения больше нуля, пока в очереди не обнаружится сообщение WM_QUIT. В случае возникновения какой-либо ошибки функция GetMessage возвращает значение -1. Функция TranslateMessage преобразует сообщения типа WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN иWM_ SYSKEYUP в сообщения символьного ввода(WM_CHAR, WM_SYS CHAR, WM_ DEADCHAR, WM_SYSDEADCHAR). Функция DispatchMessage в общем случае (за исключением сообщения WM_TIMER) вызывает функцию обработки сообщений нужного окна.
Внешний вид самого окна, создаваемого в этом примере, показан на рис. 2.2.
Рис. 2.2. Окно, созданное вручную
Кстати, пока размер приложения равен всего 16 Кбайт.
Окно с элементами управления
После того как вы ознакомились с созданием простейшего окна, самое время позаботиться о его наполнении элементами управления. Для стандартных элементов управления в системе уже зарегистрированы классы окон:
• BUTTON – оконный класс, реализующий работу обычной кнопки, флажка, переключателя и даже рамки для группы элементов управления (GroupBox);
• COMBOBOX – раскрывающийся список;
• EDIT – текстовое поле, может быть как однострочным, так и многострочным, с полосами прокрутки и без;
• LISTBOX – список;
• SCROLLBAR – полоса прокрутки;
• STATIC – статический текст (он же Label, надпись, метка и пр.), кроме текста, может содержать изображение.
Ввиду большого количества возможных стилей окон элементов управления их перечень здесь не приводится, но его можно найти в приложении 2.
Создание элементов управления
Целесообразно написать более краткие функции создания элементов управления, чтобы, формируя интерфейс формы «на лету», не приходилось усложнять код громоздкими вызовами функций CreateWindow или CreateWindowEx. Этим мы сейчас и займемся. Сразу необходимо отметить: предполагается, что все функции помещены в модуль (модуль Controls в файле Controls.pas), в котором объявлены глобальные переменные hAppInst и hParentWnd. Эти переменные инициализируются перед вызовом первой из перечисленных ниже процедур или функций создания и работы с элементами управления (инициализацию можно посмотреть в листинге 2.21).
Внимание!
Обратите внимание на параметр id функций создания и манипулирования элементами управления. Это целочисленное значение идентифицирует элементы управления в пределах родительского окна.
Для создания обычных кнопок можно использовать функцию из листинга 2.7 (все рассмотренные далее функции создания элементов управления возвращают дескриптор созданного окна).
Листинг 2.7. Создание кнопкиfunction CreateButton(x, y, width, height, id:Integer;
caption: String):HWND;
begin
CreateButton:=
CreateWindow('BUTTON', PAnsiChar(caption), WS_CHILD or WS_VISIBLE or
BS_PUSHBUTTON or WS_TABSTOP, x, y, width, height,
hParentWnd, HMENU(id), hAppInst, nil);
end;
Приведенная в листинге 2.8 функция создает флажок и устанавливает его.
Листинг 2.8. Создание флажкаfunction CreateCheck(x, y, width, height, id: Integer; caption: String;
checked: Boolean):HWND;
var
res: HWND;
begin
res:=
CreateWindow('BUTTON', PAnsiChar(caption), WS_CHILD or WS_VISIBLE or
BS_AUTOCHECKBOX or WS_TABSTOP, x, y, width, height,
hParentWnd, HMENU(id), hAppInst, nil);
if ((res <> 0) and checked) then
SendMessage(res, BM_SETCHECK, BST_CHECKED, 0); //Флажок установлен
Жалоба
Напишите нам, и мы в срочном порядке примем меры.