Несколько иконок в Delphi exe

Кто-нибудь знает как с помощью Delphi присвоить выполнимому файлу сразу несколько иконок? Т.е. так, что если вы ассоциируете тип файла и просматриваете ваше скомпилированное приложение, вы видите несколько возможных иконок, но, к сожалению, опция Project|Options|Application|Icon позволяет установить только одну иконку.

Просто создайте файл ресурса (.res), для примера, в Image Editor, и сохраните в нем ваши иконки. Затем подлинкуйте ресурс директивой компилятора $R и ваше приложение будет иметь столько иконок, сколько вы их создадите.

 

Мультиязыковое приложение

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

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

Вот некоторый код, дающий представление об этом методе:

unit French1;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,

Forms, Dialogs, StdCtrls, IniFiles;

type

TForm1 = class(TForm)

Button1: TButton;

procedure FormActivate(Sender: TObject);

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

StringIndex: Integer;

implementation

{$R *.DFM}

{$R MULTLANG.RES}

{ Вот содержимое ресурсного файла для этого проекта:

1, "Attention"

2, "No Condition definition selected!"

3, "Always"

4, "Cannot delete the 'always' condition."

5, "Confirmation"

6, "Delete the condition?"

7, "Yes"

8, "No"

9, "Attention"

10, "Pas de condition Selectionnйe"

11, "Toulours"

12, "Ne peux effacer la condition 'Toujours'"

13, "Confirmation"

14, "Effacer cette condition?"

Компиляция ресурсов

У меня имеется приблизительно 36 маленьких растровых изображений, которые я хочу сохранить в файле и затем прилинковать его к exe. Как мне поместить их в res-файл?

Самый простой путь — создать файл с именем «BITMAPS.RC» и поместить в него список ваших .BMP-файлов:

BMAP1 BITMAP BMAP1.BMP

BMAP2 BITMAP BMAP2.BMP

CLOCK BITMAP CLOCK.BMP

DBLCK BITMAP DBLCK.BMP

DELOK BITMAP DELOK.BMP

LUPE BITMAP LUPE.BMP

OK BITMAP OK.BMP

TIMEEDIT BITMAP TIMEEDIT.BMP

Затем загрузите Resource Workshop (RW) и выберите пункт меню File|Project Open. В выпадающем списке «File Type» (тип файла) выберите RC-Resource Script и откройте файл, который вы только что создали. После того, как RW загрузит ваш файл, выберите пункт меню File|Project save as. Выберите объект RES-Resource из выпадающего списка «File Type» (тип файла). В поле редактирования «New File name» задайте имя нового файла, скажем, BITMAPS.RES. Нажмите OK. Теперь у вас есть файл ресурса. В вашем модуле Delphi добавьте после строки {$R *.RES} строку {$R BITMAPS.RES}. После компиляции вы получите exe-файл с скомпилированными ресурсами. Для получения доступа к ресурсам во время выполнения программы нужно сделать следующее:

myImage.Picture.Bitmap.Handle := LoadBitmap(HInstance, ‘TIMEEDIT’);

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

Как проиграть Wave-ресурс

Сначала делаешь файл SOUND.RC, в нем строка вида: MY_WAV RCDATA TEST.WAV Компилишь чем-нибyдь в *.RES

Далее в тексте:

{$R полное_имя_файла_с_ресурсом}

var

WaveHandle: THandle;

WavePointer: pointer;

...

WaveHandle := FindResource(hInstance, 'MY_WAV', RT_RCDATA);

if WaveHandle 0 then

begin

WaveHandle := LoadResource(hInstance, WaveHandle);

if WaveHandle 0 then

begin

;

WavePointer := LockResource(WaveHandle);

PlayResourceWave := sndPlaySound(WavePointer, snd_Memory or

SND_ASYNC);

UnlockResource(WaveHandle);

FreeResource(WaveHandle);

end;

end;

Как локализовать (русифицировать) ресурсы какого-либо пакета (runtime package)

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

Вынимаете pесуpсы из этого модуля.

Пеpеводите их на дpугой язык. (напpимеp pусский)

Создаете в Delphi свой пpоект Dll-ки (с именем того модуля, из котоpого вы вынули pесуpсы, напpимеp vcl30), в котоpый включаете _пеpеведенные_ pесуpсы: {$R vcl30rus.res}

Собиpаете все это.

Пеpеименовываете полученную vcl30.Dll в vcl30.rus и кидаете ее в System.

Если вы хотите, пpиложение «говоpило» по pусски только тогда, когда в pегиональных установках стоит Russia — то тогда это все.Если же вы хотите, чтобы ваше пpиложение _всегда_ поднимало pусские pесуpсы,то необходимо сделать следующее добавление в Registry:HKEY_CURRENT_USER\SOFTWARE\Borland\Delphi\Locales «X:\MyProject\MyApp.exe» = «rus»

Тепеpь, когда ваше пpиложение будет поднимать pakages, то всегда будут бpаться pусские pесуpсы. Дpугие пpиложения, напpимеp Delphi — это не затpонет.Таким обpазом можно заменять даже DFM-ки из пpоекта.

Более подpобно об этом — см Help — Index — Localizing…

 

Как из своего пpиложения опpеделить загpузку pесуpсов GDI и USER

Автор: Nomadic

{$APPTYPE CONSOLE}

// индикатоp pесуpсов

program res;

function MyGetFreeSystemResources32(Id: integer): integer;

stdcall; external 'rsrc32' name '_MyGetFreeSystemResources32@4';

const

rSystem = 0;

rGDI = 1;

rUSER = 2;

begin

writeln('free resources');

writeln('System:', MyGetFreeSystemResources32(rSystem), '%');

writeln('GDI:', MyGetFreeSystemResources32(rGDI), '%');

writeln('USER:', MyGetFreeSystemResources32(rUSER), '%');

end.

Как добавить в исполняемый файл WAV-файл и затем проиграть этот звук

// В файл MyWave.rc пишешь:

// MyWave RCDATA LOADONCALL MyWave.wav

// Затем компилируешь

// brcc32.exe MyWave.rc, получаешь MyWave.res.

// В своей программе пишешь:

// {$R MyWave.res}

// или используешь программу для работы с ресурсами

// ( н-р Borland Resource WorkShop) для получения res файла

procedure RetrieveMyWave;

var

hResource: THandle;

pData: Pointer;

begin

hResource:=LoadResource( hInstance, FindResource(hInstance, 'MyWave', RT_RCDATA));

try

pData := LockResource(hResource);

if pData = nil then

raise Exception.Create('Cannot read MyWave');

// Здесь pData указывает на MyWave

// Теперь можно, например, проиграть его (Win32):

PlaySound('MyWave', 0, SND_MEMORY);

finally

FreeResource(hResource);

end;

end;

Использование Bitmap из ресурса

{

Create and edit a new text file in your project directory,

eg: newres.txt

In the file, write:

MY_BMP_RES BITMAP "bmpname.bmp"

and save the file.

Open a dos shell and go to your directory, type this command:

brcc32.exe newres.txt

this will create a resource file called newres.res with your bitmap.

}


unit Unit1;

implementation

{$R *.DFM}

{$R newres.res} // add this line!

procedure TForm1.FormCreate(Sender: TObject);

var

MyBmp: TBitmap;

begin

MyBmp := TBitmap.Create;

try

MyBmp.LoadFromResourceName(HInstance, 'MY_BMP_RES');

// Do something....

finally

MyBmp.Free;

end;

end;

Изменить ресурсные строки во время выполнения

uses

Consts;

procedure TForm1.Button1Click(Sender: TObject);

begin

InputBox('Test', 'Enter something', 'Test');

end;

procedure HookResourceString(rs: PResStringRec; newStr: PChar);

var

oldprotect: DWORD;

begin

VirtualProtect(rs, SizeOf(rs^), PAGE_EXECUTE_READWRITE, @oldProtect);

rs^.Identifier := Integer(newStr);

VirtualProtect(rs, SizeOf(rs^), oldProtect, @oldProtect);

end;

const

NewOK: PChar = 'New Ok';

NewCancel: PChar = 'New Cancel';

initialization

HookResourceString(@SMsgDlgOK, NewOK);

HookResourceString(@SMsgDlgCancel, NewCancel);

end.

Загрузка изображения или курсора из RES-файла

Загрузка изображений и курсоров из RES-файлов

Изображения и курсоры могут храниться в файлах ресурсов (RES) и прилинковываться (связаваться) к EXE-файлу вашего приложения. RES-файлы могут создаваться с помощью Delphi утилит Image Editor и Borland Resource Workshop, входящие в поставку Delphi RAD Pack. Изображения и курсоры, хранимые в RES-файлах (после упаковки их в EXE или DLL) могут быть извлечены с помощью API функций LoadBitmap и LoadCursor соответственно.

Загрузка изображений

Функция API LoadBitmap определена следующим образом:

function LoadBitmap(Instance: THandle; BitmapName: PChar): HBitmap;

Первый параметр должен содержать дескриптор модуля (EXE или DLL), содержащего файл RES, из которого вы хотите получить ресурс. Delphi хранит дескриптор запущенного EXE-файла в глобальной переменной с именем Hinstance. В приведенном ниже примере мы предполагаем, что модуль, из которого мы пытаемся загрузить изображение, — ваше приложение. Тем не менее, модуль мог бы быть другим EXE- или DLL-файлом. Следующий пример загружает изображение с именем BITMAP_1 из RES-файла, прилинкованного к EXE-файлу приложения:

procedure TForm1.Button1Click(Sender: TObject);

var

Bmp: TBitmap;

begin

Bmp := TBitmap.Create;

Bmp.Handle := LoadBitmap(HInstance,'BITMAP_1');

Canvas.Draw(0, 0, Bmp);

Bmp.Free;

end;

Имеется один недостаток использования API вызова LoadBitmap: LoadBitmap все же является API вызовом Windows 3.0, и грузит изображение только как DDB (Device Dependent Bitmaps). Это может вызвать проблемы с цветовой палитрой при загрузке DIB (Device Independent Bitmaps) из RES-файла. Приведенный ниже код может использоваться для извлечения DIB-ов из RES-файлов. Данный код загружает изображение как общий ресурс, передает его в поток, после чего делает Delphi вызов LoadFromStream, реализующий палитру автоматически.

procedure TForm1.Button1Click(Sender: TObject);

const

BM = $4D42; {Идентификатор типа изображения}

var

Bmp: TBitmap;

BMF: TBitmapFileHeader;

HResInfo: THandle;

MemHandle: THandle;

Stream: TMemoryStream;

ResPtr: PByte;

ResSize: Longint;

begin

BMF.bfType := BM;

{Ищем, загружаем и блокируем ресурс, содержащий BITMAP_1}

HResInfo := FindResource(HInstance, 'BITMAP_1', RT_Bitmap);

MemHandle := LoadResource(HInstance, HResInfo);

ResPtr := LockResource(MemHandle);

{Создаем Memory-поток, устанавливаем его размер, записываем

туда заголовок изображения и, наконец, само изображение }


Stream := TMemoryStream.Create;

ResSize := SizeofResource(HInstance, HResInfo);

Stream.SetSize(ResSize SizeOf(BMF));

Stream.Write(BMF, SizeOf(BMF));

Stream.Write(ResPtr^, ResSize);

{Освобождаем поток и сбрасываем его позицию в 0}

FreeResource(MemHandle);

Stream.Seek(0, 0);

{Создаем TBitmap и загружаем изображение из MemoryStream}

Bmp := TBitmap.Create;

Bmp.LoadFromStream(Stream);

Canvas.Draw(0, 0, Bmp);

Bmp.Free;

Stream.Free;

end;

Загрузка курсоров

Функция API LoadCursor определена следующим образом:

function LoadCursor(Instance: THandle; CursorName: PChar): HCursor;

Первый параметр Instance должен содержать дескриптор модуля, содержащего файл RES. Как и пример, приведенный выше, данный пример предполагает, что модуль, из которого мы пытаемся загрузить курсор, — ваше приложение. Второй параметр — имя курсора. В секции interface сделайте следующее объявление:

const

crMyCursor = 5; {Другие модули могут также использовать эту константу}

Затем добавьте следующие две строчки к обработчику события формы OnCreate:

procedure TForm1.FormCreate(Sender: TObject);

begin

Screen.Cursors[crMyCursor] := LoadCursor(HInstance, 'CURSOR_1');

Cursor := crMyCursor;

end;

или же вы можете изменить один из стандартных курсоров Delphi как показано ниже (константы Cursor описаны в электронной справке в статье Cursors Property):

procedure TForm1.FormCreate(Sender: TObject);

begin

{Данный пример изменяет курсор SQL Hourglass}

Screen.Cursors[crSQLWait] := LoadCursor(HInstance, 'CURSOR_1');

end;

Примечание: в нормальной ситуации необходимо удалить любые ресурсы курсоров с помощью DeleteCursor, тем не менее, в Delphi в этом нет необходимости, поскольку Delphi сама удаляет все курсоры из массива Cursors.