С уважением, ведущий уроков Semen *****@***net

Урок23. Защита программы от бесплатного использования. Испытательный срок.

Вместо предисловия.
Безопасность и хакинг. Это два разных понятия. Сколько будут существовать компьютерные программы их всегда будут ломать. Чем сильнее защита, тем к ней сильнее интерес, и сколько будет существовать его величество дизассемблер, столько программистам терпеть убытки. Насколько обеднеет всемогущий Билл я не знаю, но по карману обычного программера бьют больно. Виноваты в этом не только хакеры. Как ни странно виноваты в этом мы сами. Покупая нелицензионные программные продукты, бродя по просторам internet в поисках крека мы тем самым поддерживаем пиратские компании, производящие подпольные лазерные диски, увеличиваем спрос на крек, принуждаем отдельных людей заниматься взломом. А государство со своей позиции борьбы с теневой экономикой (а это именно и есть теневая экономика) выглядит не очень. По крайней мере по сравнению с западными странами.

На этом уроке мы рассмотрим немного теории, которая будет полезна как для начинающих, так и для профессиональных программистов. Для вторых этот урок будет наиболее полезен, поскольку считаю, что профессионал начинается там, где его программы стают востребованными. Вам может показаться удивительным, но от начинающего писателя программ до разработчика востребованных приложений - один шаг. В моем случае переход от языка программирования pascal на object pascal занял не больше недели, после чего была написана довольно интересная программа, структура которой и порядок работы  до сих пор загадка :).

В большинстве случаев перед продажей программного продукта заказчик требует испытательный или ознакомительный срок. Возможно даже, что он испытывает программу уже на ранних стадиях разработки, желая убедиться в работоспособности, убедиться в правильности направления процесса программирования. И будет совсем неудивительно, если он вдруг откажется от ваших услуг, услуг программиста. Это не означает, что заказчик бросил пользоваться программой. Возможно, его устраивает и текущая версия. Или ваша программа полностью готова, тогда такая проблема может иметь место. Труднее может быть в случае распространения программы в сети internet, когда вы ее пускаете в свободное плаванье, надеясь, что она не утонет в море бизнес приложений, а принесет желаемый доход в ваш кошелек.

Автор этой статьи имеет довольно горький опыт работы с заказчиком. Свыше 50% полностью готовых и работоспособных программ до сих пор не оплачены, находятся на стадии "испытания" или отбракованы навсегда. Скорее всего, во всем этом виноват наш постсоветский менталитет, стремление к халяве. Тут вы можете не согласиться, но я у вас спрошу, а ваш интернет браузер, почтовая программа, наконец, операционная система, купленная? Порой, мы даже и не задумываемся над этой проблемой, покупая компакт диск с новой версией программы, с новой версией операционной системы. Труд человека должен быть оплачиваем. Программный продукт этот как и результат производства, например стул, требует затрат как физических, так и умственных сил.

Как бы то ни было, а защищать свои программы от наглого халявного эксплуатирования вы должны самостоятельно. И просто так погрозить пальчиком бывает недостаточно. По уровню вашей квалификации в области программирования пользователь может и судить о возможной угрозе, поэтому может хватить и простого предупреждения. Если ваши программы предназначены для определенного заказчика, то, скорее всего у этой организации, группы людей, или одного пользователя плохо с программированием (если сами не смогли справиться со своей проблемой). Отсюда вывод - поломать вашу защиту им будет настолько же проблематично, насколько самим написать программу от начала и до конца. Я не учитываю тех людей, которые этим занимаются профессионально, так называемых хакеры, но услуга взлома одной средней программы может стоить намного дороже ее самой. Имеет смысл ломать только при глобальном, неоднократном использовании пользователями, например, ломают даже аппаратную защиту HASP, используемую бухгалтерским программным комплексом 1С. Это я веду к тому, что абсолютно 100% защиты от взлома, нелицензионного тиражирования нет. Поэтому вы не должны слишком много сил отдавать организации защиты. Если на то будет большая необходимость, ее сломают все равно. Но иметь защиту от простого чайника надо обязательно. Хватит и нескольких строчек продуманного программного кода.
Так же вы не должны использовать один и тот же алгоритм защиты в программах, поставляемых одному и тому же заказчику. Это усложнит поиск обходных путей "лицензирования".

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

