Чтение онлайн

на главную - закладки

Жанры

Графика DirectX в Delphi

Краснов Михаил

Шрифт:

Сразу после создания первичной поверхности формируется этот объект, ответственный за отсечение области вывода, и присоединяется к области вывода:

// Создание объекта отсечения

hRet := FDD.CreateClipper(0, FDDCiipper, nil);

if Failed (hRet) then ErrorOut(hRet, 'CreateClipper FAILED');

// Определяем окно, связанное с отсечением области вывода

hRet := FDDCiipper.SetHWnd(0, Handle);

if Failed (hRet) then ErrorOut(hRet, 'SetHWnd FAILED');

// Устанавливаем объект отсечения для первичной поверхности

hRet := FDDSPrimary.SetClipper(FDDClipper);

if Failed (hRet) then ErrorOut(hRet, 'SetClipper FAILED^);

Можете

для проверки работы отсечения удалить в коде строку с вызовом offsetRect, чтобы принудить приложение воспроизводить за границами своей клиентской области. Картинка окажется искаженной, но приложение уже не испортит вид рабочего стола.

Одно небольшое замечание. В программах DirectX SDK можно обнаружить, что объект отсечения не удаляется по окончании работы, я же делаю это в моих примерах намеренно. Легко проверить это: объект, связанный с отсечением, имеет по окончании работы значение, отличное от nil, а в таком случае лучше будет явным образом освобождать память, занятую им. Также иногда можно встретить, что эта переменная присваивается nil сразу после присоединения к первичной поверхности.

Важно подчеркнуть, что при использовании отсечения нельзя применять для вывода на первичную поверхность метод BitFast.

Следующий пример, проект каталога Ех27, продолжает тему оконных приложений, отличается он от предыдущего пользовательским курсором (рис. 3.13).

Буферизацию приходится организовывать самостоятельно, для экономии памяти вспомогательная поверхность создается при каждом изменении размеров окна:

procedure TfrmDD.FormResize(Sender: TObject);

var

hRet : HRESULT;

ddsd : TDDSurfaceDesc2;

begin

if Assigned(FDDSBack) then FDDSBack := nil;

ZeroMemory(@ddsd, SizeOf(ddsd));

with ddsd do begin

dwSize := SizeOf(ddsd);

dwFlags := DDSD_CAPS or DDSDJiEIGHT or DDSD_WIDTH;

ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;

dwWidth := ClientWidth; // Размеры совпадают с текущими размерами

dwHeight := ClientHeight; // окна

end;

hRet := FDD.CreateSurface(ddsd, FDDSBack, nil);

if Failed(hRet) then ErrorOut(hRet, 'Create Back Surface');

FormPaint (nil);

end;

Обратите внимание, что в этом примере пользовательским курсором можно указать на любую точку клиентской области окна. Для отсечения нужной части поверхности образа (ее размер 32x32 пиксела) объявлена переменная rcMouse типа TRECT. При перемещении курсора вблизи границы окна оставляем для воспроизведения только часть образа:

procedure TfrmDD.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

Y: Integer);

var

wrkl, wrkJ : Integer;

begin

mouseX := X;

if X < ClientWidth - 32

then wrkl := 32 //

По Х помещается весь растр

else wrkl := ClientWidth - X; // Воспроизводить только часть образа

mouseY := Y;

if Y < ClientHeight - 32

then wrkJ := 32 // По Y помещается весь растр

else wrkJ := ClientHeight - Y; // Воспроизводить только часть образа

SetRect (rcMouse, 0, 0, wrkl, wrkJ); // Итоговый прямоугольник образа

FormPaint (nil); // Принудительно перерисовываем окно

end;

При перерисовке окна метод BitFast приходится использовать только для вывода растрового изображения курсора:

procedure TfrmDD.FormPaint(Sender: TObject);

var

rcDest, wrkRect : TRECT;

p : TPOINT;

begin

p.X := 0;

p.Y := 0;

Windows.ClientToScreen(Handle, p);

Windows.GetClientRect(Handle, rcDest);

OffsetRect(rcDest, p.X, p.Y);

SetRect (wrkRect, 0, 0, ClientWidth, ClientHeight);

//На вспомогательную поверхность помещаем растровое изображение фона

if Failed (FDDSBack.Blt (SwrkRect, FDDSBackGround, nil,

DDBLT^WAIT, nil}) then if Failed (RestoreAll) then Exit;

// Поверх фона размещаем растровое изображение курсора

if Failed (FDDSBack.BltFast (mouseX, mouseY, FDDSImage, @rcMouse,

DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY))

then if Failed (RestoreAll) then Exit;

// Копируем содержимое вспомогательной поверхности на первичную

if Failed (FDDSPrimary.Blt (@rcDest, FDDSBack, nil, DDBLT__WAIT, nil))

then if Failed (RestoreAll) then Exit;

end;

Для отключения отображения курсора в этом примере прибегнем к альтернативному способу: воспользуемся процедурой showcursor. В начале работы вызовем ее с аргументом False. Однако с курсором осталась связанной одна проблема, возникающая при нахождении его в области заголовка и в пределах рамки окна, когда пользовательский курсор мы отобразить уже не можем, а системный отключен. Полного решения данной проблемы достичь нелегко, если включать курсор в ловушке сообщения WM_NCMOUSEMOVE, возникающего при нахождении курсора за пределами клиентской части окна, то результат может получиться неустойчивым, придется все равно отслеживать возвращение курсора в окно.

Самое простое решение - управлять видимостью курсора в обработчике OnMouseMove, включать его при нахождении курсора вблизи границ окна. Но для хорошего функционирования алгоритма надо либо беспрерывно перерисовывать окно, либо добиться более высокой скорости работы с мышью.

Вскользь я уже говорил, что для поверхностей можно принудительно устанавливать одинаковый формат пиксела. Посмотрим на примере проекта каталога Ех28, как это сделать. Здесь введена переменная Pixel Format типа TDDPixelFormat; после создания первичной поверхности заносим ее формат в данную переменную:

Поделиться:
Популярные книги

Сын Тишайшего

Яманов Александр
1. Царь Федя
Фантастика:
попаданцы
альтернативная история
фэнтези
5.20
рейтинг книги
Сын Тишайшего

"Искажающие реальность" Компиляция. Книги 1-14

Атаманов Михаил Александрович
Искажающие реальность
Фантастика:
боевая фантастика
космическая фантастика
киберпанк
рпг
5.00
рейтинг книги
Искажающие реальность Компиляция. Книги 1-14

Школа. Первый пояс

Игнатов Михаил Павлович
2. Путь
Фантастика:
фэнтези
7.67
рейтинг книги
Школа. Первый пояс

Невеста на откуп

Белецкая Наталья
2. Невеста на откуп
Фантастика:
фэнтези
5.83
рейтинг книги
Невеста на откуп

Убивать чтобы жить 2

Бор Жорж
2. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 2

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Аргумент барона Бронина 4

Ковальчук Олег Валентинович
4. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Аргумент барона Бронина 4

Измена. (Не)любимая жена олигарха

Лаванда Марго
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. (Не)любимая жена олигарха

Измена. Право на обман

Арская Арина
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на обман

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Жаба с кошельком

Донцова Дарья
19. Любительница частного сыска Даша Васильева
Детективы:
иронические детективы
8.26
рейтинг книги
Жаба с кошельком

Бастард Императора. Том 11

Орлов Андрей Юрьевич
11. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 11

Академия чаросвет. Тень

Ярошинская Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Академия чаросвет. Тень

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4