Добро пожаловать,
Поиск
ScaleMK - библиотека (dll) для работы с весами фирмы "Масса-К", марки: ВП-15T и ВП-15Ф
Линейки с возможностью масштабирования (Scale: 1-1000), есть возможность показать позицию курсора на линейке (Hairline). Линейка имеет 4 позиции размещения (сверху, снизу, слева, справа). В архиве с компонентом есть пример, в нем все очень хорошо продемонстрировано. Установка: тестировалось на 7 версии delphi.
Вопрос создания непрямоугольных окон часто интересует начинающих программистов и время от времени обсуждается на форумах разработчиков в среде Delphi. А вообще, нужно ли это кому-нибудь? Ответ - да! Это уже было нужно таким известным фирмам, как Symantec (Norton Utilities, Norton CrashGuard), Microsoft (Приложение "
Часы" в Windows NT4 может принимать круглую форму, Deluxe CD Player из MS Plus! 98 имеет вид прямоугольника со скругленными краями). У Borland Jbuilder 2 в окне начальной загрузки стрела крана "выскочила" за пределы прямоугольника. Программы для видеокарт TV Capture фирмы AverMedia имитируют пульт управления. Окно переводчика Magic Goody принимает вид гуся, разгуливающего по экрану.
Список можно продолжить, а вывод такой: окно "хитрой" формы – это "изюминка" оформления Вашей программы, нечто запоминающееся, дополнительный плюс в борьбе за потенциального покупателя. Главное в этом – не переборщить. Вряд ли будет удобно работать с текстовым редактором в треугольном окне. Окна произвольной формы неплохо смотрятся при начальной загрузке (Splash) и, возможно, в качестве окна "О программе … ".
Как это делается? Средствами Delphi – достаточно просто. Приведенные ниже примеры можно также перевести в C++ Builder или Visual C++.
Код type
TForm1 = class(TForm)
// Данную процедуру будем использовать для задания
// формы окна
procedure FormCreate(Sender: TObject);
protected
// Данную процедуру необходимо переопределить,
// чтобы иметь возможность перемещать окно "мышкой"
// не только за за заголовок, который в данном
// случае отсутствует
procedure WMNCHitTest(var Message: TWMNCHitTest);message WM_NCHITTEST;
private
{ Private declarations }
public
{ Public declarations }
end;
При создании окна непрямоугольной формы используются API функции
CreateEllipticRgn, CreateRectRgn, CreatePolygonRgn, CreateRoundRectRgn, CombineRgn.
Код procedure TForm1.FormCreate(Sender: TObject);
var
R1, R2: HRgn;
begin
// Создаем линзу (пересечение двух эллипсов)
R1 := CreateElliPticRgn(-150,-300,363,400); // Задаем
// координаты эллипса. Верхняя левая точка формы имеет
// координаты 0,0
R2 := CreateEllipticRgn(363+150,-300,5,400);
CombineRgn(R1,R1,R2,RGN_AND); // Получаем пересечение
// Отрезаем сверху слева
R2:= CreateEllipticRgn(-40,-30,182,20);
CombineRgn(R1,R1,R2,RGN_DIFF); // Вычитаем
// Отрезаем сверху справа
R2:= CreateEllipticRgn(180,-30,363+40,20);
CombineRgn(R1,R1,R2,RGN_DIFF);
// Назначаем полученный регион форме
SetWindowRgn(Handle, R1, True);
end;
Переопределение функции WMNCHitTest позволит перетаскивать окно, захватив его мышкой.
Код procedure TForm1.WMNCHitTest(var Message: TWMNCHitTest);
begin
inherited;
Message.Result := HTCAPTION;
end;
До сих пор в примерах мы рассматривали регионы с абсолютными значениями линейных величин. Пример непрямоугольного окна, которое масштабирует свою форму в зависимости от его размера. Искодный код, приведенный ниже, создает окно в виде бабочки, причем бабочка исполльзует максимально высоту и ширину исходной формы.
Код procedure TForm1.FormCreate(Sender: TObject);
var
R1, R2 : HRgn;
P : array [0..2] of TPoint;
X : Word;
begin
// левое верхнее крыло
R1 :=CreateEllipticRgn(Round(-Width*0.4),
0,Round(Width*0.49),Round(Height*1.1));
// правое верхнее крыло
R2 :=CreateEllipticRgn(Round(Width*0.51),
0,Round(Width*1.4),Round(Height*1.1));
CombineRgn(R2,R1,R2,RGN_OR);
// отсекаем лишнее от верхних крыльев,
// остаются линзы на пересечении эллипсов
R1 :=CreateEllipticRgn(0,Round(-Height*0.3),
Width,Round(Height*0.71));
CombineRgn(R1,R1,R2,RGN_AND);
//эллипс - основа нижних крыльев
R2 :=CreateEllipticRgn(Round(Width*0.1),
Round(Height*0.65), Round(Width*0.9), Height);
CombineRgn(R1,R1,R2,RGN_OR);
// вырезаем эллипс - разрез между нижних крыльев
R2 :=CreateEllipticRgn(Round(Width*0.3),
Round(Height*0.7), Round(Width*0.7), Round(Height*1.5));
CombineRgn(R1,R1,R2,RGN_DIFF);
// вертикальный эллипс - туловище бабочки
R2 :=CreateEllipticRgn(Round(Width*0.46),
Round(Height*0.3), Round(Width*0.54),
Round(Height*0.8));
CombineRgn(R1,R1,R2,RGN_OR);
// голова - круг; за основу берем меньшую
// из двух величин - высоты и ширины окна
X := Width;
if Height < X then X := Height;
X := Round(X/18);
R2 :=CreateEllipticRgn(Round(Width*0.5)-X,
Round(Height*0.3)-X, Round(Width*0.5)+X,
Round(Height*0.3)+X);
CombineRgn(R1,R1,R2,RGN_OR);
// левый усик
P[0] := Point(Round(Width*0.5), Round(Height*0.3));
P[1] := Point(Round(Width*0.35), Round(Height*0.01));
P[2] := Point(Round(Width*0.355)+1, 0);
R2 := CreatePolygonRgn(P, 3, WINDING);
CombineRgn(R1,R1,R2,RGN_OR);
// правый усик
P[0] := Point(Round(Width*0.5), Round(Height*0.3));
P[1] := Point(Round(Width*0.655+1), Round(Height*0.01));
P[2] := Point(Round(Width*0.65), 0);
R2 := CreatePolygonRgn(P, 3, WINDING);
CombineRgn(R1,R1,R2,RGN_OR);
// острие на крыле слева снизу
P[0] := Point(Round(Width*0.15), Height);
P[1] := Point(Round(Width*0.2), Round(Height*0.8));
P[2] := Point(Round(Width*0.3), Round(Height*0.9));
R2 := CreatePolygonRgn(P, 3, WINDING);
CombineRgn(R1,R1,R2,RGN_OR);
// острие на крыле справа снизу
P[0] := Point(Round(Width*0.85), Height);
P[1] := Point(Round(Width*0.8), Round(Height*0.8));
P[2] := Point(Round(Width*0.7), Round(Height*0.9));
R2 := CreatePolygonRgn(P, 3, WINDING);
CombineRgn(R1,R1,R2,RGN_OR);
// Назначаем полученный регион форме
SetWindowRgn(Handle, R1, True);
end;
Если грамотно разложить фигуру на элементарные составляющие, то Вам вполне по силам создать окно абсолютно любой формы. Это похоже на детскую игру "конструктор", только Ваши "кубики" намного разнообразнее.
Для завершения проекта необходимо создать фоновую картинку, которая подчеркнет границы нового окна. И обязательно установить свойство формы Scaled = False, иначе фоновая картинка и форма могут "разъехаться" при использовании нестандартных видеорежимов или стилей оформления Windows.
В заключение следует сказать, что существуют готовые компоненты и библиотеки компонент для решения подобных задач, например, CoolForm, TPlasmaForm. Однако при использовании компонент от сторонних производителей могут возникнуть проблемы лицензионности их использования и проблемы перехода на новую версию компилятора. А приведенные в данной статье примеры компилируются без изменений в исходном коде на Borland Delphi 3.0 - 7.0 и, вероятно, будут совместимы с последующими версиями.
Интересно, есть ли технология преобразования Wave-формата в обычный набор звуковых данных? К примеру, мне необходимо удалить заголовок и механизм (метод) сжатия, которые могут компилироваться и сохраняться вместе с Wave-файлами.
Код unit LinearSystem;
interface
{============== Тип, описывающий формат WAV ==================}
type WAVHeader = record
nChannels : Word;
nBitsPerSample : LongInt;
nSamplesPerSec : LongInt;
nAvgBytesPerSec : LongInt;
RIFFSize : LongInt;
fmtSize : LongInt;
formatTag : Word;
nBlockAlign : LongInt;
DataSize : LongInt;
end;
{============== Поток данных сэмпла ========================}
const MaxN = 300; { максимальное значение величины сэмпла }
type SampleIndex = 0 .. MaxN+3;
type DataStream = array[ SampleIndex ] of Real;
var N : SampleIndex;
{============== Переменные сопровождения ======================}
type Observation = record
Name : String[40]; {Имя данного сопровождения}
yyy : DataStream; {Массив указателей на данные}
WAV : WAVHeader; {Спецификация WAV для сопровождения}
Last : SampleIndex; {Последний доступный индекс yyy}
MinO, MaxO : Real; {Диапазон значений yyy}
end;
var K0R, K1R, K2R, K3R : Observation;
K0B, K1B, K2B, K3B : Observation;
{================== Переменные имени файла ===================}
var StandardDatabase : String[ 80 ];
BaseFileName : String[ 80 ];
StandardOutput : String[ 80 ];
StandardInput : String[ 80 ];
{=============== Объявления процедур ==================}
procedure ReadWAVFile (var Ki, Kj : Observation);
procedure WriteWAVFile (var Ki, Kj : Observation);
procedure ScaleData (var Kk : Observation);
procedure InitAllSignals;
procedure InitLinearSystem;
implementation
{$R *.DFM}
uses VarGraph, SysUtils;
{================== Стандартный формат WAV-файла ===================}
const MaxDataSize : LongInt = (MaxN+1)*2*2;
const MaxRIFFSize : LongInt = (MaxN+1)*2*2+36;
const StandardWAV : WAVHeader = (
nChannels : Word(2);
nBitsPerSample : LongInt(16);
nSamplesPerSec : LongInt(8000);
nAvgBytesPerSec : LongInt(32000);
RIFFSize : LongInt((MaxN+1)*2*2+36);
fmtSize : LongInt(16);
formatTag : Word(1);
nBlockAlign : LongInt(4);
DataSize : LongInt((MaxN+1)*2*2)
);
{================== Сканирование переменных сопровождения ===================}
procedure ScaleData(var Kk : Observation);
var I : SampleIndex;
begin
{Инициализация переменных сканирования}
Kk.MaxO := Kk.yyy[0];
Kk.MinO := Kk.yyy[0];
{Сканирование для получения максимального и минимального значения}
for I := 1 to Kk.Last do
begin
if Kk.MaxO < Kk.yyy[I] then Kk.MaxO := Kk.yyy[I];
if Kk.MinO > Kk.yyy[I] then Kk.MinO := Kk.yyy[I];
end;
end; { ScaleData }
procedure ScaleAllData;
begin
ScaleData(K0R);
ScaleData(K0B);
ScaleData(K1R);
ScaleData(K1B);
ScaleData(K2R);
ScaleData(K2B);
ScaleData(K3R);
ScaleData(K3B);
end; {ScaleAllData}
{================== Считывание/запись WAV-данных ===================}
VAR InFile, : file of Byte;
type Tag = (F0, T1, M1);
type FudgeNum = record
case X:Tag of
F0 : (chrs : array[0..3] of Byte);
T1 : (lint : LongInt);
M1 : (up,dn: Integer);
end;
var ChunkSize : FudgeNum;
procedure WriteChunkName(Name:String);
var i : Integer;
MM : Byte;
begin
for i := 1 to 4 do
begin
MM := ord(Name[i]);
write(,MM);
end;
end; {WriteChunkName}
procedure WriteChunkSize(LL:Longint);
var I : integer;
begin
ChunkSize.x:=T1;
ChunkSize.lint:=LL;
ChunkSize.x:=F0;
for I := 0 to 3 do Write(,ChunkSize.chrs[I]);
end;
procedure WriteChunkWord(WW:Word);
var I : integer;
begin
ChunkSize.x:=T1;
ChunkSize.up:=WW;
ChunkSize.x:=M1;
for I := 0 to 1 do Write(,ChunkSize.chrs[I]);
end; {WriteChunkWord}
procedure WriteOneDataBlock(var Ki, Kj : Observation);
var I : Integer;
begin
ChunkSize.x:=M1;
with Ki.WAV do
begin
case nChannels of
1:if nBitsPerSample=16
then begin {1..2 Помещаем в буфер одноканальный 16-битный сэмпл}
ChunkSize.up := trunc(Ki.yyy[N]+0.5);
if N<=Ki.Last do WriteOneDataBlock(Ki,Kj); {помещаем 4 байта и увеличиваем счетчик N}
{Освобождаем буфер файла}
CloseFile( );
end; {WriteWAVFile}
procedure InitSpecs;
begin
end; { InitSpecs }
procedure InitSignals(var Kk : Observation);
var J : Integer;
begin
for J := 0 to MaxN do Kk.yyy[J] := 0.0;
Kk.MinO := 0.0;
Kk.MaxO := 0.0;
Kk.Last := MaxN;
end; {InitSignals}
procedure InitAllSignals;
begin
InitSignals(K0R);
InitSignals(K0B);
InitSignals(K1R);
InitSignals(K1B);
InitSignals(K2R);
InitSignals(K2B);
InitSignals(K3R);
InitSignals(K3B);
end; {InitAllSignals}
[pagebreak]
Код var ChunkName : string[4];
procedure ReadChunkName;
var I : integer;
MM : Byte;
begin
ChunkName[0]:=chr(4);
for I := 1 to 4 do
begin
Read(InFile,MM);
ChunkName[I]:=chr(MM);
end;
end; {ReadChunkName}
procedure ReadChunkSize;
var I : integer;
MM : Byte;
begin
ChunkSize.x := F0;
ChunkSize.lint := 0;
for I := 0 to 3 do
begin
Read(InFile,MM);
ChunkSize.chrs[I]:=MM;
end;
ChunkSize.x := T1;
end; {ReadChunkSize}
procedure ReadOneDataBlock(var Ki,Kj:Observation);
var I : Integer;
begin
if N<=MaxN then
begin
ReadChunkSize; {получаем 4 байта данных}
ChunkSize.x:=M1;
with Ki.WAV do
case nChannels of
1:if nBitsPerSample=16
then begin {1..2 Помещаем в буфер одноканальный 16-битный сэмпл}
Ki.yyy[N] :=1.0*ChunkSize.up;
if N<=MaxN then begin {LastN := N;}
Ki.Last := N;
if Ki.WAV.nChannels=2 then Kj.Last := N;
end
else begin {LastN := MaxN;}
Ki.Last := MaxN;
if Ki.WAV.nChannels=2 then Kj.Last := MaxN;
end;
end;
end; {ReadOneDataBlock}
procedure ReadWAVFile(var Ki, Kj :Observation);
var MM : Byte;
I : Integer;
OK : Boolean;
NoDataYet : Boolean;
DataYet : Boolean;
nDataBytes : LongInt;
begin
if FileExists(StandardInput)
then
with Ki.WAV do
begin { Вызов диалога открытия файла }
OK := True; {если не изменится где-нибудь ниже}
{Приготовления для чтения файла данных}
AssignFile(InFile, StandardInput); { Файл, выбранный в диалоговом окне }
Reset( InFile );
{Считываем ChunkName "RIFF"}
ReadChunkName;
if ChunkName<>'RIFF' then OK := False;
{Считываем ChunkSize}
ReadChunkSize;
RIFFSize := ChunkSize.lint; {должно быть 18,678}
{Считываем ChunkName "WAVE"}
ReadChunkName;
if ChunkName<>'WAVE' then OK := False;
{Считываем ChunkName "fmt_"}
ReadChunkName;
if ChunkName<>'fmt ' then OK := False;
{Считываем ChunkSize}
ReadChunkSize;
fmtSize := ChunkSize.lint; {должно быть 18}
{Считываем formatTag, nChannels}
ReadChunkSize;
ChunkSize.x := M1;
formatTag := ChunkSize.up;
nChannels := ChunkSize.dn;
{Считываем nSamplesPerSec}
ReadChunkSize;
nSamplesPerSec := ChunkSize.lint;
{Считываем nAvgBytesPerSec}
ReadChunkSize;
nAvgBytesPerSec := ChunkSize.lint;
{Считываем nBlockAlign}
ChunkSize.x := F0;
ChunkSize.lint := 0;
for I := 0 to 3 do
begin Read(InFile,MM);
ChunkSize.chrs[I]:=MM;
end;
ChunkSize.x := M1;
nBlockAlign := ChunkSize.up;
{Считываем nBitsPerSample}
nBitsPerSample := ChunkSize.dn;
for I := 17 to fmtSize do Read(InFile,MM);
NoDataYet := True;
while NoDataYet do
begin
{Считываем метку блока данных "data"}
ReadChunkName;
{Считываем DataSize}
ReadChunkSize;
DataSize := ChunkSize.lint;
if ChunkName<>'data' then
begin
for I := 1 to DataSize do {пропуск данных, не относящихся к набору звуковых данных}
Read(InFile,MM);
end
else NoDataYet := False;
end;
nDataBytes := DataSize;
{Наконец, начинаем считывать данные для байтов nDataBytes}
if nDataBytes>0 then DataYet := True;
N:=0; {чтение с первой позиции}
while DataYet do
begin
ReadOneDataBlock(Ki,Kj); {получаем 4 байта}
nDataBytes := nDataBytes-4;
if nDataBytes<=4 then DataYet := False;
end;
ScaleData(Ki);
if Ki.WAV.nChannels=2
then begin Kj.WAV := Ki.WAV;
ScaleData(Kj);
end;
{Освобождаем буфер файла}
CloseFile( InFile );
end
else begin
InitSpecs;{файл не существует}
InitSignals(Ki);{обнуляем массив "Ki"}
InitSignals(Kj);{обнуляем массив "Kj"}
end;
end; { ReadWAVFile }
{================= Операции с набором данных ====================}
const MaxNumberOfDataBaseItems = 360;
type SignalDirectoryIndex = 0 .. MaxNumberOfDataBaseItems;
VAR DataBaseFile : file of Observation;
LastDataBaseItem : LongInt; {Номер текущего элемента набора данных}
ItemNameS : array[SignalDirectoryIndex] of String[40];
procedure GetDatabaseItem( Kk : Observation; N : LongInt );
begin
if N<=LastDataBaseItem
then begin
Seek(DataBaseFile, N);
Read(DataBaseFile, Kk);
end
else InitSignals(Kk);
end; {GetDatabaseItem}
procedure PutDatabaseItem( Kk : Observation; N : LongInt );
begin
if N<=LastDataBaseItem
then begin
Seek(DataBaseFile, N);
Write(DataBaseFile, Kk);
LastDataBaseItem := LastDataBaseItem+1;
end
else while LastDataBaseItem<=N do
begin
Seek(DataBaseFile, LastDataBaseItem);
Write(DataBaseFile, Kk);
LastDataBaseItem := LastDataBaseItem+1;
end
else ReportError(1); {Попытка чтения MaxNumberOfDataBaseItems}
end; {PutDatabaseItem}
procedure InitDataBase;
begin
LastDataBaseItem := 0;
if FileExists(StandardDataBase)
then
begin
Assign(DataBaseFile,StandardDataBase);
Reset(DataBaseFile);
while not EOF(DataBaseFile) do
begin
GetDataBaseItem(K0R, LastDataBaseItem);
ItemNameS[LastDataBaseItem] := K0R.Name;
LastDataBaseItem := LastDataBaseItem+1;
end;
if EOF(DataBaseFile)
then if LastDataBaseItem>0
then LastDataBaseItem := LastDataBaseItem-1;
end;
end; {InitDataBase}
function FindDataBaseName( Nstg : String ):LongInt;
var ThisOne : LongInt;
begin
ThisOne := 0;
FindDataBaseName := -1;
while ThisOne
Внимание! Если у вас не получилось найти нужную информацию, используйте
рубрикатор или воспользуйтесь
поиском .
книги по программированию исходники компоненты шаблоны сайтов C++ PHP Delphi скачать