Delphi javascript не компилится файл ресурсов

Обновлено: 06.07.2024

Подключение ресурсов в исполнимые файлы Delphi

В этой статье я попытаюсь объяснить как включать файлы в приложения Delphi как различные виды ресурсов и как управлять ими.

Можно включить любой файл в исполнимый файл для использования как ресурс. Некоторые виды ресурсов признаются API и могут использоваться непостредственно. Другие просто принимаются как двоичные данные. В этой статье мы рассмотрим примеры обоих видов.

Чтобы создать файл ресурса, мы начинаем с исходного файла *.RC, например, по имени Resources.rc , который содержит виды ресурсов (имя, класс и файл).

Имена ресурсов (sample_bmp, sample_ico и т.д.) произвольны. Вид ресурса может быть поддерживаемый API (BITMAP, ICON, CURSOR) или произвольный (JPEG, WAVE, TEXT). Имена файла определяют файлы, которые будут включены в .RES, а позже .EXE.

Теперь мы должны скомпилировать .RC файл, чтобы получился .RES файл. Для этого мы можем использовать Borland Resource Compiler (brcc32.exe).

Набрав в командной строке, мы получим:

Для того, чтобы присоединить файл ресурсов к нашему проекту, мы используем директиву или :

Загрузка поддерживаемых ресурсов (BITMAP, CURSOR, ICON) проста, так как Windows API предоставляет нам функции LoadBitmap, LoadCursor, LoadIcon соответственно для получения дескрипторов этих элементов.

Другие ресурсы использовать немного сложнее. Давайте начнем с изображения JPEG. Мы будем использовать функцию TResouceStream, чтобы загрузить ресурс как поток, который будет загружен в объект TJpegImage.

Для WAV файлов мы нуждаемся в указателе на ресурс, загруженный в память, а для текстового файла мы должны загрузить ресурс в строку. Мы можем сделать это, используя TResourceStream, но давайте посмотрим пример, который использует API:

Как только мы загрузим WAV ресурс в память, мы можем его проигрывать столько раз, сколько нужно, используя sndPlaySound, объявленную в модуле MMSystem.

Есть некоторые ресурсы (типа шрифтов, анимированных курсоров), которые не могут использоваться из памяти. Мы обязательно должны сохранить эти ресурсы во временном файле на диске и загружать их оттуда. Следующая функция сохраняет ресурс в файл:

Следующая функция использует предыдущую, чтобы сохранить ресурс во временном файле:

Следующая функция использует SaveResourceAsTempFile, чтобы сохранить ресурс анимированного курсора во временном файле, затем загризить этот ресурс из файла при помощи LoadImage и затем удалить временный файл. Функция возвращает дескриптор, возвращенный функцией LoadImage.

Эпиграф: «Пусть это вдохновит Вас на подвиг!» (Бел Кауфман, «Вверх по лестнице, ведущей вниз»).

О костылях и велосипедах, неотъемлемой части современной некромантии.


Это история интеграции в процесс разработки одного единственного решения. Решение доведено до конечного результата, ссылка на репозиторий будет далее по тексту.

Казалось бы, что может быть более простым и естественным, чем прозрачная, без «нелепых телодвижений», работа с размещёнными в специально выделенной для этого папке ресурсами? А если среда разработки выпущена на границе тысячелетия?

Первым великим неудобством, с которым я столкнулся, «подписавшись» года четыре назад на сопровождение и активную доработку проекта на Delphi 7, было категорическое неудобство работы с входящими в проект относительно крупными SQL запросами. Проект обеспечивает отчётность перед поставщиками (десятки поставщиков, взаимодействие с которыми идёт через множество компаний-интеграторов), и этих запросов там, что гуталина у сторожа — «ну просто завались». Причём запросы эти изначально описывались прямо в тексте, вперемешку с кодом… представьте мой восторг с учётом того, что запросы приходилось время от времени переносить в SSMS, исправлять и переносить обратно. А если вспомнить, что и Delphi, и в SQL используются одиночные кавычки, становится ещё печальнее.

Первая реакция на эту «красоту» была вполне предсказуемой: срочно отделить данные от кода! Идеальным (и очевидным) решением кажется создание структуры папок с файлами запросов, которые при компиляции автоматически попадали бы в ресурсы с соответствующими идентификаторами. При этом, однако, компилятору нужно явно предоставлять список ресурсов в виде отдельно сформированного *.rc файла с соответствующими именами для доступа, который надо ещё предварительно сформировать.

Однако, компиляция проекта из-под IDE Delphi 7 является чёрным ящиком без малейшей возможности прикрутить к ней хоть что-то своё. У неё просто нет ни одного хука, чтобы зацепить собственный обработчик. Современные версии работают с MS Build, но у меня-то этого нет! Конечно, для сборки продуктивной версии можно использовать батник и компилятор командной строки, где можно добавить любую предварительную обработку, но для запуска из-под IDE этот вариант не годится.

Ещё одна печалька оказалась в том, что файл ресурсов (*.rc) перекомпилируется только тогда, когда изменилась его собственная дата. То, что изменилась дата файла, на который он ссылается (то есть сам ресурс), компилятор не волнует никак. Плюс rc-файл ещё и создать надо! И очень, очень хочется делать это автоматически.

Но сначала появился костыль. До этого я работал с Дельфи лет восемь назад, и с ресурсами тогда совсем не сталкивался, зато свободно делал компоненты. Итак, для решения вопроса «по-быстрому» я набросал визуальный компонент, который можно было кинуть на форму и открыть текст в редакторе (в окончательной версии - вообще двойным кликом). Набросок был готов в течение пары часов, затем после нескольких подходов компонент был окончательно оформлен и разделён на две части (просто текст и SQL) ради синтаксической подсветки в редакторе кода. Ниже, на скриншоте, Вы можете увидеть аж четыре компонента (два из которых успели активно поработать), но… Проект, хотя и обеспечил очень быстро возможность по-человечески работать с текстом запросов, был заброшен в силу присущих ему принципиальных недостатков.

Первым и самым важным из них оказался формат хранения контента в .dfm файле — «почти текстовый». Текст принудительно разбивался на строки, закавычивался, все символы не из базовой латиницы записывались многосимвольными кодами… Представляете себе, как выглядели при этом диффы? Невозможным оказывался также контекстный поиск по всему проекту (тексты запросов в него не попадали). Поиск сторонними средствами по латинице мог споткнуться о размер строки и её принудительный перенос посреди слова.


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

С учётом перечисленного, проект с компонентами замер на полушаге из-за потери целесообразности, а я начал исследовать возможность всё-таки перейти на использование текстовых файлов с автоматическим добавлением их в ресурсы.

Итак, я вернулся к идее хранить отдельные запросы в файлах. Предстояло решить следующие проблемы:

Должен автоматически формироваться файл со списком ресурсов для компилятора

ВАЖНО. изменение файла с запросом должно автоматически попасть в программу, при первой же компиляции (даже если не делать build)

Обеспечить включение ресурсов в операцию контекстного поиска по проекту.

Опционально — ещё и шифровать для пущего пафоса. Требование проекта на уровне «Очень желательно».

По первому пункту я решил использовать Gulp.js — инструмент для сборки фронтенда, с которым мельком удалось познакомится незадолго до этого. Он умеет следить за изменением файлов в папке и обрабатывать это событие. Мне требовалась лишь возможность запустить по событию командный файл. Этот же файл используется и для билда продуктивной версии.

Обеспечение второго пункта разложилось на две половинки. Во-первых, при изменении исходных файлов требовалось сразу же, не дожидаясь перестроения списка, изменить дату .rc файла. Это инициирует запрос на перезагрузку файла при переключении в Delphi. Во-вторых, этот файл должен быть постоянно открыт в IDE, иначе компилятор не обращает внимания на то, что он изменился (он-то, наивный, предполагает, что я всё через IDE делаю). А так — при переключении извне в IDE дата файла проверяется и задаётся вопрос о необходимости его перезагрузить.

Третий пункт (контекстный поиск) решается добавлением исходного файла в проект, до первого USES, в директиве компилятора вида:

Четвёртый решается элементарно запуском отдельной утилитки для шифрования всё в том же пакетном файле, и расшифровкой непосредственно в основном проекте при обращении к ресурсу.

Ну, и собственно список файлов сформировать надо было. В результате шапка проекта стала выглядеть примерно так:

SomeProject.dpr

AutoGenerated.rc (пример):

Галпфайл был простой до безобразия:

gulpfile.js

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

Впрочем, это уже не важно — от Галпа я буквально в процессе написания статьи избавился.

сразу же меняет дату сгенерированного файла

составляет список файлов в обслуживаемой папке, за вычетом исключений

запускает программку на Perl, которая преобразует сырой список файлов во все виды, в которых он употребляется, в том числе генерирует rc-файл, и формирует задание на подготовку (шифрование) для изменённых файлов

запускает подготовку ресурсов

выделяет из dpr ранее добавленный туда список ссылок. Если он изменился, то заменяет его

компилирует сформированный rc-файл

