⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wview.c

📁 mit数据库ecg波形观察软件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* file: wview.c        G. Moody        20 January 1993
                        Last revised:     11 June 2000 (but see *** below)
   
-------------------------------------------------------------------------------
wview: view WFDB-format signals and annotations under MS Windows
Copyright (C) 2000 George B. Moody

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA.

You may contact the author by e-mail (george@mit.edu) or postal mail
(MIT Room E25-505A, Cambridge, MA 02139 USA).  For updates to this software,
please visit PhysioNet (http://www.physionet.org/).
_______________________________________________________________________________

*/

#include <windows.h>
#include <string.h>
#include <wfdb/wfdb.h>
#include <wfdb/ecgcodes.h>
#include <stdlib.h>
#include "wview.h"
extern int sprintf();

#define SIGNAL_COLOR    RGB(0, 0, 255)          /* blue */
#define GRID_COLOR      RGB(192, 192, 192)      /* 25% grey */
#define PGRID_COLOR     RGB(0, 0, 0)            /* black */
#define MARKER_COLOR    RGB(255, 0, 0)          /* red */

/* Default scales and grid intervals. */
#define TSI          9  /* index (within tsi[], see below) of default time
			   scale */
#define VSI          3  /* index (within vsi[], see below) of default amplitude
			   scale */
#define GTICKSPERSEC 5  /* grid ticks per second */
#define GTICKSPERMV  2  /* grid ticks per millivolt */

/* Printing defaults. */
#define MAXCOPIES   10  /* maximum number of copies to be printed by a single
			   request */

/* Convert mm coordinates (origin at lower left of window) to window
   coordinates (origin at upper left of window).*/
#define xtr(A)  ((int)((A)*xppmm))
#define ytr(A)  ((int)(wheight - (A)*yppmm))

/* Convert signal coordinates (origin on left edge of window at baseline
   level yb, units sample intervals and A/D units) to window coordinates. */
#define xt(A)   ((int)((A)*xppsi))
#define yt(A)   ((int)(yb - (A)*ysc))

/* Similarly for printer coordinates. */
#define pxtr(A) ((int)((A)*pxppmm))
#define pytr(A) ((int)(pheight - (A)*pyppmm))
#define pxt(A)  ((int)((A)*pxppsi))
#define pyt(A)  ((int)(yb - (A)*pysc))

HANDLE hInst, hLibrary;
HPEN signal_pen;
HPEN grid_pen;
HPEN pgrid_pen;
HPEN marker_pen;
TEXTMETRIC tm;
static int cheight;                     /* y-spacing between rows of text */
static char record[20];                 /* name of record to be browsed */
static char annotator[20] = "atr";      /* name of annotator to be browsed */
static char cfname[40];                 /* name of calibration file */
static char wfdbpath[200];              /* search path for WFDB files */
static char title[80];                  /* title of main window */
static double sg[WFDB_MAXSIG];          /* signal gain * calibration scale */
static double sps = WFDB_DEFFREQ;       /* sampling frequency (Hz) */
static WFDB_Time tf = 100000L;             /* time of end of record */
static WFDB_Time t0, t1;                   /* times of left, right window edges */
static double tscale;                   /* time scale (units are mm/sec) */
static double vscale;                   /* amplitude scale (units are mm/mV) */
static WFDB_Siginfo si[WFDB_MAXSIG];    /* signal specifications */
static int nsig;                        /* number of valid signals in si[] */
static int nann;                        /* number of open annotation files */
static int tmode;             /* 0: show elapsed time; 1: show absolute time */

/* User-selectable time and amplitude scales. */
static double tsc[] = { 0.25/60., 1./60., 5./60., 25./60., 50./60., 125./60.,
                         250./60., 500./60., 12.5, 25., 50., 125., 250. };
static char *tst[] = { "0.25 mm/min", "1 mm/min", "5 mm/min", "25 mm/min",
                           "50 mm/min", "125 mm/min", "250 mm/min",
			   "500 mm/min", "12.5 mm/sec", "25 mm/sec",
                           "50 mm/sec", "125 mm/sec", "250 mm/sec" };
static int tsi = TSI;   /* index (within tsc[] and tst[]) of current tscale */
#define MAXTSI (sizeof(tsc)/sizeof(double) - 1)

static double vsc[] = { 1., 2.5, 5., 10., 20., 40., 100. };
static char *vst[] = { "1 mm/mV", "2.5 mm/mV", "5 mm/mV", "10 mm/mV",
			   "20 mm/mV", "40 mm/mV", "100 mm/mV" };
static int vsi = VSI;   /* index (within vsc[] and vst[]) of current vscale */
#define MAXVSI (sizeof(vsc)/sizeof(double) - 1)

int find_next();
int find_previous();
int open_record();
int open_annotation_file();
void paint_main_window();
void print_window();
void set_title();

int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR lpCmdLine;
int nCmdShow;
{
    static char *p, *q, rtemp[80], pstart[40], pdate[20];
    MSG msg;
    extern int sscanf();
    
    /* If specified, read the calibration file to get standard scales. */
    if (cfname[0] == '\0' && (p = getenv("WFDBCAL"))) {
	strncpy(cfname, p, sizeof(cfname)-1);
	calopen(cfname);
    }
    /* Set the default display scales. */
    tscale = tsc[TSI];
    vscale = vsc[VSI];
    
    rtemp[0] = '\0';
    if (lpCmdLine)
        sscanf(lpCmdLine, "%s%s%s%s", rtemp, annotator, pstart, pdate);
    
    /* Open the signal file(s) for the record to be browsed. */
    if (*rtemp) {
	/* Convert upper case characters to lower case. */
	for (p = rtemp; *p; p++)
	    if ('A' <= *p && *p <= 'Z') *p += 'a' - 'A';
	/* Was the first argument actually a header file name? */
	if (strlen(rtemp) > 4 &&
	    strcmp(rtemp+strlen(rtemp)-4, ".hea") == 0) {       /* yes */
	    /* Locate any drive/path prefix in the first argument. */
	    for (p = rtemp, q = rtemp-1; *p != '.'; p++)
		if (*p == ':' || *p == '\\') q = p;
	    /* Replace the '.' with a null to strip the '.hea' suffix. */
	    *p = '\0';
	    /* Extract the record name. */
	    strncpy(record, q+1, sizeof(record));
	    /* If there was a drive/path prefix, add it to the WFDB path. */
	    if (q >= rtemp) {
		size_t l = (size_t)(q-rtemp+1);
		
		strncpy(wfdbpath, rtemp, l);
		wfdbpath[l] = ';';
		strncpy(wfdbpath+l+1, getwfdb(), sizeof(wfdbpath)-l);
		setwfdb(wfdbpath);
	    }
	}
	else                                                    /* no */
	    strncpy(record, rtemp, sizeof(record));
	open_record();
    }
    
    /* If specified, open the annotation file for the record. */
    if (*record && *annotator && *annotator != '-')
	open_annotation_file();

    /* If specified, set the start time. */
    if (*record && *pstart) {
        if (*pstart == '[') {   /* absolute time */
            tmode = 1;
            if (*pdate) {
                strcat(pstart, " ");
                strcat(pstart, pdate);
            }
            if ((t0 = -strtim(pstart)) < 0L)
                t0 = 0L;     /* pstart precedes start of record; go to 0 */
        }
        else
            t0 = strtim(pstart);
    }

    if (!hPrevInstance)
	if (!InitApplication(hInstance))
	    return (FALSE);
    
    if (!InitInstance(hInstance, nCmdShow))
	return (FALSE);
    
    while (GetMessage(&msg, NULL, NULL, NULL)) {
	TranslateMessage(&msg);
	DispatchMessage(&msg);
    }
    
    wfdbquit();
    return (msg.wParam);
}

BOOL InitApplication(hInstance)
HANDLE hInstance;
{
    WNDCLASS  wc;
    
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, "ecgicon");
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName =  "wviewmenu";
    wc.lpszClassName = "wviewclass";
    return (RegisterClass(&wc));
}

BOOL InitInstance(hInstance, nCmdShow)
HANDLE hInstance;
int nCmdShow;
{
    HWND hWnd;
    
    hInst = hInstance;
    
    set_title();
    hWnd = CreateWindow(
			"wviewclass",
			title,
			WS_OVERLAPPEDWINDOW | WS_HSCROLL,
			0,
			0,
			GetSystemMetrics(SM_CXSCREEN),
			GetSystemMetrics(SM_CYSCREEN),
			NULL,
			NULL,
			hInstance,
			NULL
			);
    if (!hWnd)
	return (FALSE);
    
    if (*record == '\0') {
	static FARPROC lpProcChoose;
	
	lpProcChoose = MakeProcInstance(Choose, hInst);
	DialogBox(hInst, "ChooseBox", hWnd, lpProcChoose);
	FreeProcInstance(lpProcChoose);
	set_title();
	SetWindowText(hWnd, title);
    }
    
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return (TRUE);
}

static double xppmm, yppmm;     /* display resolution */
static double wwsec, whmv;      /* window size in seconds (x) and mV (y) */
static int bflag = 0;           /* draw signal baselines if non-zero */
static int gtflag = 1;          /* draw time grid if non-zero */
static int gvflag = 1;          /* draw amplitude grid if non-zero */
static int mflag = 0;           /* draw marker bars if non-zero */
static int nflag = 1;           /* show signal names if non-zero */
static int show_subtyp = 0, show_chan = 0, show_num = 0, show_aux = 0;
/* display respective fields of annotations if non-zero */
static int wwidth, wheight;     /* window size in pixels */

long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
    static FARPROC lpProcAbout;
    static FARPROC lpProcChoose;
    static FARPROC lpProcFind;
    static FARPROC lpProcPrint;
    static FARPROC lpProcPrintOptions;
    static FARPROC lpProcViewOptions;
    HDC hDC;
    HMENU hMenu;
    static int scrollpos = 0;   /* scroll position (0 - 2048) */
    
    switch (message) {
      case WM_COMMAND:
	hMenu = GetMenu(hWnd);
	
	switch (wParam) {
	  case IDM_OPEN:
	    lpProcChoose = MakeProcInstance(Choose, hInst);
	    if (DialogBox(hInst, "ChooseBox", hWnd, lpProcChoose))
		InvalidateRect(hWnd, NULL, TRUE);
	    FreeProcInstance(lpProcChoose);
	    set_title();
	    SetWindowText(hWnd, title);
	    break;
	  case IDM_FIND:        
	    lpProcFind = MakeProcInstance(Find, hInst);
	    if (DialogBox(hInst, "FindBox", hWnd, lpProcFind)) {
		scrollpos = (int)(2048.*t0/tf);
		SetScrollPos(hWnd, SB_HORZ, scrollpos, TRUE);
		InvalidateRect(hWnd, NULL, TRUE);
	    }
	    FreeProcInstance(lpProcFind);
	    break;
	  case IDM_NEW:
	  case IDM_SAVE:
	  case IDM_SAVEAS:
	  case IDM_UNDO:
	  case IDM_CUT:
	  case IDM_COPY:
	  case IDM_PASTE:
	  case IDM_DEL:
	    MessageBox(hWnd, "Sorry, this command is not yet implemented!",
		       "WVIEW", MB_ICONEXCLAMATION | MB_OK);
	    break;
	  case IDM_EXIT:
	    SendMessage(hWnd, WM_CLOSE, 0, 0L);
	    break;
	  case IDM_HELP_INDEX:
	    WinHelp(hWnd, "wview.hlp", HELP_CONTENTS, 0L);
	    break;
	  case IDM_HELP_CHOOSING:
	    WinHelp(hWnd, "wview.hlp", HELP_CONTEXT, (long)Choosing_Topic);
	    break;
	  case IDM_HELP_BROWSING:
	    WinHelp(hWnd, "wview.hlp", HELP_CONTEXT, (long)Browsing_Topic);
	    break;
	  case IDM_HELP_OPTIONS:
	    WinHelp(hWnd, "wview.hlp", HELP_CONTEXT, (long)Options_Topic);
	    break;
	  case IDM_HELP_SEARCHING:
	    WinHelp(hWnd, "wview.hlp", HELP_CONTEXT, (long)Searching_Topic);
	    break;
	  case IDM_HELP_PRINTING:
	    WinHelp(hWnd, "wview.hlp", HELP_CONTEXT, (long)Printing_Topic);
	    break;
	  case IDM_ABOUT:
	    lpProcAbout = MakeProcInstance(About, hInst);
	    DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
	    FreeProcInstance(lpProcAbout);
	    break;
	  case IDM_PRINT:
	    lpProcPrint = MakeProcInstance(Print, hInst);
	    DialogBox(hInst, "PrintBox", hWnd, lpProcPrint);
	    FreeProcInstance(lpProcPrint);
	    break;
	  case IDM_VIEW:
	    lpProcViewOptions = MakeProcInstance(ViewOptions, hInst);
	    DialogBox(hInst, "ViewOptionsBox", hWnd, lpProcViewOptions);
	    FreeProcInstance(lpProcViewOptions);
	    InvalidateRect(hWnd, NULL, TRUE);
	    break;
	  case IDM_PROPT:
	    lpProcPrintOptions = MakeProcInstance(PrintOptions, hInst);
	    DialogBox(hInst, "PrintOptionsBox", hWnd, lpProcPrintOptions);
	    FreeProcInstance(lpProcPrintOptions);
	    break;
	  default:
	    return (DefWindowProc(hWnd, message, wParam, lParam));
	}
	break;
	
      case WM_CREATE:
	/* Create the pen objects. */
	signal_pen = CreatePen(PS_SOLID, 0, SIGNAL_COLOR);
	grid_pen = CreatePen(PS_SOLID, 0, GRID_COLOR);
	pgrid_pen = CreatePen(PS_DOT, 0, PGRID_COLOR);
	marker_pen = CreatePen(PS_DOT, 0, MARKER_COLOR);
	
	hDC = GetDC(hWnd);
	
	/* Determine display resolution (pixels per millimeter in x and y). */
	xppmm = GetDeviceCaps(hDC,HORZRES)/(double)GetDeviceCaps(hDC,HORZSIZE);
	yppmm = GetDeviceCaps(hDC,VERTRES)/(double)GetDeviceCaps(hDC,VERTSIZE);
	
	/* Get the size characteristics of the current font.  */
	GetTextMetrics(hDC, &tm);
	cheight = tm.tmExternalLeading + tm.tmHeight;
	
	ReleaseDC(hWnd, hDC);
	break;
	
      case WM_SIZE:
	wwidth = LOWORD(lParam);
	wheight = HIWORD(lParam);
	SetScrollRange(hWnd, SB_HORZ, 0, 2048, FALSE);
	scrollpos = (int)(2048.*t0/tf);
	SetScrollPos(hWnd, SB_HORZ, scrollpos, TRUE);
	break;
	
      case WM_HSCROLL:
	switch (wParam) {
	  case SB_TOP:
	    t0 = 0L;
	    break;
	  case SB_BOTTOM:
	    t0 = tf - (WFDB_Time)(wwsec*sps);
	    break;
	  case SB_LINEUP:
	    if ((t0 -= (WFDB_Time)sps) < 0L) t0 = 0L;
	    break;
	  case SB_LINEDOWN:
	    t0 += (WFDB_Time)sps;
	    break;
	  case SB_PAGEUP:
	    if ((t0 -= (WFDB_Time)(sps*(int)wwsec)) < 0L) t0 = 0L;
	    break;
	  case SB_PAGEDOWN:
	    t0 += (WFDB_Time)(sps*(int)wwsec);
	    break;
	  case SB_THUMBTRACK:	/* events occur while dragging "thumb" */
	    /* Show the time corresponding to the current thumb position. */
	    {
		char ts[30];
		int x, y;
		
		hDC = GetDC(hWnd);
		SetBkMode(hDC, OPAQUE);
		SetTextColor(hDC, MARKER_COLOR);
		sprintf(ts, "<< %20s >>",
			timstr(-(WFDB_Time)(tf*(LOWORD(lParam)/2048.))));
		x = 200;
		y = ytr(5.) - tm.tmExternalLeading;
		TextOut(hDC, x, y, ts, strlen(ts));               
		ReleaseDC(hWnd, hDC);
	    }
	    return (NULL);	/* do not redraw the entire window */
	  case SB_THUMBPOSITION: /* event occurs when "thumb" is dropped */
	    t0 = (WFDB_Time)(tf * (LOWORD(lParam)/2048.));
	    if (t0 >= tf && tf > 0L)
		t0 = tf - (WFDB_Time)(wwsec*sps);
	    break;
	  default:
	    return (NULL);
	}
	scrollpos = (int)(2048.*t0/tf);
	SetScrollPos(hWnd, SB_HORZ, scrollpos, TRUE);
	InvalidateRect(hWnd, NULL, TRUE);
	break;
	
      case WM_KEYDOWN:
	switch (wParam) {
	  case VK_HOME:         /* <Home> key */
	    SendMessage(hWnd, WM_HSCROLL, SB_TOP, 0L);
	    break;
	  case VK_END:          /* <End> key */
	    SendMessage(hWnd, WM_HSCROLL, SB_BOTTOM, 0L);
	    break;
	  case VK_LEFT:         /* <left arrow> */
	    SendMessage(hWnd, WM_HSCROLL, SB_LINEUP, 0L);
	    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -