Чтение онлайн

на главную - закладки

Жанры

Шрифт:

Не будем заострять внимание на регистрации класса главного окна приложения, так как она аналогична приведенной в листинге 2.4. Рассмотрим создание окна с элементами управления в нем (листинг 2.21).

...

Листинг 2.21.

Создание главного окна приложения (с элементами управления)

program ControlsDemo;

uses

Windows, Messages,

Controls in \'Controls.pas\

{$R *.res}

var

hMainWnd: HWND;

hInst: Cardinal;

mess: MSG;

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

//Создание окна и цикла обработки сообщений

begin

hInst := GetModuleHandle(nil);

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

if not RegisterWindow then Exit;

hMainWnd := CreateWindow(

\'MyWindowClass\', //Имя класса окна

\'Главное окно\', //Заголовок окна

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, //Координата X по умолчанию

CW_USEDEFAULT, //Координата Y по умолчанию

CW_USEDEFAULT, //Ширина по умолчанию

CW_USEDEFAULT, //Высота

по умолчанию

HWND(nil), //Нет родительского окна

HMENU(nil), //Нет меню

hInst,

nil);

if (hMainWnd = HWND(nil)) then Exit;

//Инициализация модуля Controls для работы с главным окном

Controls.hParentWnd := hMainWnd;

Controls.hAppInst := hInst;

//Создание элементов управления

