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

ЖАНРЫ

Графика для Windows средствами DirectDraw

Трухильо Стэн

Шрифт:

Начнем с более простой функции UpdateCursorSimpleCase (см. листинг 7.6).

Листинг 7.6. Функция UpdateCursorSimpleCase

BOOL CursorWin::UpdateCursorSimpleCase(int curx, int cury, int oldcurx, int oldcury) {

 RECT src;

 HRESULT r;

 //------ Блиттинг 1: стирание старого курсора ----------

 r=primsurf->BltFast(oldcurx, oldcury, cursor_under, 0, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 1 failed\n");

CheckResult(r);

 }

 //------
Блиттинг 2: сохранение области под новым курсором ------

 src.left=curx;

 src.top=cury;

 src.right=curx+cursor_width;

 src.bottom=cury+cursor_height;

 r=cursor_under->BltFast(0, 0, primsurf, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 2 failed\n");

CheckResult(r);

 }

 //------ Блиттинг 3: рисование нового курсора ----------

 r=primsurf->BltFast(curx, cury, cursor, 0, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 3 failed\n");

CheckResult(r);

 }

 return TRUE;

}

С помощью трех последовательных вызовов функции BltFast интерфейса DirectDrawSurface, функция UpdateCursorSimpleCase стирает существующий курсор, сохраняет область под новым курсором и рисует новый курсор.

В UpdateCursorComplexCase функция BltFast вызывается пять раз. Два дополнительных блиттинга предназначены для копирования обновляемой части первичной поверхности на вспомогательную поверхность (cursor_union) и обратно. Функция UpdateCursorComplexCase приведена в листинге 7.7.

Листинг 7.7. Функция UpdateCursorComplexCase

BOOL CursorWin::UpdateCursorComplexCase(int curx, int cury, int oldcurx, int oldcury) {

 RECT src;

 HRESULT r;

 int unionx=min(curx, oldcurx);

 int uniony=min(cury, oldcury);

 int unionw=max(curx, oldcurx)-unionx+cursor_width;

 int unionh=max(cury, oldcury)-uniony+cursor_height;

 //----- Блиттинг 1: копирование объединяющего прямоугольника

 // во вспомогательный буфер --------

 src.left=unionx;

 src.top=uniony;

 src.right=unionx+unionw;

 src.bottom=uniony+unionh;

 r=cursor_union->BltFast(0, 0, primsurf, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 1 failed\n");

CheckResult(r);

 }

 //------ Блиттинг 2: стирание старого курсора

 // во вспомогательном буфере ---------

 r=cursor_union->BltFast(oldcurx-unionx, oldcury-uniony, cursor_under, 0, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 2 failed\n");

CheckResult(r);

 }

 //------
Блиттинг 3: сохранение области под новым курсором -----

 src.left=curx-unionx;

 src.top=cury-uniony;

 src.right=src.left+cursor_width;

 src.bottom=src.top+cursor_height;

 r=cursor_under->BltFast(0, 0, cursor_union, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 3 failed\n");

CheckResult(r);

 }

 //------ Блиттинг 4: рисование нового курсора

 // во вспомогательном буфере ---------

 r=cursor_union->BltFast(curx-unionx, cury-uniony, cursor, 0, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 4 failed\n");

CheckResult(r);

 }

 //------- Блиттинг 5: копирование вспомогательного буфера

 // на первичную поверхность --------

 src.left=0;

 src.top=0;

 src.right=unionw;

 src.bottom=unionh;

 r=primsurf->BltFast(unionx, uniony, cursor_union, &src, DDBLTFAST_WAIT);

 if (r!=DD_OK) {

TRACE("Blt 5 failed\n");

CheckResult(r);

 }

 return TRUE;

}

Пользуясь одной из этих двух функций, поток ввода обновляет курсор. При этом удается избежать мерцания и разрушения текущего изображения на первичной поверхности.

Завершение приложения 

Осталось лишь поговорить о том, как завершается работа приложения. Эта тема неоднократно рассматривалась, и ее можно было бы пропустить, но для программы Cursor она важна из-за наличия дополнительного потока. Мы должны не только послать потоку ввода сигнал о завершении, но и проследить за тем, чтобы поток завершился до уничтожения объекта устройства мыши и поверхностей DirectDraw. В противном случае он может попытаться обратиться к мыши или обновить первичную поверхность после того, как соответствующие объекты перестанут существовать. Функция OnDestroy выглядит так:

void CursorWin::OnDestroy {

 critsection.Lock;

 DirectDrawWin::OnDestroy;

 if (mouse) {

TRACE("mouse->Unacquire\n");

mouse->Unacquire;

TRACE("sending mouse quit message...\n");

mouse_event[quit_event_index]->SetEvent;

Sleep(100);

// дать потоку мыши возможность ответить

TRACE("Releasing mouse pointer...\n");

Поделиться с друзьями: