Хорошо, если нение нужно произвести только однажды, но когда это приходится делатьизме-по нескольку раз на дню, то такие улучшения начинают надоедать.. Кто-то ин-до вас уже выяснил, где
Trang 2{ Private declarations }
Dragging : Boolean;
OldLeft, OldTop: Integer;
Переменная Dragging будет отвечать за возможность перетаскивания В ременных OldLeft и OldTop будут сохраняться первоначальные координатыокна На всякий случай в обработчике события oncreate можно принуди-тельно записать в переменную Dragging значение false, чтобы случайнопри старте в нее не попало true и непроизвольное перетаскивание
Trang 3Здесь происходит проверка: если щелкнули левой кнопкой, то нужно своить переменной Dragging значение true и запомнить координаты,
при-в которых произошел щелчок
Теперь создайте обработчик события onMowseMove и напишите в нем дующее:
сле-procedure TForrnl FomMouseMove (Sender: TObject; Shift: TShiftState; X,Y: Integer) ;
В обработчике события onMouseup нужно написать только одну строчку:Dragging := False.
Раз кнопка отпущена, то мы должны изменить переменную Dragging наfalse и закончить перетаскивание
HI
width - 1 do then
Рис 3.12 Приложение с окном нестандартной формыПосмотрите на рис 3.12 и вы увидите окно моей программы Я специальнорасположил окно поверх редактора с кодом программы, чтобы вы могли
Trang 4видеть его нестандартный вид Никакой квадратности, никаких оборочек,окно имеет вид Троицы из фильма "Матрица" за ноутбуком.
и видно, что календарь также обрезался вместе с окном Учитывайте это,если будете размещать что-то в таком окне
На компакт-диске в директории \Примеры\Глава 3\Cool Window вы можетеувидеть пример этой программы
функ-В результате Windows обладала самыми слабыми возможностями по охранебезопасности информации
В системах NT/2000/XP эта ошибка испраштена, и в них невозможно такпросто добраться до пароля пользователя Однако по данным многих иссле-довательских фирм, Windows 98 до сих пор доминирующая ОС на компью-терах пользователей Это связано с тем, что накопился большой парк ком-пьютеров, на которых современные версии Windows будут работать оченьмедленно, и не каждый может позволить себе установить 2000/ХР
Итак, сейчас вы узнаете эти функции, с помощью которых можно реть все пароли На рис 3.14 вы можете увидеть форму будущей программы
подсмот-На ней расположен только один компонент ListBox, которвш я растянул повсей форме
Trang 7procedure TForml.FormShow(Sender: TObject);
begin
if WNetEnumCachedPasswords(nil, 0, $FF, @AddPassword, 0) <> 0 then
begin
Application.MessageBox('А не могу я прочитать пароли.', 'Error', mb 0k or mb_IconWarning) ;
недокументи-в кэше и недокументи-вознедокументи-вращает их недокументи-в процедуру, указанную недокументи-в качестнедокументи-ве четнедокументи-вертого метра
пара-Теперь посмотрим, как объявлена эта функция Объявление состоит из двухстрок В первой просто описано, что она представляет собой:
Trang 8па-Единственное, что еще надо сказать, так это то, что пароль хранится в кодировке Поэтому чтобы его увидеть, надо перевести его в Windows-кодировку Для этого использована функция charToOem Первый параметр —
DOS-то, что надо перекодировать, а второй — результат перекодировки
На компакт-диске в директории \Примеры\Глава 3\Password вы можетеувидеть пример этой программы
3.10 Изменение файлов
Любители игр очень часто встречаются с проблемой улучшения стик своего героя В такие моменты мы идем на какой-нибудь игровой сайт
характери-и характери-информацхарактери-ию, как сделать себя в характери-игре бессмертным характери-илхарактери-и дать себе оружхарактери-ие
с бесконечным ресурсом Большинство сайтов просто переполнены ной информацией, и как бывает хорошо, когда ее легко использовать
подоб-Но такое бывает редко Обычно нам предлагают шестнадцатеричные коды,которые нужно изменить в исполняемом файле или файле с записью Длятого чтобы сделать такое изменение, нужно загрузить шестнадцатеричный
Trang 9редактор и изменять все вручную, что не очень удобно Хорошо, если нение нужно произвести только однажды, но когда это приходится делать
изме-по нескольку раз на дню, то такие улучшения начинают надоедать
В данном случае программисты находятся в более выгодном положениепотому что написать программу, которая будет делать все автоматически,очень просто В этом разделе я покажу, как написать подобную программу.Допустим, что нам достался следующий информационный файл:
- подпатчить XXXXX.EXE:
0АС0Е9 - 74 ЕВ
OAC0FE - 74 ЕВ
Как использовать эти спецефические данные? На первый взгляд эта записьнепонятна, особенно если вы никогда не подправляли программы Если выпоняли эту надпись, то пропустите пару абзацев и продолжайте читатьдальше Если нет, то давайте разберемся с этим более подробно
Для начала определимся, что такое патч В данном случае патч — это формация, какие байты нужно подправить в программе так, чтобы она рабо-тала по-другому (например, открыла вам секретные возможности) Кто-то
ин-до вас уже выяснил, где и что нужно подправить, а вам осталось только лать это у себя на компьютере Для правки вам понадобится любой редак-тор, позволяющий работать с файлами в шестнадцатеричном виде Я попривычке люблю использовать встроенный в DOS Navigator редактор из-заего простоты Если вам нужно что-то более продвинутое, то ваш выбор —специализированные программы
сде-D:\WINNT\5ystem32\cmd.eKe
Е >Фа^я Диск УТИЛИТЫ Панель
Рис 3.15 Шестнадцатеричный редактор в DOS Navigator
Trang 10Сейчас я рассмотрю процесс использования патча на примере одной вой программы Я не буду говорить ее название, потому что это не имеетзначения Главное — это процесс Если вы сможете понять все, что я рас-скажу, то сможете подправлять любые программы и игры.
игро-Итак, запускайте свой шестнадцатеричный редактор и открывайте файл,который надо подправить В DOS Navigator для этого нужно перейти нафайл и нажать <F3> После этого нажимаете <F4> и видите данные в шест-надцатеричном виде Файл к операции готов Теперь взглянем на сам патч:0АС0Е9 - 74 ЕВ
Перед внесением исправлений проверяйте, чтобы там действительно былнужный байт (в примере это 74, который нужно поменять на ЕВ) ЕСЛИ ВЫувидите другое число, значит, вы нашли не тот адрес или используете патч
не для той версии программы В этом случае лучше ничего не делать,
пото-му что можно испортить работающую програмпото-му А вообще в любом случаелучше сначала скопировать редактируемый файл в отдельную директорию,чтобы в случае неудачи можно было вернуться в исходное состояние
В рассмотренном патче две строки, два адреса и два байта, которые нужноисправить Сколько строк, столько байтов нужно подправить
То, что вы смогли подправить свою программу вручную — это хорошо.Теперь вы можете сохранить где-нибудь исправленный исполняемый файл,
и в случае переустановки программы или всей Windows сможете сразу пользовать модифицированную версию Но что если вы подправляете непросто программу, а игру? После каждого сохранения редактировать байты
ис-в шестнадцатеричном редакторе достаточно нудно и неинтересно
Вот теперь мы переходим к самому интересному Сейчас я постараюсь робно объяснить, как наиболее простым способом написать программу,которая сама будет производить редактирование Потратив пять минут насоздание собственного варианта, вы можете выиграть множество времени инервов Утилиту я буду писать на примере все того же патча, ну а вы ужесможете без проблем адаптировать ее под любые нужды
Trang 11под-Запустите Delphi Можете перенести на форму любую картинку для ния приличного вида, но это уже на ваш вкус Главное — это установитькнопку Что вы напишете на ней, меня тоже не особо волнует Мой вариант
созда-вы можете видеть на рис 3.16
Рис 3.16 Форма будущей программы
Теперь приступим к программированию Дважды щелкните на созданнойкнопке, и Delphi сгенерирует для нее обработчик события Onclick В немнапишите следующее:
Trang 12одно-После инициализации переменная F содержит указатель на объект с тым файлом Теперь мне надо перейти на нужную позицию и прочитать от-туда значение Для перехода на нужное место в файле я использую методseek У него тоже есть два параметра.
откры-П Число, указывающее на позицию, в которую надо перейти Здесь вам
нужно поставить адрес, указанный в патче
Trang 13П Точка отсчета Указанный параметр soFromBeginning означает, что
дви-гаться надо от начала
После выполнения F.seek мы переместились на нужную позицию в файле.Теперь нужно проверить, какое там записано значение Для этого нужнопрочитать один байт с помощью метода Read У этого метода также два па-раметра
1 Переменная, в которую будет записан результат чтения
2 Количество байт, которые надо прочитать
После этого делается проверка прочитанного байта Если все нормально, томожно записать вместо него новое значение Но перед записью нужно сноваустановить указатель в файле на нужное место, потому что после чтения
он сдвинулся на количество прочитанных байт Поэтому снова вызываемметод seek
Для записи используем метод write, у которого опять же два параметра
1 Переменная, содержимое которой нужно записать Мы записываем держимое переменной s, в которой уже находится нужное значение
со-2 Число байт для записи
Все, первый байт мы исправили Теперь повторяем ту же операцию для рой строки патча и исправляем второй байт
вто-В этом примере я использовал объект TFiiestream А почему я не захотелсделать проще и написать приложение на WinAPI? Прежде всего потому,что это не будет проще; количество строк не уменьшится, и нет смысламучиться Во-вторых, использование объектов всегда удобнее Почему? Сей-час объясню
Сначала для работы с файлами существовали функции: _fcreat, _fseek,fread И Т Д После ЭТОГО ПОЯВИЛИСЬ C r e a t e F i l e , S e t F i l e P o i n t e r ,writeFiLe Теперь начинают использовать writeFiieEx и ей подобные.Всеми любимая фирма MS встраивает новые функции в API-функцииWindows, а старые забрасывает, из-за чего появляются проблемы несовмес-тимости Это что, я теперь должен после каждого нововведения в Microsoftпеределывать свои программы на использование новых функций? А если у меня
их сотня? Нет!!! Уж лучше я один раз исправлю объект TFiiestream и потомпросто перекомпилирую свои программы с учетом новых возможностей
Поэтому я вам тоже не советую обращаться к WinAPI напрямую, и везде,где только возможно, нужно стараться использовать объекты и компонентыDelphi
Если вы смогли усвоить все, что я вам сказал, то сможете без проблем сать свои собственные программы для патчей Только не забывайте, что явам рассказал это только в познавательных целях Вы можете без проблемиспользовать эти знания для исправления игр, потому что за это никто
Trang 14пи-преследовать не будет Ну есть у вас бесконечная жизнь — вам же менее тересно играть.
ин-Однако если вы захотите подправить какую-нибудь программу с ным сроком работы, то я должен вас предупредить: измение программы,нарушающее пользовательское соглашение — это взлом, который может ка-раться законом Совсем недавно ребята из великобританской полиции поса-дили шестерых человек за взломы программ Россия, конечно же, не Вели-кобритания, но и не Африка Наша страна тоже цивилизованная, хотя ибедная Так что посадить имеют право (если захотят) Конечно, чем вы за-нимаетесь на личном компьютере, никому не интересно, но это совсемдругой вопрос В любой момент все может измениться, поэтому лучше неискать себе лишних приключений
ограничен-На компакт-диске в директории \Примеры\Глава 3\Patch вы можете увидетьпример программы и цветные рисунки из этого раздела
3.11 Работа с файлами
и директориями
В реальных программах иногда необходимо копировать, перемещать и лять файлы В Delphi для этих целей служат очень простые функции
уда-DeleteFile( л Имя или полный путь к файлу');
Эта функция возвращает true, если операция прошла успешно, и false,если неудачно
Функция DeieteFiie умеет удалять только файлы и только по одному
У вас не получится работать сразу с несколькими файлами, и придется длякаждого из них вызывать функцию удаления Помимо этого, можно удалятьтолько файлы Если указать директорию, то операция не будет выполнена.Для удаления директорий есть отдельная функция:
RemoveDir('Имя или полный путь к директории');
Функция возвращает true, если операция прошла успешно, и false, еслинеудачно
Trang 15Перед операциями над файлами и директориями желательно убедиться в ихсуществовании Для того чтобы узнать, существует ли файл, можно восполь-зоваться следующей функцией:
FileExists('Имя или полный путь к файлу');
Если файл существует, то функция вернет true, иначе — false
Узнать о существовании директории можно с помощью следующей функции:DirectoryExists( 'Имя или полный путь к директории' );
Если директория существует, то функция вернет true, иначе — false.Вот небольшой пример использования описанных функций:
Использовать данные функции Delphi очень просто, но они имеют слишкоммало возможностей и среди них нет хорошей функции для копирования иперемещения файлов Среди справки Delphi можно найти описание функ-ций копирования и перемещения, которые можно использовать в своихпроектах Для этого нужно только добавить их в свой проект
procedure CopyFile(const FileName, DestName: string);
Trang 16FileWrite(Dest, CopyBuffar" f BytesCopied);
until BytesCopied < ChunkSize;
ве второго параметра (путь к файлу, в который надо скопировать) указанатолько директория без имени файла, то программа подставляет в качествеимени файла имя источника
После этого файл источника открывается для чтения данных с запретом назапись со стороны других программ Открыв источник, процедура создает
Trang 17файл приемника Если он существовал, то без каких-либо предупрежденийфайл будет перезаписан Дальше запускается цикл, в котором из файла ис-точника считываются данные по 8 192 байт и тут же записываются в файлприемника Таким образом, в цикле происходит копирование файла не-большими порциями Чем больше порция, тем быстрее будет происходитькопирование.
Процедура копирования — очень хороший пример использования функцийработы с файлами Все сделано очень грамотно и великолепно работает, хо-
тя и не очень универсально Например, нет вызова предупреждения о ствовании результирующего файла перед его уничтожением Но это не так
Если источник и приемник находятся на разных дисках, то такой трюк непройдет, поэтому процедура вызовет функцию CopyFile, описанную выше,для копирования источника в новое место, а потом удалит файл источника.Для запуска файла можно использовать следующую универсальную функ-цию (листинг 3.15)
Trang 18| И | 3 1 5 Запуск файла на ЩШШШ ^ 7 Т^ "7function ExecuteFile(const FileName, Params, DefaultDir: string;
ShowCmd: Integer): THandle;
var
zFileName, zPararas, zDir: array[0 79] of Char;
begin
Result := ShellExecute(Application.MainForm.Handle, nil,
StrPCopy(zFileName, FileName), StrFCopy(zParams, Params),
StrPCopy(zDir, DefaultDir}, ShowCmd);
E x e c u t e F i l e ( ' h t t p : //www c y d s o f t с о г п / v r - o n l i n e ' , ' ' , ' ' , SW SHOW) ;
Если нужно создать электронное письмо, то это можно сделать следующимспособом:
ExecuteFile('MailTo:vr_onlone@cydsoft.com','','',SW_SHOW);
Функцию ShellExecute мы уже рассматривали в разд 2.5, и все же я решил
описать ее еще раз, чтобы выделить в отдельную процедуру Применяя ее,вам не надо следить за типом pchar, который используется-для передачистрок, потому что наша функция ExecuteFile сама сделает необходимыепреобразования