
Продолжение... Начало в статье - «Рокировка» блоков экрана. Часть 1...
Нужно отметить, что значения rW и rH значением определяются DELTA. Как ранее объяснялось уже, когда экрана разрешение 800x600 и DELTA = 8, изображение экрана поделено будет на 8x8 частичек, каждая размером 100x75 (rW = 100, rH = 75).
К тому же, созданный нами битмап redRect, размещён будет внутри самой картинки, с целью замены перемещённого блока. redRect представляет собой простой красный прямоугольником с синим текстом внутри. С этой целью еще использовать можно готовую эмблему либо логотип.
И наконец-то, шырина и высота устанавливается формы, как и у экрана.
Вызов API функции SetWindowPos использовать можно, для того чтобы форму установить именно на переднем плане всегда (OnTop), не перемещаемую и не изменяемую фактически. Процедура под названием InitScreen вызывается. Интервал самого таймера устанавливает, и выполнять начинает известный уже нам обработчик событий OnTimer, запуская саму процедуру DrawScreen.
Процедура InitScreen - Скриншот
Процедура под названием InitScreen, которая вызывается из обработчика события OnCreate, именно с целью используется получения скриншота изображения текущего десктопа, начальную позицию redRect устанавливая и саму сетку рисуя. Код, который рисовать будет сетку и вовсе необязателен.
Чтобы сам скриншот десктопа получить, GetDC используется для GetDesktopWindow. Сама API функция BitBt для передачи картинки используется десктопа в DesktopBitmap. GetDC(GetDesktopWindow) сам дескриптор получает контекста, устройства дисплея для окна - окна указаного, возвращённого именно функцией GetDesktopWindow. Вконце DesktopBitmap с компонентой Image1 ассоциируется. Когда что-то Вам непонятно, хорошо бы просмотреть еще и справочник по Дельфи.
Сама же начальная позиция redRect, случайным образом выбирается. Trunc(Random * DELTA) целое число возвращает от 0 и до DELTA. Продолжая, redRect рисуется именно в точке gx, gy, функцию используя CopyRect самого объекта Canvas. Вновь же, когда Вы с алгоритмом рисования Дельфи не знакомы, то вновь же, хорошо было бы поискать в справке.
Далее с помощью MoveTo и также LineTo сетка рисуется. Сетка является необязательной и только с той целью используется, чтобы различать лучше границы самих блоков.
procedure InitScreen;
var i,j:integer;
begin
//здесь получаем битмап десктопа
DesktopBitmap := TBitmap.Create;
with DesktopBitmap do begin
Width := Screen.Width;
Height := Screen.Height;
end;
BitBlt(DesktopBitmap.Canvas.Handle,
0,0,Screen.Width,Screen.Height,
GetDC(GetDesktopWindow),0,0,SrcCopy);
Shuffler.Image1.Picture.Bitmap := DesktopBitmap;
//находим изначальные координаты redRect
Randomize;
gx := Trunc(Random * DELTA);
gy := Trunc(Random * DELTA);
Shuffler.Image1.Canvas.CopyRect(
Rect(rW * gx, rH * gy, rW * gx + rW, rH * gy + rH),
redRect.Canvas,
Rect(0,0,rW,rH));
//тут рисуем сетку
for i:=0 to DELTA-1 do begin
Shuffler.Image1.Canvas.MoveTo(rW * i,0);
Shuffler.Image1.Canvas.LineTo(rW * i,Screen.Height);
Shuffler.Image1.Canvas.MoveTo(0, rH * i);
Shuffler.Image1.Canvas.LineTo(Screen.Width, rH * i);
end;
end;
Процедура Draw Screen
Самый основной код в процедуре находится DrawScreen. Данная процедура внутри события вызывается OnTimer самого компонента Timer.
procedure DrawScreen;
var
r1,r2:TRect;
Direction:integer;
begin
r1:=Rect(rW * gx , rH * gy, rW * gx + rW , rH * gy + rH);
Direction := Trunc(Random*4);
case Direction of
0: gx := Abs((gx + 1) MOD DELTA); //здесь право
1: gx := Abs((gx - 1) MOD DELTA); //здесь лево
2: gy := Abs((gy + 1) MOD DELTA); //здесь низ
3: gy := Abs((gy - 1) MOD DELTA); //здесь верх
end; //case
r2 := Rect(rW * gx , rH * gy, rW * gx + rW , rH * gy + rH);
with Shuffler.Image1.Canvas do begin
CopyRect(r1, Shuffler.Image1.Canvas, r2);
CopyRect(r2, redRect.Canvas, redRect.Canvas.ClipRect);
end;
end;
Сам код достаточно прост в использовании, несмотря на то, что на первый взгляд он кажется очень сложным. Местами менять только можно смежные части с redRect, являются доступными только четыре возможных варианта.
Именно прямоугольник r1 текущию позицию содержит redRect, а r2 на сам прямоугольник с блоком указывает, который ранее перемещён был. CopyRect для перемещения используется блока выбранного на место redRect, а также рисования redRect его уже в новом месте – именно таким образом обмен данных 2 блоков происходит.
Приятней конечно, обмен блоков анимированный наблюдать, но оставим мы данную задачу для другой статьи )))