Последние записи
- Windows 10 сменить администратора
- Рандомное слайдшоу
- Событие для произвольной области внутри TImage
- Удаление папки с файлами
- Распечатка файла
- Преобразовать массив байт в вещественное число (single)
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
16th
Июн
Создание динамической ссылки.
const
MySite = 'www.sait.ru'; // название твоего сайта
procedure TForm1.Edit1Change(Sender: TObject);
var
Mylink: string; // новая ссылка
begin
stat:= Copy(edit1.text, 1, Pos(' ',edit1.Text)-1);
Mylink:= MySite + '/' + stat; // www.sait.ru/stat
end;
15th
Июн
3D НЕБО в DELPHI
Здравствуйте уважаемые программисты, я пишу 3D движок и столкнулся с проблемой, как делать небо?
Если можно, то скажите как рисуется небо в авиа симуляторах?
Метод CubeMap, берешь 6 картиночек CubeMap, грузишь их при создании сцены и обрабатываешь типа:
Код:
procedure DrawSkyBox; begin glColor3f(0.3,0.3,0.3); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glPushMatrix; glTranslatef(Scene1.Player.x,Scene1.Player.y,Scene1.Player.z);
glBindTexture(GL_TEXTURE_2D,Tex[SB_BACK]); glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(-SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 0); glVertex3f(SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 1); glVertex3f(SkyRad, SkyRad, SkyRad); glTexCoord2f(1, 1); glVertex3f(-SkyRad, SkyRad, SkyRad); glEnd;
glBindTexture(GL_TEXTURE_2D,Tex[SB_FRONT]); glPushMatrix; glRotatef(180, 0, 1, 0); glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(-SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 0); glVertex3f(SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 1); glVertex3f(SkyRad, SkyRad, SkyRad); glTexCoord2f(1, 1); glVertex3f(-SkyRad, SkyRad, SkyRad); glEnd; glPopMatrix;
glBindTexture(GL_TEXTURE_2D,Tex[SB_LEFT]); glPushMatrix; glRotatef(-90, 0, 1, 0); glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(-SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 0); glVertex3f(SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 1); glVertex3f(SkyRad, SkyRad, SkyRad); glTexCoord2f(1, 1); glVertex3f(-SkyRad, SkyRad, SkyRad); glEnd; glPopMatrix;
glBindTexture(GL_TEXTURE_2D,Tex[SB_RIGHT]); glPushMatrix; glRotatef(90, 0, 1, 0); glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(-SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 0); glVertex3f(SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 1); glVertex3f(SkyRad, SkyRad, SkyRad); glTexCoord2f(1, 1); glVertex3f(-SkyRad, SkyRad, SkyRad); glEnd; glPopMatrix;
glBindTexture(GL_TEXTURE_2D,Tex[SB_TOP]); glPushMatrix; glRotatef(-90, 1, 0, 0); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(-SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 1); glVertex3f(SkyRad, -SkyRad, SkyRad); glTexCoord2f(1, 1); glVertex3f(SkyRad, SkyRad, SkyRad); glTexCoord2f(1, 0); glVertex3f(-SkyRad, SkyRad, SkyRad); glEnd; glPopMatrix;
glBindTexture(GL_TEXTURE_2D,Tex[SB_BOTTOM]); glPushMatrix; glRotatef(90, 1, 0, 0); glBegin(GL_QUADS); glTexCoord2f(1, 1); glVertex3f(-SkyRad, -SkyRad, SkyRad); glTexCoord2f(1, 0); glVertex3f(SkyRad, -SkyRad, SkyRad); glTexCoord2f(0, 0); glVertex3f(SkyRad, SkyRad, SkyRad); glTexCoord2f(0, 1); glVertex3f(-SkyRad, SkyRad, SkyRad); glEnd; glPopMatrix; glPopMatrix; end;
end.
А т.н. окружение сцены можно делать просто скроллом картинок по небу, можно добавить 3Д анимацию. много можно чего…
13th
Июн
Аудио вКонтакте.
И так, в последнее время развелось очень много программ – фейков для вконтакта. Некоторые программы ищут музыку вконтакте, и дают возможность скачать её. Программам этим я не доверяю, и решил сделать свою, для себя. Разубеждать меня не надо =)
Вопрос: как получить ссылку на скачивание той или иной музыки?
Исходный код audio.php перерыл, ссылок не нашел, хорошо, видать, Дуров защитил =)Может, кто поможет.. Я не прошу написать за меня код, прошу просто подсказки. Копирование из кеша неподойдет.
http://cs4586.vkontakte.ru/u2663363/audio/61bea91731fc.mp3
вот, надеюсь понятно?)) (правда запоздал немного)
вот моя старая функция(раньше то везде ссылок чистых не было)
function WB_AudioLinkMP3(sourse:string):string;
var s:string;
begin
s:=sourse;
if Pos('operate',s)=0 then exit;
Delete(s,1,PosEx('(',s,Pos('operate',s)));
Delete(s,1,Pos(',',s));
sourse:='http://cs'+Copy(s,1,pos(',',s)-1);
Delete(s,1,Pos(',',s));
sourse:=sourse+'.vkontakte.ru/u'+Copy(s,1,pos(',',s)-1);
Delete(s,1,Pos(',',s));
sourse:=sourse+'/audio/'+Copy(s,2,pos(',',s)-3)+'.mp3';
Result:=Sourse;
end;
правда он не очень оптимизирован
можно и лист бокс, раньше я когда то занимался этим(сейчас то вернусь в эту тему…но не раньше чем разберусь со своей библиотекой классов на С++/Delphi(правда С++ важнее в этом плане))
я юзал листбокс, а если парсить и далее этой кнопки(данные песни) то можно и в листвиев все запихать как угодно
Интересная тема на форуме. Советую присоединиться к обсуждению.
6th
Июн
Нажать программно win+L
Есть WinApi из user32
The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. The keyboard driver’s interrupt handler calls the keybd_event function.
VOID keybd_event( BYTE bVk, // virtual-key code |
Насчёт делфи неуверен, наверное так:
keybd_event(VK_LWIN, 0, 0, 0);
keybd_event('L', 0, 0, 0);
keybd_event('L', 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);
6th
Поиск по Listbox
Функция ищет первое совпадение в листбоксе и возвращает индекс строки в которой это совпадение находиться; если ничего не найдено возвращает -1:
function ListBoxFind(template:string; listbox:TListBox):integer;
var i,j:integer;
begin
for i:=1 to listbox.Count do
begin
if Pos(template,listbox.Items.Strings)<>0 then
begin
Result:=i;
exit;
end;
end;
Result:=-1;
end;
4th
Июн
Работа с LPT портом в Дельфи или компьютер в роли управляющего контроллера. Часть 1
Большинство пользователей персонального компьютера привыкли к тому, что весь результат деятельности на компьютере в той или иной степени все равно отражается в самом компьютере. В крайнем случае, отправляется на принтер или в Интернет, или же запись информации происходит на внешние носители (диски, флеш-память и т.п.). И уж мало кто задумывается, что с помощью простого РС – компьютера можно управлять различными внешними физическими устройствами.
Владимир Дегтярь
by DeKot degvv@mail.ru
Тем не менее, на форуме http://www.programmersforum.ru (да и на других также) часто появляются вопросы: «Как с компьютера зажечь светодиод?», «Как управлять освещением?» или «Можно ли компьютером закрывать шторы на окне?». Ответ: «…однозначно да». С помощью современного персонального компьютера можно создавать, воспроизводить, управлять, хранить, моделировать, обучать и еще реализовать много и много других функций.
Введение
Мы же рассмотрим возможности управления внешними устройствами – при этом возможно управление, как простым вентилятором или светодиодом, так производственными устройствами. Как известно, любой персональный компьютер, да и не только персональный, а и любое компьютерное (еще одно общепринятое название – микропроцессорное) устройство имеет устройства ввода и вывода информации, называемые портами. Для нас пользователей – это просто разъемы для подключения (клавиатура, мышь, модем, флешка и т. д.). Следует заметить, что по одному и тому порту (разъему)
можно как выводить информацию, так и вводить. Кроме этого понятие порт – это не только физически внешний элемент (разъем), а больше наоборот – внутренняя логическая структура устройства компьютера, часть его архитектуры.
Думаю что уже достаточно теории. Перейдем к практической реализации – управлению реальными устройствами с помощью компьютера. Более всего для этого подходит «параллельный» порт LPT. Более подробно смотрим о LPT http://ru.wikipedia.org/wiki/IEEE_1284.
Параллельный порт LPT
Итак, почему параллельный, а не перпендикулярный? А какие еще бывают? Параллельный, потому что информация через такое устройство передается параллельным способом. А еще может передаваться последовательным – тогда устройство (порт) называется последовательным (последовательные порты компьютера: COM-порт, USB- порт). Наглядно это можно увидеть на рисунке 2:
Аналогично ввод информации также может быть параллельным или последовательным. Порты (устройства) через которые можно вводить и выводить информацию называют двунаправленными устройствами или устройствами ввода/вывода. Таким и есть параллельный порт LPT, имеющийся в большинстве компьютеров. Посмотрим, что из себя представляет этот порт (см. рисунок 3):
где С0…С3 – регистры контроля, S3…S7 – регистры статуса, D0…D7 – регистры данных
Как видите, это такой разъем с 25-ю выводами на задней стенке системного блока компьютера. Итак, имеем физический порт LPT, который фактически состоит из трех регистров. Состав регистров и распределение по контактам разъема приведены в таблице 1:
Каждый из регистров может содержать байт информации (256 состояний). Часть битов не используется или используется только во внутренней архитектуре компьютера для организации прерываний при работе с принтером или для переключения режимов ввод/вывод регистра «Data».
Регистр данных «Data», номер регистра в шестнадцатеричной системе счисления $378 (в десятичной 888) – двунаправленный, восьмибитный. Данные через этот регистр можно как вводить, так и выводить с компьютера, программно устанавливая уровни на выходе порта или же вводить в компьютер, также программно считывая уровни, устанавливаемые внешними устройствами.
Регистр управления «Control» $37A (890). Через него можно только выводить информацию из компьютера. На разъем LPT выводятся четыре младших байта.
Регистр статуса «Status» $379 (889). Через порт можно только считывать уровни, установленные внешними устройствами. На разъем LPT выведены пять старших байтов.
Таким образом, на разъеме LPT задействовано 17 сигнальных контактов (8 двунаправленных – регистр 888, четыре только на вывод информации – регистр 890 и пять только на ввод информации – регистр 889).
Порт LPT разрабатывался еще на заре создания персональных компьютеров для подключения печатающих устройств (принтер). Этим объясняется специфическое наименования цепей и инверсия некоторых битов, из-за которой наблюдается несоответствие уровней напряжения на контактах и логических кодов регистров. В связи с этим, операции с информацией через LPT порт требуют учитывать эти особенности соответствия физических уровней и логических кодов.
Следует отметить, что в некоторых компьютерах может быть до трех портов LPT: LPT1, LPT2, LPT3 (в современных компьютерах LPT порты зачастую вообще отсутствуют). Адрес самого LPT порта соответствует адресу регистра «Data» и может быть $278, $378 или $3BC. Регистры в соответствующих портах имеют адресацию +1 и +2.
Следующие таблицы (см. таблицы 2, 3) показывают эти особенности данного порта. Для регистра $378 (888) соблюдается полное соответствие между уровнями напряжения на контактах и логическим кодом. А вот с регистрами $379 (889) и $37A (890) все обстоит по-другому:
Управление регистрами
В компьютерах с операционными системами MS-DOS, Windows 9x возможен доступ к портам непосредственно из самой операционной системы, тогда как в системах с NT такой прямой доступ невозможен. Для этих целей используются драйвера в виде библиотек (Inpout32.dll, WinIO, Giveo). Подключив соответствующие библиотеки к средам программирования, получаем возможность программно работать с портами (считывание состояния порта или установка выводов порта в необходимое состояние).
* Автор отдает предпочтение библиотеке <inpout32.dll> для работы в среде Дельфи. Библиотека
<inpout32.dll> свободно распространяется в Интернете (см. ресурсы к статье).
Итак, во-первых – помещаем <inpout32.dll> в папке с проектом. Далее в коде модуля Unit после раздела uses размещаем объявления необходимых нам функций из библиотеки:
// импорт функций inpout32.dll
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,StdCtrls, ExtCtrls, ComCtrls;
function Inp32(PortAdr: word): byte; stdcall; external 'inpout32.dll';
function Out32(PortAdr: word; Data: byte): byte; stdcall; external 'inpout32.dll';
Функция Inp32(PortAdr) возвращает число (тип – байт), соответствующее коду, находящемся в регистре PortAdr. Функция Out32(PortAdr, Data) возвращает число (Data, тип – байт), которое запишется в регистр PortAdr. Проще сказать Inp32 считывает значение регистра, а Out32 устанавливает значение в регистр. Пример применения функций:
var val1, val2: byte;
val1:= Inp32($378); // значение регистра «data» запишется в переменную val1
val2:= 54;
Out32($378,val2); // в регистр «data» запишется число 54 (b 0 0 1 1 0 1 1 0)
При этом следует учитывать, что состояние уровней напряжения на выходных контактах LPT порта соответствует таблице 2 и 3. При необходимости управления отдельными битами регистров можно применить следующие функции преобразований десятичного числа в двоичное и наоборот:
// weight (для byte(8 разр.)) = 128, j = 7; weight( для word (16 разр.)) = 32 768, j = 15 ;
function Dec_Bin(N_dec: integer; weight: integer; _bit: byte): byte;
var i ,j : byte;
mas_bin: array[0..j] of byte;
N_dec: integer;
begin
for i:= 0 to j do
begin
mas_bin:= N_dec div weight;
if mas_bin = 1 then N_dec:= N_dec - weight;
weight:= weight div 2;
end;
Result:= mas_bin[_bit]; // возвращает значение бита (0 или 1) двоичного числа,
// соответствующего N_dec
end;
function Bin_Dec(weight: integer): integer;
var i , j: byte;
mas_bin: array[0..j] of byte;
N_dec: integer;
begin
N_dec:= 0;
for i:= 0 to j do
begin
N_dec:= N_dec + mas_bin * weight;
weight:= weight div 2;
end;
Result:= N_dec; // возвращает десятичное число, соответствующее двоичному
// в виде массива битов mas_bin [ 0 .. j ]
end;
Пример применения функций:
var bit : byte;
bit := Dec_Bin(Inp32($378))[3]; // переменная bit принимает значение 3-го бита регистра «data»
** Переключение регистра «data» ($378) c «выхода» на « вход»
Возможность использования регистра «data» ($378) в качестве порта ввода определяется в настройках
BIOS для параллельного порта. Следует установить Parallel Port в EPP. Переключение регистра на «вход»
осуществляется программно, путем установки 5-го бита регистра «control» ($37A) в «1» (при этом все биты
регистра «data» устанавливаются в «1»). Следует отметить, что данная процедура возможна не на каждом
компьютере и определяется, кроме настроек, еще и конструктивными особенностями порта LPT или
материнской платы.
Вариант тестовой утилиты управления и считывания состояния регистров LPT представлен на рисунке 4 и приведен в ресурсах к статье [1]:
Заключение
Продолжение смотрите в следующем выпуске журнала «ПРОграммист»…
Ресурсы
. Модули и проекты, использованные в статье http://programmersclub.ru/pro/pro3.zip
. Сайт Валерия Ковтуна с множеством интересных программ для работы с LPT портом
http://valery-us4leh.narod.ru/main.html
Это статья из третьего номера журнала “ПРОграммист”.
Скачать его можно по ссылке.
Ознакомиться со всеми номерами журнала.
31st
Май
Отловить момент сворачивания окна
SERG1980:
Ну тогда в разделе Public пишем следующую строку:
procedure WMSysCommand(var Msg: TWMSysCommand);message WM_SYSCOMMAND;
далее после слова implementation описываем эту процедуруProcedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if msg.CmdType=SC_MINIMIZE then
begin
//здесь делаем что надо
end else inherited;
end;
31st
Пароль на приложение в Delphi
Tform2 =class(Tform)
..........
private
i: integer;
end;
procedure TForm2.OnCreate(sender: TObject);
begin
self.i=0;
end;
procedure TForm2.Button1Click(Sender: TObject);
const
pas='159357';
var
n:integer;
begin
self.i:=self.i+1;
n:=3-self.i;
if edit1.Text=pas then
begin
hide;
free;
31st
Алгоритм Брезенхема
Рисование прямой методом Брезенхема.
procedure TForm1.Button1Click(Sender: TObject);
var
x1,x2,y1,y2,dx,dy,s1,s2,x,y,o,i,v,obmen : integer;
begin
x1:=strtoint(edit1.Text);
y1:=strtoint(edit2.Text);
x2:=strtoint(edit3.Text);
y2:=strtoint(edit4.Text);
x:=x1;
y:=y1;
dx:=(abs(x2-x1));
dy:=(abs(y2-y1));
if (x2-x1)<=0 then s1:=-1 else s1:=1;
if (y2-y1)<=0 then s2:=-1 else s2:=1;
if dy>dx then
begin
v:=dx;
dx:=dy;
dy:=v;
obmen:=1;
end
else obmen:=0;
o:=2*dy-dx;
for i := 1 to dx do
begin
form1.Canvas.Pixels[x,y]:=clBlack;
while o>=0 do
begin
if obmen=1 then
x:=x+s1
else
y:=y+s2;
o:=o-2*dx;
end;
if obmen=1 then y:=y+s2
else x:=x+x1;
o:=o+2*dy;
end;
//form1.refresh;
//self.Repaint;
end;
30th
Май
Как работать с графикой на канве в среде Дельфи
Здравствуйте, уважаемые читатели. Как и обещал, сегодня с вами мы подробно рассмотрим процедуры работы с графическими объектами, вынесенными в отдельный модуль, позволяющий использовать универсальные методы для создания движущихся изображений, находящихся в файлах, обычно в виде спрайтов…
Продолжение. Начало цикла смотрите в первом и втором выпусках журнала…
Владимир Дегтярь
DeKot degvv@mail.ru
Создание проекта с несколькими движущимися объектами. Урок 5
Создадим новый проект <Lesson 3> аналогично предыдущим. Введем в него новые движущиеся графические объекты (в папке <data> добавлено еще четыре звездолета. Размер каждого спрайта 100х80 pix. Новые звездолеты будут появляться по случайному закону (используем функцию Randomize) и двигаться будут сверху вниз. Вывод фона и основного звездолета ’ship1′ осуществляется также как и в предыдущем проекте <Lesson 2>. Для новых объектов вводим дополнительно BufShipR и BufPicR. Также объявим новые переменные – координаты вывода новых звездолетов и приращения этих координат.
Одновременно у нас будут отображаться основной звездолет ’ship 1′ и два из ’ship 2′ – ’ship 5′, выбираемые по случайному закону (см. листинг 1):
ЛИСТИНГ 1
Var
Form1: TForm1;
BufFon,BufFonDop,Buffer: TBitMap;
BufShip1,BufShipR: TBitMap; // буферы спрайтов
BufPicS1,BufPicR: TBitMap; // буферы изображений одного спрайта
xf,yf: integer; // координаты вывода общего буфера на форму
dyf: integer; // приращение изменения координаты yf по вертикали
xS1,yS1: integer; // координаты звездолета 'ship1'
dxS1,dyS1: integer; // приращение координат 'ship1' по гориз. и вертик.
xR1,yR1,xR2,yR2: integer; // координаты звездолетов 'ship2 - ship5'
dyR1,dxR2,dyR2: integer; // приращение координат 'ship2 - 5'
ns,nr1: byte; // номер спрайта и выбор ship2 - ship5
nr2: byte = 3;
implementation
В процедуре OnCreate формы проведем инициализацию буферов и введем начальные данные для переменных. Процедура DrawShipR(i,j: byte) для вывода новых объектов (’ship2′ – ’ship5′) имеет два
параметра: i (изменение номера рисунка в файле спрайтов) и j (переменная для номера файла спрайтов). Т.к. выбор файла спрайта происходит по передаваемому параметру j, то инициализация буфера BufShipR и загрузка в него файла спрайтов находится в процедуре DrawShipR(i,j: byte) (см. листинг 2):
ЛИСТИНГ 2
procedure DrawShip1(i: byte);
begin
// загрузка одного спрайта в буфер рисунка
BufPicS1.Canvas.CopyRect(bounds(0,0,BufPicS1.Width,
BufPicS1.Height),
BufShip1.Canvas,
bounds(i * 66,0,
BufPicS1.Width,
BufPicS1.Height));
BufPicS1.Transparent:= true; // зададим прозрачность фона рисунка спрайта
BufPicS1.TransparentColor:= BufPicS1.Canvas.Pixels[1,1];
end;
Все движения организованы в обработчике таймера. Звездолеты ’ship2′ — ’ship5′ выводятся в Buffer в координаты xR1, yR1 и xR2, yR2 вне видимого окна формы выше. В каждом такте таймера происходит приращение координат для одного dyR1 по вертикали, для другого dxR2 и dyR2 – по горизонтали и вертикали. После того, как объекты выходят за пределы видимого окна формы внизу, вызываются методы random( ) для задания новых координат xR1, xR2 и номера файла спрайта (nr1, nr2). Координаты yR1, yR2 привязаны к координате yS1 , так как ’ship1′ неподвижен в координатах окна формы. Функция
random ( 4 ) возвращает числа в дипазоне 0 .. 3, а файлы спрайтов встречных звездолетов имеют номера 2 .. 5. Поэтому в процедуре загрузки спрайтов BufShipR.LoadFromFile(’data/ship’ + IntToStr(j+2) + ‘.bmp’) номер загружаемого файла определяется как IntToStr(j + 2)… В остальном процедуры обработчиков таймера и нажатия клавиш не отличаются от проекта <Lesson 2>.
Использование универсального модуля для работы с графикой. Урок 6
Если рассмотреть внимательно код программы в проекте <Lesson 3>, можно заметить, что многие методы часто повторяются для разных графических объектов (создание буферов, загрузка изображений из файлов, копирование и т.п.). При этом для упрощения, я сознательно применил файлы спрайтов одинакового размера и с равным количеством рисунков в файлах. А если файлов спрайтов будет не пять, а больше и если количество рисунков в каждом файле будет разным? Придется значительно увеличивать код для
каждого вида спрайтов. Следовательно, необходимо оптимизировать код программы. Выход здесь в написании методов обработки объектов, не зависящих от количества объектов и применимых для разных изображений.
Даная задача реализована в отдельном модуле <LoadObjectToBufferMod>, позволяющий использовать универсальные методы для создания движущихся графических объектов (находящихся в файлах, обычно в виде спрайтов), имеющих различный размер и разное количество изображений отдельных рисунков.
Модуль находится в папке <Lesson 4> (см. ресурсы к статье). Принцип организации модуля следующий:
- вся работа с графическими объектами проводится через битовые образы TBitMap и области
копирования битовых образов TRect
- для работы с фоном используются процедуры InitFon (инициализация) и LoadFon (загрузка фона из
файлов)
- функция InitSprite предназначена для инициализации и загрузки рисунков спрайтов
- для вывода фона и изображений спрайтов использован общий буфер типа TBitMap
- в процедуре InitBuff происходит инициализация общего буфера, а в процедуре FreeBuff ”переустановка”,
т.е. уничтожение общего буфера и создание снова, но уже без изображений спрайтов
- в процедуре LoadBuff происходит наложение изображений спрайтов на фон
Подробно работа модуля показана ниже…
Применение модуля LoadObjectToBufferMod
1. procedure InitFon(nw, nh: byte; FileName: string)
Создаем дополнительный и основной буферы фона:
BufFonD:= TBitmap.Create;
BufFon := TBitmap.Create;
Далее загружаем рисунок одного из фонов в дополнительный буфер:
BufFonD.LoadFromFile(FileName) или
LoadFromResourceName(hinstance.filename);
По загруженному рисунку получаем размер одного рисунка фона (см. рисунок 1):
Причем, размер буфера фона определяем как:
WF:= nw * WFD;
HF:= nh * HFD;
2. procedure LoadFon(xf, yf: integer; FileName: string)
Загружаем все рисунки фонов в буфер фона через дополнительный буфер (см. рисунок 2):
BufFonD.LoadFromFile(FileName) или
LoadFromResourceName(hinstance.filename);
3. procedure initBuffer
Создаем основной буфер (Buffer) через который выводим спрайты на форму:
Buffer:= TBitmap.Create;
Размер основного буфера устанавливаем равным размеру буфера фона WF и HF. Загружаем в основной буфер весь фон (cм. рисунок 3):
Buffer.Canvas.Draw(0, 0, BufFon);
4. procedure FreeBuffer
Процедура уничтожаем основной буфер Buffer. Применяется когда необходимо убрать какой-либо спрайт с формы:
Buffer.Free;
Восстанавливаем-же основной буфер с фоном так:
InitBuffer;
Спрайты, которые должны оставаться на форме, следует перерисовать по новому (см. процедуру InitStprite)…
5. procedure InitStprite(SpriteName: string; N_goriz, N_vertic, N_stroka, N_kadr: byte): byte
Cоздаем буфер массива спрайтов и загружаем туда файл спрайтов (см. рисунок 4):
BufSprite:= TBitmap.Create; BufSprite.LoadFromFile(SpriteName) или LoadFromResourceName(hinstance.spritename);
Создаем буфер рисунка (одного спрайта):
BufPic:= TBitmap.Create;
Далее определяем размеры буферов массива спрайтов и буфера рисунка, а также области (типа TRoot) загрузки рисунка. Загружаем спрайт в буфер рисунка (см. рисунок 5):
BufPic.Canvas.CopyRect(RectPic.BufSprite.Canvas, rectSprite);
Задаем прозрачность рисунку:
BufPic.Transparent:= true;
Для вывода следующего спрайта функция возвращает (правильнее сказать – функция принимает значение = Result) значение следующего номера спрайта N_kadr:
Result:= N_kadr;
Уничтожаем буфер массива спрайтов
BufSprite.Free;
6. procedure LoadBuffer(xf, yf, xs, ys, bs: integer)
В этой процедуре на Buffer выводится участок фона с координатами ранее выведенного спрайта, а затем очередное положение спрайта. Определяем область фона и область дополнительного буфера (см. рисунок 6):
Выводим участок фона в буфер, т.е. затираем спрайт фоном (см. рисунок 7):
Выводим очередной спрайт в дополнительный буфер Buffer (см. рисунок 8):
Buffer.Canvas.StretchDraw(Bounds(xs, ys, WP + bs, HP + bs), BufPic);
Уничтожаем буфер рисунка:
BufPic.Free;
Далее в программе выводим дополнительный буфер Buffer на форму методом Draw:
Form1.Canvas.Draw(x, y, Buffer);
Битовые образы фона (BufFon и BufFonD инициализируются (создаются – Create) в программе проекта всего один раз при инициализации программы (обычно вызовом процедуры InitFon в событиях OnCreate или OnActivate). Методы InitBuff, FreeBuff, InitSprite, LoadBuf в программе вызываются неоднократно*. Соответственно и объекты Buffer, BufSprite, BufPic создаются многократно. Поэтому после окончания действия каждого из методов происходит уничтожение битовых образов Buffer, BufSprite, BufPic методом Free.
Комментарий автора.
Загрузку фона можно производить из n – количества файлов, c одинаковым размером не более 1024 х
1024. Для этого вызывать процедуру LoadFon n -раз для разных файлов FonName и изменяя
координаты xf и yf.
Модуль можно применять и для простых объектов (один рисунок в файле SpriteName). Присвойте
переменным N_goriz и N_vertic значения = 1. Если размер спрайта не изменяется, присвойте
переменной bs значение = 0.
Можно загружать рисунки из файлов .jpg. Для этого вместо TBitMap применять класс TJpegImage и в
разделах uses LoadObjectToBufferMod и uses Unit1 добавить модуль Jpeg.
Как работать с модулем?
Для этого необходимо выполнить следующие действия:
1. В процедуре FormActivate (можно в FormCreate) инициализируем буфер фона. Вызываем procedure InitFon(nw,nh: byte; FonName: string) с одним из файлов фонов:
. n раз вызываем procedure LoadFon(xf,yf: integer; FonName: string), последовательно прикрепляя рисунки фонов как бы друг к другу
. инициализируем дополнительный буфер Buffer, вызвав procedure InitBuff. Он получит размер равный сумме размеров всех файлов фонов.
2. Для вывода необходимых спрайтов в нужном месте программы вызываем function InitSprite(SpriteName: string; N_goriz,N_vertic,N_stroka, N_kadr: byte). Функция возвращает очередной номер спрайта для последующего вывода очередного спрайта. Этот номер (N_kadr) необходимо передавать в функцию при каждом ее вызове. Причем, функцию можно использовать для вывода нескольких спрайтов, не забывая передавать ей значение N_kadr для каждых спрайтов.
Далее, вызвав процедуру LoadBuff(xf,yf,xs,ys,bs: integer), выводим спрайт на канву дополнительного буфера поверх фона. Окончательный вывод дополнительного буфера на канву формы производим методом Draw().
Заключение
Рассматриваемые в данной статье проекты полностью приведены в виде ресурсов в теме «Журнал клуба программистов. Третий выпуск» или непосредственно в архиве с журналом (папка Lesson3). Продолжение наших уроков смотрите в следующем выпуске журнала «ПРОграммист»…
Комментарий автора.
Перед запуском в среде Дельфи скопируйте в папку с проектом папку data с графическими файлами.
Это статья из третьего номера журнала “ПРОграммист”.
Скачать его можно по ссылке.
Ознакомиться со всеми номерами журнала.
Обсудить на форуме — Как работать с графикой на канве в среде Дельфи
Облако меток
css реестр ассемблер timer SaveToFile ShellExecute программы массив советы word MySQL SQL ListView pos random компоненты дата LoadFromFile form база данных сеть html php RichEdit indy строки Win Api tstringlist Image мысли макросы Edit ListBox office C/C++ memo графика StringGrid canvas поиск файл Pascal форма Файлы интернет Microsoft Office Excel excel winapi журнал ПРОграммист DelphiКупить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)