Итак, программа написана и установлена на компьютер заказчика. Ей дан испытательный срок. Не дай Бог вам сказать прямо об этом пользователю. Тогда он может искать окружные методы еще до ответных действий программы. При этом его действия могут быть непредсказуемы, например позовет знакомого программиста со стороны и похвастается, что эта программа имеет какую-то хитрую защиту. Если возникнет остановка производства после, например полугодового использования всего программного комплекса, то вас найдут и за кратчайшие сроки, причем тут стоимость программы может и возрасти. Инфляция, знаете ли :). Как кто-то когда-то сказал, стоимость данных может быть большей самого компьютера. Поэтому ставя зеркализацию дисков на компьютеры, в первую очередь думают про сохранение данных на случай выхода из строя дискового накопителя.

Допустим, вы даете пользовадней испытательного срока. Об этом должно быть обязательно где-нибудь ненавязчиво написано, типа "Незарегистрированная версия. Пожалуйста, зарегистрируйтесь в 30 дневный срок". Желательно в заставке при загрузке программы (урок 8), можно и в окне "О программе". Тогда вы можете во всем обвинить заказчика, что он не придерживался условий эксплуатации программы, если одним прекрасным утром программа исчезает с диска со всеми набранными на месяц данными.

Теперь мы подошли к способам бесплатной работы, предупреждения (и наказания). Я разделю их на три группы:
1. Постоянное предупреждение о том, что программа еще не куплена, и просьба связаться с программистом. Поверьте, такая методика может приносить больше плодов, чем другие известные на сей день. Приведу пример. Мне предлагали для примера моей новой программы одну программу, которая замечательно работает, имеет отличный интерфейс, много удобных дополнительных утилит. Пользователю она не понравилась потому, что каждые три минуты высвечивалось окошко, что ее необходимо зарегистрировать. Это окошко закрывается одним нажатием кнопки мышки, но пользователя это очень бесит. Вы можете в таком окне еще привязать таймер, который будет "вешать" программу на заданное время при OnCloseQuery этого окна. Это будет сильно тормозить нормальную работу с программой, потому, что окно будет закрываться несразу.
01.gif (2216 bytes)
procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
Sleep(5000); //Ждать 5 секунд, после чего процедура закрытия окна продолжится
end;

2. Отказ от работы после истечения заданного срока. Довольно большой процент программ, имеющих изначально не тронутую хакерами защиту, имеют такой способ испытательного срока.
Слабым местом для этого вида защиты есть то, где вы храните информацию о первом запуске программы (дата, время, количество запусков и т. п.). Наиболее оптимальным местом хранения такой информации есть реестр windows. Реже - ini файлы, еще реже - другие файлы.
Почему реестр, а не другое место. На мое мнение, для чайников туда место закрыто (некоторые даже не знают что это такое), обилие информации, среди которой можно затерять вашу скрытую информацию. Самым идеальным будет совместное использование как реестра, так и INI файла. Если в одном из них информация уничтожена начинающим хакером, то вы всегда можете это обнаружить и программно наказать. Сразу скажу, что есть хорошо известные многим программы, которые отслеживают любые изменения в реестре, предательски выдавая добавленные строки. Достаточно их удалить и произойдет сброс счетчика дней.
Программа с таймером в реестре работает по такому принципу. Первый запуск программы, поиск в реестре вашей специальной записи. Если таковой нет (первый запуск), то она создается. Запись включает в себя дату и время запуска.
ВНИМАНИЕ! Многие хакерские примочки не что иное, как простой запускатель программы с переводом времени (переводится время назад и программа запускается). Поэтому повторяем операцию записи последнего запуска обязательно и при завершении работы программы, возможно даже после определенного времени работы, скажем в 5 минут.
Последующие запуски сводятся к чтению данных и исправление их на текущее, за одним исключением. Если текущее время меньше, чем было в прошлом запуске (время было переведено назад), то, во-первых, оно переписывается под текущее (время перевели, например, чтобы в бухгалтерской программе провести задним числом документ, многие программы неправильно решают, что их пытаются обмануть и блокируют свою работу), во-вторых увеличивается специальный штрафной балл на единицу, соответственно, срок использования программы увеличивается на единицу дней.
Если таких переводов времени слишком много (работает автоматический перевод времени), то срок использования программы закончится уже после 30 запусков.
Если после очередного запуска вы насчитали (ТЕКУЩАЯ_ДАТА - ДАТА_ПРЕДЫДУЩЕГО_ЗАПУСКА + КОЛИЧЕСТВО_ДНЕЙ_РАБОТЫ_ПРОГРАММЫ)>=30, тогда вы знаете что делать :). Можно просто завершать работу, а можно поступить так, как сказано в следующем пункте.

