Excel. Трюки и эффекты
Шрифт:
1.7. Добавление пункта в системное меню окна
Обратите внимание на меню, раскрывающееся при щелчке кнопкой мыши на значке окна. В этом системном меню обычно присутствуют пункты, выполняющие стандартные действия над окном, такие, как закрытие, минимизация, максимизация и др. Однако есть функции, позволяющие получить доступ к этому меню, что дает возможность использовать его в своих целях.
Для получения дескриптора (HMENU) системного меню окна используем API-функцию GetSystemMenu, а для добавления пункта в меню – функцию AppentMenu. Пример процедуры, добавляющей пункты в системное меню, приведен в листинге 1.26.
Листинг 1.26.
Добавление
procedure TForm1.FormCreate(Sender: TObject);
var hSysMenu: HMENU;
begin
hSysMenu := GetSystemMenu(Handle, False);
AppendMenu(hSysMenu, MF_SEPARATOR, 0, \'\');
AppendMenu(hSysMenu, MF_STRING, 10001, \'Увеличить на 20%\');
AppendMenu(hSysMenu, MF_STRING, 10002, \'Уменьшить на 20%\');
end;
В результате системное меню формы Forml станет похожим на меню, показанное на рис. 1.18.
Рис. 1.18. Пользовательские пункты в системном меню
Однако мало просто создать пункты меню, нужно предусмотреть обработку их выбора. Это делается в обработчике сообщения WM_SYSCOMMAND (листинг 1.27).
Листинг 1.27.
Обработка выбора пользовательских пунктов в системном меню
procedure TForm1.WMSysCommand(var Message: TWMSysCommand);
begin
if Message.CmdType = 10001 then
//Увеличение масштаба
ChangeScale(120, 100)
else if Message.CmdType = 10002 then
//Уменьшение масштаба
ChangeScale(80, 100)
else
//Обработка по умолчанию
DefWindowProc(Handle, Message.Msg, Message.CmdType,
65536 * Message.YPos + Message.XPos);
end;
Обратите внимание на то, что числовые значения, которые переданы в функцию AppendMenu, используются для определения, какой именно пункт меню выбран. Чтобы меню вело себя обычным образом, все поступающие от него команды должны быть обработаны. Поэтому для всех команд, реакция на которые не заложена в реализованном нами обработчике, вызывается обработчик по умолчанию (функция DefWindowProc).
1.8. Отображение формы поверх других окон
Иногда вам может пригодиться возможность отображения формы поверх всех окон. За примером далеко ходить не надо: посмотрите на окно Диспетчера задач Windows. А теперь вспомните, терялось ли хоть раз окно Свойства: Экран среди других открытых окон. Это происходит из-за того, что оно перекрывается другими окнами и при этом не имеет никакого значка на Панели задач (правда, это окно все же можно найти с помощью Диспетчера задач).
Из сказанного выше можно заключить, что как минимум в двух случаях отображение поверх других окон может пригодиться: для важных окон приложения (например, окно ввода пароля) и/или в случае, если значок приложения не выводится на Панели задач (как скрыть значок, было рассказано выше).
После небольшого отступления рассмотрим способы, позволяющие задать положение формы так, чтобы другие окна не могли ее закрыть.
Первый способ прост «до безобразия»: достаточно задать свойству FormStyle в окне Object Inspector значение f sStayOnTo. Результат этого действия показан на рис. 1.19 (обратите внимание,
Рис. 1.19. Форма, отображаемая поверх других окон
Второй способ пригодится, если форма отображается постоянно как обычно, однако в определенные моменты времени требует к себе пристального внимания, для чего и помещается наверх. Способ основан на использовании API-функции SetWindowPos, которая кроме позиции и размера окна может еще устанавливать порядок рисования окна (Z-order).
Примечание
Под Z-order подразумевается порядок следования окон вдоль оси Z, направленной перпендикулярно экрану (оси X и Улежат в плоскости экрана).
Вызов функции SetWindowPos для помещения окна наверх выглядит следующим образом (Handle – дескриптор нужного окна):
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE)
В таком случае окно может быть закрыто другим окном, также отображающимся поверх других (например, Диспетчером задач).
Чтобы восстановить нормальное положение (порядок рисования) окна, можно вызвать функцию SetWindowPos со следующим набором параметров:
SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE)
После этого другие, неотображаемые поверх остальных, окна могут снова перекрывать нашу форму.
Глава 2 Уменьшение размера ЕХЕ-файла. Использование Windows API
• Источник лишних килобайт
• Создание окна вручную
• Окно с элементами управления
• Стандартные диалоговые окна Windows
• Установка шрифта элементов управления
Не секрет, что размер скомпилированного ЕХЕ-файла Delphi часто значительно превосходит размер программ, написанных с использованием сред разработки от Microsoft (например, Visual C++, Visual Basic).
Примечание
Здесь и далее имеются в виду приложения с оконным интерфейсом (не консольные).
При разработке крупных проектов этот факт абсолютно не смущает. Однако что же делать, если программисту на Delphi нужно написать программу, занимающую как можно меньше места (например, инсталлятор) или загружающуюся за минимальное время (например, сервисную программу). Конечно, такое приложение можно написать на C++, но что делать, если осваивать новый язык программирования нет времени?
В этой главе будут рассмотрены два способа уменьшения размера ЕХЕ-файла: отказ от библиотеки Borland за счет прямого использования Windows API и разбиение приложения на несколько DLL. Первый способ позволяет реально уменьшить размер приложения. Однако написание Delphi-приложения (да еще и с оконным интерфейсом) с использованием только API-функций является задачей весьма трудоемкой, хотя и интересной, да к тому же и экзотичной. Второй же способ не уменьшает размера проекта в целом, но может сэкономить время запуска приложения.