Извлечение ресурсов (например, файл MP4) из пакетов .BPL [дубликат]

Ваш код getElementById() работает, поскольку идентификаторы должны быть уникальными, и поэтому функция всегда возвращает ровно один элемент (или null, если ни один не найден).

Однако getElementsByClassName() , querySelectorAll() и другие методы getElementsBy* возвращают массивный набор элементов. Итерации над ним, как и с реальным массивом:

var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
    elems[i].style.size = '100px';
}

Если вы предпочитаете что-то более короткое, рассмотрите использование jQuery :

$('.myElement').css('size', '100px');

3
задан ivarec 22 March 2012 в 19:13
поделиться

3 ответа

Вам нужно использовать FindClassHInstance(), указав тип класса вашего компонента, вместо использования глобальной переменной HInstance или GetModuleHandle(). Таким образом, вы получаете правильный дескриптор модуля независимо от того, ставится ли пакет статически связан или динамически связан с основным исполняемым файлом.

7
ответ дан Remy Lebeau 22 August 2018 в 08:23
поделиться
  • 1
    +1 Это лучший способ сделать это, я согласен, но я до сих пор не могу понять, почему GetModuleHandle может потерпеть неудачу. – David Heffernan 22 March 2012 в 17:39
  • 2
    FindClassHInstance успешно получает дескриптор, но Delphi бросает одно и то же исключение. Ресурс есть (в проекте пакета), и все имена правы. Я тестировал данные png и данные BMP, и получаю те же результаты. – ivarec 22 March 2012 в 17:48
  • 3
    Следующий шаг после подтверждения того, что ресурс находится в проекте пакета, должен подтвердить, что он находится в скомпилированном пакете. Проверьте, находится ли ресурс в файле BPL. Убедитесь, что файл BPL, который вы проверяете, является тем же, который загружается вашим приложением, - что нет двух копий вашего BPL, плавающего вокруг. – Rob Kennedy 22 March 2012 в 18:02
  • 4
    Как проверить, находится ли ресурс в файле BPL? Я подтвердил, что ресурс действительно находится в файле .res. И есть только один из «my_package.bpl». файл, загруженный в ProcessExplorer. – ivarec 22 March 2012 в 18:42
  • 5
    Используйте редактор ресурсов, например, редактор ресурсов XN или ResourceHacker – David Heffernan 22 March 2012 в 18:45

Вы передаете HInstance, дескриптор исполняемого модуля, в функцию загрузки ресурсов. Это не удается, потому что ресурс находится в модуле пакета. Поэтому вам нужно передать дескриптор модуля для пакета. Вы можете получить дескриптор модуля пакета следующим образом:

PackageModuleHandle := GetModuleHandle(PChar('MyPackage.bpl'));

Если вы загружаете свой пакет динамически, вызов LoadPackage возвращает дескриптор модуля.

Обновление: Рекомендация Реми об использовании FindClassHInstance, безусловно, является лучшим способом получения дескриптора модуля.

3
ответ дан David Heffernan 22 August 2018 в 08:23
поделиться
  • 1
    Я использую HInstance в коде моего пакета. Я отредактирую и добавлю эту строку. – ivarec 22 March 2012 в 16:53
  • 2
    @haole Да, я предположил, что код, о котором идет речь, жил в пакете. Виноват. Ответ должен вернуть вас домой. – David Heffernan 22 March 2012 в 17:04
  • 3
    Практически там: Функция GetModuleHandle всегда возвращает 0, нет mather, если я пытаюсь использовать MyPackage.bpl, просто MyPackage или абсолютный путь к bpl. Что еще может быть неправильно? Спасибо за внимание. – ivarec 22 March 2012 в 17:15
  • 4
    GetModuleHandle работает. Думаю, вы должны каким-то образом передать неправильное имя. Вы заменяете MyPackage.bpl именем своего пакета. – David Heffernan 22 March 2012 в 17:18
  • 5
    Не работает. Есть ли способ отладить это? – ivarec 22 March 2012 в 17:29

Компонент, который использует ресурс, который реализован в модуле с именем MyUnit1.pas, должен включать следующую строку внутри:

{$R MyUnitRc.res MyUnitRc.rc}

Обратите внимание, что приведенный выше синтаксис не будет работать на некоторых старых версиях delphi (Delphi 7). Вышеизложенное работает в 2010, XE, XE2 и т. Д., И он компилирует .rc в .res, когда проект создает этот блок. В качестве альтернативы вы добавили бы объявление {$R} в каждое статически связанное приложение, а также в файл .dpr вашего BPL.

Этот файл .RC mYUnitRc.res будет содержать одну или несколько строк, объявляющих ваши ресурсы. Я использую объявления RCDATA для загрузки PNG, например:

MYIMAGENAME RCDATA "MyFile.png"

Если вы сделаете это так, вместо использования файла RC, добавленного только в .dproj / .dpr, тогда он будет работать в двух важные случаи:

  1. Когда BPL загружается во время разработки.
  2. Когда компонент загружается во время выполнения из приложения, которое скомпилировано с отключенными пакетами времени выполнения.

Чтобы справиться с третьим случаем, с которым отвечает другой (Реми и Дэвид), вам нужно вызвать FindClassHinstance, как заявил Реми. Однако я считаю, что вы также должны посмотреть, как вы включаете файл ресурсов и скомпилировать его и связать как внутри вашего пакета, так и внутри приложений, которые используют этот компонент.

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

procedure TSampleControl.LoadImageFromResource( button:TSubControl);
var
    png:TPngImage;
begin
  if button.DefaultResourceId='' then exit;
      png := TPngImage.Create;
      try
        try
        png.LoadFromResourceName(HInstance,button.DefaultResourceId);
          button.Glyph.Assign(png);
        except
          on E:Exception do begin
               OutputDebugString( PChar(button.DefaultResourceId+' load error:'+E.Message) );

          end;

        end;
      finally
        png.Free;
      end;

end;

Обратите внимание, что я улавливаю исключения загрузки ресурсов, которые оставляют некоторые элементы в моем управлении без их глифов, но по крайней мере не разбивают Delphi , HInstance, возможно, потребуется изменить, поскольку Дэвид и Реми Пойнт используют LoadFromResourceName для обработки случая, когда вам нужно загрузить с .BPL, но я не думаю, что вы можете предположить, что человек, который использует ваши компоненты, всегда перераспределяем ваш файл BPL, и, следовательно, FindClassHinstance предпочтительнее GetModuleHandle ..

Обновление: я должен был использовать то, что предложил Реми:

       png.LoadFromResourceName( FindClassHInstance(TSampleControl),
                 button.DefaultResourceId);
2
ответ дан Warren P 22 August 2018 в 08:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: