- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Delphi. Трюки и эффекты - Валерий Борисок
Шрифт:
Интервал:
Закладка:
used: Boolean; //Служебное поле
end;
Каждый элемент массива styles хранит информацию об определенном оконном стиле. Объявление этого массива, так же, как структуры Stylelnfo и прочих рассмотренных в этом разделе типов данных, находится в модуле WindowData, расположенном на диске в папке с номером главы.
Ниже приведено объявление массива styles (флаги стиля, являющиеся комбинацией других флагов, в массив не попали) (листинг 10.7).
...Листинг 10.7.
Массив с информацией об оконных стилях
styles: array [0..17] of StyleInfo =
(
(value: WS_BORDER; name: 'WS_BORDER'),
(value: WS_CAPTION; name: 'WS_CAPTION'),
(value: WS_CHILD; name: 'WS_CHILD'),
(value: WS_CLIPCHILDREN; name: 'WS_CLIPCHILDREN'),
(value: WS_DISABLED; name: 'WS_DISABLED'),
(value: WS_DLGFRAME; name: 'WS_DLGFRAME'),
(value: WS_HSCROLL; name: 'WS_HSCROLL'),
(value: WS_MAXIMIZE; name: 'WS_MAXIMIZE'),
(value: WS_MAXIMIZEBOX; name: 'WS_MAXIMIZEBOX'),
(value: WS_MINIMIZE; name: 'WS_MINIMIZE'),
(value: WS_MINIMIZEBOX; name: 'WS_MINIMIZEBOX'),
(value: WS_OVERLAPPED; name: 'WS_OVERLAPPED'),
(value: WS_POPUP; name: 'WS_POPUP'),
(value: WS_SYSMENU; name: 'WS_SYSMENU'),
(value: WS_TABSTOP; name: 'WS_TABSTOP'),
(value: WS_THICKFRAME; name: 'WS_THICKFRAME'),
(value: WS_VISIBLE; name: 'WS_VISIBLE'),
(value: WS_VSCROLL; name: 'WS_VSCROLL')
);
Процедура LoadWindowExStyle реализована практически так же, как и процедура LoadWindowStyle. Только она заполняет cnncKHlstExStyle HlstAvailExStyle и обращается к массиву exstyles, а не styles. Поэтому приведем объявление только массива exstyles (листинг 10.8).
...Листинг 10.8.
Массив с информацией о дополнительных оконных стилях
exstyles: array [0..18] of StyleInfo =
(
(value: WS_EX_ACCEPTFILES; name: 'WS_EX_ACCEPTFILES'),
(value: WS_EX_APPWINDOW; name: 'WS_EX_APPWINDOW'),
(value: WS_EX_CLIENTEDGE; name: 'WS_EX_CLIENTEDGE'),
(value: WS_EX_CONTEXTHELP; name: 'WS_EX_CONTEXTHELP'),
(value: WS_EX_CONTROLPARENT; name: 'WS_EX_CONTROLPARENT'),
(value: WS_EX_DLGMODALFRAME; name: 'WS_EX_DLGMODALFRAME'),
(value: WS_EX_LAYERED; name: 'WS_EX_LAYERED'),
(value: WS_EX_LEFT; name: 'WS_EX_LEFT'),
(value: WS_EX_LEFTSCROLLBAR; name: 'WS_EX_LEFTSCROLLBAR'),
(value: WS_EX_MDICHILD; name: 'WS_EX_MDICHILD'),
(value: WS_EX_NOACTIVATE; name: 'WS_EX_NOACTIVATE'),
(value: WS_EX_NOINHERITLAYOUT; name: 'WS_EX_NOINHERITLAYOUT'),
(value: WS_EX_NOPARENTNOTIFY; name: 'WS_EX_NOPARENTNOTIFY'),
(value: WS_EX_RIGHTSCROLLBAR; name: 'WS_EX_RIGHTSCROLLBAR'),
(value: WS_EX_STATICEDGE; name: 'WS_EX_STATICEDGE'),
(value: WS_EX_TOOLWINDOW; name: 'WS_EX_TOOLWINDOW'),
(value: WS_EX_TOPMOST; name: 'WS_EX_TOPMOST'),
(value: WS_EX_TRANSPARENT; name: 'WS_EX_TRANSPARENT'),
(value: WS_EX_WINDOWEDGE; name: 'WS_EX_WINDOWEDGE')
);
Изменение оконных стилей
Изменение стилей окна «на лету» производится не сложнее, чем их определение: с помощью API-функций GetWindowLong и SetWindowsLong. Пример добавления флага, обозначение которого выбрано в списке доступных стилей, приводится в листинге 10.9.
...Листинг 10.9.
Добавление оконного стиля
procedure TfrmWindowProp.cmbAddStyleClick(Sender: TObject);
var
style: DWORD;
addstyle: DWORD;
begin
if lstAvailStyle.ItemIndex = –1 then Exit;
//Удаление выбранного стиля окна
//..определяем, какой стиль удалить
addstyle := styles[GetStyleIndex(lstAvailStyle.ItemIndex,
False)].value;
//..вычисляем и устанавливаем новое значение стиля окна
style := GetWindowLong(wnd, GWL_STYLE);
style := style or addstyle;
SetWindowLong(wnd, GWL_STYLE, style);
//..перерисуем все окна
InvalidateRect(0, nil, True);
//Обновим список стилей окна
LoadWindowStyle();
end;
Удаление флага стиля производится аналогично добавлению, просто над битами стиля окна выполняется другая операция (листинг 10.10).
...Листинг 10.10.
Удаление оконного стиля
procedure TfrmWindowProp.cmbDelStyleClick(Sender: TObject);
var
style: DWORD;
delstyle: DWORD;
begin
if lstStyle.ItemIndex = –1 then Exit;
//Удаление выбранного стиля окна
//..определяем, какой стиль удалить
delstyle := styles[GetStyleIndex(lstStyle.ItemIndex, True)].value;
//..вычисляем и устанавливаем новое значение стиля окна
style := GetWindowLong(wnd, GWL_STYLE);
style := style and not delstyle;
SetWindowLong(wnd, GWL_STYLE, style);
//..перерисуем все окна
InvalidateRect(0, nil, True);
//Обновим список стилей окна
LoadWindowStyle();
end;
После удаления или добавления оконного стиля вызывается перерисовка всех окон, чтобы проявился результат проведенной операции. Удаление и добавление дополнительных (расширенных) оконных стилей осуществляется аналогично. Только при этом используются массив exstyles, функция GetExStylelndex и константа GWL_EXSTYLE, передаваемая в функции GetWindowLongи SetWindowLong.
Что же за функция GetStylelndex используется в листинге 10.10? Она позволяет определить положение в массиве styles стиля, выбранного в списке доступных или используемых стилей (верхний список) (листинг 10.11).
...Листинг 10.11.
Определение положения записи о нужном стиле
function TfrmWindowProp.GetStyleIndex(listIndex: Integer;
used: Boolean): Integer;
var
i, count: Integer;
begin
count := 0;
for i := 0 to 17 do
if styles[i].used = used then
begin
if count = listIndex then
begin
//Нашли
GetStyleIndex := i;
Exit;
end;
Inc(count);
end;
GetStyleIndex := 0;
end;
Функция GetStylelndex принимает в качестве параметров номер строки в соответствующем списке и логическое значение, от истинности или ложности которого зависит, используемые или неиспользуемые стили будут подсчитываться внутри функции.
Применение функции GetStylelndex и введение в структуру Styleinf о поля used несколько усложняет алгоритм работы с массивом стилей, но зато позволяет избавиться от постоянного перемещения данных, например, из массива доступных стилей в массив используемых стилей. К тому же пришлось бы использовать по два массива для обычных и дополнительных оконных стилей.
Перехват сообщений
Теперь рассмотрим самую сложную часть программы, отвечающую за перехват сообщений выбранного окна. Форма, ведущая статистику перехваченных сообщений, приведена на рис. 10.5.
Показанная на рис. 10.5 форма имеет имя frmMessages.
Перехватчик сообщений состоит из двух частей: части программы (ЕХЕ), отвечающей за построение фильтра сообщений, а также обрабатывающей перехваченные сообщения, и ловушки, заключенной в DLL(hookhook.dll).
Взаимодействие ловушки и ЕХЕ-файла построено по следующей схеме.
1. Из приложения вызываются функции создания и удаления ловушки (расположенные в DLL).
2. При перехвате каждого сообщения функция-ловушка посылает окну (форме) frmMessages сообщение WM_SPY_NOTIFY (определенное пользователем, точнее, программистом сообщение, листинг 10.12).
Рис. 10.5. Форма перехвата сообщений
Но ведь ловушка предназначена для работы в другом процессе, а если так, то как ей дать знать, какому именно окну посылать сообщения? Для этого и используется именованная проекция файла в память, в которой сохраняются данные, необходимые для ловушки. В проекции файла ловушка также сохраняет информацию о перехваченном сообщении (код и параметры сообщения). Эта информация используется приложением, ведущим слежение. Данные в проекции файла хранятся в виде записи THooklnfo, объявленной в модуле HookData. В этом же модуле объявлены константа с именем проекции файла, код сообщения WM_SPY_NOTIFY (листинг 10.12) и две служебные переменные, использование которых будет пояснено далее.
...Листинг 10.12.
Содержимое файла HookData.pas
type
//Структура (запись), которая хранится в разделяемом файле
//и используется для передачи данных между процессами
THookInfo = record
wnd: HWND; //Окно, за которым ведется наблюдение
hook_handle: HHOOK; //Дескриптор ловушки
spy_wnd: HWND; //Окно, уведомляемое о перехвате сообщения
//Следующие поля заполняются при перехвате сообщения
mess: UINT;
wParam: WPARAM;
lParam: LPARAM;
end;
var
//Указатель на разделяемую область памяти
hook_info: ^THookInfo;
//Дескриптор проекции файла в память
hFile: THandle;
const
//Имя проекции файла
strFileMapName = 'TricksDelphi_WinSpy_Mapping
//Сообщение для уведомления окна-шпиона
WM_SPY_NOTIFY = WM_USER + 1;
Построение фильтра и обработка перехваченных сообщений
Теперь вернемся к приложению-шпиону, а точнее, к той его части, которая отвечает за работу формы, показанной на рис. 10.5.
Начнем с самого простого – управления фильтром сообщений. Он построен по тому же принципу, что управление списками оконных стилей (форма свойств окна, рассмотренная ранее).
Итак, структура, хранящая информацию о сообщении, выглядит следующим образом:
...type MessageInfo = record
value: DWORD; //Код сообщения
name: String; //Название сообщения
used: Boolean; //Служебное поле
end;
При написании программы не стояла цель поместить в фильтр все возможные сообщения, поэтому массив messageslist (листинг 10.13) содержит только 16 элементов. При необходимости вы можете добавить нужные сообщения самостоятельно, взяв их обозначения из модуля Windows.
...Листинг 10.13.
Сообщения, поддерживаемые программой
const
mess_first = 0;
mess_last = 15;
var
messages_list: array [mess_first..mess_last] of MessageInfo =
(
(value: WM_DESTROY; name: 'WM_DESTROY used: False),
(value: WM_MOVE; name: 'WM_MOVE used: False),
(value: WM_SIZE; name: 'WM_SIZE used: False),
(value: WM_ACTIVATE; name: 'WM_ACTIVATE used: False),
(value: WM_SETFOCUS; name: 'WM_SETFOCUS used: False),
(value: WM_KILLFOCUS; name: 'WM_KILLFOCUS used: False),
(value: WM_ENABLE; name: 'WM_ENABLE used: False),
(value: WM_SETTEXT; name: 'WM_SETTEXT used: False),
(value: WM_GETTEXT; name: 'WM_GETTEXT used: False),
(value: WM_PAINT; name: 'WM_PAINT used: False),
(value: WM_CLOSE; name: 'WM_CLOSE used: False),
(value: WM_QUIT; name: 'WM_QUIT used: False),
(value: WM_SIZING; name: 'WM_SIZING used: False),
(value: WM_MOVING; name: 'WM_MOVING used: False),
(value: WM_NOTIFY; name: 'WM_NOTIFY used: False),
(value: WM_NCHITTEST; name: 'WM_NCHITTEST used: False)
);
Загрузка фильтра (выбранных и невыбранных сообщений в соответствующие списки) производится очень просто (листинг 10.14).

