#include <windows.h>
#include <shellapi.h> //DragQueryFile, DragFinish
#include <commdlg.h> //GetOpenFileName, GetSaveFileName
#ifdef _WIN32
# define SetViewportExt(a,b,c) SetViewportExtEx(a,b,c,NULL)
# define SetWindowExt(a,b,c) SetWindowExtEx(a,b,c,NULL)
#else
# include <time.h> //time, asctime, localtime
# include <stdarg.h> //va_list
#endif
#include <stdio.h> //fprintf...
#include <math.h> //fabs, sqrt, atof
#include <string.h> //memmove
#pragma hdrstop
#include "driver.h"
#include "dialog.h" //Verschiedene Dialoge
#include "a_input.h" //Dialog: Konfiguration des analogen Eingangs
#include "d_output.h" //Dialog: Konfiguration der digitalen Ausgänge
#include "sensokom.rh" //Definition aller Ressourcen (CM_xxxx-Konstanten)
#include "toolstat.h" //Buttonleiste und Statuszeile
#include <commctrl.h> //bei WIN32 System-Header zuerst finden lassen!
/*******************************
** Datei-Ein/Ausgabe (*.SES) **
*******************************/
typedef struct{
char x[32]; // Datum und Uhrzeit in ASCII - wer hat sich das ausgedacht??
float y;
int i,io,o;
}WERT, near*NPWERT;
// Zu speichernde/anzuzeigende Daten:
char MessartStr[64],EinheitStr[8];
NPWERT Werte;
int Messnumber, Messmax;
BOOL dirty;
static BOOL ReAllocWerte(int n) {
register NPWERT w=Werte;
if (n) {
register UINT bytes=n*sizeof(WERT);
w=w?(NPWERT)LocalReAlloc(w,bytes,LMEM_MOVEABLE|LMEM_ZEROINIT):
(NPWERT)LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,bytes);
if (!w) { // kann eigentlich nur beim Vergrößern passieren
MBox(MainWnd,0xA21,0);
return FALSE; // nichts ändern, Einlesen abbrechen lassen
}
}else{
if (w) w=(NPWERT)LocalFree(w);
}
Werte=w;
Messmax=n;
if (Messnumber>Messmax) Messnumber=Messmax;
return TRUE;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL FileOpen(LPCSTR fname,UINT unused) {
// lädt die Datei in die globale Datenstruktur
FILE *f;
char buf[80];
#if defined(__SMALL__) || defined(__MEDIUM__)
lstrcpy(buf,fname);
f=fopen(buf,"rt");
#else
f=fopen(fname,"rt");
#endif
if (!f) return FALSE;
ReAllocWerte(0); // alles freigeben
fgets(MessartStr,sizeof(MessartStr),f);
MessartStr[lstrlen(MessartStr)-1]=0; // \n abhacken
fgets(EinheitStr,sizeof(EinheitStr),f);
EinheitStr[lstrlen(EinheitStr)-1]=0;
while (fgets(buf,sizeof(buf)-1,f)) {
WERT wert;
if (sscanf(buf,"%31[^\t]%f%d%d%d",wert.x,&wert.y,&wert.i,&wert.io,&wert.o)
==5) {
if (Messnumber==Messmax && !ReAllocWerte(Messmax+50)) break;
Werte[Messnumber]=wert;
Messnumber++;
}
}
fclose(f);
ReAllocWerte(Messnumber); // verkleinern
return TRUE;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL FileSave(LPCSTR fname,UINT unused) {
FILE *f;
int i;
#if defined(__SMALL__) || defined(__MEDIUM__)
char buf[80];
lstrcpy(buf,fname);
f=fopen(buf,"wt");
#else
f=fopen(fname,"wt");
#endif
if (!f) return FALSE;
fprintf(f,"%s\n",MessartStr);
fprintf(f,"%s\n",EinheitStr);
for (i=0; i<Messnumber; i++) {
fprintf(f,"%s\t%f\t%i\t%i\t%i\n",
Werte[i].x,
Werte[i].y,
Werte[i].i,
Werte[i].io,
Werte[i].o);
}
if (fclose(f)) return FALSE;
return TRUE;
}
/******************************************
** Paint-Routinen zur Selbstdarstellung **
******************************************/
float Y_Max,Y_Min,Y_MB; // Minimum, Maximum, Differenz
float Y_am, Y_ls, Y_es; // Mittelwert,lin. Abweichung, Standardabweichung
BYTE KennlinienModus=TRUE, MinMaxModus=TRUE;
BYTE Nullinie=TRUE; BYTE Unendlich=TRUE;
BYTE IsRaster,IsMessung;
RECT RA={65,10,365,310}; // Analog-Display-Rechteck
int y3=320, y4=340, y5=360, y6=380;
int Digital(int x) {
return x?-15:-1; // bestimmt die Höhe der Digitalsignale
}
static void MaleKennlinie(HDC dc, int X_Current, int X_max) {
// Zeichnet die ganze Kennlinie
// X_Current=Anzahl der Messpunkte, X_max=Nummer Messpunkt rechts
int i;
if (X_max<2) return; //Notbremse
X_max--;
if (Y_MB!=0) {
HPEN pen=CreatePen(PS_SOLID,1,0xFF0000L); //blau
HPEN open=(HPEN)SelectObject(dc,pen);
if (!KennlinienModus) { // Messpunktmodus: senkrechte Linien
for (i=0; i<X_Current; i++) {
int x=iitrafo(i,0,X_max,RA.left,RA.right);
int y=fitrafo(Werte[i].y,Y_Min,Y_Max,RA.bottom,RA.top);
int y0=Limit(fitrafo(0,Y_Min,Y_Max,RA.bottom,RA.top),RA.top,RA.bottom);
Line(dc,x,y,x,y0);
}
}else{ // Kennlinienmodus
NPPOINT pt=(NPPOINT)LocalAlloc(LMEM_FIXED,X_Current*sizeof(POINT));
if (pt) {
NPPOINT pt_it=pt;
for (i=0; i<X_Current; i++) {
pt_it->x=iitrafo(i,0,X_max,RA.left,RA.right);
pt_it->y=fitrafo(Werte[i].y,Y_Min,Y_Max,RA.bottom,RA.top);
pt_it++;
}
SaveDC(dc);
IntersectClipRect(dc,RA.left,RA.top,RA.right+1,RA.bottom+1);
Polyline(dc,pt,X_Current);
RestoreDC(dc,-1);
LocalFree(pt);
}
}
SelectObject(dc,open);
DeleteObject(pen);
}//(Y_MB!=0)
//------------- Zeichnen des I-, IO- und O-Verlaufs ------------------------
if (X_Current) {
HPEN pen,open;
UINT bytes=X_Current*(2*sizeof(POINT));
NPPOINT i_pt =(NPPOINT)LocalAlloc(LMEM_FIXED,bytes);
NPPOINT io_pt=(NPPOINT)LocalAlloc(LMEM_FIXED,bytes);
NPPOINT o_pt =(NPPOINT)LocalAlloc(LMEM_FIXED,bytes);
if (i_pt && io_pt && o_pt) { // kein Chaos stiften, wenn =0
NPPOINT i_it =i_pt;
NPPOINT io_it=io_pt;
NPPOINT o_it =o_pt;
int i_pr=0, io_pr=0, o_pr=0; // Initialisierung nur für Warnings
X_Current--;
for (i=0; i<=X_Current; i++) {
int x=RA.left+MulDiv(RA.right-RA.left,i,X_max);
int y=Werte[i].i;
if (i==X_Current || i && y!=i_pr) { // bei Ende oder Flanke
i_it->x=x; i_it->y=y4+Digital(i_pr); i_it++;
}
if (!i || y!=i_pr) { // bei Anfang oder Flanke
i_it->x=x; i_it->y=y4+Digital(y); i_it++;
}
i_pr=y; // vorherigen Wert merken
y=Werte[i].io;
if (i==X_Current || i && y!=io_pr) { // bei Ende oder Flanke
io_it->x=x; io_it->y=y5+Digital(io_pr);io_it++;
}
if (!i || y!=io_pr) { // bei Anfang oder Flanke
io_it->x=x; io_it->y=y5+Digital(y); io_it++;
}
io_pr=y; // vorherigen Wert merken
y=Werte[i].o;
if (i==X_Current || i && y!=o_pr) { // bei Ende oder Flanke
o_it->x=x; o_it->y=y6+Digital(o_pr); o_it++;
}
if (!i || y!=o_pr) { // bei Anfang oder Flanke
o_it->x=x; o_it->y=y6+Digital(y); o_it++;
}
o_pr=y; // vorherigen Wert merken
}
pen=CreatePen(PS_SOLID,1,0x00FF00L); //grün
open=(HPEN)SelectObject(dc,pen);
Polyline(dc,i_pt,i_it-i_pt); // C++ dividiert die Differenz selbst!
Polyline(dc,io_pt,io_it-io_pt);
Polyline(dc,o_pt,o_it-o_pt);
SelectObject(dc,open);
DeleteObject(pen);
}
LocalFree(i_pt);
LocalFree(io_pt);
LocalFree(o_pt);
}
}
static void _cdecl MyDrawText(HDC dc, int x, int y, int w, int h, UINT f,
char *format, ...) {
RECT R;
char s[256];
SetRect(&R,x,y,x+w,y+h);
if (f&DT_RIGHT) {
SetTextAlign(dc,TA_RIGHT);
x+=w;
}
// DrawText(dc,s,,&R,f);
ExtTextOut(dc,x,y,ETO_OPAQUE,&R,s,
vsprintf(s,format,(va_list)(&format+1)),NULL);
if (f&DT_RIGHT) SetTextAlign(dc,0);
}
void ExpandMinMax(void) {
int i;
for (i=0; i<Messnumber; i++) {
if (Werte[i].y<Y_Min) Y_Min=Werte[i].y;
if (Werte[i].y>Y_Max) Y_Max=Werte[i].y;
}
Y_MB=Y_Max-Y_Min;
}
void CalcMinMax(void) {
//--- Ermittlung von Y_Min,Y_Max der Messwerte ---
if (MinMaxModus) {
Y_Min=1E38F; Y_Max=-1E38F;
if (Nullinie) Y_Min=Y_Max=0; // Nullinie erzwingen
ExpandMinMax();
}
Y_MB=Y_Max-Y_Min;
}
void CalcKennwerte(void) {
//--- Streuungen usw. berechnen ---
int i;
CalcMinMax();
Y_am=Y_ls=Y_es=0;
if (!Messnumber) return;
for (i=0; i<Messnumber; i++) Y_am+=Werte[i].y;
Y_am/=Messnumber;
for (i=0; i<Messnumber; i++) {
float y=Werte[i].y-Y_am;
Y_ls+=(float)fabs(y); // Fehler addieren
Y_es+=y*y; // Fehlerquadrate addieren
}
Y_ls/=Messnumber;
Y_es=Messnumber>1?(float)sqrt(Y_es/(Messnumber-1)):0;
} // Standardabweichung
void BuildKennlinie(HDC dci) {
// Veränderliche Größen (neu) zeichnen, auch dci=0 möglich
HDC dc=dci;
HFONT font,ofont;
if (!dci) {
RECT R;
HRGN rgn;
dc=GetDC(MainWnd);
CalcClientRect(&R); // Nicht in die Toolbar / Statuszeile malen!
rgn=CreateRectRgn(R.left,R.top,R.right,R.bottom);
SelectClipRgn(dc,rgn);
DeleteObject(rgn);
SetViewportOrgEx(dc,R.left,R.top,NULL);
font=CreateFont(-12,0,0,0,0,0,0,0,0,0,0,0,0,T("Arial"));
ofont=SelectObject(dc,font);
}
// Kennlinie wegen neuer Minima und Maxima neu skaliert zeichnen
if (dci || MinMaxModus) {
MyDrawText(dc,0,RA.top,RA.left-8,20,DT_RIGHT,"%.3f %s",Y_Max, EinheitStr);
MyDrawText(dc,0,RA.bottom-20,RA.left-8,20,DT_RIGHT,"%.3f %s",Y_Min, EinheitStr);
Rectangle(dc,RA.left-1,RA.top-1,RA.right+1,RA.bottom+1);
if (IsRaster) { // waagerechte Hilfslinien
HPEN pen=CreatePen(PS_DOT,0,0);
HPEN open=(HPEN)SelectObject(dc,pen);
int i;
for (i=1;i<=9;i++) {
Line(dc,RA.left,RA.bottom-i*30,RA.right,RA.bottom-i*30);
}
SelectObject(dc,open);
DeleteObject(pen);
}
//------------------------- Zeichnen der Abszisse (y=0) ---------------------
if (Y_Min<0 && Y_Max>0) { // Null-Linie (Y_MB ist <>0)
HPEN pen=CreatePen(PS_DASH,0,0);
HPEN open=(HPEN)SelectObject(dc,pen);
int y0=fitrafo(0,Y_Min,Y_Max,RA.bottom,RA.top);
Line(dc, RA.left,y0,RA.right,y0);
SelectObject(dc,open);
DeleteObject(pen);
}
}
//-------------------------- Zeichnen der Kennlinie ------------------------
MaleKennlinie(dc,Messnumber,Messmax);
MyDrawText(dc,RA.right+8, 30,180,20,0,"%s",MessartStr);
if (Messnumber) {
MyDrawText(dc,RA.right+8, 80,180,20,0,"%s",Werte[0].x); // Uhrzeit
MyDrawText(dc,RA.right+8,160,130,20,0,"%.3f %s",Y_am,EinheitStr);
MyDrawText(dc,RA.right+8,220,130,20,0,"%.3f %s",Y_ls,EinheitStr);
MyDrawText(dc,RA.right+8,280,130,20,0,"%.3f %s",Y_es,EinheitStr);
}
if (!dci) {
SelectObject(dc,ofont);
DeleteObject(font);
ReleaseDC(MainWnd,dc);
}
}
void OnPaint (HDC dc) {
// Paint-Routine für Fenster, Drucker und Druckvorschau.
HFONT font,ofont;
font=CreateFont(-12,0,0,0,0,0,0,0,0,0,0,0,0,T("Arial"));
ofont=SelectObject(dc,font);
MyDrawText(dc,RA.right+8, 10,130, 20,0,"Messart:");
MyDrawText(dc,RA.right+8, 60,130, 20,0,"Startzeit:");
// MyDrawText(dc,370, 70,80, 20,"Messwert:");
// MyDrawText(dc,370,100,80, 20,"Eingang:");
// MyDrawText(dc,370,120,80, 20,"E/A:");
// MyDrawText(dc,370,140,80, 20,"Ausgang:");
MyDrawText(dc,RA.right+8,140,130,40,0,"arithm. Mittelwert:");
MyDrawText(dc,RA.right+8,200,130,40,0,"lineare Streuung:");
MyDrawText(dc,RA.right+8,260,130,40,0,"empirische Streuung:");
MyDrawText(dc,0,320,RA.left-8,20,DT_RIGHT,"Eingang:");
MyDrawText(dc,0,340,RA.left-8,20,DT_RIGHT,"E/A:");
MyDrawText(dc,0,360,RA.left-8,20,DT_RIGHT,"Ausgang:");
Rectangle(dc,RA.left-1,y3,RA.right+1,y6+1);
BuildKennlinie(dc);
SelectObject(dc,ofont);
DeleteObject(font);
}
/****************************************
** Laden und Speichern (SENSOKOM.INI) **
****************************************/
BYTE CurrentAdresse=0;
char DdeServer[32]; // leer wenn lokal
BYTE HaveToolbar=TRUE;
BYTE HaveStatus=TRUE;
INTERVALL intervall={10,2}; // Vorgabe-Intervall beim Messung starten
void EscapeIfHaveBlanks(char*s) {
if (lstrchr(s,' ')) {
int l=lstrlen(s);
memmove(s+1,s,l);
s[0]=s[++l]='"';
s[++l]=0;
}
}
static void RegisterSES(void) {
// Endung .SES auf dieses Programm festnageln
TCHAR s[MAX_PATH];
// RegSetValue(HKEY_CLASSES_ROOT,T(".SES"),REG_SZ,"SENSOKOM-Daten",15);
GetModuleFileName(hInstance,s,elemof(s));
EscapeIfHaveBlanks(s);
lstrcat(s,T(" \"%1\""));
RegSetValue(HKEY_CLASSES_ROOT,T(".SES\\shell\\open\\command"),REG_SZ,
s,(lstrlen(s)+1)*sizeof(TCHAR));
}
static void MyQueryByte(LPCTSTR key, BYTE *val) {
*val=(BYTE)GetPrivateProfileInt(T("SK"),key,*val,StdProfile);
}
static void MyQueryInt(LPCTSTR key, int *val) {
*val=(int)GetPrivateProfileInt(T("SK"),key,*val,StdProfile);
}
static void LoadSetup(void) {
MyQueryByte(T("Adresse"),&CurrentAdresse);
GetPrivateProfileString(T("SK"),T("DdeServer"),T(""),DdeServer,sizeof(DdeServer),
StdProfile);
MyQueryByte(T("KennlinienModus"),&KennlinienModus);
MyQueryByte(T("MinMaxModus"),&MinMaxModus);
MyQueryByte(T("Nullinie"),&Nullinie);
MyQueryByte(T("Raster"),&IsRaster);
MyQueryByte(T("Unendlich"),&Unendlich);
MyQueryByte(T("Werkzeugleiste"),&HaveToolbar);
MyQueryByte(T("Statuszeile"),&HaveStatus);
MyQueryInt(T("Intervall.Anzahl") ,&intervall.count);
MyQueryInt(T("Intervall.Sekunden"),&intervall.elaps);
}
static void LoadDlgPos(LPCTSTR key, UINT idCommand, PPOINT pt) {
// lädt die Position modusloser Dialoge und stellt sie ggf. wieder her
TCHAR buf[32];
BOOL state;
GetPrivateProfileString(T("SK"),key,T(""),buf,elemof(buf),StdProfile);
if (sscanf(buf,"%d,%d,%d",&state,&pt->x,&pt->y)==3 && state)
PostMessage(MainWnd,WM_COMMAND,idCommand,1); // lParam = Kennung
}
static void LoadWinPos(void) {
WINDOWPLACEMENT wp;
TCHAR buf[32];
InitStruct(&wp,sizeof(wp));
GetWindowPlacement(MainWnd,&wp);
GetPrivateProfileString(T("SK"),T("WinPos"),T(""),buf,elemof(buf),StdProfile);
sscanf(buf,"%d,%d,%d,%d",
&wp.rcNormalPosition.left,
&wp.rcNormalPosition.top,
&wp.rcNormalPosition.right,
&wp.rcNormalPosition.bottom);
MoveRectIntoFullScreen(&wp.rcNormalPosition);
SetWindowPlacement(MainWnd,&wp);
LoadDlgPos(T("DisplayDlg"),CM_ANZEIGEN_DISPLAY,&DisplayDlgPos);
LoadDlgPos(T("TabelleDlg"),CM_ANZEIGEN_TABELLE,&TabelleDlgPos);
LoadDlgPos(T("SchaltplanDlg"),CM_ANZEIGEN_SCHALTUNG,&SchaltplanDlgPos);
}
static void MySetInt(LPCTSTR key, int val) {
TCHAR buf[8];
wsprintf(buf,T("%i"),val);
WritePrivateProfileString(T("SK"),key,buf,StdProfile);
}
static void SaveSetup(void) {
MySetInt(T("Adresse"),CurrentAdresse);
WritePrivateProfileString(T("SK"),T("DdeServer"),DdeServer,StdProfile);
MySetInt(T("KennlinienModus"),KennlinienModus);
MySetInt(T("MinMaxModus"),MinMaxModus);
MySetInt(T("Nullinie"),Nullinie);
MySetInt(T("Raster"),IsRaster);
MySetInt(T("Unendlich"),Unendlich);
MySetInt(T("Werkzeugleiste"),Toolbar?1:0);
MySetInt(T("Statuszeile"),Status?1:0);
MySetInt(T("Intervall.Anzahl") ,intervall.count);
MySetInt(T("Intervall.Sekunden"),intervall.elaps);
}
static void SaveDlgPos(LPCTSTR key, HWND Wnd, PPOINT pt) {
// Dialog-Position und ~Anzeigezustand speichern
TCHAR buf[32];
wsprintf(buf,"%d,%d,%d",Wnd?1:0,pt->x,pt->y);
WritePrivateProfileString(T("SK"),key,buf,StdProfile);
}
static void SaveWinPos(void) {
WINDOWPLACEMENT wp;
TCHAR buf[32];
InitStruct(&wp,sizeof(wp));
GetWindowPlacement(MainWnd,&wp);
wvsprintf(buf,"%d,%d,%d,%d",(va_list)&wp.rcNormalPosition);
WritePrivateProfileString(T("SK"),T("WinPos"),buf,StdProfile);
SaveDlgPos(T("DisplayDlg"),DisplayDlg,&DisplayDlgPos);
SaveDlgPos(T("TabelleDlg"),TabelleDlg,&TabelleDlgPos);
SaveDlgPos(T("SchaltplanDlg"),SchaltplanDlg,&SchaltplanDlgPos);
}
/***************************************
** Helferlein von globalen Variablen **
***************************************/
static BOOL ModulOK(void) {
if (!ISM_Info(CurrentAdresse,NULL,0)) {
MessageBox(0,"Modul nicht betriebsbereit!","Fehler", MB_ICONSTOP|MB_TASKMODAL);
return FALSE;
}
return TRUE;
}
static void MyCreateDialogParam(HWND *Wnd,UINT id, DLGPROC dlgproc,LPARAM lParam) {
if (*Wnd) SetActiveWindow(*Wnd);
else *Wnd=CreateDialogParam(gHInstance,MAKEINTRESOURCE(id),MainWnd,
dlgproc,lParam);
}
static void _cdecl SetStatusText(int n, const char *format, ...) {
char s[64];
vsprintf(s,format,(va_list)(&format+1));
SendMessage(Status,SB_SETTEXT,n,(LPARAM)(LPSTR)s);
}
static void ShowAdresse(void) {
SetStatusText(0,
CurrentAdresse?"aktuelle Adresse: %d":"keine Adresse gewählt!",
CurrentAdresse);
}
static void Invalidate(void) {
RECT R;
CalcClientRect(&R);
InvalidateRect(MainWnd,&R,TRUE);
}
TCHAR current[MAX_PATH]; // Momentaner Dateiname
static void SetWindowTitle(void) {
TCHAR buf[64];
if (IsMessung) {
if (Messnumber) {
wsprintf(buf,"%d Prozent vom Messvorgang",MulDiv(100,Messnumber,Messmax));
}else lstrcpy(buf,T("Messung gestartet"));
}else{
lstrcpy(buf,current[0]?GetFileNamePtr(current):"unbenannt");
lstrcat(buf,dirty?" *":" -");
lstrcat(buf," SENSOKOM");
}
SetWindowText(MainWnd,buf);
}
static void MyCheckMenuItem(UINT id, BOOL state) {
CheckMenuItem(MainMenu,id,state?MF_CHECKED:MF_UNCHECKED);
if (Toolbar) SendMessage(Toolbar,TB_CHECKBUTTON,id,MAKELONG(state,0));
}
static void MenuCheck(void) {
MyCheckMenuItem(CM_NULLINIE,Nullinie);
MyCheckMenuItem(CM_RASTER,IsRaster);
MyCheckMenuItem(CM_MESSUNG_UNENDLICH,Unendlich);
}
static void MyEnableMenuItem(UINT id, BOOL state) {
EnableMenuItem(MainMenu,id,state?MF_ENABLED:MF_GRAYED);
if (Toolbar) SendMessage(Toolbar,TB_ENABLEBUTTON,id,MAKELONG(state,0));
}
static void MenuEnable(void) {
// schaltet in Menü und Toolbar, wenn es etwas zu sehen gibt
int i;
static UINT IDs[]={CM_FILENEW,CM_FILESAVE,CM_FILESAVEAS,
CM_PRINTPREVIEW,CM_PRINT,
CM_BEARBEITEN_KENNLINIE,CM_BEARBEITEN_MESSPUNKTE,
CM_BEARBEITEN_DEFBEREICH,CM_BEARBEITEN_MINMAX};
for (i=0; i<elemof(IDs); i++) MyEnableMenuItem(IDs[i],Messnumber);
}
static void MenuEnableStartStop(void) {
MyEnableMenuItem(CM_MESSUNG_STARTEN,!IsMessung);
MyEnableMenuItem(CM_MESSUNG_STOPPEN, IsMessung);
}
void SetStatusParts(void) {
static int widths[]={130,320,420,450,475,-1};
if (!Status) return;
SendMessage(Status,SB_SETPARTS,elemof(widths),(LPARAM)(LPINT)widths);
ShowAdresse();
}
BOOL DirtyOK(void) { // Liefert TRUE wenn bereit zur Aktenvernichtung
if (dirty) switch (MBox(MainWnd,0xA20,MB_YESNOCANCEL)) {
case IDYES: SendMessage(MainWnd,WM_COMMAND,CM_FILESAVE,0); break;
case IDNO: dirty=FALSE; break; // Akte vernichten
}
return !dirty; // wenn <dirty> FALSE war oder jetzt ist
}
/***********************
** Messung ausführen **
***********************/
HCURSOR Cursor;
BOOL block_wm_mousemove;
void MessungStarten(void) {
if (DialogBoxParam(hInstance,MAKEINTRESOURCE(8000),MainWnd,IntervallDlgProc,
(LPARAM)&intervall)!=IDOK) return;
if (!MinMaxModus) {
Y_Min=-10; Y_Max=10;
if (PairInput(MainWnd,MAKEINTRESOURCE(0xB00), //"Eingabe des erwarteten Messbereiches"
NULL,NULL,&Y_Min,&Y_Max,TRUE,3)!=IDOK) return;
}
LoadString(hInstance,Get_Messart(CurrentAdresse)+2560,MessartStr,elemof(MessartStr));
Get_Einheit(CurrentAdresse,EinheitStr);
current[0]=0;
dirty=TRUE;
ReAllocWerte(intervall.count);
Messnumber=0;
IsMessung=TRUE;
MenuEnableStartStop();
SetWindowTitle();
Cursor=LoadCursor(gHInstance,MAKEINTRESOURCE(SENSOCURSOR_2));
SetCursor(Cursor);
ShowCursor(TRUE);
Invalidate();
SetTimer(MainWnd,2,intervall.elaps*1000,NULL);
}
void MessungStoppen(void) {
if (IsMessung) {
MenuEnable();
IsMessung=FALSE;
MenuEnableStartStop();
SetWindowTitle();
KillTimer(MainWnd,2);
ShowCursor(FALSE);
Cursor=LoadCursor(gHInstance,MAKEINTRESOURCE(SENSOCURSOR_1));
SetCursor(Cursor);
ReAllocWerte(Messnumber); // stutzen
Invalidate();
}
}
void MessungMachen (void) {
char AntwortString[32];
if (Messnumber<Messmax) { // eigentlich unsinnige Notbremse
block_wm_mousemove=TRUE;
if (ISM_Abfrage(CurrentAdresse,AntwortString,sizeof(AntwortString))) {
WERT wert;
#ifdef _WIN32
int i=GetDateFormatA(LOCALE_USER_DEFAULT,0,NULL,NULL,wert.x,sizeof(wert.x));
if (!wert.x[i-1]) i--; // diese Fkt. scheint das Null-Byte mitzuzählen!
wert.x[i]=' '; i++;
GetTimeFormatA(LOCALE_USER_DEFAULT,TIME_FORCE24HOURFORMAT,
NULL,NULL,wert.x+i,sizeof(wert.x)-i);
#else
time_t t;
time(&t);
lstrcpy(wert.x,asctime(localtime(&t)));
wert.x[24]='\0'; // \n entfernen!
#endif
wert.y= (float)atof(Get_Messwert(AntwortString));
wert.i= GetInp(AntwortString);
wert.io=Get_IO(AntwortString);
wert.o= GetOut(AntwortString);
Werte[Messnumber++]=wert;
SetWindowTitle();
CalcKennwerte();
BuildKennlinie(0);
}
block_wm_mousemove=FALSE;
}
if (Messnumber==2) MenuEnable(); // zwischendurch Schaltmöglichkeit
if (Messnumber==Messmax) {
MessageBeep(0); // Gong(?) für Ende der Messung
if (Unendlich) {
if (ReAllocWerte(Messmax+10)) {
Invalidate(); // Kurven (auch digital) verschieben sich
}else MessungStoppen();
}else MessungStoppen(); // hoffentlich optimiert der Compiler!
}
}
/****************************************************
** Hauptfenster-Prozedur (lange switch-Anweisung) **
****************************************************/
#define WM_OPENFILE (WM_USER+101) // wParam=FilterIndex, lParam=FileName
UINT WM_ComDlgHelp;
LRESULT CALLBACK FrameWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
LRESULT ret=HandleToolStat(Wnd,Msg,wParam,lParam);
switch (Msg) {
case WM_CREATE: {
BOOL InQuote;
TCHAR s[MAX_PATH], *dst;
LPTSTR src;
Cursor=LoadCursor(gHInstance,MAKEINTRESOURCE(SENSOCURSOR_1));
RegisterSES();
WM_ComDlgHelp=RegisterWindowMessage(HELPMSGSTRING);
LoadSetup();
Com_Init(*DdeServer?(LPCSTR)DdeServer:(LPCSTR)NULL,2,9600); /* DDE starten */
LoadWinPos();
if (HaveToolbar) ToggleToolbar(CM_TOOLBAR);
if (HaveStatus) ToggleStatus(CM_STATUS);
SetStatusParts();
SetMenuBitmaps();
MenuCheck();
src=((LPCREATESTRUCT)lParam)->lpCreateParams; // Kommandozeile
InQuote=FALSE;
dst=s;
for (;;src++) {
switch (*src) {
case '"': InQuote=!InQuote; break;
case 0 : InQuote=FALSE; nobreak;
case ' ': if (!InQuote) {
*dst=0; // terminieren
if (s!=dst) SendMessage(Wnd,WM_OPENFILE,0,(LPARAM)(LPTSTR)s);
dst=s; // Wenn mindestens ein Zeichen drin
break;
}nobreak;
default: *dst++=*src; // alle anderen Zeichen rausfummeln
}
if (!*src) break;
}
}break;
case WM_OPENFILE: {
if (!DirtyOK()) break;
MessungStoppen();
if (FileOpen((LPTSTR)lParam,wParam)) {
lstrcpyn(current,(LPTSTR)lParam,sizeof(current));
SetWindowTitle();
MenuEnable();
if (!MinMaxModus) ExpandMinMax();
CalcKennwerte();
Invalidate();
}else MBox(Wnd,0xA1F,0,lParam);
}break;
case WM_DROPFILES: {
TCHAR s[260];
DragQueryFile((HDROP)wParam,0,s,elemof(s));
DragFinish((HDROP)wParam);
SendMessage(Wnd,WM_OPENFILE,0,(LPARAM)(LPTSTR)s);
}break;
case WM_PAINT: {
PAINTSTRUCT PS;
RECT R;
CalcClientRect(&R);
BeginPaint(Wnd,&PS);
SetViewportOrgEx(PS.hdc,R.left,R.top,NULL);
OnPaint(PS.hdc);
EndPaint(Wnd,&PS);
}return 0;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 98:
case 99: return ret;
case CM_FILENEW: {
if (!DirtyOK()) break;
MessungStoppen();
ReAllocWerte(0); // Wertetabelle vernichten
current[0]=0; // Dateiname vernichten
MessartStr[0]=EinheitStr[0]=0;
MenuEnable(); // Menü umstellen
SetWindowTitle(); // Fenstertitel auf "unbenannt"
Invalidate(); // Client neu zeichnen
}break;
case CM_FILEOPEN: {
OPENFILENAME ofn;
TCHAR s[MAX_PATH];
InitStruct(&ofn,sizeof(ofn));
ofn.hwndOwner=Wnd;
ofn.lpstrFilter=T("Diagrammdateien\0*.ses\0");
ofn.lpstrFile=s;
ofn.nMaxFile=elemof(s);
s[0]=0;
ofn.Flags=OFN_LONGNAMES|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_SHOWHELP;
if (GetOpenFileName(&ofn))
SendMessage(Wnd,WM_OPENFILE,(WPARAM)ofn.nFilterIndex,(LPARAM)(LPSTR)s);
}break;
case CM_FILESAVE: if (current[0]) {
filesave:
MessungStoppen();
if (FileSave(current,0)) {
dirty=FALSE;
SetWindowTitle();
}else MBox(Wnd,0xA1F,0,(LPTSTR)current);
break;
}nobreak;
case CM_FILESAVEAS: {
OPENFILENAME ofn;
InitStruct(&ofn,sizeof(ofn));
ofn.hwndOwner=Wnd;
ofn.lpstrFilter=T("Diagrammdateien\0*.ses\0");
ofn.lpstrFile=current;
ofn.nMaxFile=elemof(current);
ofn.Flags=OFN_LONGNAMES|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_SHOWHELP;
if (GetSaveFileName(&ofn)) goto filesave;
}break;
case CM_PRINTPREVIEW:
case CM_PRINT:
case CM_PRINTERSETUP: {
static HGLOBAL ghDevMode;
static HGLOBAL ghDevNames;
PRINTDLG pd;
InitStruct(&pd,sizeof(pd));
pd.hwndOwner=Wnd;
pd.hDevMode=ghDevMode;
pd.hDevNames=ghDevNames;
pd.Flags=PD_ALLPAGES|PD_USEDEVMODECOPIES|PD_NOPAGENUMS|PD_NOSELECTION
|PD_RETURNIC|PD_SHOWHELP;
switch (LOWORD(wParam)) {
case CM_PRINTPREVIEW: pd.Flags|=PD_RETURNDEFAULT; break;
case CM_PRINT: pd.Flags|=PD_RETURNDC; break;
case CM_PRINTERSETUP: pd.Flags=PD_PRINTSETUP; nobreak;
}
if (LOWORD(wParam)==CM_PRINTPREVIEW && ghDevNames || PrintDlg(&pd)) {
POINT sheet;
ghDevMode=pd.hDevMode;
ghDevNames=pd.hDevNames;
if (LOWORD(wParam)==CM_PRINTERSETUP) break;
if (!pd.hDC) {
LPDEVNAMES dn=GlobalLock(ghDevNames);
if (dn) pd.hDC=CreateIC(
(LPTSTR)dn+dn->wDriverOffset,
(LPTSTR)dn+dn->wDeviceOffset,
(LPTSTR)dn+dn->wOutputOffset,
NULL);
GlobalUnlock(ghDevNames);
}
sheet.x=GetDeviceCaps(pd.hDC,HORZRES);
sheet.y=GetDeviceCaps(pd.hDC,VERTRES);
if (LOWORD(wParam)==CM_PRINT) {
DOCINFO di;
InitStruct(&di,sizeof(di));
di.lpszDocName=current;
if (pd.Flags&PD_PRINTTOFILE) di.lpszOutput="C:/TEMP/AUSDRUCK.PS";
StartDoc(pd.hDC,&di);
StartPage(pd.hDC);
SetMapMode(pd.hDC,MM_ISOTROPIC);
SetWindowExt(pd.hDC,550,550);
SetViewportExt(pd.hDC,sheet.x,sheet.y);
OnPaint(pd.hDC);
EndPage(pd.hDC);
EndDoc(pd.hDC);
}else MBox(Wnd,0xA1E,0,sheet.x,sheet.y); // Druckvorschau fehlt (X,Y)
DeleteDC(pd.hDC);
}
}break;
case CM_EXIT: {
SendMessage(Wnd,WM_CLOSE,0,0);
}break;
case CM_HELPINDEX: {
WinHelp(MainWnd,HelpFileName,HELP_INDEX,0);
}break;
case CM_HELPABOUT: {
DialogBox(hInstance,MAKEINTRESOURCE(CM_HELPABOUT),Wnd,AboutDlgProc);
}break;
case CM_KONFIGURATION_ADRESSENSELEKTION: {
int a=DialogBox(hInstance,MAKEINTRESOURCE(LOWORD(wParam)),
Wnd,SearchDlgProc);
if (a && Status) {
CurrentAdresse=(BYTE)a;
ShowAdresse();
}
}break;
case CM_KONFIGURATION_A_INPUT: {
if (!ModulOK()) return 0;
DialogBoxParam(hInstance,MAKEINTRESOURCE(LOWORD(wParam)),
Wnd,ParamDlgProc,CurrentAdresse);
}break;
case CM_KONFIGURATION_D_OUTPUT: {
if (!ModulOK()) return 0;
DialogBoxParam(hInstance,MAKEINTRESOURCE(LOWORD(wParam)),
Wnd,OutputDlgProc,CurrentAdresse);
}break;
case CM_KONFIGURATION_TRANSMITTER: {
if (!ModulOK()) return 0;
if (DialogBoxParam(hInstance,MAKEINTRESOURCE(LOWORD(wParam)),
Wnd,TransmitterDlgProc,CurrentAdresse)!=IDOK) return 0;
MBox(Wnd,0xA1C,MB_OK);
}break;
case CM_KONFIGURATION_SCHNITTSTELLE: {
DialogBoxParam(hInstance,MAKEINTRESOURCE(LOWORD(wParam)),
Wnd,SchnittstelleDlgProc,(LPARAM)DdeServer);
}break;
case CM_ANZEIGEN_DISPLAY: {
MyCreateDialogParam(&DisplayDlg,LOWORD(wParam),DisplayDlgProc,0);
SetTimer(Wnd,1,1000,NULL);
}break;
case CM_ANZEIGEN_TABELLE: {
MyCreateDialogParam(&TabelleDlg,LOWORD(wParam),TabelleDlgProc,CurrentAdresse);
SetTimer(Wnd,1,1000,NULL);
}break;
case CM_ANZEIGEN_SCHALTUNG: {
MyCreateDialogParam(&SchaltplanDlg,LOWORD(wParam),SchaltplanDlgProc,
Get_Messart(CurrentAdresse));
}break;
case CM_BEARBEITEN_MESSPUNKTE: {
KennlinienModus=FALSE;
Invalidate();
}break;
case CM_BEARBEITEN_KENNLINIE: {
KennlinienModus=TRUE;
Invalidate();
}break;
case CM_BEARBEITEN_DEFBEREICH: {
if (PairInput(Wnd,MAKEINTRESOURCE(0xB01),
//"Eingabe des darzustellenden Messbereiches",
NULL, NULL, &Y_Min, &Y_Max, TRUE, 3) ==IDOK) {
MinMaxModus=FALSE;
Invalidate();
}
}break;
case CM_BEARBEITEN_MINMAX: {
MinMaxModus=TRUE;
CalcMinMax();
Invalidate();
}break;
case CM_NULLINIE: {
Nullinie=(BYTE)!Nullinie;
MenuCheck();
Invalidate();
}break;
case CM_RASTER: {
IsRaster=(BYTE)!IsRaster;
MenuCheck();
Invalidate();
}break;
case CM_BEARBEITEN_COPY: {
SendMessage(Wnd,WM_COPY,0,0); // zu Standard-Windows-Nachricht umsetzen
}break;
case CM_TOOLBAR: {
ToggleToolbar(CM_TOOLBAR);
MenuEnable(); // Toolbar-Enables mitführen
MenuEnableStartStop();
MenuCheck();
}break;
case CM_STATUS: {
ToggleStatus(CM_STATUS);
SetStatusParts();
}break;
case CM_MESSUNG_STARTEN: {
if (!ModulOK()) break;
if (!DirtyOK()) break;
MessungStarten();
}break;
case CM_MESSUNG_UNENDLICH: {
Unendlich=(BYTE)!Unendlich;
MenuCheck();
}break;
case CM_MESSUNG_STOPPEN: {
MessungStoppen();
}break;
}break;
case WM_KEYDOWN: switch (wParam) {
case VK_ESCAPE: MessungStoppen(); break;
}break;
#ifdef _WIN32
case WM_NOTIFY: {
}return ret;
#endif
case WM_COPY: {
HDC hMeta;
RECT R;
#ifdef _WIN32
SetRect(&R,0,0,12000,10240);
hMeta=CreateEnhMetaFile(0,NULL,&R,T("Sensokom\0Kurve\0"));
SetWindowExtEx(hMeta,550,400,NULL);
OnPaint(hMeta);
OpenClipboard(Wnd);
EmptyClipboard();
SetClipboardData(CF_ENHMETAFILE,CloseEnhMetaFile(hMeta));
#else
HGLOBAL hMFP=GlobalAlloc(GMEM_SHARE,sizeof(METAFILEPICT));
LPMETAFILEPICT pMFP=(LPMETAFILEPICT)GlobalLock(hMFP);
SetRect(&R,0,0,550,400);
hMeta=CreateMetaFile(NULL);
SetWindowExt(hMeta,R.right,R.bottom);
OnPaint(hMeta);
pMFP->mm=MM_ANISOTROPIC;
pMFP->xExt=R.right;
pMFP->yExt=R.bottom;
pMFP->hMF=CloseMetaFile(hMeta);
GlobalUnlock(hMFP);
OpenClipboard(Wnd);
EmptyClipboard();
SetClipboardData(CF_METAFILEPICT,hMFP);
#endif
CloseClipboard();
}break;
case WM_TIMER: switch (wParam) {
case 1: {
char recv[32];
block_wm_mousemove=TRUE; // verhindert den unerklärlichen Effekt,
// dass bei aufgeklapptem Menü WM_MOUSEMOVE-Nachrichten vorbei kommen,
// mit dem stark störenden Effekt, dass der Mauspfeil zum Kreuz wird
if (ISM_Abfrage(CurrentAdresse,recv,sizeof(recv))) {
if (DisplayDlg) SendMessage(DisplayDlg,WM_USER,0,(LPARAM)(LPSTR)recv);
if (TabelleDlg) SendMessage(TabelleDlg,WM_USER,0,(LPARAM)(LPSTR)recv);
if (!DisplayDlg && !TabelleDlg) KillTimer(Wnd,1);
}
block_wm_mousemove=FALSE;
}break;
case 2: {
MessungMachen();
}break;
}break;
case WM_MOUSEMOVE: if (!block_wm_mousemove) {
SetCursor(Cursor);
if (Messnumber>=2
&& RA.left<=(int)LOWORD(lParam) && (int)LOWORD(lParam)<=RA.right
&& RA.top<=(int)HIWORD(lParam) && (int)HIWORD(lParam)<=y6 ) {
// Berechnung des X-Wertes aus den grafischen Koordinaten
int xw=MulDiv((int)LOWORD(lParam)-RA.left,Messmax-1,RA.right-RA.left);
// Anzeigen der Werte
SetStatusText(1,"%s",Werte[xw].x);
SetStatusText(2,"%.3f %s",Werte[xw].y,EinheitStr);
SetStatusText(3,"%d",Werte[xw].i);
SetStatusText(4,"%d",Werte[xw].io);
SetStatusText(5,"%d",Werte[xw].o);
}
}break;
case WM_QUERYENDSESSION:
case WM_CLOSE: {
if (!DirtyOK()) return FALSE; // kein DefWindowProc, kein Windows beenden
Cursor=LoadCursor(0,IDC_WAIT); SetCursor(Cursor);
Com_Init(NULL,0,0); /* abmelden und DDE beenden */
SaveWinPos();
SaveSetup();
}break;
case WM_DESTROY: {
WinHelp(Wnd,HelpFileName,HELP_QUIT,0);
DeleteMenuBitmaps();
PostQuitMessage(0);
}break;
default: if (Msg==WM_ComDlgHelp){
WinHelp(Wnd,HelpFileName,HELP_CONTEXT,100);
}
}
return DefWindowProc(Wnd,Msg,wParam,lParam);
}
/************************
** Mini-Hauptprogramm **
************************/
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,LPSTR cmdLine,int cmdShow) {
static WNDCLASS wc={CS_HREDRAW|CS_VREDRAW,FrameWndProc,0,0,0,0,0,
(HBRUSH)(COLOR_WINDOW+1),MAKEINTRESOURCE(SDI_MENU),T("SK")};
MSG Msg;
wc.hInstance=hInstance=gHInstance=hInst;
StdProfile=T("SENSOKOM.INI");
HelpFileName=T("SENSOKOM.HLP");
if (!hPrevInst) {
wc.hInstance=hInst;
wc.hIcon=LoadIcon(gHInstance,MAKEINTRESOURCE(IDI_SENSOKOMAPPLICATION));
RegisterClass(&wc);
}
AccTable=LoadAccelerators(gHInstance,MAKEINTRESOURCE(SDI_MENU));
CreateWindowEx(WS_EX_ACCEPTFILES|WS_EX_OVERLAPPEDWINDOW,T("SK"),T("SENSOKOM - Steuerprogramm"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
0,0,gHInstance,cmdLine);
ShowWindow(MainWnd,cmdShow);
while (GetMessage(&Msg,0,0,0)) {
if (AccTable && TranslateAccelerator(MainWnd,AccTable,&Msg)) continue;
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Detected encoding: ANSI (CP1252) | 4
|
|