Модель программирования Component Object Model. Разработка COM-сервера, страница 35

Этот обычный (неэкспонируемый) метод должен быть вам знаком.

void COpenGL::SetLight()

{

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1);

float fPos[] =

{

(m_LightParam[0]-50) * 10 * m_fRangeX/10,

(m_LightParam[1]-50) * 10 * m_fRangeY/10,

(m_LightParam[2]-50) * 10 * m_fRangeZ/10,

1.f

};

glLightfv(GL_LIGHT0, GL_POSITION, fPos);

float f = m_LightParam[3]/100.f;

float amb[4] = { f, f, f, 0.f };

glLightfv(GL_LIGHT0, GL_AMBIENT, amb);

f = m_LightParam[4]/100.f;

float diff [4] = { f, f, f, 0.f };

glLightfv(GL_LIGHT0, GL_DIFFUSE, diff);

f = m_LightParam[5]/100.f;

float spec[4] = { f, f, f, 0.f };

glLightfv(GL_LIGHT0, GL_SPECULAR, spec);

f = m_LightParam[6]/100.f;

float ambm[4] = { f, f, f, 0.f };

glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambm);

f = m_LightParam[7]/100.f;

float difm[4] = { f, f, f, 1.f };

glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, difm);

f = m_LightParam[8]/100.f;

float specm[4] = { f, f, f, 0.f };

glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specm);

float shine = 128 * m_LightParam[9]/100.f;

glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shine);

f = m_LightParam[10]/100.f;

float emis [4] = { f, f, f, 0.f };

glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emis);

}

Анимация вращения с помощью таймера

Вот этот немудрящий алгоритм, но будьте внимательны, так как мы вновь возвращаемся к обработчику события. Этот код надо вставить внутрь обработчика OnTimer.

m_AngleX += m_dy;

if (m_AngleX > 360)

m_AngleX -= 360;

m_AngleY += m_dx;

if (m_AngleY > 360)

m_AngleY -= 360;

FireViewChange();

bHandled = TRUE;

return 0;

Реакция на сообщения мыши

Здесь надо все придумать самим и лучше, чем сделано у меня. Это код обработки события WM_LBUTTONDOWN:

KillTimer(1);

m_dx = 0.f;   m_dy = 0.f;

SetCapture();

m_bCaptured = true;

m_xPos = (short)LOWORD(lParam);

m_yPos = (short)HIWORD(lParam);

bHandled = TRUE;

return 0;

Теперь приведем код обработки отпускания левой кнопки мыши.

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;

Алгоритм функции OnMouseMove тоже должен быть вам знаком.

if (m_bCaptured)

{

short xPos = (short)LOWORD(lParam);

short yPos = (short)HIWORD(lParam);

m_dy = float (yPos - m_yPos)/20.f;

m_dx = float (xPos - m_xPos)/20.f;

if (wParam & MK_CONTROL)

{

m_xTrans += m_dx;

m_yTrans -= m_dy;

}

else

{

if (m_bRightButton)

m_zTrans += (m_dx + m_dy)/2.f;

else

{

m_AngleX += m_dy;

m_AngleY += m_dx;

}

}

m_xPos = xPos;   m_yPos = yPos;

FireViewChange();

}

bHandled = TRUE;

return 0;

Далее следует обработка нажатия правой кнопки мыши,

m_bRightButton = true;

OnLButtonDown(uMsg, wParam, lParam, bHandled);

return 0;

затем отпускания.

m_bRightButton = false;

m_bCaptured = false;

ReleaseCapture();

bHandled = TRUE;

return 0;

Экспонируемые методы

Вновь возвращаемся к методам, зарегистрированным в интерфейсе IOpenGL Заготовки этих методов должны присутствовать в файле реализации. Алгоритм GetLightParams прозрачен.

for (int i=0; i<11; i++)

pPos[i] = m_LightParam[i];

return S_OK;

Алгоритм SetLightParam еще проще.

m_LightParam[lp] = nPos;

FireViewChange();

return S_OK;

В данный момент вы можете попытаться запустить сервер, но компилятор обнаружит серию ошибок, характерных для ATL-приложений.

Дело в том, что большинство параметров функций обработки сообщений выключено с помощью символов комментария. Это сделано в целях экономии. Если параметр не виден компилятору, то это означает, что он не будет использован, то есть не нужен. В этом случае компилятор не создает кода для выбора параметра их стека.

Все хорошо, но некоторые параметры нам все-таки нужны. Анализируя код функций обработки, раскройте комментарии только для тех параметров, которые действительно используются. После этого вы можете построить DLL и посмотреть, что получилось, запустив тестовый контейнер.