Александр Чиртик - Программирование в Delphi. Трюки и эффекты Страница 10
- Категория: Компьютеры и Интернет / Программирование
- Автор: Александр Чиртик
- Год выпуска: -
- ISBN: -
- Издательство: -
- Страниц: 15
- Добавлено: 2019-05-29 10:56:59
Александр Чиртик - Программирование в Delphi. Трюки и эффекты краткое содержание
Прочтите описание перед тем, как прочитать онлайн книгу «Александр Чиртик - Программирование в Delphi. Трюки и эффекты» бесплатно полную версию:Как и все издания данной серии, эта книга адресована тем, кто хочет научиться делать с помощью уже знакомых программных пакетов новые интересные вещи. Издание будет полезно и новичкам, и опытным программистам. Автор описывает удивительные возможности, скрытые в языке, и на примерах учит читателя программистским фокусам – от «мышек-невидимок» и «непослушных окон» до воспроизведения MP3 и управления офисными программами Word и Excel из приложений Delphi. Купив эту книгу, вы пройдете непростой путь к вершинам программистского мастерства весело и интересно.
Александр Чиртик - Программирование в Delphi. Трюки и эффекты читать онлайн бесплатно
• старшие 16 бит wParam представляют собой целочисленный код уведомления, позволяющий определить, что именно произошло с элементом управления;
• младшие 16 бит wParam представляют собой идентификатор элемента управления, состояние которого изменилось (именно этот идентификатор передавался вместо дескриптора меню при создании элементов управления);
• lParam содержит дескриптор (HWND) окна элемента управления, состояние которого изменилось.
Для выделения старших 16 бит из 32-битного значения можно использовать функцию HiWord. Для получения младших 16 бит можно использовать функцию с именем LoWord. Обе функции объявлены в модуле Windows.
В качестве примеров можно привести следующие коды уведомлений:
• BN_CLICKED – нажата кнопка;
• EN CHANGE – изменен текст в текстовом поле;
• LBN_SELCHANGE – изменилось выделение в списке;
• CBN_SELCHANGE – изменилось выделение в раскрывающемся списке.
Эти и все остальные константы уведомлений стандартных элементов управления объявлены в модуле Messages.
Примечание
Коды и описания уведомлений рассматриваемых в этой главе элементов управления приведены в приложении 3.
Пример приложения
Рассмотрим небольшой пример, иллюстрирующий принцип работы с элементами управления, помещенными на форму описанным ранее способом. Проект этого приложения называется ControlsDemo.
Не буду заострять внимание на регистрации класса главного окна приложения, так как она аналогична приведенной в листинге 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(2 0, 100, 70, 30, 1001, 'Кнопка 1');
CreateButton(100, 100, 70, 30, 1002,'Кнопка 2');
CreateFrame(2 00, 10, 200, 180, –1, 'Флажки и переключатели');
CreateCheck(2 10, 30, 180, 20, 2001, 'Флажок 1');
CreateCheck(2 10, 60, 180, 20, 2002, 'Флажок 2', True);
CreateOption(2 10, 100, 180, 20, 3001, 'Переключатель 1', True);
CreateOption(2 10, 130, 180, 20, 3002, 'Переключатель 2', False, True);
CreateOption(2 10, 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(2 00, 200, 200, 240, –1, 'Текстовые поля');
CreateEdit(2 10, 22 0, 180, 20, 6001, 'Текст в текстовом поле');
CreateMemo(2 10, 25 0, 180, 180, 6002, 'Текст в многострочном'+ #13
+ #10 + 'текстовом поле');
//Добавление строк в списки
AddToCombo(4001, 'Строка 1');
AddToCombo(4001, 'Строка 2');
AddToCombo(4001, 'Строка 3');
AddToList(5 001, 'Строка 1');
AddToList(5 001, 'Строка 2');
AddToList(5 001, 'Строка 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);
Text Out (ps.hdc, 10, 10, 'Текст в окне', 12);
EndPaint(hWnd, ps);
end;
WM_CLOSE:
if (hWnd = hMainWnd) then
PostQuit Message(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 функция не претендует на то, чтобы быть эталоном в порядке классификации сообщений от элементов управления. Иногда бывает полезно сразу классифицировать сообщения не по элементам управления, которые их прислали, а по типу самих сообщений. К тому же в ряде случаев можно предусмотреть один обработчик сообщений сразу для нескольких элементов управления, например, для группы переключателей. В таком случае полезным окажется параметр lParam сообщения WM COMMAND.
Кстати, размер исполняемого файла этого приложения равен всего 19 Кбайт.
Стандартные окна Windows
Теперь рассмотрим, как можно с помощью только функций Windows API вызывать некоторые распространенные окна. Чтобы использовать API-функции и структуры с информацией для этих окон, необходимо подключить следующие модули:
• CommDlg – для окон открытия и сохранения файла, выбора цвета и шрифта, поиска и замены текста;
• ShlObj и ActiveX – для окна выбора папки (второй модуль нужен для доступа к интерфейсу IMalloc, зачем – будет рассказано далее);
• Windows – помимо объявления основных структур и API-функций, этот модуль содержит объявления функций для работы с окнами подключения и отключения от сетевого ресурса (сетевого диска);
• ShellAPI – для системного окна О программе.
Вариант использования рассматриваемых в этом разделе окон приведен в подразделе «Демонстрационное приложение» данной главы (стр. 81).
Примечание
В приведенных далее примерах вызова окон можно увидеть не объявленные, но используемые в программах переменные hAppInst и hParentWnd. Подразумевается, что это глобальные переменные, которые инициализируются вне процедур и функций, приведенных в примерах. Для инициализации этих переменных можно также написать специальную процедуру, например, с именем Init, в которую и передавать значения для hParentWnd и hAppInst.
Окно открытия и сохранения файла
Чтобы использовать возможности окна открытия файла, достаточно воспользоваться функцией, представленной в листинге 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_PATHMUSTEXIST – данный флаг не дает ввести имя файла в несуществующей папке (например, при вводе c: \docs\mydoc1.doc, если папки docs не существует, будет выдано соответствующее сообщение);
• OFN_HIDEREADONLY – позволяет скрыть флажок Только для чтения.
Теперь отдельно рассмотрим, зачем в приведенном примере вызывается дополнительная функция 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;
Дело в том, что при задании фильтров (поле lpstrFile) требуется, чтобы каждое название и обозначение фильтров были отделены символом #0, а за последним фильтром шла последовательность из двух нулевых символов. На практике задавать строку из нескольких фильтров в следующем виде недостаточно удобно:
Жалоба
Напишите нам, и мы в срочном порядке примем меры.