3. По истечению бесплатного использования программы она делает специальную пометку в реестре и полностью удаляется. Если пользователь оставил заначку в виде резервной копии программы, то она тоже сама удалится, как только прочитает эту пометку при запуске. Хотя я и предлагаю вашему вниманию этот метод, все же не советую его использовать т. к. он наиболее конфликтный. 100% гарантии у вас нет, что эта процедура не сработает на уже купленной версии, и вы можете тем самым потерять ценного клиента. Но, тем не менее, вот идея. Перед уничтожением всех данных программы, а обычно они располагаются в каталоге вашей программы, необходимо закрыть все открытые файлы. Далее все файлы по очереди уничтожаются командой:

DeleteFile(НАЗВАНИЕ_ФАЙЛА);

При этом их восстановление возможно специальной утилитой, например UnErase. Сложнее будет восстановить физически затертый файл. Для этого вам надо такой файл создать заново процедурой Rewrite и закрыть. Далее файл нулевого размера можно удалить. Восстановление таких данных без специальных средств дисковых редакторов невозможно. Стандартными средствами восстанавливаются только перезаписанные нами нулевые файлы. Пользователь при этом только напрасно потеряет время. Можно сказать уверенно, что все данные из такого удаленного файла навсегда утеряны.
Если вы еще не находитесь в шоке или азарте от такого откровения, то я вам расскажу про то, как удалить вашу запущенную программу.
Ваша программа уже очистила все свои рабочие файлы и готова сама удалиться. Но если вы попытаетесь ее удалить, то ничего не выйдет. Программа запущена и пока она работает, ее и с места двинуть нельзя. Удалить ее только после закрытия может внешний процесс. Для этого вы программно создаете BAT файл, в котором пишите:

:povtor
del ВАША_ПРОГРАММА
if exist ВАША_ПРОГРАММА goto povtor

Далее запускаете этот bat файл на выполнение командой WinExec или ShellExecute, после чего закрываете свою программу. Используя преимущества многозадачности системы, вы порождаете внешний процесс, который удалят вашу программу.
Для тех, кто не знаком с командами DOS разъясняю. Первая строчка является меткой, к которой можно перейти из любой строки bat файла командой GOTO. Вторая строка пытается удалить вашу программу с диска. Пока ваша программа запущена, ей это не удастся сделать. Третья строка проверяет наличие файла на диске. Если он еще не удален, то происходит переход на метку з названием POVTOR, где снова производится попытка удалить программу.
Откровенно скажу, что этот цикл повторится не один раз, пока ваша запущенная EXE программа не исчезнет, но я вас уверяю, что пользователь не успеет глазом моргнуть, как для него все будет уже закончено. Единственным следом разрушающей деятельности останется этот BAT файл, а может и не остаться, если вы четвертой строкой укажете:
del ТЕКУЩИЙ_BAT_ФАЙЛ
Я пробовал, BAT файл действительно может удалить сам себя.

А теперь три примера для каждой рассмотренной группы.

Пример первый вы можете скачать по этой ссылке (5КБ). Не буду подробно останавливаться на работе этой программы, можете самостоятельно раскрыть проект и изучить работу как отдельных команд, так и всей программы в целом.

