Работа с Visual Studio.Net

         

Файловые операции

Создание тестовой поверхности, чтение данных из файла и хранение этих данных в контейнере мы будем делать так же, как и в проекте MFC. Для разнообразия используем другую формулу для описания поверхности по умолчанию, то есть того графика, который увидит пользователь элемента ActiveX при его инициализации в рамках окна контейнера. Вот эта формула:

Yi,j=exp[-(i+20*j)/256]*SIN[3*п*

(i-Nz/2)/Nz]*SIN[3*п*(j-Nx/2)/Nx]

Приведем тело функции Def aultGraphic, которая генерирует значения этой функции над дискретной сеткой узлов в плоскости X-Z и записывает их в файл с именем «expidat». В теле

этой функции мы вызываем другую вспомогательную функцию SetGraphPoints, которая наполняет контейнер точек типа CPointSD. При этом, как вы помните, она генерирует недостающие две координаты (z, x) и масштабирует ординаты (у) так, чтобы соблюсти разумные пропорции изображения графика на экране:

void COGView::DefaultGraphic()

{

//====== Размеры сетки узлов

m_xSize = m_zSize = 33;

//====== число ячеек на единицу меньше числа узлов

UINTnz = 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;

// Размещаем данные целого типа

*р++ = m_xSize;

*р++ = m_zSize;

//===== Меняем тип указателя, так как дальше

//====== собираемся записывать вещественные числа

float *pf = (float*)p;

// Предварительно вычисляем коэффициенты уравнения

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

//=== В двойном цикле пробега по сетке узлов

//=== вычисляем и помещаем в буфер данные типа float

for (UINT i=0; i<m_zSize;

for (UINT j=0; j<m_xSize;

*pf++ = float (exp(-(i+20.*j)/256.)

*sin(kz* (i-nz/2. ) ) *sin(kx* (j-nx/2.) ) ) ;

//=== Переменная для того, чтобы узнать сколько

//=== байт было реально записано в файл DWORD nBytes;

//=== Создание и открытие файла данных sin.dat

HANDLE hFile = CreateFile(_T("sin.dat") , GENERIC_WRITE, 0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0)

//=== Запись в файл всего буфера

WriteFile(hFile, (LPCVOID)buff, nSize,SnBytes, 0) ;

CloseHandle(hFile); // Закрываем файл

//=== Создание динамического массива m cPoints

SetGraphPoints (buff, nSize);

//=== Освобождаем временный буфер

delete [] buff;

}

Коды функций SetGraphPoints, ReadData и DoRead возьмите из MFC-ГфИЛО-ження OG, которое мы разработали ранее. При этом не забудьте изменить заголовки функций. Например, функция SetGraphPoints теперь является членом класса COpenGL, а не COGView, как было ранее. Кроме того, метод ReadData теперь стал экспонируемым, а это означает, что он описывается как STDMETHODIMP COpenGL: : ReadData (void) и должен возвращать значения во всех ветвях своего алгоритма. В связи с этими изменениями приведем полностью код функции ReadData.

STDMETHODIMP COpenGL::ReadData(void)

{

//=== Строка, в которую будет помещен файловый путь

TCHAR szFile[MAX_PATH] = { 0 };

//=== Строка фильтров демонстрации файлов

TCHAR *szFilter =

TEXT("Graphics Data Files (*.dat)\0")

TEXT("*.dat\0")

TEXT("All FilesX()")

TEXT("*.*\0");

//=== Выявляем текущую директорию

TCHAR szCurDir[MAX_PATH];

::GetCurrentDirectory(MAX_PATH-l,szCurDir) ;

// Структура данных, используемая файловым диалогом

OPENFILENAME ofn;

ZeroMemory(&ofn,sizeof(OPENFILENAME));

//=== Установка параметров будущего диалога

ofn.lStructSize = sizeof(OPENFILENAME) ;

//=== Окно-владелец диалога

ofn.hwndOwner = GetSafeHwnd();

ofn.IpstrFilter = szFilter;

//=== Индекс строки фильтра (начиная с единицы)

ofn.nFilterlndex= 1;

ofn.IpstrFile = szFile;

ofn.nMaxFile = sizeof(szFile);

//=== Заголовок окна диалога

ofn.IpstrTitle = _Т("Найдите файл с данными");

ofn.nMaxFileTitle = sizeof (ofn.IpstrTitle);

//=== Особый стиль диалога (только в Win2K)

ofn.Flags = OFN_EXPLORER;

//=== Создание и вызов диалога

// В случае неудачи GetOpenFileName возвращает О

if (GetOpenFileName(&ofn))

{

// Попытка открыть файл, который должен существовать

HANDLE hFile = CreateFile(ofn.IpstrFile, GENERIC READ, FILE SHARE READ, 0,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) ;

//===== В случае неудачи CreateFile возвращает -1

if (hFile == (HANDLE)-1)

{

MessageBox(_T("He удалось открыть файл"));

return S_FALSE;

}

//=== Попытка прочесть данные о графике

if (IDoRead(hFile))

return S_FALSE;

//====== Создание нового изображения

DrawScene();

//====== Перерисовка окна OpenGL

Invalidate(FALSE);

}

return S_OK;

}

Если вы используете операционную систему Windows 2000, то файловый диалог, который создает функция GetOpenFileName, должен иметь другой стиль. Он задан флагом OFN_EXPLORER.

Содержание раздела