Как создать скин

Автор: Борисов Сергей

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

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

Начнем с первой программы. Для начала поясню, как я хочу чтобы все это работало. Будем создавать файл и в него писать информацию в следующей последовательности: некоторые данные о самом скине (далее разберем поподробнее) и сами графические файлы, один за другим.

Приступим. Объявим тип:

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.

Просмотров: 18190

Обсудить на форуме

0   Спам
(20.02.2012)
7. exeshnik
а как загрузить не bmp а png файл? выкидывает ошибку access violation если оставить как есть. Помогите пожалуйста!

0   Спам
(31.01.2012)
6. Александр
Как делать кнопки - понятно. А как можно сделать, допустим, раскрывающийся список? Думаю, там мало будет просто картинки подгружать)
Ответ: В этом случае конечно-же должна быть дополнительная логика.

0   Спам
(11.05.2011)
5. Василий
Я ОДОБРЯЮ!!! Очень, очень нужная вещь!!! Автору, респект!!!!

0   Спам
(08.06.2009)
4. Делфак-рулит
Как с помощью скина изменять форму формы? Нельзя ли использовать код засунутый в файл?
Ответ: И какой код вы хотите запихивать в файл? А с помощю скина конечно можно изменять форму формы. Это можно сделать немножко дополнив немного код из этой статьи.
Можно намного проще сделать скин, просто загружая на Image нужные файлы, но в этом случае они будут открыты для изменения, и будет много файлов, а так файл скина сложно изменить и он один. Удобнее. Да еще и в скине можно добавить информацию о положении кнопок их размере и так далее.

0   Спам
(01.06.2009)
3. Leo.exe
А на кнопку как это налепить?
Ответ: А как вы собираетесь кнопку изменять? Ее графической не сделать. А чем вас Image не устроил?

0   Спам
(30.09.2008)
2. жекаизжека
класс )) долго думал как сделать )) спасибо )

0   Спам
(20.09.2008)
1. Bad
Отличная статья! 1 файл 1 скин! да к томуже можно как в Winamp сделать уникальный скин, т.е. в разных скинах кнопки на разных позициях! biggrin


Имя *:
Email:


Код *:

Copyright © 2008-2016 Программирование на Delphi для начинающих и не только

Полнота авторских прав на все материалы, опубликованные на сервере DelphiDevelop.ru принадлежит их авторам

Перепечатка материалов разрешается с указанием авторства и гиперссылки на первоисточник информации

Хостинг от uCoz

Автор проекта: Борисов Сергей

e-mail: save-x@yandex.ru

Связь с администрацией сайта