Программирование на Visual C++. Архив рассылки | страница 8



Способ №1 (универсальный). Нужно перекрыть функцию OnSetCursor() класса CWnd, родителя вашего окна (вида). В ней необходимо сообщение обработать самому, устанавливая нужный курсор. Для тех, кто не знает, сообщение WM_SETCURSOR посылается окну тогда, когда курсор мыши двигается внутри окна, причем  мышь приложением  не захвачена (с помощью функции SetCapture()). Вот пример из MSDN:

>BOOL CMyView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {

> if (m_ChangeCursor) {

>  // устанавливаем стандартный курсор вида "I"

>  ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_IBEAM));

>  return TRUE;

> }

> return CView::OnSetCursor(pWnd, nHitTest, message);

>}

Конечно, можно установить и ваш собственный курсор, только вместо LoadStandardCursor() нужно будет воспользоваться LoadCursor() или LoadOEMCursor(). С помощью параметра nHitTest можно определить область, в которой сейчас находится курсор. Вообще, этот способ лучше применять только тогда, когда вам в самом деле нужно динамически менять один курсор на другой (причем отличный от песочных часов), потому этот способ самый нерациональный (прикиньте-ка. сколько раз будет выполняться этот обработчик). Лучше все нужные курсоры загрузить заранее, а из функции– обработчика Load..Cursor() не вызывать. Хотя, в принципе, я для примера сделал такой обработчик – никакой разницы в скорости не заметил…но это уже зависит от конкретного компьютера, наверное. И потом, наверное не стали бы в MSDN это советовать, если бы не знали, что делали ;) 

Ну а тем, кому лишь надо видом курсора  показать пользователю, что компьютер сейчас занят какой-то операцией, идеально подходит

Способ №2 (песочные часы). Этот способ самый простой. Вызывайте функцию BeginWaitCursor() перед началом операции и EndWaitCursor() после ее завершения. Единственный нюанс здесь в том, что если эти два вызова должны находиться в разных функциях-обработчиках, то вам все же придется перекрыть OnSetCursor(), причем это выглядит примерно так:

>BOOL CMyView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {

> if (m_ChangeCursor) {

>  RestoreWaitCursor(); // восстанавливаем курсор-пес.часы

>  return TRUE;

> }

> return CView::OnSetCursor(pWnd, nHitTest, message);

>}

В этом случае перед вызовом BeginWaitCursor()  m_ChangeCursor нужно приравнять к TRUE, а после EndWaitCursor() – к FALSE.

Способ №3 (класс окна). Этот метод применяется, когда вам для какого-то окна нужно установить конкретный курсор, причем желательно на все время существования окна. Перекрываете PreCreateWindow() и регистрируете свой класс окна, изменяя поле lpszClass параметра cs типа CREATESTRUCT: