Обновление курсора
Итак, курсор мыши должен обновляться прямо на первичной поверхности. При очередном перемещении курсора необходимо выполнить два действия:
- Стереть курсор в старом месте.
- Нарисовать курсор в новом месте.
- Восстановить фоновое изображение в старом месте.
- Сохранить часть изображения в новом месте.
- Нарисовать курсор в новом месте.
И все же такой подход связан с некоторыми ограничениями. Он хорошо работает, если старая область курсора не накладывается на новую. Но если области перекрываются, курсор мерцает, потому что стирание происходит поблизости от места рисования. Чтобы полностью избавиться от мерцания, мы должны одновременно обновлять старую и новую области расположения курсора, а описанный выше алгоритм можно использовать для неперекрывающихся областей курсора.
Прежде чем продолжать, я хотел бы заметить, что чаще встречаются именно перекрывающиеся области. Старая и новая области курсора перекрываются при любом медленном перемещении мыши, а мышь обычно перемещается быстро лишь из одного края экрана в другой. Во всех остальных случаях при выборе конкретного участка экрана курсор перемещается медленно. Следовательно, борьба с мерцанием становится очень важной задачей.
Чтобы справиться с мерцанием, можно обновлять изображение на внеэкранной поверхности. Мы копируем в нее обе области курсора (старую и новую), обновляем изображение, а затем копируем обе области обратно на первичную поверхность как единое целое. Алгоритм состоит из пяти этапов:
- Скопировать объединение старой и новой областей курсора на вспомогательную поверхность.
- Стереть старый курсор на вспомогательной поверхности.
- Сохранить фоновое изображение, занятое новой областью курсора.
- Нарисовать новый курсор на вспомогательной поверхности.
- Скопировать содержимое вспомогательной поверхности на первичную поверхность.
Для реализации двух алгоритмов потребуются три внеэкранные поверхности: поверхность с курсором, поверхность для хранения фонового изображения и вспомогательный буфер для перекрывающихся курсорных областей. Размеры первой и второй поверхностей совпадают с размерами курсора. Однако вспомогательный буфер должен быть вдвое выше и вдвое шире поверхности курсора, чтобы в нем могли разместиться области при минимальном перекрытии (на самом деле при таком размере буфер получается на один пиксель выше и шире, чем необходимо, но это непринципиально).