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

void COpenGL::DefaultGraphic()

{

m_xSize = m_zSize = 33;

UINT

nz = m_zSize - 1,

nx = m_xSize - 1;

DWORD nSize = m_xSize * m_zSize * sizeof(float) + 2*sizeof(UINT);

BYTE *buff = new BYTE[nSize+1];

UINT *p = (UINT*)buff;

*p++ = m_xSize;

*p++ = m_zSize;

float *pf = (float*)p;

double fi = atan(1.)*12, kx=fi/nx, kz=fi/nz;

for (UINT i=0;  i<m_zSize;  i++)

for (UINT j=0;  j<m_xSize;  j++)

*pf++ = float (exp(-(i+20.*j)/256)*sin(kz*(i-nz/2.))*sin(kx*(j-nx/2.)));

DWORD nBytes;

HANDLE hFile = CreateFile(_T("exp.dat"), GENERIC_WRITE,

0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);

WriteFile (hFile,(LPCVOID)buff, nSize, &nBytes, 0);

CloseHandle(hFile);

SetGraphPoints (buff, nSize);

delete [] buff;

}

void COpenGL::SetGraphPoints (BYTE* buff, DWORD nSize)

{

UINT *p = (UINT*)buff;

m_xSize = *p;

m_zSize = *++p;

if (m_xSize<2 || m_zSize<2 || m_xSize*m_zSize*sizeof(float)

+2 * sizeof(UINT) != nSize)

{

MessageBox(_T("Wrong file format"));

return;

}

m_cPoints.resize (m_xSize * m_zSize);

if (m_cPoints.empty())

{

MessageBox(_T("No graphics data"));

return;

}

float

x, z,

*pf   = (float*)++p,

fMinY = *pf,

fMaxY = *pf,

right = (m_xSize-1)/2.f,

left  = -right,

rear  = (m_zSize-1)/2.f,

front = -rear,

range = (right + rear)/2.f;

UINT i, j, n;

m_fRangeY = range;

m_fRangeX = float(m_xSize);

m_fRangeZ = float(m_zSize);

m_zTrans = -1.5f*m_fRangeZ;

for (z=front, i=0, n=0;  i<m_zSize;  i++, z+=1.f)

{

for (x=left, j=0;  j<m_xSize;  j++, x+=1.f, n++)

{

MinMax (*pf, fMinY, fMaxY);

m_cPoints[n] = Point3D(x,z,*pf++);

}

}

float zoom = fMaxY > fMinY ? range/(fMaxY-fMinY) : 1.f;

for (n=0;  n<m_xSize*m_zSize;  n++)

m_cPoints[n].y = zoom*(m_cPoints[n].y - fMinY) - range/2.f;

}

Внимание. Следующий код надо вставить внутрь уже существующей заготовки метода ReadData, который является не простым методом класса, а методом интерфейса IOpenGL (поэтому он и возвращает HRESULT). Он предоставлен клиентам (реализован) с помощью класса COpenGL.

TCHAR szFile[MAX_PATH] = { 0 }, szCurDir[MAX_PATH];

::GetCurrentDirectory (MAX_PATH-1, szCurDir);

OPENFILENAME ofn =

{

sizeof(OPENFILENAME),

m_hWnd, GetModuleHandle(0), // Dialog Owner, App Instance

_T("Dat Files (*.dat)\0*.dat\0"), 0, 0, 1,  // Filter, Custom Filter and Filter Index

szFile, MAX_PATH, 0, 0,      // Recieve File Name, File Name Buffer

szCurDir, _T("Open a graphics data file"),  // InitialDir, Dialog Title

OFN_EXPLORER | OFN_OVERWRITEPROMPT, // Flags

0, 0, "dat", 0, 0, 0,    // Offsets, Default extension, CustData, Hook, TemplateName

#if (_WIN32_WINNT >= 0x0500)

0, 0, 0 // Reserved, Reserved, FlagsEx

#endif

};

if (GetOpenFileName(&ofn))

{

HANDLE hFile = CreateFile (ofn.lpstrFile, GENERIC_READ,

FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

if (hFile == (HANDLE)-1)

{

MessageBox(_T("Could not open this file"));

return S_FALSE;

}

if (!DoRead(hFile))

return S_FALSE;

DrawScene();

FireViewChange();

}

return S_OK;

Метод FireViewChange унаследован от шаблона классов CComControl. Если компонент активен, то метод уведомляет клиента о необходимости перерисовать весь элемент, если нет, то он уведомляет зарегистрированный сток (sink) о том, что облик компонента изменился. Слушающий клиент услышит и, возможно, отреагирует, а не слушающий не имеет стока. Далее опять идет простой (то есть наш) метод, который не виден клиентскому приложению.

bool COpenGL::DoRead (HANDLE hFile)

{

DWORD nSize = GetFileSize (hFile, 0);

if (nSize == 0xFFFFFFFF)

{

GetLastError();

MessageBox(_T("The file is too big"));

CloseHandle(hFile);

return false;

}

BYTE *buff = new BYTE[nSize+1];

if (!buff)

{

MessageBox(_T("No core"));

CloseHandle(hFile);

return false;

}

DWORD nBytes;

ReadFile (hFile, buff, nSize, &nBytes, 0);

CloseHandle(hFile);

if (nSize != nBytes)

{

MessageBox(_T("Wrong file data"));

return false;

}

SetGraphPoints (buff, nSize);

delete [] buff;

return true;

}

Установка освещения