Информирует о времени запуска и завершения и об обслуживаемой папке (на случай одновременного запуска нескольких экзкмпляров.

И всё это запускается из отслеживающего изменения монитора.

CompileAllResources.cmd

Внутри он содержит сборную солянку технологий, использует линуксовские find и grep (под Виндой они ставятся вместе с git) и даже Перл. Каюсь, побаловаться захотелось. Забавный опыт, хотя и немного травматичный. Своей лаконичностью и непрозрачностью (вроде наличия «переменной по умолчанию») он напомнил мне ассемблер:

CreateRc.pl

В процессе многолетней эксплуатации вылезли забавные особенности. Для примера, обновление git (с последующим обновлением линуксовских утилит) как-то раз мою автоматизацию сломало. Конкретно, более новый grep отказался воспринимать список исключений как список регэкспов, по одному на строку. Find тоже что-то такое подбрасывал (по крайней мере, тот, что установлен глобально сейчас, уже не отрабатывает именно так, как ожидается). В результате пришлось зафиксировать их версию — банально кинуть бинарники в репозиторий, чтобы потом не плакать, благо, они не шибко большие, и изменять я их не планирую. Было ли что-то подобное в связи с Перлом — не помню, но на всякий случай и его туда же пихнул.

Помню ещё, что добавление шифрования вынудило запоминать дату изменения файлов и шифровать только обновлённые, иначе просто долго получалось — скрипт не успевал отработать до того, как я отвечал согласием на предложение перезагрузить исходные файлы в IDE.

И уже после того, как взялся за эту статью, решил всё-таки избавиться от Галпа. Зачем мне (или тому, кто попробует это за мной повторить) неконтролируемая глобальная внешняя зависимость, имеющая ещё одну неконтролируемую внешнюю зависимость (я по node.js), и из возможностей которой используется откровенный мизер?

Инсталлятор проекта CompileRc работает с использованием git. Он создаёт ветку в репозитории проекта и добавляет туда необходимые модули и настроечные файлы. Вместо шифрования по умолчанию используется заглушка (копирование), что позволяет добавлять ресурсы «как есть». Вот скриншот репозитория тестового проекта в SmartGit, после добавления в него CompileRc (все три коммита ветки CompileRc, как и сама ветка, сформированы инсталлятором), запуска монитора и добавления нескольких файлов ресурсов (в рабочем дереве):


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

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

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

Если честно, хотел в первую очередь рассказать о параметризованных модульных тестах и об автоматизации их запуска, но вот вылезла именно эта тема, не отвертишься: «пиши меня», и всё тут.

UPD:

Возможно, осталось за кадром: данное решение только генерирует валидный для Delphi код и автоматизирует рутину: своевременно добавляет файл ресурса к списку на компиляцию и к списку внешних файлов проекта, и своевременно компилирует rc в RES (средствами Delphi). Всё. Шифрует ещё в конкретном проекте, но это как раз излишество в общем случае. Запуская его под монитором изменений я перевожу работу с ресурсами из состояния статики («созданы раз и навсегда») в динамику («редактирую на лету»).

UPD2:

UPD3:

Испробовав на практике подготовку ресурсов по событиям компилятора вместо мониторинга изменений исходных файлов. К сожалению, не удалось (пока?) спровоцировать компиляцию тогда, когда исходники ресурсов изменились, а IDE считает, что ничего не менялось и вообще не запускает компиляцию, вместе с соответствующими событиями. Поэтому приведённое в статье решение так и осталось в строю.

Пожалуйста, выделяйте текст программы тегом [сode=pas] . [/сode] . Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля. Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
. (продолжение следует) .
Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.
Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца.

'> Delphi+JAVAScript , Как Выполнить JAVA SCRIPT и вывести результат в memo1 ?


Нужно программно в Delphi с помощью этого java скрипта зашифровать 20 строк.
И получившийся результат:

document. write(unescape("%u041F%u043E%u043F%u044B%u0442%u043A%u0438%20%u043E%u0442%u043A%u0440%u044B%u0442%u0438%u044F%20%u043E%u0431%u0441%u0443%u0436%u0434%u0435%u043D%u0438%u0439%20%u0440%u0435%u0430%u043B%u0438%u0437%u0430%u0446%u0438%u0438%20%u0432%u0440%u0435%u0434%u043E%u043D%u043E%u0441%u043D%u043E%u0433%u043E%20%u041F%u041E%20%u043D%u0430%u043A%u0430%u0437%u044B%u0432%u0430%u0435%u0442%u0441%u044F%20%u043F%u0440%u0435%u0434%u0443%u043F%u0440%u0435%u0436%u0434%u0435%u043D%u0438%u0435%u043C%20%u043D%u0430%2030%20%u0434%u043D%u0435%u0439.%20%0A%u041F%u043E%u0432%u0442%u043E%u0440%u043D%u0430%u044F%20%u043F%u043E%u043F%u044B%u0442%u043A%u0430%20-%2060%20%u0434%u043D%u0435%u0439.%20%u041F%u043E%u0441%u043B%u0435%u0434%u0443%u044E%u0449%u0438%u0435%20%u043F%u043E%u043F%u044B%u0442%u043A%u0438%20%u0431%u0430%u043D.%0A%u041C%u0430%u0442%20%u0432%20%u0440%u0430%u0437%u0434%u0435%u043B%u0435%20-%20%u0431%u0430%u043D%20%u043D%u0430%20%u0442%u0440%u0438%20%u043C%u0435%u0441%u044F%u0446%u0430. "));


Вывести в memo1 ОДНОЙ СТРОКОЙ . (иначе Java скрипт потом не работает. )
Помогите пожалуйста





user posted image

user posted image

Вот. Сделал форму:

Добавил код:

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Добавлено 10.05.10, 14:49
без IDE запустил. говорит script control не инсталирован. где достать его.

From bitmaps to icons to cursors to string tables, every Windows program uses resources. Ресурсы - это те элементы программы, которые поддерживают программу, но не являются исполняемым кодом. В этой статье мы рассмотрим несколько примеров использования растровых изображений, значков и курсоров из ресурсов.

LOCATION OF RESOURCES

Placing resources in the .exe file has two main преимущества:

  • Доступ к ресурсам можно получить быстрее, потому что для поиска ресурса в исполняемом файле требуется меньше времени, чем для его загрузки из файла на диске.
  • Программный файл и ресурсы могут содержаться в одном блоке (файл .exe) без необходимости в большом количестве вспомогательных файлов.

THE IMAGE EDITOR

Прежде всего, нам нужно создать файл ресурсов. Расширение по умолчанию для файлов ресурсов - .RES. Файлы ресурсов могут быть созданы с помощью Delphi's Image Editor.

You can name the resource file anything you want, as long as it has the extension ".RES" and the filename without the extension is not the same as any unit or project filename. This is important, because, by default, each Delphi project that compiles into an application has a resource file with the same name as the project file, but with the extension ".RES". It's best to save the file to the same directory as your project file.

ВКЛЮЧЕНИЕ РЕСУРСОВ В ПРИЛОЖЕНИЯ

In order to access our own resource file, we have to tell Delphi to link our resource file in with our application. This is accomplished by adding a compiler directive to the source code.

This directive needs to immediately follow the form directive, like the following:

Do not accidentally erase part, as this is the line of code that tells Delphi to link in the form's visual part. When you choose bitmaps for speed buttons, Image components or Button components, Delphi includes the bitmap file you chose as part of the form's resource.

Delphi изолирует элементы пользовательского интерфейса в файле .DFM.

Чтобы действительно использовать ресурс, вы должны сделать несколько вызовов Windows API. Растровые изображения, курсоры и значки, хранящиеся в файлах RES, можно получить с помощью функций API. LoadBitmap, LoadCursor и LoadIcon соответственно.

PICTURES IN RESOURCES

В первом примере показано, как загрузить растровое изображение, хранящееся как ресурс, и отобразить его в TImage компонент.

Note: If the bitmap that is to be loaded is not in the resource file, the program will still run, it just won't display the bitmap. This situation can be avoided by testing to see if the bBitmap.Handle is zero after a call to LoadBitmap() и предпринимая соответствующие шаги. Часть try / finally в предыдущем коде не решает эту проблему, она предназначена только для того, чтобы убедиться, что bBitmap уничтожен, а связанная с ним память освобождена.

Другой способ, который мы можем использовать для отображения растрового изображения из ресурса, заключается в следующем:

CURSORS IN RESOURCES

Screen.Cursors[] is an array of cursors supplied by Delphi. By using resource files, we can add custom cursors to the Cursors property. Unless we wish to replace any of the defaults, the best strategy is to use cursor numbers starting from XNUMX.

ICONS IN RESOURCES

If we look at Delphi's Project-Options-Application settings, мы можем обнаружить, что Delphi предоставляет значок по умолчанию для проекта. Этот значок представляет приложение в проводнике Windows и когда приложение свернуто.

Мы можем легко изменить это, нажав кнопку «Загрузить значок».

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

For the animation, we need a TTimer component on a form. The code loads two icons from resource file into an array of TIcon объекты; этот массив нужно объявить в публичной части основной формы. Нам также понадобится NrIco, that is an Целое напишите переменная, declared in the что такое варган? part. The NrIco используется для отслеживания следующего отображаемого значка.

В TimerXNUMX.OnTimer обработчик события, IsMinimized Функция используется, чтобы увидеть, нужно ли нам анимировать наш основной значок или нет. Лучшим способом добиться этого было бы захватить кнопки максимизации / минимизации, а затем действовать.

FINAL WORDS

Мы можем разместить что угодно (ну, не все) в файлах ресурсов. В этой статье показано, как использовать ресурсы для использования / отображения растрового изображения, курсора или значка в вашем приложении Delphi.

Note: When we save a Delphi project to the disk, Delphi automatically creates one .RES file that has the same name as the project (if nothing else, the main icon of the project is inside). Although we can alter this resource file, this is not advisable.

Читайте также: