Взаимодействие классов
Ниже приведены функции обработки других сообщений мыши. Они сходны с теми, которые мы разработали для MFC-приложения, за исключением прототипов и возвращаемых значений. Начнем с обработки нажатия левой кнопки. Оно, очевидно, должно всегда останавливать таймер, запоминать факт нажатия кнопки и текущие координаты курсора мыши:
LRESULT COpenGL::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM IParam, BOOL& bHandled) { //====== Останавливаем таймер KillTimer(1); //====== Обнуляем кванты перемещения m_dx = O.f; m_dy = 0.f; //====== Захватываем сообщения мыши, //====== направляя их в свое окно SetCapture(); //====== Запоминаем факт захвата m_bCaptured = true; //====== Запоминаем координаты курсора m_xPos = (short)LOWORD(IParam); m_yPos = (short)HIWORD(IParam); bHandled = TRUE; return 0; }
В обработчик отпускания левой кнопки вводится анализ на необходимость продолжения вращения с помощью таймера. В случае превышения порога чувствительности, следует запустить таймер, который продолжает вращение, поддерживая текущее значение его скорости. Любопытно, что в алгоритме нам не понадобился ни один их входных параметров функции:
LRESULT COpenGL::OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { //====== Если был захват, if (m_bCaptured) { //=== то анализируем желаемый квант перемещения //=== на превышение порога чувствительности if (fabs(m_dx) > 0.5f || fabs(m_dy) > 0.5f) //====== Включаем режим постоянного вращения SetTimer(1.33); else //====== Выключаем режим постоянного вращения KillTimer(1); //====== Снимаем флаг захвата мыши m_bCaptured = false; //====== Отпускаем сообщения мыши ReleaseCapture(); } bHandled = TRUE; return 0; }
При нажатии на правую кнопку выполняются те же действия, что и при нажатии на левую, но дополнительно запоминается факт нажатия правой кнопки, с тем чтобы можно было правильно интерпретировать последующие сообщения о перемещении указателя мыши и вместо вращения изображения производить его сдвиг вдоль оси Z. Отметьте тот факт, что мы должны убрать символы комментариев вокруг параметров:
LRESULT COpenGL::OnRButtonDown(UINT uMsg, WPARAM wParam, LPARAM IParam, BOOL& bHandled) { //====== Запоминаем факт нажатия правой кнопки m_bRightButton = true; //====== Воспроизводим реакцию на левую кнопку OnLButtonDown(uMsg, wParam, IParam, bHandled); return 0; }
Отпускание правой кнопки просто отмечает факт прекращения перемещения вдоль оси Z и отпускает сообщения мыши (ReleaseCapture), для того чтобы они могли правильно обрабатываться другими окнами, в том числе и нашим окном-рамкой. Если этого не сделать, то будет невозможно использоваться меню:
LRESULT COpenGL::OnRButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { m_bRightButton = false; m_bCaptured = false; ReleaseCapture(); bHandled = TRUE; return 0; }
Запустите и проверьте управляемость объекта. Введите коррективы чувствительности мыши. В заключение отметим, что при выборе параметров заготовки ATL мы могли на вкладке Miscellaneous (Разное) поднять не только флажок Insertable, но и windowed Only. Это действие сэкономило бы те усилия, которые были потрачены на поиск неполадок, вызванных отсутствием флага mbWindowOnly.