Иллюстрированный самоучитель по Visual Studio .NET

Взаимодействие классов

Ниже приведены функции обработки других сообщений мыши. Они сходны с теми, которые мы разработали для 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.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.