В этой статье я решил описать один вариант создания своего диалога выбора цвета. Диалог выбора цвета, описанный в этой статье немного напоминает Photoshop-овский (но не совсем). Для лучшего взаимопонимания рекомендую скачать сначала исходник:
В общем приступим! Сначала создаём форму и помещаем туда всё необходимое:
7 компонентов типа TImage и назовём их так:
• MainViewer – экран вывода градиента;
• ScalKontr – определяет присутствие изменяемого компонента RGB цвета в градиенте (если выбран R _ GB - то красного, если G _ RB – то зелёного, если B _ RG – то синего) от 0 до 255, путем нажатия курсора на нужную область.
• Yarcost – шкала яркости выбранного оттенка.
• Proba 1 – для выода цвета, находящегося под курсором при выборе насыщенности компонентом ScalKontr.
• Proba 2 – для вывода оттенка, находящегося под курсором при выборе результата и яркости с помощью MainViewer или Yarcost.
• ImageZahvat – для вывода выбранной в ScalKontr насыщенности.
• Itog – для вывода выбранного оттенка.
12 Edit-ов , 3 RadioButton и 2 кнопки . Их оставим в покое (в смысле не переименовываем).
Теперь нам необходимо определиться с необходимыми процедурами.
Во-первых – это процедура генерирования шкалы контраста.
Во-вторых – это процедура генерирования градиента в MainViewer (в соответствии с выбранным типом градиента и выбранной насыщенностью).
В-третьих – процедура генерирования шкалы яркости, в соответствии с выбранным оттенком.
Начнём с первого. Сам нижеприведённый код я поместил в обработчик OnCreate формы.
Пояснения смотрите в комментариях к коду:
var
LineColor, ViewColor: TColor;
ColR, ColG, ColB, i, j:integer;
begin
{Если выбран баланс Красного с Синим и Зелёным (R_GB)}
if RadioButton1.Checked then
begin
ColR:=255;
ColG:=0;
ColB:=0;
for j:=0 to 255 do
begin
LineColor:=RGB(255-j, 0, 0); //Изменяем значение красного цвета
for i:=0 to 17 do
begin
ScalKontr.Canvas.Pixels[i, j]:=LineColor; //рисуем точку
end;
end;
end;
{Если выбран баланс Зелёного с Красным и Синим (G_RB)}
if RadioButton2.Checked then
begin
ColR:=0;
ColG:=255;
ColB:=0;
for j:=0 to 255 do
begin
LineColor:=RGB(0, 255-j, 0); //Изменяем значение зелёного цвета
for i:=0 to 17 do
begin
ScalKontr.Canvas.Pixels[i,j]:=LineColor; //рисуем точку
end;
end;
end;
{Если выбран баланс Синего с Красным и Зелёным (B_RG)}
if RadioButton3.Checked then
begin
ColR:=0;
ColG:=0;
ColB:=255;
for j:=0 to 255 do
begin
LineColor:=RGB(0, 0, 255-j); //Изменяем значение синего цвета
for i:=0 to 17 do
begin
ScalKontr.Canvas.Pixels[i,j]:=LineColor; //рисуем точку
end;
end;
end;
Думаю здесь всё понятно. Далее приступим к основной процедуре рисования градиента в MainViewer. Вот код:
{========================================================== Процедура генерации RGB-градиента}
procedure GenerateRGBInOutGrad(ClrOutR, ClrOutG, ClrOutB: Integer);
var
i, j: Integer; //счётчики
PixelColor: TColor; //цвет пиксела
Holst: TBitMap; //Объект для записи пикселей
begin
Holst:=TBitMap.Create; //создаём объект типа TBitMap
Holst.Width:=256; //указываем ширины
Holst.Height:=256; //указываем высоту
if ClrDialog.RadioButton1.Checked then //если выбрана RadioButton1
begin
{Палитра красного с зелёным и синим}
for j:=0 to 255 do //цикл по оси Y
begin
for i:=0 to 255 do //цикл по оси X
begin
PixelColor:=RGB(ClrOutR, j, i); {привязываем значения зелёного и синего к
изменениям координат и переводим из RGB в
TColor}
Holst.Canvas.Pixels[i, j]:=PixelColor; //Рисуем точку
end;
end;
end;
if ClrDialog.RadioButton2.Checked=true then //если выбрана RadioButton2
begin
{Палитра зелёного с красным и синим}
for j:=0 to 255 do //цикл по оси Y
begin
for i:=0 to 255 do //цикл по оси X
begin
PixelColor:=RGB(j, ClrOutG, i); {привязываем значения красного и синего к
изменениям координат и переводим из RGB в
TColor}
Holst.Canvas.Pixels[i, j]:=PixelColor; //Рисуем точку
end;
end;
end;
if ClrDialog.RadioButton3.Checked=true then //если выбрана RadioButton3
begin
{Палитра синего с красным и зелёным}
for j:=0 to 255 do //цикл по оси Y
begin
for i:=0 to 255 do //цикл по оси X
begin
PixelColor:=RGB(j, i, ClrOutB); {привязываем значения красного и зелёного к
изменениям координат и переводим из RGB в
TColor}
Holst.Canvas.Pixels[i, j]:=PixelColor; //Рисуем точку
end;
end;
end;
ClrDialog.MainViewer.Canvas.Draw(0,0,Holst); //рисуем всю картину на компонент TImage
Holst.Free; //освобождаем память, занимаемую объёктом Holst
end;
Вот!
Ну и, наконец, код вывода шкалы яркости:
{========================================================== Процедура генерации полосы яркости выбранного оттенка}
procedure GenerYarkost(ColR, ColG, ColB: Real);
var
i, j: integer; //счётчики
LineColor: TColor; //цвет TColor
StepR, StepG, StepB: Real; {шаг изменения для каждого цвета,
необходимы для равномерного смешивания
цветов по всей длине линии яркости . }
begin
ClrDialog.Edit4.Text:=IntToStr(round(ColR)); {Эти строки}
ClrDialog.Edit5.Text:=IntToStr(round(ColG)); {нужны лишь в моём}
ClrDialog.Edit6.Text:=IntToStr(round(ColB)); {примере. В Вашем
может и не понадобятся.}
{+++++++++++++++++++++++++++++++++++++++}
{Генерация шкалы яркости для выбранного оттенка}
StepR:=(256-ColR)/256; //определение шага для красного
StepG:=(256-ColG)/256; //определение шага для зелёного
StepB:=(256-ColB)/256; //определение шага для синего
j:=256; //здесь счётчику по Y-ку присваивается начальное значение
repeat j:=j-1; {Цикл по Y-ку организован с помощью repeat until чтобы
организовать обратный отсчёт от 256 до 1. Это сделано
для того, чтобы заполнять шкалу не с верху вниз, а снизу
вверх (т.к. начальная точка экранных координат
расположена в верхнем правом углу.)}
ColR:=ColR+StepR; {В каждом переходе цикла по Y}
ColG:=ColG+StepG; {увеличиваем значение соответствующего цвета}
ColB:=ColB+StepB; {на соответствующий ему шаг.}
for i:=0 to 17 do
begin
{На всякий случай проверим значения цветов на вхождение
в пределы 255}
if ColR>255 then ColR:=255;
if ColG>255 then ColG:=255;
if ColB>255 then ColB:=255;
LineColor:=RGB(round(ColR), round(ColG), round(ColB)); //Записываем оттенок
ClrDialog.Yarcost.Canvas.Pixels[i, j]:=LineColor; //Рисуем точку в компонент TImage
end;
until j=1;
end;
Вот в принципе все необходимые процедуры для написания такого диалога. Всё остальное – дело техники и это вы найдёте в примере к статье. Правда есть ещё один момент, который необходимо описать – это перевод из TColor в RGB формат. Чисто для примера сделаем 3 переменные типа integer (пусть это будут ColR , ColG и ColB ) и одну переменную типа TColor (Например, ColTColor). Далее присвоим значение переменной ColTColor. Пусть это будет зелёный (clGreen). Ну и, наконец, выделим из этой переменной значения RGB компонентов в соответствующие переменные типа integer. Весь код :
procedure TestTColorToRGB;
var
ColR, ColG, ColB: integer;
ColTColor: TColor;
begin
ColTColor:=clGreen; //присваиваем зелёный цвет
ColR:= ColTColor mod $100; //выделяем красный
ColG:=( ColTColor div $100) mod $100; //выделяем зелёный
ColB:= ColTColor div $10000; //выделяем синий
end;
У переменных должны получиться следующие значения:
ColR = 0;
ColG = 255;
ColB = 0.
Вот и всё. Конечно, для крутого графического редактора этого мало, но ведь можно и дополнить чем-нибудь ещё!
Июль
4,
2008
— Рубрика: Delphi
Метки: mageZahvat, выбор цвета, шкала яркости
В модуле StrUtils.pas содержатся полезные функции для обработки строковых переменных. Чтобы подключить этот модуль к программе, нужно добавить его имя (StrUtils) в раздел Uses.
1) PosEx(SubStr, Str: String; Offset: Integer) - функция аналогична функции Pos(), но позволяет задать отступ от начала строки для поиска. Если значение Offset задано (оно не является обязательным), то поиск начинается с символа Offset в строке. Если Offset больше длины строки Str, то функция возратит 0. Также 0 возвращается, если подстрока не найдена в строке. Пример:
uses StrUtils;
{ … }
var Str1, Str2: String; P1, P2: Integer;
{ … }
Str1:=’Hello! How do you do?’;
Str2:=’do’;
P1:=PosEx(Str2, Str1, 1); { P1 = 12 }
P2:=PosEx(Str2, Str1, 15); { P2 = 19 }
2) Функция AnsiReplaceStr(Str, FromText, ToText: String) - производит замену выражения FromText на выражение ToText в строке Str. Поиск осуществляется с учётом регистра символов. Следует учитывать, что функция НЕ изменяет самой строки Str, а только возвращает строку с произведёнными заменами. Пример:
uses StrUtils;
{ … }
var Str1, Str2, Str3, Str4: String;
{ … }
Str1:=’ABCabcAaBbCc’;
Str2:=’abc’;
Str3:=’123′;
Str4:=AnsiReplaceStr(Str1, Str2, Str3); { Str4 = “ABC123AaBbCc” }
3) Функция AnsiReplaceText(Str, FromText, ToText: String) - выполняет то же самое действие, что и AnsiReplaceStr(), но с одним исключением - замена производится без учёта регистра. Пример:
uses StrUtils;
{ … }
var Str1, Str2, Str3, Str4: String;
{ … }
Str1:=’ABCabcAaBbCc’;
Str2:=’abc’;
Str3:=’123′;
Str4:=AnsiReplaceText(Str1, Str2, Str3); { Str4 = “123123AaBbCc” }
4) Функция DupeString(Str: String; Count: Integer) - возвращает строку, образовавшуюся из строки Str её копированием Count раз. Пример:
uses StrUtils;
{ … }
var Str1, Str2: String;
{ … }
Str1:=’123′;
Str2:=DupeString(Str1, 5); { Str2 = “123123123123123″ }
5) Функции ReverseString(Str: String) и AnsiReverseString(Str: AnsiString) - инвертируют строку, т.е. располагают её символы в обратном порядке. Пример:
uses StrUtils;
{ … }
var Str1: String;
{ … }
Str1:=’0123456789′;
Str1:=ReverseString(Str1); { Str1 = “9876543210″ }
6) Функция IfThen(Value: Boolean; ATrue, AFalse: String) - возвращает строку ATrue, если Value = True и строку AFalse если Value = False. Параметр AFalse является необязательным - в случае его отсутствия возвращается пустая строка.
uses StrUtils;
{ … }
var Str1, Str2: String;
{ … }
Str1:=IfThen(True, ‘Yes’); { Str1 = “Yes” }
Str2:=IfThen(False, ‘Yes’, ‘No’); { Str2 = “No” }
Мы рассмотрели функции, позволяющие выполнять со строками практически любые манипуляции. Как правило, вместо строки с указанным типом данных, можно использовать и другой тип - всё воспринимается одинаково. Но иногда требуются преобразования. Например, многие методы компонент требуют параметр типа PChar, получить который можно из обычного типа String функцией PChar(Str: String):
uses ShellAPI;
{ … }
var FileName: String;
{ … }
FileName:=’C:\WINDOWS\notepad.exe’;
ShellExecute(0, ‘open’, PChar(FileName), ”, ”, SW_SHOWNORMAL);
Тип Char представляет собой один-единственный символ. Работать с ним можно как и со строковым типом. Для работы с символами также существует несколько функций:
Chr(Code: Byte) - возвращает символ с указанным кодом (по стандарту ASCII):
var A: Char;
{ … }
A:=Chr(69); { A = “E” }
Ord(X: Ordinal) - возвращает код указанного символа, т.е. выполняет противоположное действие функции Chr():
var X: Integer;
{ … }
X:=Ord(’F'); { X = 70 }
Из строки можно получить любой её символ - следует рассматривать строку как массив. Например:
var Str, S: String; P: Char;
{ … }
Str:=’Hello!’;
S:=Str[2]; { S = “e” }
P:=Str[5]; { P = “o” }
В этой статье описаны основные приёмы работы со строковыми типами данных. Как правило, этих данных достаточно для написания любого алгоритма.
Июль
1,
2008
— Рубрика: Delphi
Метки: алгоритм, данные, Дополнительные функции
1) Функция Length(Str: String) - возвращает длину строки (количество символов). Пример:
var
Str: String; L: Integer;
{ … }
Str:=’Hello!’;
L:=Length(Str); { L = 6 }
2) Функция SetLength(Str: String; NewLength: Integer) позволяет изменить длину строки. Если строка содержала большее количество символов, чем задано в функции, то “лишние” символы обрезаются. Пример:
var Str: String;
{ … }
Str:=’Hello, world!’;
SetLength(Str, 5); { Str = “Hello” }
3) Функция Pos(SubStr, Str: String) - возвращает позицию подстроки в строке. Нумерация символов начинается с единицы (1). В случае отсутствия подстроки в строке возращается 0. Пример:
var Str1, Str2: String; P: Integer;
{ … }
Str1:=’Hi! How do you do?’;
Str2:=’do’;
P:=Pos(Str2, Str1); { P = 9 }
4) Функция Copy(Str: String; Start, Length: Integer) - возвращает часть строки Str, начиная с символа Start длиной Length. Ограничений на Length нет - если оно превышает количество символов от Start до конца строки, то строка будет скопирована до конца. Пример:
var Str1, Str2: String;
{ … }
Str1:=’This is a test for Copy() function.’;
Str2:=Copy(Str1, 11, 4); { Str2 = “test” }
5) Функция Delete(Str: String; Start, Length: Integer) - удаляет из строки Str символы, начиная с позиции Start длиной Length. Пример:
var Str1: String;
{ … }
Str1:=’Hello, world!’;
Delete(Str1, 6, 7); { Str1 = “Hello!” }
6) Функции UpperCase(Str: String) и LowerCase(Str: String) преобразуют строку соответственно в верхний и нижний регистры:
var Str1, Str2, Str3: String;
{ … }
Str1:=’hELLo’;
Str2:=UpperCase(Str1); { Str2 = “HELLO” }
Str3:=LowerCase(Str1); { Str3 = “hello” }
Строки можно сравнивать друг с другом стандартным способом:
var Str1, Str2, Str3: String; B1, B2: Boolean;
{ … }
Str1:=’123′;
Str2:=’456′;
Str3:=’123′;
B1:=(Str1 = Str2); { B1 = False }
B2:=(Str1 = Str3); { B2 = True }
Если строки полностью идентичны, логическое выражение станет равным True.
Июнь
30,
2008
— Рубрика: Delphi
Метки: True, Стандартные функции, Строки
Строковый тип данных - один из самых часто используемых в программах тип. Действительно, без него не обходится практически ни один алгоритм. Даже программы, выполняющие исключительно математические операции, порой, написаны с использованием строковых типов данных.
Строка - это последовательность символов. В Object Pascal существует несколько строковых типов. Вот основные из них:Тип данных Максимальная длина Используемая память Используется для…
ShortString 255 символов от 2 до 256 байт Минимальная совместимость, хранение небольших строк
AnsiString около 2^31 символов от 4 байт до 2 Гб 8-битные символы (ANSI), DBCS ANSI, MBCS ANSI и т.д.
WideString около 2^30 символов от 4 байт до 2 Гб Юникод-символы - многопользовательские сервера, мультиязыковые приложения
Для большинства целей подходит тип AnsiString (иногда называется Long String).
Июнь
28,
2008
— Рубрика: Delphi
Метки: Object Pascal, типы данных
uses ShellApi;
function WindowsCopyFile(FromFile, ToDir : string) : boolean;
var F : TShFileOpStruct;
begin
F.Wnd := 0; F.wFunc := FO_COPY;
FromFile:=FromFile+#0; F.pFrom:=pchar(FromFile);
ToDir:=ToDir+#0; F.pTo:=pchar(ToDir);
F.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
result:=ShFileOperation(F) = 0;
end;
// Пример копирования:
procedure TForm1.Button1Click(Sender: TObject);
begin
if not WindowsCopyFile(’C:\UTIL\ARJ.EXE’, GetCurrentDir) then
ShowMessage(’Copy Failed’);
end;
Июнь
19,
2008
— Рубрика: Delphi
Метки: CopyFile, Windows, Копирование
uses LZExpand;
procedure CopyFile(FromFileName, ToFileName : string);
var
FromFile, ToFile: File;
begin
AssignFile(FromFile, FromFileName);
AssignFile(ToFile, ToFileName);
Reset(FromFile);
try
Rewrite(ToFile);
try
if LZCopy(TFileRec(FromFile).Handle, TFileRec(ToFile).Handle)<0 then
raise Exception.Create(’Error using LZCopy’)
finally
CloseFile(ToFile);
end;
finally
CloseFile(FromFile);
end;
end;
Июнь
5,
2008
— Рубрика: Delphi
Метки: LZExpand, Копирование
type
TCallBack=procedure (Position,Size:Longint); {Для индикации процесса копирования}
procedure FastFileCopy(Const InfileName, OutFileName: String; CallBack: TCallBack);
Const BufSize = 3*4*4096; { 48Kbytes дает прекрасный результат }
type
PBuffer = ^TBuffer;
TBuffer = array [1..BufSize] of Byte;
var
Size : integer;
Buffer : PBuffer;
infile, outfile : File;
SizeDone,SizeFile: Longint;
begin
if (InFileName <> OutFileName) then
begin
buffer := Nil;
AssignFile(infile, InFileName);
System.Reset(infile, 1);
try
SizeFile := FileSize(infile);
AssignFile(outfile, OutFileName);
System.Rewrite(outfile, 1);
try
SizeDone := 0; New(Buffer);
repeat
BlockRead(infile, Buffer^, BufSize, Size);
Inc(SizeDone, Size);
CallBack(SizeDone, SizeFile);
BlockWrite(outfile,Buffer^, Size)
until Size < BufSize;
FileSetDate(TFileRec(outfile).Handle,
FileGetDate(TFileRec(infile).Handle));
finally
if Buffer <> Nil then Dispose(Buffer);
System.close(outfile)
end;
finally
System.close(infile);
end;
end else
Raise EInOutError.Create(’File cannot be copied into itself’);
end;
Июнь
1,
2008
— Рубрика: Delphi
Метки: Pascal, Копирование
Продолжим нашу работу над медиа-проигрывателем, основанным на Windows Media Player. Хочется подчеркнуть, что кардинально изменить что-либо не удастся, поэтому в этой статье я просто расскажу о небольших усовершенствованиях и на этом мы остановимся.
Обычно во время воспроизведения мы должны видеть название файла, который проигрывается в данное время. Давайте снабдим проигрыватель этой функцией. Для этого изменим обработчик пункта меню “Открыть” на следующее:
if OpenDialog.Execute then
begin
MediaPlayer.URL:=OpenDialog.FileName;
Form1.Caption:=’SMP - ‘+ExtractFileName(OpenDialog.FileName);
end;
Как работает добавленная строка? Функция ExtractFileName() возвращает имя файла из указанного пути - то, что нам нужно. “SMP” - это сокращённо “Simple Media Player”
Наконец, значение присваивается заголовку формы.
Что ещё можно добавить? Да, действительно странный проигрыватель… Можно сделать окошко “О программе”. Для этого в меню добавьте соответствующий пункт и назовите его “О программе…” По правилам Windows любая надпись, приводящая к открытию диалогового окна, должна заканчиваться многоточием - “…” Рекомендую запомнить это правило и всегда и везде его использовать. Окно можно создать “с нуля”: File - New - Form (в разных версиях Delphi названия пунктов меню могут отличаться). А ещё можно воспользоваться окном, подготовленным разработчиками - открываем File - New - Other, переходим на вкладку Forms, выбираем “About box” и нажимаем “ОК”. В результате создаётся форма. В ней напишите название программы, своё имя, версию… Далее создаём обработчик для созданного пункта меню
AboutBox.ShowModal;
Пытаемся запустить программу, но Delphi выдаёт предупреждение, что второй модуль не связан с первым и предлагает это сделать. Соглашаемся, и приложение запускается.
Вот и всё. Конечно, такому проигрывателю далеко до Winamp, Light Alloy и даже до стандартного Windows Media Player, но основы, я думаю, понятны. Если вы повнимательнее изучите список ActiveX-компонент, то найдёте там много интересного.
Май
28,
2008
— Рубрика: Delphi
Метки: File, Winamp, медиа-проигрыватель
ростейший медиа-проигрыватель можно создать стандартными средствами Windows. Существуют модули, которые доступны из любого языка программирования - это ActiveX. Delphi в этом плане не исключение. Встроенный в систему Windows Media Player имеет собственный ActiveX-модуль, который мы легко можем использовать в своей программе. Правда, кардинально изменить в нём что-либо не получится. В данной статье я покажу пример, как использовать этот компонент.
Для начала ActiveX-компонент (сокращённо AX) нужно интегрировать в оболочку Delphi. Делается это легко: открываем диалоговое окно Component - Import ActiveX Control. В разных версиях Delphi этот пункт меню может называться по-разному, но ключевым остаётся слово ActiveX. В открывшемся окне в списке компонент найдите строку Windows Media Player. Нажмите кнопку Install. В появившемся окне можно указать, в какой пакет следует установить компонент. Можно оставить всё по умолчанию и нажать ОК. После этого на вкладке ActiveX палитры компонент появится кнопка WindowsMediaPlayer. Теперь можно приступить к созданию проигрывателя.
Для начала поместите компонент на форму - щёлкните по его значку и затем по форме. Вы увидите знакомое изображение - изображение проигрывателя. Его внешний вид зависит от версии установленного в системе компонента. Примерный вид того, что вы увидите, изображён на рисунке 1.
рис. 1
рис. 2
Для начала давайте сделаем возможность открытия нужного файла. За путь к файлу, который нужно воспроизводить, отвечает свойство URL типа WideString (строка). Давайте сделаем для программы меню, куда и добавим нужный нам пункт. Поместите на форму TMainMenu (страница Standard). Дважды щёлкните по значку TMainMenu, лежащему на форме. Откроется дизайнер меню. Выделите единственный пункт в заголовке меню и в его свойстве Caption напишите “Файл”. Затем щёлкните по созданному пункту и снизу появистя ещё одна пустая строка. Там и введите название нашего пункта - “Открыть”. Следующей строкой давайте создадим разделитель для меню - в свойстве Caption поставьте один-единственный символ - минус (”-”). Следующей строкой сделайте пункт “Выход”. Ну вот, программа уже имеет меню, хотя и небольшое. Теперь нужно связать пункт меню с диалогом открытия файла. Найдите компонент TOpenDialog на странице Dialogs и поместите его на форму. Активируйте свойство Filter и нажмите на кнопку с тремя точками (”…”). В появившемся окне введите желаемые типы файлов. В поле Filter Name нужно ввести описание типов файлов, а в поле Filter - сам фильтр. Пример на рисунке 2.
Чтобы с компонентом было удобно работать, измените его свойство Name на MediaPlayer.
Выделите компонент и перейдите в окно Object Inspector. Свойств (Properties) у компонента не очень много, а вот событий (Events) гораздо больше. Но мы используем лишь некоторые из них.
Для удобства, компонент MainMenu1 переименуем в MainMenu, а OpenDialog1 - в OpenDialog.
Пришло время запрограммировать пункт меню “Открыть”. Откройте дизайнер меню и дважды щёлкните по нужному пункту - откроется редактор кода. В этом месте следует написать:
if OpenDialog.Execute then
MediaPlayer.URL:=OpenDialog.FileName;
Метод Execute открывает диалог и, если пользователь не нажал “Отмена”, то функция возвращает значение True, а в FileName записывается путь к выбранному файлу. Затем мы присваиваем свойству URL проигрывателя выбранный файл. Запустите программу и попробуйте открыть файл. Всё должно работать, файл должен воспроизводиться.
Теперь давайте приведём окно проигрывателя к нормальному виду. Сам проигрыватель нужно растянуть на всю ширину окна - измените его свойство Align на alClient. Саму форму стоит сделать поменьше, т.к. наш проигрыватель пока что воспроизводит только аудио-файлы. На мой взгляд, для формы можно установить ширину (Width) равной 300, а высоту (Height) - 200. Наконец, можно изменить вид окна и установить BorderStyle в значение bsSizeToolWin, а заголовок (Caption) - “Simple Media Player”.
Теперь запрограммируем пункт “Выход” - для этого следует написать в его обработчике всего одну строку:
Self.Close;
Этот метод закрывает текущую форму (Self - объект, выбранный по умолчанию, форма) и завершает приложение.
Теперь нужно сделать в меню элементарные команды управления воспроизведением - Start, Stop, Pause. Конечно, в проигрывателе и без того есть существующие кнопки, но они должны иметь своё отражение и в меню.
Для начала добавьте в заглавную строку меню (туда, где “Файл”) пункт “Управление”. Затем добавьте два пункта - “Старт / Стоп” и “Пауза”. Запрограммировать эти команды легко. Для управление воспроизведением служит набор методов Controls, а узнать текущее состояние проигрывателя можно из свойства PlayState. Вот как выглядит обработчик пункта “Старт / Стоп”:
if MediaPlayer.PlayState =wmppsPlaying then
MediaPlayer.Controls.Stop
else
MediaPlayer.Controls.Play;
А вот обработчик “Паузы”:
if MediaPlayer.PlayState =wmppsPlaying then
MediaPlayer.Controls.Pause;
Запустите программу и проверьте её работоспособность.
рис. 3
Как видите, мы создали сравнительно простой, но рабочий проигрыватель. В следующий раз мы продолжим его разработку. Примерное изображение окна программы после выполнения всех действий, описанных в статье, показано на рисунке 3.
Май
20,
2008
— Рубрика: Delphi
Метки: медиа-проигрыватель
Алгоритм пирамидальной сортировки (heapsort) - один из самых быстрых алгоритмов сортировки.
Program heapsort;
{$APPTYPE CONSOLE}
type
tkey = integer;
int = integer;
const N = 10;
var a,b : array [0..N+1] of tkey;
function parent(x : int) : int;
begin
result:=x shr 1;
end;
function left(x : int) : int;
begin
result := x shl 1;
if result > a[0] then result := N+1;
end;
function right(x:int):int;
begin
result := x shl 1 + 1;
if result > a[0] then result := N+1;
end;
procedure swap(i,j : int);
var temp : tkey;
begin
temp := a[i];
a[i] := a[j];
a[j] := temp;
end;
procedure moveup(x : int);
begin
while (a[x] > a[parent(x)]) and (parent(x) > 0) do begin
swap(x, parent(x));
x := parent(x);
end;
end;
procedure movedown(x : int);
var max : integer;
begin
if a[left(x)] > a[right(x)] then max := left(x)
else max := right(x);
while (a[max] > a[x]) and (max <= a[0]) do begin
swap(max, x);
x := max;
if a[left(x)] > a[right(x)] then max := left(x)
else max := right(x);
end;
end;
procedure update(x : int; k : tkey);
begin
a[x] := k;
moveup(x);
movedown(x);
end;
procedure add(k : tkey);
begin
inc(a[0]);
update(a[0], k);
end;
procedure delete(x : int);
begin
swap(x, a[0]);
dec(a[0]);
update(x, a[x]);
end;
procedure hsort;
var i:int;
begin
a[0] := 1;
a[1] := b[1];
for i := 2 to N do
add(b[i]);
for i := 1 to N do
delete(1);
end;
var i : int;
begin
randomize;
fillchar(a, sizeof(a), 0);
fillchar(b, sizeof(b), 0);
for i := 1 to N do
b[i] := random(10);
writeln(’Non-sorted elements’);
for i := 1 to N do
write(b[i], ‘ ‘);
writeln;
hsort;
writeln(’Sorted elements’);
for i := 1 to N do
write(a[i], ‘ ‘);
readln;
end.
Май
19,
2008
— Рубрика: Delphi
Метки: Пирамидальная сортировка