Проблема курсора
Если вы пытались работать с мышью в полноэкранном приложении DirectDraw, скорее всего, проблема с курсором вам уже знакома. Ввод от мыши нетрудно получить и использовать в программе, пока не приходится отображать курсор на экране. Но попробуйте-ка вывести стандартный курсор Windows — и проблема заявит о себе.
Первая трудность связана с переключением страниц. Если курсор мыши не был отключен, Windows не подозревает о том, что видеоустройства находятся под управлением DirectDraw, и выводит курсор мыши на поверхности GDI. Если поверхность GDI скрыта, а вместо нее на экране отображается другая поверхность, курсор исчезает. Эта переменчивость приводит к тому, что курсор мыши мерцает и выглядит полупрозрачным.
Более того, курсор может оказаться искаженным или вообще отсутствовать. Например, в видеорежимах Mode X используется нелинейная организация пикселей. Windows пытается вывести курсор мыши, но поскольку режимы Mode X не поддерживаются Windows GDI, изображение курсора портится. Кроме того, Windows не умеет выводить курсор мыши на вторичных видеоустройствах (например, на видеокартах с чипами 3Dfx). Вывод продолжает поступать на первичное видеоустройство независимо от того, какое устройство активно в данный момент, поэтому курсор мыши пропадает.
Значит, если полноэкранное приложение захочет вывести курсор мыши, ему придется делать это самостоятельно. На первый взгляд все просто: нужно создать небольшую поверхность с изображением курсора и перемещать ее в соответствии с вводом от мыши. Такое решение работает, но у него есть свои недостатки.
Раз курсор мыши отображается самим приложением, а не Windows, частота его прорисовки зависит от быстродействия приложения. Если приложение постоянно работает на 75 FPS, это будет приемлемо, но что если частота вывода кадров упадет до 30 FPS и ниже? С падением частоты курсор будет все медленнее реагировать на действия пользователя.
Существует множество причин, по которым приложение может иметь низкую частоту вывода кадров. Трехмерные приложения предъявляют особенно жесткие требования к системе и часто работают с частотой 30 FPS и менее. Но «тормозить» могут и обычные, не трехмерные приложения. Сложное приложение, выводящее сотни объектов, будет иметь низкий FPS (конечно, все зависит от компьютера и видеокарты). Кроме того, режимы High и True Color часто оказываются намного медленнее 8-битных режимов.
Более того, простому приложению DirectDraw вряд ли потребуется курсор мыши. Если возникла необходимость в курсоре, значит, пользователь должен выделять определенные области экрана. Сомнительно, чтобы сложное приложение смогло обеспечить высокую частоту вывода, пока пользователь работает с мышью.
Итак, нам придется искать нетривиальное решение. Оно должно обеспечивать быструю реакцию на действия с мышью независимо от FPS, а курсор не должен мерцать. Поскольку нам все равно придется создавать собственный курсор, для него можно выбрать произвольный размер.
Эта глава посвящена решению, которое удовлетворяет всем перечисленным критериям. Сначала мы обсудим частичное обновление экрана (прямой блиттинг на первичную поверхность), а затем поговорим о том, как многопоточность обеспечивает обновление курсора, не зависящее от частоты вывода. Наконец, теория воплотится на практике в виде программы Cursor.