В данной статье я опишу как создать приложение с поддержкой скинов. Скин будет состоять всего из одного файла и его нельзя будет открыть графическими редакторами. В скине будут описаны координаты положения объектов (например кнопок). То есть каждый скин будет уникален.
Нам понадобится написать два приложения: первое будет создавать скин, а вторая будет грузить его, всмысле это и будет программа спользующая скин.
Начнем с первой программы. Для начала поясню, как я хочу чтобы все это работало. Будем создавать файл и в него писать информацию в следующей последовательности: некоторые данные о самом скине (далее разберем поподробнее) и сами графические файлы, один за другим.
Приступим. Объявим тип:
Type
TSkins = Record
SkinName: string[255];
sze: array [1..3] of Int64;
crd: array [1..3] of TPoint;
end;
Объявленный массив sze - это массив размеров файлов, для облегчения последующей загрузки скина. А массив crd - это координаты объекта.
Добавим следующую строчку в глобальную секцию var:
sk: TSkins;
Нам понадобится определять размеры файла. Напишем функцию, которая будет возвращать размер файла:
Function GetFileSize(FileName: String): Longint;
var FS: TFileStream;
begin
FS := TFileStream.Create(FileName, fmOpenRead);
Result := FS.Size;
FS.Free;
end;
Напишем процедуру добавления файла к скину:
Procedure AddToFile(s:string; F:TFileStream);
var L:Longint;
F1:TFileStream;
begin
F1:=TFileStream.Create(S, fmOpenRead);
L:=F1.Size;
F.CopyFrom(F1, L);// копируем в F из F1 данные размером L
F1.Free;
end;
Теперь по нажатию на кнопку будем создавать скин:
procedure TForm1.Button1Click(Sender: TObject);
var fs:TFileStream;
begin
sk.SkinName:='www.DelphiDevelop.ru'
;
Sk.sze[1] := GetFileSize('fone.bmp'
);// записываем размеры файлов
Sk.sze[2] := GetFileSize('2.bmp'
);
Sk.sze[3] := GetFileSize('3.bmp'
);
Sk.crd[1] := Point(0,0);// записываем координаты
Sk.crd[2] := Point(50,50);
Sk.crd[3] := Point(50,90);
FS:=TFileStream.Create('SkinName.skin'
, fmCreate);
FS.WriteBuffer(sk, SizeOF(sk));// записываем доп данные
AddToFile('fone.bmp'
, FS);// пишем сами файлы
AddToFile('2.bmp'
, FS);
AddToFile('3.bmp'
, FS);
FS.Free;
end;
Естественно в папке с этой программой должны быть четыре BMP файла с названиями: fone.bmp, 2.bmp, 3.bmp, 4.bmp
Запускаем приложение жмем кнопку и появляется файл SkinName.skin. Конечно программу для создания скина можно сделать и лучше, например указывать какой файл грузить и куда создавать готовый файл скина.
Итак, файл создали осталось его загрузить. Создайте новое приложение и точно также добавьте:
Type
TSkins = Record
SkinName: string[255];
sze: array [1..3] of Int64;
crd: array [1..3] of TPoint;
end;
Еще нужно добавить это в глобальную секцию var:
sk: TSkins;
Напишем процедуру которая будет загружать из файла-скина нужную графику:
Procedure ReadSkinsFile(F:TFileStream; si:int64; crd:TPoint;img:Timage);
var F1:TMemoryStream;
begin
F1:=TMemoryStream.Create;
F1.CopyFrom(F, Si);
F1.Position:=0;// возвращаем позицию в начало
Img.Picture.Bitmap.LoadFromStream(F1);// загружаем
// изменяем положение Img
img.Left:=crd.X;
img.Top:=crd.Y;
F1.Free;
end;
F - будет передаваться читаемый файл; si - размер файла; crd - координаты. Будем тутже изменять положение Image; img - в какой TImage будет грузиться графика.
Выложим кнопку на форму и по клику по ней напишем:
procedure TForm1.Button1Click(Sender: TObject);
var fs:TFileStream;
begin
// открываем файл-скин
FS:=TFileStream.Create('SkinName.skin'
, fmOpenRead);
FS.ReadBuffer(sk, SizeOF(sk));// Читаем тип (мы его сохраняли)
Label1.Caption:=sk.SkinName;
// читаем файлы с указанием какой размер файла и куда
// выводить полученную графику
ReadSkinsFile(FS, sk.sze[1], sk.crd[1], Image1);
ReadSkinsFile(FS, sk.sze[2], sk.crd[2], Image2);
ReadSkinsFile(FS, sk.sze[3], sk.crd[3], Image3);
FS.Free;
end;
Также необходимо выложить 3 TImage и 1 TLabel и не забудьте скопировать в папку с программой сам файл скина, иначе будет возникать ошибка.
Запускаем программу, нажимаем на кнопку и в Image грузится графика.
Обратите внимание, что массив нужно будет увеличить если графических файлов используется больше чем 3.
Конечно можно сделать обработку разнообразных ошибок но это уже другая история. Также можно сделать чтобы при наведении на кнопку она "загоралась". Это также уже вне этой статьи.
Скачать исходник [21,4 Кб]
Приведу полный код первой программы (создает скин):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, xpman;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Type
TSkins = Record
SkinName: String[255];
sze: array [1..3] of Int64;
crd: array [1..3] of TPoint;
end;
var
Form1: TForm1;
sk: TSkins;
implementation{$R *.dfm}
Function GetFileSize(FileName: String): Longint;
var FS: TFileStream;
begin
FS := TFileStream.Create(FileName, fmOpenRead);
Result := FS.Size;
FS.Free;
end;
Procedure AddToFile(s:string; F:TFileStream);
var L:Longint;
F1:TFileStream;
begin
F1:=TFileStream.Create(S, fmOpenRead);
L:=F1.Size;
F.CopyFrom(F1, L);// копируем в F из F1 данные размером L
F1.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var fs:TFileStream;
begin
sk.SkinName:='www.CodeLab.3dn.ru'
;
Sk.sze[1] := GetFileSize('fone.bmp'
);// записываем размеры файлов
Sk.sze[2] := GetFileSize('2.bmp'
);
Sk.sze[3] := GetFileSize('3.bmp'
);
Sk.crd[1] := Point(0,0);
Sk.crd[2] := Point(50,50);
Sk.crd[3] := Point(50,90);
FS:=TFileStream.Create('SkinName.skin'
, fmCreate);// Создаем файл-скин
FS.WriteBuffer(sk, SizeOF(sk));// записываем доп данные
AddToFile('fone.bmp'
, FS);// пишем сами файлы
AddToFile('2.bmp'
, FS);
AddToFile('3.bmp'
, FS);
FS.Free;
end;
end.
Код второй программы (которая загружает скин):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, xpman;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
Image2: TImage;
Image3: TImage;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Type
TSkins = Record
SkinName: String[255];
sze: array [1..3] of Int64;
crd: array [1..3] of TPoint;
end;
var
Form1: TForm1;
sk: TSkins;
implementation{$R *.dfm}
Procedure ReadSkinsFile(F:TFileStream; si:int64; crd:TPoint; img:Timage);
var F1:TMemoryStream;
begin
F1:=TMemoryStream.Create;
F1.CopyFrom(F, Si);
F1.Position:=0;// возвращаем позицию в начало
Img.Picture.Bitmap.LoadFromStream(F1);// загружаем
// изменяем положение Img
img.Left:=crd.X;
img.Top:=crd.Y;
F1.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var fs:TFileStream;
begin
FS:=TFileStream.Create('SkinName.skin'
, fmOpenRead);// открываем файл-скин
FS.ReadBuffer(sk, SizeOF(sk));// Читаем сохраненный тип
Label1.Caption:=sk.SkinName;
// читаем файлы с указанием какой размер файла и куда
// выводить полученную графику
ReadSkinsFile(FS, sk.sze[1], sk.crd[1], Image1);
ReadSkinsFile(FS, sk.sze[2], sk.crd[2], Image2);
ReadSkinsFile(FS, sk.sze[3], sk.crd[3], Image3);
FS.Free;
end;
end.
Просмотров: 18921
а как загрузить не bmp а png файл? выкидывает ошибку access violation если оставить как есть. Помогите пожалуйста!
|
Как делать кнопки - понятно. А как можно сделать, допустим, раскрывающийся список? Думаю, там мало будет просто картинки подгружать)
Ответ: В этом случае конечно-же должна быть дополнительная логика.
|
Как с помощью скина изменять форму формы? Нельзя ли использовать код засунутый в файл?
Ответ: И какой код вы хотите запихивать в файл? А с помощю скина конечно можно изменять форму формы. Это можно сделать немножко дополнив немного код из этой статьи.
Можно намного проще сделать скин, просто загружая на Image нужные файлы, но в этом случае они будут открыты для изменения, и будет много файлов, а так файл скина сложно изменить и он один. Удобнее. Да еще и в скине можно добавить информацию о положении кнопок их размере и так далее. |
Ответ: А как вы собираетесь кнопку изменять? Ее графической не сделать. А чем вас Image не устроил?
|
1. Bad
Отличная статья! 1 файл 1 скин! да к томуже можно как в Winamp сделать уникальный скин, т.е. в разных скинах кнопки на разных позициях!
|
Copyright © 2008 - 2018 Программирование на Delphi для начинающих и не только.
Полнота авторских прав на все материалы, опубликованные на сервере DelphiDevelop.ru принадлежит их авторам.
Перепечатка материалов разрешается с указанием авторства и гиперссылки на первоисточник информации.