Пример второй немного сложнее.
На уроке 17 мы рассмотрели методы сохранения данных в реестр. Скажу, что такая методика для нашего случая не подходит т. к. все данные записываются в раздел HKEY_CURRENT_USER, и в многопользовательской операционной среде такие данные будут вестись по-разному. Когда время для одного пользователя истечет, то программой может пользоваться другой пользователь. А их может быть неограниченное количество. Нам же надо все данные писать в одно место реестра. Выберем это место HKEY_LOCAL_MACHINE\SOFTWARE с подключом, например LAB. Название подключа можете придумать самостоятельно, а опытные пользователи, имеющие опыт работы с реестром, вообще могут придумать оригинальное место хранения данных своей программы. Вообще, в HKEY_LOCAL_MACHINE\SOFTWARE пишут свои данные различные программы. Перед началом написания такой программы не забудьте добавить в раздел подключаемых модулей Uses модуль Registry для работы с реестром.
Пример можно забрать по этой ссылке (4КБ).

В третьем примере вы можете узнать, как программа уничтожает себя и все свои данные. Ее вы можете забрать по этой ссылке (3КБ). Пример удаления запущенной EXE программы был взят мной из моей же программы, в которой есть свойство автоматического обновления по сети.

НЕ нашли? Не то? Что вы ищете?

С уважением, ведущий уроков Semen *****@***net

Урок24. Программа с многоязычным интерфейсом

Автор благодарит читателя этих уроков, программиста Alexey Salo за идею, без которой написание данного материала было бы невозможным. Сразу отмечу, что урок получился не совсем для начинающих, количество написанного кода в примерах испугало даже меня, но тем не менее, попробуйте разобраться. Повсюду даны описание команд, некоторые мы рассматривали в предыдущих уроках. Возможно непонятные моменты рассмотрены более подробно.

Для начала немного теории.
Ваша собственная программа может быть полезна не только вам, но и вашим друзьям, организации, где вы работаете. Если вы работаете не только на себя. Живя в нашем веке компьютерных технологий, информация может распространяться с довольно большой скоростью. Примером тому служат нашумевшие недавно волны интернет-вирусов, за считанные дни облетевшие по многим серверам мира. Так же дело и обстоит с полезными программами. Отличием полезной программы от вредоносной есть сам метод переноса от компьютера к компьютеру. По степени ее уникальности и полезности она может понравиться многим. Я не буду говорить о методах рекламы программных продуктов, они такие же самые, как и реклама обычных продуктов, будь то интернет-ресурс или обычных хозяйственный товар. Дело в том, что ваша программа, выпущенная в свободное распространение (выложенная на сайте, отправленная друзьям по почте и т. п.) абсолютно независимо от вашего желания может попасть любому человеку. Этот человек может быть другой национальности, абсолютно не понимающий русского языка.
Если ваша программа изначально рассчитана на свободное распространение, свободное распространение с ограниченными функциями для последующего приобретения, если ваша программа может оказаться полезной для многих (утилита, игра, экранная заставка), то надо стараться изначально ее оформлять с англоязычным интерфейсом. Все дело в том, что большинство пользователей компьютеров в полной мере или частично знакомы с английским языком. Следовательно, разобраться в такой вашей программе смогут больше человек в мире, чем, скажем в программе с белорусским языковым интерфейсом. Здесь имеется в виду ни что иное, как глобальное внедрение вашего приложения в масштабе целой планеты, а не касательно, скажем, ваших знакомых. Но делая программу, даже с языком, являющимся международным (даже с китайским языком :), трудно рассчитывать на популярность во многих странах.

Большую популярность получили программы с многоязычным интерфейсом. Я имею в виду, что описанные выше программы получают большую популярность, чем аналогичные с однотипным диалоговым языком. К примеру, это некоторые командные оболочки (FAR, Windows Commander), антивирус DrWeb, интернет броузер Opera. В таких программах нужный язык можно выбрать из списка в окнах настройки.

В большинстве случаев, весь языковой интерфейс хранится в отдельном файле. И это правильно. Не стоит загромождать исполняемый EXE файл излишком информации, а настройка и адаптация нового языка, первоначально не включенного в такой программный пакет, происходит быстро и без перекомпиляции всего проекта.

Какой же метод выбрать для хранения и последующего считывания данных из файла языков. В большей степени для этого подходит рассмотренные нами в 16 уроке ini файлы. Такие файлы легко переносятся на другой компьютер вместе с самой программой, возможно редактировать из любого текстового редактора, изменить текст может любой человек.
Различные секции в таком ini-файле будут хранить в себе отдельные языковые интерфейсы. Например, секция
[RUSSIAN]
будет озаглавливать русскоязычный внешний вид программы,
[ENGLISH]
- англоязычный, и т. д. Я думаю, что с этим проблем у пользователя не будет.
Названия хранимых параметров состоят из названия окна (формы), в котором находится компонент плюс название самого компонента. Параметр должен состоять из одного слова. Хранимая величина - текст, который отображается на экране на этом компоненте. Это может быть свойство Caption или свойство Text, в зависимости от типа (класс) компонента. Например, для компонента Button1, находящегося в окне Form1 записываемый параметр и значение выглядит:
Form1Button1=Кнопка1
В нашей программе при чтении такого параметра должна произойти замена:

Form1.Button1.Caption := 'Кнопка1';

Естественно, это делается автоматически для всех визуальных компонентов, на каких есть текст. Проблема может состоять в том, что таких компонентов на каждой форме может быть, скажем 200. Тогда это очень загромоздит программный код. При оперативном исправлении такой программы (добавление, удаление компонентов), необходимо будет исправлять и эту часть кода. Выходом из создавшейся проблемы может быть свойства для определенного окна ComponentCount и Components. Свойство Components позволяет через массив получить доступ к любому элементу управления формы. Свойтсво ComponentCount показывает, сколько этих элементов управления (компонентов) у нас присутствует в окне. Нам нужно будет просто организовать цикл от 1 до ComponentsCount и для каждого компонента прочитать соответствующее значение Caption или Text из INI файла.
Внутри такого цикла нужно определять тип компонента. Ведь для кнопки (Button, BitBtn, SpeedButton), метки (Label, StaticText), флажка (CheckBox, RadioButton) и пр. свойство Caption определяет текст, который будет виден на этом компоненте. Для Edit, Memo, ComboBox и пр. свойтсво Text. Следовательно, очень важно верно определить тип, выбранного из цикла компонента, чтобы в последствии правильно занести соответствующее значение в соответствующее свойство.
Следующим этапом, когда мы определили тип компонента, следует само чтение данных из ini-файла. Вот примерный кусок кода такой программы:

if ComponentCount<>0 then // если в окне есть хотя бы один элемент управления (компонент)
  for i:=1 to ComponentCount do // цикл от 1 до кол-ва компонентов
  if Components[i-1].ClassType = TButton then // если текущий элемент является элементом класса TButton, то
  (Components[i-1] as TButton).Caption:= ЧТЕНИЕ_ДАННЫХ_ИЗ_INI

Разъясню последнюю строчку из этого примера. Через

(Components[i-1] as TButton)

Мы получаем доступ к свойствам компонента, представляя его к классу TButton. Для этого в предпоследней строке примера мы и производим проверку класса выбранного циклом компонента. Если такую проверку не производить, то во время выполнения программы при обращении, скажем к компоненту класса TEdit к свойству Caption, появится сообщение об ошибке (У TEdit свойство Text!).
(i-1) как вы наверное уже догадались, список массива элементов управления формы начинается с нуля. А заканчивается ComponentCount-1.

Еще один нюанс. Если такой многоязычный ini-файл был потерян в процессе эксплуатации, то пользователя рискует остаться вообще без каких либо намеков в вашей программе. Поэтому рекомендую все-таки изначально давать текст вашим компонентам как в обычной программе. В случае невозможности чтения данных из INI файла текст на этих компонентах останется нетронутым.

Теперь я даю вам универсальный модуль, который должен присутствовать в каждом оконном модуле вашей программы, где необходимо менять язык по указанию пользователя. Я являюсь автором этого куска программы, поэтому, возможно, что-то можно и сократить, тем не менее...

В раздел Uses необходимо дописать модуль для работы с ini-файлами:

Uses IniFiles;

Раздел public дописываем одну строку объявления процедуры:

public
  { Public declarations }
  procedure ChangeLang(LangSection:string);

Сама процедура пишется изначально вручную вместе с заголовком:

procedure TForm1.ChangeLang(LangSection:string);
Var i:Integer; // временная числовая переменная для выборки всех компонентов
  LangIniFile:TIniFile;
  ProgramPath:String; // строковая переменная для получения каталога, где находится запущенный EXE файл
begin
if ComponentCount<>0 then // если в окне больше одного компонента
  begin
  ProgramPath:=ExtractFileDir(Application. ExeName); // получаем каталог, где лежит запущенный EXE файл
  if ProgramPath[Length(ProgramPath)]<>'\' then ProgramPath:=ProgramPath+'\'; // гарантированно устанавливаем последний символ '\' в конце строки
  LangIniFile:=TIniFile. Create(ProgramPath+'lang. ini'); // подготавливаем INI файл. Он должен иметь название lang. ini и должен находиться в каталоге программы
  Caption:=LangIniFile. ReadString(LangSection, Name, Caption); // читаем заголовок окна
  for i:=1 to ComponentCount do // перебираем все компоненты в этом окне
  begin
  if Components[i-1].ClassType=TButton then // если выбран из массива компонент Button, то изменяем текст на кнопке
    (Components[i-1] as TButton).Caption := LangIniFile. ReadString(LangSection, Name+Components[i-1].Name, (Components[i-1] as TButton).Caption);
// Напомню описание функции ReadString:
// LangIniFile. ReadString( СЕКЦИЯ, ПАРАМЕТР, ЗНАЧЕНИЕ_ПО_УМОЛЧАНИЮ );
// 1. LangSection - передаваемый параметр в процедуру. В процедуру передается название секции для выбранного языка
// 2. Name+Components[i-1].Name - Name - название формы, Components[i-1].Name - название компонента
// 3. (Components[i-1] as TButton).Caption - в случае неудачного чтения этого параметра из ini файла (нет такого параметра), то ничего меняться не будет
// аналогично для других типов:
  if Components[i-1].ClassType=TLabel then
  (Components[i-1] as TLabel).Caption := LangIniFile. ReadString(LangSection, Name+Components[i-1].Name, (Components[i-1] as TLabel).Caption);
  if Components[i-1].ClassType=TEdit then
  (Components[i-1] as TEdit).Text := LangIniFile. ReadString(LangSection, Name+Components[i-1].Name, (Components[i-1] as TEdit).Text);
  // ...
  // ...
  // ...
  end;
  LangIniFile. Free; // освобождаем ресурс
  end;
end;

Этот пример можно забрать по этой ссылке (4КБ). Обратите внимание, в программе два окна. В каждом модуле для каждого отдельного окна присутствует эта вышеописанная процедура.

Вместо строк // ... вы можете добавлять другие типы компонентов, например, можете описать тип компонента TCheckBox, если таковой имеет место в вашей программе. В идеале описывайте по шаблону все или большинство типов компонентов, имеющиеся в наличие в delphi. Для этого вам понадобится несколько десятков строк программного кода, но зато вы гарантированно можете применять эту процедуру не только в одной вашей программе, не проверяя наличие всех используемых типов компонентов.

Напомню, аналогичную вышеприведенную процедуру, без изменений, вы должны вписать в каждый модуль вашей программы. При смене языка, например, в программе с тремя окнами (Form1, Form2, Form3) происходит следующим куском программного кода:

Form1.ChangeLang('RUSSIAN');
Form2.ChangeLang('RUSSIAN');
Form3.ChangeLang('RUSSIAN');

Поскольку процедуру смена языка мы объявляем в разделе public, то доступ к этой процедуре мы можем получить из любого места программы. Как вы заметили из примера, для переключения на русский язык указана имя секции RUSSIAN.

Теперь рассмотрим содержание самого INI файла. Его вы должны создавать самостоятельно. Во-первых, нужно помнить правила орфографии windows ini-файла, во-вторых, названия параметров должны соответствовать имени формы плюс названия компонента, хранимое значение следует за знаком равенства. Для примера, ini-файл с двумя языками, с двумя окнами, на каждом окне находится по две кнопки.

; начало файла lang. ini
[RUSSIAN]
Form1Button1=Кнопка 1 на форме 1
Form1Button2=Кнопка 2 на форме 1
Form2Button1=Кнопка 1 на форме 2
Form2Button2=Кнопка 2 на форме 2

[ENGLISH]
Form1Button1=Button 1 on form 1
Form1Button2=Button 2 on form 1
Form2Button1=Button 1 on form 2
Form2Button2=Button 2 on form 2
; конец файла lang. ini

Кроме текста на визуальных элементах управления вашей программы, текст содержится еще в заголовке программы, в панели задач. Еще могут присутствовать всплывающие подсказки Hint. Полномасштабный перевод всех компонентов на несколько языков в ini файле может несколько затруднить сам процесс программирования. Но ради гибкости настройки интерфейса программы пожертвовуйте лишним временем. Ведь для изменения текста, добавления нового языка (возможно даже это делаете не вы) не нужно перекомпилировать проект. Это максимально упрощает языковую настройку. Можете вообще сделать ini-файл одноязычным. Перевести его можете после окончания проектирования, или вообще предоставьте это профессиональному переводчику.

Одним из слабых мест в такой программе есть необходимость помещать процедуру смены языка в каждый модуль. Если у вас в программе множество окон, это довольно сильно загромождает программный код, следовательно, увеличивает размер программы, следовательно, замедляет ее работу. Как же сделать так, чтобы весь процесс смены языка во всем приложении умещался с одной процедуре. Очень просто. А может и не просто. А в общем, через компонент Application. Он является по своей сути самой программой, значит,  содержит в себе все компоненты форм (уже упоминалось в первых уроках, что сама форма и есть компонент). Таким образом:

if ponentCount<>0 then // если в приложении есть компоненты форм (не консольное приложение)
  for i:=1 to ponentCount do // перебираем все компоненты
  if ponents[i-1].ClassParent=TForm then // если выбранный компонент является подклассом окна, то
  begin
  // обработка переключения языка для этого окна
  end;

Очень похоже на предыдущий пример...
Извините, что на первый взгляд эта тема урока кажется, немного сложноватой для начинающего, но тут важно разобраться в общих принципах, в нескольких свойствах, внимательно перечитать весь урок снова и все может стать понятным. Обязательно рассмотрите прилагаемый первый пример, прежде чем продолжать рассматривать этот урок далее.

Опять ищем слабые места в программе. Для начинающих программистов может быть новостью, что в одной программе не может быть двух и более окон с одинаковыми названиями. А как же дело обстоит с MDI приложениями. Дочернее окно проектируется в единственном варианте, а в внутри родительской формы, во время работы программы, оно может создаваться теоретически в неограниченном количестве. Имена же самой вновь создаваемой дочерней форме присваиваются системой автоматически. Следовательно, читать параметр из ini-файла по свойству Name не подойдет. Таким методом можно максимально прочитать язык для компонентов только для одного дочернего MDI-окна. Отсюда следует, что нужно читать данные согласно свойству ClassName, которое является уникальным для отдельного класса окна. Например, для окна Form1, являющегося главным MDI-окном такой класс TForm1. Для окна Form2, дочернего MDI-окна класс TForm2. Вот, вы наконец и узнали, что же это за такая туква Т, стоящая в начале названия компонента. Это надкласс, объединяющий однотипные компоненты (в том числе и окно программы) в единую группу, с одинаковыми вложенными свойствами. Это краткое описание, можно сказать, своими словами.

Эти все "наваяния" организованы во втором примере. Там смена языка происходит из одной процедуры абсолютно для всех окон. Тем самым мы уменьшили программный код за счет увеличения качества, увеличили количество вложенных циклов. Программа примера номер 2 является незаконченным каркасом MDI-приложения. Не удивляйтесь, почему программа не выполняет функции редактора.
Забирайте второй пример по этой ссылке (8КБ).

Оъявление. Автор уроков для начинающих по delphi ищет темы, какие вам было бы интересно узнать. Свои предложения отсылайте мне, Semen'у, по адресу *****@***net, указав в теме письма слово "предложение". Ваше предложение не должно быть очень сложным для программного решения, понятным для начинающего, тема не должна отклоняться от тематики ведения уроков (например, не рассматривается управление базами данных, SQL, internet и пр.). Материал, написанный по вашему предложению, ориентировочно должен быть дан в объеме одного урока. Предложение в текущий урок должно быть отправлено до пятницы.

По вашему дополнительному пожеланию ссылка на автора идеи будет помещена в начале урока. В таком случае обязательно делайте соответствующую пометку и указывайте свое имя с обратным адресом в письме с предложением.

С уважением, ведущий уроков Semen *****@***net

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8