CreateFrame(10, 80, 170, 70, –1, \'Кнопки\');

CreateButton(20, 100, 70, 30, 1001, \'Кнопка 1\');

CreateButton(100, 100, 70, 30, 1002,\'Кнопка 2\');

CreateFrame(200, 10, 200, 180, –1, \'Флажки и переключатели\');

CreateCheck(210, 30, 180, 20, 2001, \'Флажок 1\');

CreateCheck(210, 60, 180, 20, 2002, \'Флажок 2\', True);

CreateOption(210, 100, 180, 20, 3001, \'Переключатель 1\', True);

CreateOption(210, 130, 180, 20, 3002, \'Переключатель 2\', False,

True);

CreateOption(210, 160, 180, 20, 3003, \'Переключатель 3\', True);

CreateFrame(420, 10, 300, 180, –1, \'Списки и статические

надписи\');

CreateLabel(430, 30, 70, 20, -1, \'Надпись\');

CreateCombo(510, 30, 200, 100, 4001);

CreateList(430, 60, 280, 120, 5001);

CreateFrame(200, 200, 200, 240, –1, \'Текстовые поля\');

CreateEdit(210, 220, 180, 20, 6001, \'Текст в текстовом поле\');

CreateMemo(210, 250, 180, 180, 6002, \'Текст в многострочном\'

+ #13 + #10 + \'текстовом поле\');

//Добавление строк в списки

AddToCombo(4001, \'Строка 1\');

AddToCombo(4001, \'Строка 2\');

AddToCombo(4001, \'Строка 3\');

AddToList(5001, \'Строка 1\');

AddToList(5001, \'Строка 2\');

AddToList(5001, \'Строка 3\');

ShowWindow(hMainWnd, SW_NORMAL);

//Запуск цикла обработки сообщений

while (Longint(GetMessage(mess, 0, 0, 0)) <> 0)

do begin

TranslateMessage(mess);

DispatchMessage(mess);

end;

end.

Листинг 2.21 заодно демонстрирует использование некоторых из приведенных ранее функций работы с элементами управления. Выглядит созданное окно так, как показано на рис. 2.3.

Рис. 2.3. Окно с элементами управления

Принцип построения функции обработки сообщений для этого окна приведен в листинге 2.22.

...

Листинг 2.22.

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

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

function WindowFunc(hWnd:HWND; msg:UINT; wParam:WPARAM;

lParam:LPARAM):LRESULT; stdcall;

var

ps: PAINTSTRUCT;

begin

case msg of

WM_PAINT:

begin

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

BeginPaint(hWnd, ps);

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

EndPaint(hWnd, ps);

end;

WM_CLOSE:

if (hWnd = hMainWnd) then

PostQuitMessage(0); //При закрытии этого окна

//завершается приложение

WM_COMMAND:

begin

case LOWORD(wParam) of

//нажата «Кнопка 1»

1001: if HIWORD(wParam) = BN_CLICKED then;

//нажата «Кнопка 2»

1002: if HIWORD(wParam) = BN_CLICKED then;

//установлен «Флажок 1»

2001: if HIWORD(wParam) = BN_CLICKED then;

//установлен «Флажок 2»

2002: if HIWORD(wParam) = BN_CLICKED then;

//установлен «Переключатель 1»

3001: if HIWORD(wParam) = BN_CLICKED then;

//установлен «Переключатель 2»

3002: if HIWORD(wParam) = BN_CLICKED then;

//установлен «Переключатель 3»

3003: if HIWORD(wParam) = BN_CLICKED then;

//выделение в ComboBox

4001: if HIWORD(wParam) = CBN_SELCHANGE then;

//выделение в ListBox

5001: if HIWORD(wParam) = LBN_SELCHANGE then;

//изменен текст в Edit

6001: if HIWORD(wParam) = EN_CHANGE then;

//изменен текст в Memo

6002: if HIWORD(wParam) = EN_CHANGE then;

end;

end;

else

begin

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

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

Exit;

end;

end;

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

end;

Приведенная в листинге 2.22 функция отнюдь не претендует на то, чтобы быть эталоном в порядке классификации сообщений от элементов управления. Иногда бывает полезно сразу классифицировать сообщения не по элементам управления, которые их прислали, а по типу. К тому же в ряде случаев можно предусмотреть один обработчик сообщений сразу для нескольких элементов управления, например для группы переключателей. В таком случае полезным окажется параметр 1 Par am сообщения WM_COMMAND.

Кстати, размер исполняемого файла этого приложения всего 19 Кбайт.

2.4. Стандартные диалоговые окна Windows

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

• CommDlg – для окон открытия/сохранения файла, выбора цвета и шрифта, поиска и замены текста;

• ShlObj и ActiveX – для окна выбора папки (второй модуль нужен для дос

тупа к интерфейсу IMalloc, зачем – будет рассказано далее);

• Windows – помимо объявления основных структур и API-функций, этот модуль содержит объявления функций для работы с окнами подключения и отключения от сетевого ресурса (сетевого диска);

• ShellAPI – для системного окна О программе.

Вариант использования рассматриваемых в этом разделе диалоговых окон приведен в подразд. «Демонстрационное приложение».

...

Примечание

В приведенных далее примерах вызова диалоговых окон можно увидеть не объявленные, но используемые в программах переменные hApplnst и hParentWnd. Подразумевается, что это глобальные переменные, которые инициализируются вне процедур и функций, приведенных в примерах. Для инициализации этих переменных можно также написать специальную процедуру, например с именем I nit, в которую и передавать значения для hParentWnd и hApplnst.

Окно открытия/сохранения файла

Чтобы воспользоваться возможностями окна открытия файла, достаточно задействовать листинг 2.23.

...

Листинг 2.23.

Окно открытия файла

function ShowOpen(strFilter: string; nFilterIndex: Integer = 0;

strInitFileName: string = \'\

var

ofn: OPENFILENAME;

begin

ZeroMemory(Addr(ofn), SizeOf(ofn));

//Формирование буфера (260 символов)

SetLength(strInitFileName, MAX_PATH);

PrepareFilterString(strFilter);

//Заполнение структуры для диалога

ofn.lStructSize := SizeOf(ofn);

ofn.hWndOwner := hParentWnd;

ofn.hInstance := hAppInst;

ofn.lpstrFilter := PAnsiChar(strFilter);

ofn.nFilterIndex := nFilterIndex;

ofn.lpstrFile := PAnsiChar(strInitFileName);

ofn.nMaxFile := MAX_PATH;

ofn.lpstrTitle := pAnsiChar(strTitle);

ofn.Flags := OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or

OFN_HIDEREADONLY;

//Отображение окна диалога и обработка результата

if (GetOpenFileName(ofn) = True) then

ShowOpen := ofn.lpstrFile;

end;

Приведенная в листинге 2.23 функция возвращает не пустую строку – полный путь файла в случае, если пользователь выбрал или ввел имя файла. Здесь главной трудностью является заполнение довольно большой структуры OPENFILENAME. В данном примере используются только базовые возможности диалога открытия файла и лишь некоторые из поддерживаемых им флагов (поле Flags):

• OFN_FILEMUSTEXIST – при успешном завершении работы диалогового окна можно быть уверенным, что результирующий путь является путем существующего файла;

• OFN_PATHMUSTEXI ST – не дает ввести имя файла в несуществующей папке (например, при вводе с:\docs\mydocl.doc, если папки docs не существует, будет выдано соответствующее сообщение);

• OFNHIDEREADONLY – не показывать флажок Только для чтения.

Отдельно рассмотрим, зачем в приведенном примере вызывается дополнительная функция PrepareFilterString (листинг 2.24).

...

Листинг 2.24.

Преобразование строки фильтра

procedure PrepareFilterString(var strFilter: string);

var

i: Integer;

begin

for i := 1 to length(strFilter) do

if (strFilter[i] = \'|\') then strFilter[i] := #0;

end;

Дело в том, что при задании фильтров (поле IpstrFile) требуется, чтобы каждое их название и обозначение были отделены символом #0, а за последним фильтром шла последовательность из двух нулевых символов. На практике задавать строку из нескольких фильтров в следующем виде не особо удобно:

...

\'Текстовые файлы\' + #0 + \'*.txt\' + #0 + \'Все файлы\' + \'*.*\' + #0 + #0

Поэтому часто применяются другие разделители, которые впоследствии преобразуются в символы #0. В нашем случае в качестве разделителя используется символ |, поэтому приведенная выше строка фильтра может быть записана так:

...

\'Текстовые файлы|*.txt|Все файлы|*.*||\'

Согласитесь, что получилось более кратко и понятно.

Теперь обратимся к диалоговому окну сохранения файла. Для его вызова достаточно переделать пример из листинга 2.23 следующим образом (листинг 2.25).

...

Листинг 2.25.

Окно сохранения файла

function ShowSave(strFilter: string; nFilterIndex: Integer = 0;

strInitFileName: string = \'\

strTitle: string = \'Сохранение файла\'):string;

var

ofn: OPENFILENAME;

begin

ZeroMemory(Addr(ofn), SizeOf(ofn));

//Формирование буфера (260 символов)

SetLength(strInitFileName, MAX_PATH);

PrepareFilterString(strFilter);

//Заполнение структуры для диалога

ofn.lStructSize := SizeOf(ofn);

ofn.hWndOwner := hParentWnd;

ofn.hInstance := hAppInst;

ofn.lpstrFilter := PAnsiChar(strFilter);

ofn.nFilterIndex := nFilterIndex;

ofn.lpstrFile := PAnsiChar(strInitFileName);

ofn.nMaxFile := MAX_PATH;

ofn.lpstrTitle := pAnsiChar(strTitle);

ofn.Flags := OFN_PATHMUSTEXIST or OFN_OVERWRITEPROMPT;

//Отображение окна диалога и обработка результата

if (GetSaveFileName(ofn) = True) then

ShowSave := ofn.lpstrFile;

end;

Поделиться:
Популярные книги

Вернувшийся: Корпорация. Том III

Vector
3. Вернувшийся
Фантастика:
космическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Вернувшийся: Корпорация. Том III

Эпоха Опустошителя. Том II

Павлов Вел
2. Вечное Ристалище
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эпоха Опустошителя. Том II

Кодекс Охотника

Винокуров Юрий
1. Кодекс Охотника
Фантастика:
фэнтези
юмористическое фэнтези
попаданцы
боевая фантастика
5.00
рейтинг книги
Кодекс Охотника

Афганский рубеж 4

Дорин Михаил
4. Рубеж
Фантастика:
попаданцы
альтернативная история
6.00
рейтинг книги
Афганский рубеж 4

Отверженный III: Вызов

Опсокополос Алексис
3. Отверженный
Фантастика:
фэнтези
альтернативная история
7.73
рейтинг книги
Отверженный III: Вызов

Последний Паладин. Том 7

Саваровский Роман
7. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 7

Абсурдистан

Штейнгарт Гари
Проза:
современная проза
5.00
рейтинг книги
Абсурдистан

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Принадлежать им

Зайцева Мария
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Принадлежать им

Запрети любить

Джейн Анна
1. Навсегда в моем сердце
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Запрети любить

Чужая семья генерала драконов

Лунёва Мария
6. Генералы драконов
Фантастика:
фэнтези
5.00
рейтинг книги
Чужая семья генерала драконов

Студиозус 2

Шмаков Алексей Семенович
4. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус 2

Барон диктует правила

Ренгач Евгений
4. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон диктует правила

Элизиум. Аликс и монеты

Андерсон Александр
1. Элизиум
Фантастика:
фэнтези
сказочная фантастика
8.98
рейтинг книги
Элизиум. Аликс и монеты