Завершить работу DirectInput несложно — для этого достаточно освободить все интерфейсы DirectInput. В нашей программе это происходит в функции OnDestroy():
| void QwertyWin::OnDestroy() { DirectDrawWin::OnDestroy();
if (dinput) dinput->Release(), dinput=0; if (keyboard) { keyboard->Unacquire(); keyboard->Release(), keyboard=0; } } |
Перед завершением приложения MFC вызывает функцию OnDestroy(); мы воспользуемся ею для освобождения объектов DirectInput. Функция OnDestroy() выглядит так:
| void SmearWin::OnDestroy() { DirectDrawWin::OnDestroy(); if (dinput) dinput->Release(), dinput=0; if (keyboard) { keyboard->Unacquire(); keyboard->Release(), keyboard=0; }
if (mouse) { mouse->Unacquire(); mouse->Release(), mouse=0; } } |
Осталось лишь поговорить о том, как завершается работа приложения. Эта тема неоднократно рассматривалась, и ее можно было бы пропустить, но для программы 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"); mouse->Release(), mouse=0; delete mouse_event[mouse_event_index]; delete mouse_event[quit_event_index]; } if (keyboard) keyboard->Release(), keyboard=0; if (dinput) dinput->Release(), dinput=0; critsection.Unlock(); } |
Далее мы уступаем мышь. Устройство перестает генерировать новые события, которые заставили бы поток ввода попытаться снова обновить экран. Затем функция CEvent::SetEvent() посылает потоку ввода сигнал о завершении.
Нам осталось лишь освободить объекты DirectInput. Но перед тем, как это делать, мы вызываем функцию Sleep(), чтобы ненадолго приостановить основной поток. Поток ввода получает возможность обработать событие и завершиться. Наконец, мы освобождаем критическую секцию, и функция завершается— на этом работа приложения заканчивается.