Смекни!
smekni.com

Использование ЭВМ в кардиологии (стр. 6 из 11)

Наступление события обозначается поступлением сообщения. Все сообщения Windows имеют стандартные имена, многие из которых начинаются с префикса WM_ (Windows Message). Например, WM_PAINT именует сообщение о том, что необходимо перерисовать содержимое окна того приложения, которое получило это сообщение. Идентификатор сообщения WM_PAINT – это символьная константа, обозначающая некое число.

Рассмотрим такой пример. Пользователь приложения нажимает клавишу на клавиатуре, а система вырабатывает сообщение об этом событии. Вы знаете, что Windows обеспечивает поддержку клавиатуры, не зависящую от типа устройства (device – independent support). Для каждого типа клавиатуры она устанавливает соответствующий драйвер, то есть специальную программу, которая служит посредником между клавиатурой и операционной системой. Клавиатурная поддержка Windows не зависит также от языка общения с системой. Это достигается использованием специальной клавиатурной раскладки (layout), которую пользователь выбрал в данный момент. Каждой клавише присвоено уникальное значение – идентификатор клавиши, зависящий от типа устройства и называемый скан – кодом. Когда пользователь вводит символ, то клавиатура генерирует два скан кода: один – когда он нажимает клавишу, и другой – когда отпускает. Скан коды с клавиатуры поступают в клавиатурный драйвер, который, используя текущую раскладку, транслирует их и преобразует в сообщения.

Клавиатурный драйвер интерпретирует скан – код и преобразует его в определяемый Windows код виртуальной клавиши (virtual - key code), не зависящий от типа устройства и идентифицирующий функциональный смысл клавиши. После этого преобразования скан - кода драйвер создает сообщение, в которое включается: скан – код, виртуальный код и другая информация о нажатии клавиши, и помещает его в очередь системных сообщений. Windows выбирает сообщение из этой очереди и посылает его в очередь сообщений соответствующего потока (thread). В конце концов цикл выборки сообщений данного потока передает его соответствующей оконной процедуре для обработки. Модель вызова с клавиатуры в системе Windows представлена на рис. 3.1.

Рис. 3.1 Схема генерации и движения сообщений Windows.

Рассмотренная модель выработки и прохождения сообщений поможет вам понять структуру, принятую во всех Windows – приложениях. Последние два блока в рассмотренной схеме определяют особенности строения любого Windows – приложения. Простейшее приложение состоит как минимум из двух функций:

- функция WinMain (имя зарезервировано), которая содержит цикл выборки сообщений и выполняется первой в любом приложении;

- оконная процедура, которую вызывает система, направляя ей соответствующие сообщения.

Имя оконной процедуры выбирается произвольно. Система Windows регистрирует это имя, связывая его с вашим приложением. Также безусловно нужно отметить, что хотя в приложениях на основе MFC трудно увидеть функцию WinMain или оконную процедуру, они там присутствуют, но скрыты от программиста разработчиками среды Visual Studio.

Главное окно приложения.

На рис. 3.2 приведено главное окно приложения. Через набор управляющих элементов производится управление основной программой.

Элементы управления:

- Кнопка “Загрузить файл” – реализует загрузку оцифрованного и упакованного файла ЭКГ диаграммы (рис. 2), хранящегося на диске и отображает распакованные данные в окне просмотра (рис. 3).

- Кнопка “Выход” – выйти из приложения.

- Комбинированное поле фильтров – Выбор фильтра для последующего отображения в окне просмотра.

- Флажок переключатель ”Фильтр пробка” – установка режима фильтрации сетевой наводки (игнорирует выбор фильтра в комбинированном поле).

- Флажок переключатель “Дифференциатор” – устанавливает режим определения подачи импульсов дефибриляции.

- Комбинированное поле отведений – Выбор номера отведения для отображения в окне просмотра.

- Кнопка “применить” – устанавливает режим отображения отфильтрованного сигнала в окне просмотра (работает после загрузки файла).

Рис. 3.2 Главное окно приложения.


Загрузка файла.

Прежде чем на экране появится второе окно с данными баз ЭКГ, в программе необходимо загрузить один из файлов *.@8. В функции, реагирующей на нажатие кнопки “Загрузить файл” используется стандартный диалог выбора файла для загрузки, далее выбранный файл передается в функцию, выделяющую массивы значений всех двенадцати отведений. После этого здесь же конструируется окно просмотра с неинициализированной фильтрованной ЭКГ.

void CNewvisualDlg::OnLoadFile()

{

//конструктор файлового диалога

CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Экгдиаграммы(*.@8)|*.@8||");

//сделать модальным и запомнить состояние

int response = dlg.DoModal();

if(response = IDOK)

{

CString fname=dlg.GetFileName();

if(fname=="") goto end;

HANDLE InputFile = CreateFile(fname,GENERIC_READ,FILE_SHARE_READ,

0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);

//распаковать и выделить 12 отведений

ReadK12(InputFile);

//создать окно просмотра

m_dlgPaint.Create(IDD_VIEW_GRAPH,this);

m_dlgPaint.SetWindowPos(&wndTop,200,0,m_dlgPaint.right*0.8,

m_dlgPaint.left-100,SWP_SHOWWINDOW);m_dlgPaint.ShowWindow(SW_SHOW);//показатьокно

m_dlgPaint.Counter = 0;

SetTimer(ID_SHOW_TIMER,2,NULL);

memcpy(m_dlgPaint.StartOtv,StartOtv[0],16000);

Flag = true;

UpdateData();

m_dlgPaint.Invalidate();

}

end:

;;

}

Дальше более интересно было бы рассмотреть алгоритм выделения отведений из файлов баз ЭКГ. У файлов *.@8 первые 53 байта содержат заголовочную информацию для параметров ЭКГ(время снятия ЭКГ, тип ЭКГ, частота сигнала и т.д.). Взятие дальнейшей информации идет в зависимости от типа ЭКГ, если ЭКГ сжата, то работает алгоритм сжатия, если не сжата, то данные берутся элементарным способом.

Окно просмотра ЭКГ диаграмм.

Окно просмотрареализует отображение ЭКГ диаграмм в режиме

прокрутки, в соответствии с реальным временем снятия ЭКГ сигнала (рис 2).

Режим прокрутки реализуется при помощи установки таймера функцией SetTimer(ID_SHOW_TIMER,2,NULL), где 2 – время в миллисекундах посыла сообщения от таймера к системе. Поскольку частота съема данных ЭКГ равна 500 Гц. , то здесь прокрутка реализована со скоростью отрисовки в один пиксел на каждый посыл сообщения от таймера. Алгоритм работы таймера будет рассмотрен ниже.

компьютерный программный импульс дефибриляция


Рис.3.3 Окно просмотра ЭКГ диаграмм (Неотфильтрованный и отфильтрованный сигнал)

В данном окне используется два режима работы; режим показа сигнала из файла загрузки, режим показа как сигнала из файла загрузки, так и отфильтрованного сигнала, в соответствии с установками управляющих элементов. Для вывода данных ЭКГ на экран была написана динамически подключаемая графическая библиотека Graph.dll, которая может использоваться в других приложениях. Созданный динамический модуль система интегрирует в пространство другого(клиентского) процесса, загрузив его по определенному базовому адресу. Мы воспользуемся преимуществом, которое предоставляет библиотека MFC, расширяющая WIN32 – поддержку DLL. DLL – расширение способно экспортировать не только отдельные функции, но и целые классы C++. Приложение, использующее DLL(клиентское приложение), может создавать объекты импортируемого класса, а так же создавать производные классы на основе класса, реализованного в DLL. Обычные DLL могут экспортировать функции. DLL-расширения могут экспортировать как функции, так и классы.

DLL – расширение динамически связывается с кодом DLL – версии библиотеки MFC и требует, чтобы клиентская программа тоже компоновалась с ним динамически. Обычная DLL может связываться с библиотекой MFC как динамически, так и статически. Но это не снижает привлекательности DLL – расширений, так как при необходимости можно поставить заказчику необходимые системные DLL, такие как Mfc42d.dll, Mfc042.dll и другие.

Исходный код определения экспортируемого класса приведен ниже.

class AFX_EXT_CLASS CGraph

{

double dXLeft;// Левыйверхнийугол

double dYTop;

double dFracX;// Ширинаивысота

double dFracY;

double dMinX, dMaxX;// Min-Max значения по горизонтали

double dMinY, dMaxY;// Min-Max значения по вертикали

double dSpanX;// Размах графика по горизонтали

double dSpanY;// Размах графика по вертикали

double dStepX, dStartX;// Шаг и начальное значение

double dStepY, dStartY;

UINT nPoints;// Количествоточек

// Целочисленныеаналоги

UINT nStepsX, nStepX, MinX, MaxX;

UINT nStepsY, nStepY, MinY, MaxY;

UINT *X, *Y;// Координаты точек на экране

int iPowerX, iPowerY;// Экспоненты

CRect rect;// Прямоугольник вывода

// Три типа шрифтов: для осей, заголовка и экспонент

CFont TextFont, TitleFont, PowerFont;

public:

void GetRect(int&,int&,int&,int&); //получить размер прямоугольника отображения

Cgraph (CRect, UINT, double ,double ,double ,double);//конструктор

// Функции нормировки исходных массивов

void ScaleX(TValues&);

void ScaleY(TValues&);

// Масштабированиемассива

void Scale (double, int&, double&);

// Изображениекоординатнойсетки

void DrawGrid (CDC*, CString&, CString&, CString&, TValues&, TValues&);

// Изображение графика зависимости

void DrawFunc (CDC*,BYTE *);

virtual ~CGraph ();

};

В конструкторе мы инициализируем область вывода графика, количество отображаемых точек и коэффициенты вывода, относительно общей области. Далее в основном приложении для вывода графики нам понадобятся функции DrawGrid и DrawFunc. Масштабирование входных координат точек графика, задаваемых числами с плавающей точкой двойной точности, производится в функции Scale, где значения по осям Х и Y масштабируются отдельно через вызовы функций ScaleX и ScaleY. Функция DrawGrid выводит на экран координатную сетку, а функция DrawFunc рисует график.