#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <windowsx.h>
#include <C:\programs\MSVC\w2k3sddk\inc\w2k\shlwapi.h>
#include <setupapi.h>
//#include <devguid.h>
#include <commctrl.h>
#include <stdlib.h>
#include <tchar.h>
#pragma intrinsic(memset)
#include "XYGraph.h"
#define T(x) TEXT(x)
#define elemof(x) (sizeof(x)/sizeof(*(x)))
#define nobreak
typedef unsigned char byte;
typedef unsigned short word;
#pragma warning(disable:4554) // Klammernsetzung
HINSTANCE ghInstance;
TCHAR MBoxTitle[64];
HWND ghMainWnd,ghTree,ghGraph,ghStatus;
UINT vMBox(int id,UINT typ,va_list va) {
TCHAR s[1024],t[1024];
LoadString(0,id,t,elemof(t));
wvnsprintf(s,elemof(s),t,va);
return MessageBox(ghMainWnd,s,MBoxTitle,typ);
}
UINT MBox(int id,UINT typ=MB_OK,...) {
va_list va;
va_start(va,typ);
return vMBox(id,typ,va);
}
struct CONFIG{
short winpos[4];
char showCmd;
byte ComNr; // /dev/cua0 aka COM1 upto /dev/cua255 aka COM256
void Load();
void Save();
}Config;
void CONFIG::Load() {
HKEY k1;
if (!RegOpenKeyEx(HKEY_CURRENT_USER,T("Software\\h#s"),0,KEY_READ,&k1)) {
HKEY k2;
if (!RegOpenKeyEx(k1,T("RezEdit"),0,KEY_READ,&k2)) {
DWORD len=sizeof Config;
if (!RegQueryValueEx(k2,T("Config"),0,0,(BYTE*)&Config,&len) && len==sizeof Config) {
WINDOWPLACEMENT wp;
wp.length=sizeof wp;
if (GetWindowPlacement(ghMainWnd,&wp)) {
for (int i=0; i<4; i++) (&wp.rcNormalPosition.left)[i]=Config.winpos[i];
//wp.showCmd=Config.showCmd;
SetWindowPlacement(ghMainWnd,&wp);
}
}
}
}
}
void CONFIG::Save() {
HKEY k1;
if (!RegCreateKeyEx(HKEY_CURRENT_USER,T("Software\\h#s"),0,0,0,KEY_WRITE,0,&k1,0)) {
TCHAR s[64];
int len=LoadString(0,0,s,elemof(s));
if (len) RegSetValueEx(k1,0,0,REG_SZ,(BYTE*)s,(len+1)*sizeof(TCHAR));
HKEY k2;
if (!RegCreateKeyEx(k1,T("RezEdit"),0,0,0,KEY_WRITE,0,&k2,0)) {
len=LoadString(0,1,s,elemof(s));
if (len) RegSetValueEx(k2,0,0,REG_SZ,(BYTE*)s,(len+1)*sizeof(TCHAR));
WINDOWPLACEMENT wp;
wp.length=sizeof wp;
if (GetWindowPlacement(ghMainWnd,&wp)) {
for (int i=0; i<4; i++) Config.winpos[i]=short((&wp.rcNormalPosition.left)[i]);
Config.showCmd=char(wp.showCmd);
RegSetValueEx(k2,T("Config"),0,REG_BINARY,(BYTE*)&Config,sizeof Config);
}
}
}
}
// Zum testweisen Öffnen
static HANDLE opencom(UINT comnr) {
TCHAR s[16];
wnsprintf(s,elemof(s),T("\\\\.\\COM%u"),comnr+1);
return CreateFile(s,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
}
static HMENU MenuWithComPorts() {
HMENU m=CreatePopupMenu();
// serielle Schnittstellen (neu) listen (bei jedem WM_DEVICECHANGE bspw. für USB)
HANDLE devs=SetupDiGetClassDevs(/*(LPGUID)&GUID_DEVCLASS_PORTS*/NULL,NULL,0,DIGCF_PRESENT);
if (devs!=INVALID_HANDLE_VALUE) {
SP_DEVINFO_DATA devInfo;
devInfo.cbSize=sizeof devInfo;
for (DWORD i=0; SetupDiEnumDeviceInfo(devs,i,&devInfo); i++) {
HKEY hKey;
TCHAR s[16]; // trotzdem ein Unicode-String
*s=0;
if ((hKey=SetupDiOpenDevRegKey(devs,&devInfo,DICS_FLAG_GLOBAL,0,DIREG_DEV,KEY_READ))
==INVALID_HANDLE_VALUE) continue;
DWORD len=sizeof(s);
RegQueryValueEx(hKey,T("PortName"),NULL,NULL,(LPBYTE)s,&len);
RegCloseKey(hKey);
if (*s=='C') { // Fehlschläge und LPTx ausfiltern
DWORD num=StrToInt(s+3)-1; // nullbasierte Nummer
UINT flags=MFT_RADIOCHECK;
if (num==Config.ComNr) flags|=MF_CHECKED;
HANDLE h=opencom(num);
if (h==INVALID_HANDLE_VALUE) flags|=MF_GRAYED; else CloseHandle(h);
AppendMenu(m,flags,0x100+num,s);
}
}
SetupDiDestroyDeviceInfoList(devs);
}
return m;
}
char Komma[]=",";
/* Aus convac.h */
struct ANALOG{
static struct scale_t{
int gain,offset;
char nk;
char unit[7];
}scale[21];
};
ANALOG::scale_t ANALOG::scale[21]={
// scale offset nk unit[7] gemessen 170314
/*0*/ {1550, 0, 1, "U/min"}, // A/D-Wert = -18 bei -109 U/min
/*1*/ {1000, 0, 2, "V"},
/*2*/ {1000, 0, 2, "V"},
/*3*/ {1000, 0, 2, "V"},
/*4*/ {1000, 0, 2, "V"},
/*5*/ {1000, 0, 2, "V"},
/*6*/ {1000, 0, 2, "V"},
/*7*/ {1000, 0, 2, "V"},
/*8*/ {1000, 0, 2, "V"},
/*9*/ {-2790, 0, 1, "U/min"}, // -109 U/min bei D/A-Wert = 100
/*10*/ {1000, 0, 2, "V"},
/*11*/ {1000, 0, 2, "V"},
/*12*/ {1000, 0, 2, "V"},
/*13*/ {1000, 0, 2, "V"},
/*14*/ {1000, 0, 2, "V"},
/*15*/ {1000, 0, 2, "V"},
/*16*/ {1000, 0, 2, "V"},
/*17*/ {1000, 0, 2, "V"},
/*18*/ {256, 0, 2, "Hz"},
/*19*/ {256, 0, 2, "Hz"},
/*20*/ {256, 0, 2, "Hz"}};
char sbuf[64];
static PTSTR floatstr(int m, int nk=0) {
char*p=0;
switch (m) {
case 0x7FFFFFFF: p="+Inf"; break;
case 0x80000000: p="NaN"; break;
case 0x80000001: p="-Inf"; break;
}
if (p) return p;
div_t q;
q.quot=abs(m);
p=sbuf;
do{
q=div(q.quot,10);
*p++=q.rem+'0';
if (!--nk) *p++=Komma[0];
}while(q.quot||nk>=0);
if (m<0) *p++='-';
*p=0;
return _strrev(sbuf);
}
#pragma pack(1)
struct N{
union{
byte b; // Ganzes Byte
struct{
byte c:6; // Anzahl Subknoten
byte rsv:1; // Ungenutztes Bit (zum Markieren)
byte f:1; // Collapse-Bit
};
};
};
struct BEFEHL{
byte operation;
byte index;
PTSTR print(char) const;
byte vlen() const {return operation&7;}
const byte*end() const {return (byte*)(this+1)+vlen();} // Datenende
const BEFEHL*fin() const {return (const BEFEHL*)end();}
int getv() const; // Datenwert lesen
char*printKanal(bool) const;
char*printVal(bool) const;
void fillDialog(char) const;
void drehzahl(int&) const;
};
struct SCHRIT{
word time;
N n;
const BEFEHL*be0() const {return (const BEFEHL*)(this+1);}
const BEFEHL*operator+(char j) const{const BEFEHL*p=be0();for(;j;--j)p=p->fin();return p;}
const BEFEHL&operator[](char j) const{return *operator+(j);}
const BEFEHL*end() const {return operator+(n.c);}
const SCHRIT*fin() const {return (const SCHRIT*)end();}
PTSTR print(char) const;
};
struct REZEPT{
N n;
const SCHRIT*st0() const {return (const SCHRIT*)(this+1);}
const SCHRIT*operator+(char j) const{const SCHRIT*p=st0();for(;j;--j)p=p->fin();return p;}
const SCHRIT&operator[](char j) const{return *operator+(j);}
const SCHRIT*end() const {return operator+(n.c);}
const REZEPT*fin() const {return (const REZEPT*)end();}
PTSTR print(char) const;
};
union{
byte space[1024];
struct{
byte config[8];
SCHRIT gs;
};
}eedata;
int fill; // aktueller Füllstand
#pragma pack()
char*BEFEHL::printKanal(bool dot) const{
if (vlen()||!dot) floatstr(index);
else{
char*s=sbuf; // oktal-artige Zahl:
*s++='0'+(index>>5); // Modulnummer (0..7)
*s++='.';
*s++='0'+(index>>3&3);// Bytenummer (0..3)
*s++='.';
*s++='0'+(index&7); // Bitnummer (0..7)
*s=0;
}
return sbuf;
}
PTSTR BEFEHL::printVal(bool withUnit) const{
int v=getv();
if (vlen()) {
const ANALOG::scale_t*k=ANALOG::scale+index;
v=MulDiv(v,k->gain,256)+k->offset;
floatstr(v,k->nk);
if (withUnit) {
char*p=sbuf+strlen(sbuf); // Ende der Zahl
*p++=' '; // mit Leerzeichen (außer bei °; kommt hier nicht vor)
p+=wsprintf(p,"%s",k->unit); // Einheit (editierbar im RAM!) anhängen
}
}else floatstr(v);
return sbuf;
}
int BEFEHL::getv() const{
byte len=vlen();
if (!len) return operation>>3&1; // Bit 3, keine Daten
len=4-len<<3;
return *(int*)(this+1)<<len>>len;
}
static TCHAR buf[256];
PTSTR BEFEHL::print(char) const{
TCHAR*p=buf;
p+=wsprintf(p,
operation&0x60?T("Wenn") // Eingaben
:vlen()||operation&8?T("Setze")
:T("Lösche"));
*p++=' ';
p+=wsprintf(p,vlen()?T("Wert"):T("Bit"));
*p++='[';
p+=wsprintf(p,printKanal(true));
*p++=' ';
*p++='=';
*p++=' ';
p+=LoadString(0,(vlen()?0x200:0x100)+index,p,128);
*p++=']';
*p++=' ';
p+=wsprintf(p,
operation&0x60?
vlen()?
operation&8?T("größer"):T("kleiner") // lesen analog
:T("gleich")
:T("auf"));
*p++=' ';
p+=wsprintf(p,printVal(true));
if (operation&0xE0) p+=wsprintf(p,T(" dann "));
if (operation&0x60) {
p+=wsprintf(p,
operation&0x60==0x20?T("weiter")
:operation&0x60==0x40?T("Start verhindern")
:T("Abbruch"));
if (operation&0x80) p+=wsprintf(p,T(" + "));
}
if (operation&0x80) {
p+=wsprintf(p,T("Log"));
}
*p=0;
return buf;
}
void BEFEHL::drehzahl(int&v) const{
if (!(operation&0x60)&&vlen()&&index==9)
v=MulDiv(getv(),ANALOG::scale[0].gain,256)+ANALOG::scale[0].offset;
}
PTSTR SCHRIT::print(char i) const{
wnsprintf(buf,elemof(buf),i?T("Schritt %d über %s s %d Befehl%s"):T("Sicherheit"),i,floatstr(time,2),n.c,n.c==1?"":"e");
return buf;
}
PTSTR REZEPT::print(char i) const{
wnsprintf(buf,elemof(buf),i<0?T("Globale Sicherheit"):T("Rezept %d: %d Schritt%s, ID=%d"),i+1,n.c-1,n.c==2?"":"e",st0()->time);
return buf;
}
/* Ende des Mikrocontroller-Programms */
void BEFEHL::fillDialog(char numb) const{
SetWindowLong(ghMainWnd,DWL_USER,(INT_PTR)this);
CheckRadioButton(ghMainWnd,66,67,operation&0x60?67:66); // Ausgeben/Prüfen
CheckRadioButton(ghMainWnd,64,65,vlen()?65:64); // digital/analog
HWND w=GetDlgItem(ghMainWnd,101);
ComboBox_ResetContent(w);
for (int i=0;i<256;i++) {
floatstr(i);
int l=strlen(sbuf);
if (LoadString(0,i+(vlen()?0x200:0x100),sbuf+l+2,elemof(sbuf)-l-2)) {
sbuf[l]=':';
sbuf[l+1]=' ';
}
int j;
if (i==index||sbuf[l]) {
j=ComboBox_AddString(w,sbuf);
ComboBox_SetItemData(w,j,i);
}
if (i==index) ComboBox_SetCurSel(w,j);
}
}
void fillHex(WORD addr,byte len) {
char*p=sbuf+wsprintf(sbuf,"%03X:",addr);
byte*q=eedata.space+addr;
do{
p+=wsprintf(p,"%02X",*q++);
}while(--len);
SetDlgItemText(ghMainWnd,110,sbuf);
}
void fillHex(DWORD lParam) {
WORD addr=LOWORD(lParam);
char level=HIBYTE(HIWORD(lParam));
switch (level) {
case 0: fillHex(addr,sizeof REZEPT); break;
case 1: fillHex(addr,sizeof SCHRIT); break;
case 2: fillHex(addr,sizeof BEFEHL+((BEFEHL*)&eedata.space[addr])->vlen()); break;
}
}
static void ShowFill() {
TCHAR s[256],t[256];
LoadString(0,4,t,elemof(t));
wnsprintf(s,elemof(s),t,fill,sizeof eedata,floatstr(MulDiv(fill,1000,sizeof eedata),1));
SendMessage(ghStatus,SB_SETTEXT,0,(LPARAM)s);
}
// Schnittstelle lesen/schreiben mit Overlapped und Timeout 200 ms (allgemein)
// Liefert Anzahl übertragener Bytes
static int ReadWrite(HANDLE h, void*p, int l, bool write=true, DWORD ms=200) {
DWORD dw=0;
OVERLAPPED o;
ZeroMemory(&o,sizeof o);
if (!(write?(BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD,LPOVERLAPPED))WriteFile:ReadFile)
(h,p,l,&dw,&o)
&& (GetLastError()!=ERROR_IO_PENDING
|| WaitForSingleObject(h,ms)
|| !GetOverlappedResult(h,&o,&dw,FALSE))) {
CancelIo(h);
}
return dw;
}
static bool LoadData(bool write=false) {
HANDLE hCom=opencom(Config.ComNr);
if (hCom==INVALID_HANDLE_VALUE) return false;
BYTE kdo=write?'K':'J';
int l=0;
if (ReadWrite(hCom,&kdo,1)==1) // Hintertür: EEPROM lesen/schreiben
l=ReadWrite(hCom,&eedata,sizeof eedata,write);
CloseHandle(hCom);
return l==sizeof eedata;
}
// TreeView-Statusbits aus N generieren
static DWORD tvstate(N n) {
DWORD ret=0;
if (!n.f) ret|=TVIS_EXPANDED;
if (n.rsv) ret|=TVIS_SELECTED;
return ret;
}
static void ShowData() {
TreeView_DeleteAllItems(ghTree);
TVINSERTSTRUCT tvi;
tvi.hInsertAfter=TVI_LAST;
tvi.item.mask=TVIF_TEXT|TVIF_STATE|TVIF_PARAM;
tvi.item.stateMask=TVIS_EXPANDED|TVIS_SELECTED;
union{ // Chamäleon-Zeiger
const void*v;
const byte*b;
const REZEPT*re;
const SCHRIT*st;
const BEFEHL*be;
// LPARAM lp;
}p;
p.st=&eedata.gs;
// Schleife über Rezepte, beginnend mit Globaler Sicherheit
char nre=0; // noch unbekannt
for (char ire=-1;ire<nre;ire++) {
tvi.item.state=ire?tvstate(p.re->n):0;
tvi.item.pszText=p.re->print(ire);
tvi.item.lParam=MAKELONG(p.b-eedata.space,MAKEWORD(ire,0)); // Listen-Zeiger
tvi.hParent=TVI_ROOT;
tvi.hParent=TreeView_InsertItem(ghTree,&tvi);
char nst=1;
if (ire>=0) {
nst=p.re->n.c;
p.st=p.re->st0();
}
int dz=0,t=0;
SendMessage(ghGraph,GM_ADDPLOT,0,0);
// Schleife über Schritte eines Rezepts
for (char ist=0;ist<nst;ist++) {
char nbe=p.st->n.c;
tvi.item.state=tvstate(p.st->n);
tvi.item.pszText=p.st->print(ist);
tvi.item.lParam=MAKELONG(p.b-eedata.space,MAKEWORD(ist,1));
HTREEITEM save=tvi.hParent;
tvi.hParent=TreeView_InsertItem(ghTree,&tvi);
if (ist) t+=p.st->time;
p.be=p.st->be0();
// Schleife über Befehle eines Schritts
for (byte ibe=0;ibe<nbe;ibe++) {
tvi.item.pszText=p.be->print(ibe);
tvi.item.lParam=MAKELONG(p.b-eedata.space,MAKEWORD(ibe,2));
TreeView_InsertItem(ghTree,&tvi);
p.be->drehzahl(dz);
p.v=p.be->end();
}
SendMessage(ghGraph,GM_ADDPOINT,t,dz);
tvi.hParent=save;
}
if (ire<0) nre=*p.b++; // jetzt erst kommt Anzahl Rezepte
}
fill=p.b-eedata.space;
ShowFill();
}
void onComListChange() {
MENUITEMINFO mii;
mii.cbSize=sizeof mii;
mii.fMask=MIIM_SUBMENU;
mii.hSubMenu=MenuWithComPorts();
SetMenuItemInfo(GetSubMenu(GetMenu(ghMainWnd),1),2,TRUE,&mii);
}
BOOL CALLBACK MainWndProc(HWND Wnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG: {
ghMainWnd=Wnd;
GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,Komma,elemof(Komma));
ghStatus=CreateStatusWindow(WS_VISIBLE|WS_CHILD|SBARS_SIZEGRIP,0,Wnd,2);
static const int widths[]={250,-1};
SendMessage(ghStatus,SB_SETPARTS,elemof(widths),(LPARAM)widths);
ghTree=GetDlgItem(Wnd,10);
ghGraph=GetDlgItem(Wnd,11);
ShowData();
SetFocus(ghTree);
}return TRUE;
case WM_NCCALCSIZE: {
}break;
case WM_SIZE: {
SendMessage(ghStatus,msg,wParam,lParam); // eigene Size-Prozedur
RECT r;
static const int info[]={1,0,1,2,0,0};
GetEffectiveClientRect(Wnd,&r,(int*)info);
r.right-=r.left; r.bottom-=r.top; // in Höhe und Breite wandeln
static int pw,ph; // vorherige Breite und Höhe
if (pw) {
int dw=r.right-pw; // Veränderung zu vorher
int dh=r.bottom-ph;
if (dw||dh) for (HWND w=GetWindow(Wnd,GW_CHILD);w;w=GetNextSibling(w)) {
RECT rc;
GetWindowRect(w,&rc);
rc.right-=rc.left; rc.bottom-=rc.top; // in Höhe und Breite wandeln
ScreenToClient(Wnd,(POINT*)&rc);
if (w==ghStatus); // bereits erledigt
else if (w==ghTree) SetWindowPos(w,0,0,0,rc.right+dw,rc.bottom+dh,SWP_NOMOVE|SWP_NOZORDER);
else if (w==ghGraph) SetWindowPos(w,0,rc.left+dw,rc.top,rc.right,rc.bottom+dh,SWP_NOZORDER);
else SetWindowPos(w,0,rc.left+dw,rc.top+dh,0,0,SWP_NOSIZE|SWP_NOZORDER);
}
}
pw=r.right;
ph=r.bottom;
}break;
case WM_CLOSE: Config.Save(); CloseWindow(Wnd); PostQuitMessage(0); break;
case WM_COMMAND: switch ((unsigned)wParam) {
case 0x11: // Datei-Dialoge
case 0x12: {
TCHAR filename[260];
*filename=0;
TCHAR filter[128];
filter[LoadString(0,2,filter,elemof(filter)-1)+1]=0;
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof ofn);
ofn.lStructSize=sizeof ofn;
ofn.hwndOwner=Wnd;
ofn.lpstrFile=filename;
ofn.nMaxFile=elemof(filename);
ofn.lpstrFilter=filter;
ofn.lpstrDefExt=T("rez");
if (wParam==0x11) {
ofn.Flags=OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
if (GetOpenFileName(&ofn)) {
HANDLE f=CreateFile(filename,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
if (f!=INVALID_HANDLE_VALUE) {
DWORD dw;
ReadFile(f,eedata.space,sizeof eedata,&dw,0);
CloseHandle(f);
ShowData();
if (dw<(unsigned)fill) MBox(5); // Daten korrupt
}
}
}else{
ofn.Flags=OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY;
if (GetSaveFileName(&ofn)) {
HANDLE f=CreateFile(filename,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
if (f!=INVALID_HANDLE_VALUE) {
DWORD dw;
WriteFile(f,eedata.space,fill,&dw,0);
CloseHandle(f);
}
}
}
}break;
case 0x13: SendMessage(Wnd,WM_CLOSE,0,0); break;
case 0x21: if (LoadData()) ShowData(); else MBox(3,MB_OK,GetLastError()); break;
case 0x22: LoadData(true); break;
}
if (0x100<=wParam && wParam<0x200) {
MENUITEMINFO mii;
mii.cbSize=sizeof mii;
mii.fMask=MIIM_STATE;
mii.fState=0;
SetMenuItemInfo(GetMenu(Wnd),0x100+Config.ComNr,FALSE,&mii);
Config.ComNr=LOBYTE(wParam);
mii.fState=MFS_CHECKED;
SetMenuItemInfo(GetMenu(Wnd),wParam,FALSE,&mii);
}break;
case WM_NOTIFY: switch ((unsigned)wParam) {
case 10: NMHDR*nm=(NMHDR*)lParam; switch (nm->code) {
case TVN_SELCHANGED: {
NMTREEVIEW*ptv=(NMTREEVIEW*)lParam;
fillHex(ptv->itemNew.lParam);
char level=HIBYTE(HIWORD(ptv->itemNew.lParam));
char numb =LOBYTE(HIWORD(ptv->itemNew.lParam));
switch (level) {
case 2: ((BEFEHL*)(eedata.space+LOWORD(ptv->itemNew.lParam)))->fillDialog(numb); break;
}
}break;
case NM_RCLICK: {
TVHITTESTINFO hti;
GetCursorPos(&hti.pt);
ScreenToClient(nm->hwndFrom,&hti.pt);
HTREEITEM htvi=TreeView_HitTest(nm->hwndFrom,&hti);
if (htvi) {
TVITEM tvi;
tvi.mask=TVIF_SELECTEDIMAGE|TVIF_PARAM;
tvi.hItem=htvi;
if (TreeView_GetItem(nm->hwndFrom,&tvi)) {
/*
HTREEITEM h=TreeView_GetDropHilight();
if (h) { //TreeView_SelectItem(nm->hwndFrom,h);
*/
HMENU m=CreatePopupMenu();
char level=HIBYTE(HIWORD(tvi.lParam));
char numb =LOBYTE(HIWORD(tvi.lParam));
if (level==2) {
AppendMenu(m,0,0x62,"Kanal ändern");
AppendMenu(m,0,0x63,"Aktion festlegen");
}else{
AppendMenu(m,0,0x64,"nach oben verschieben");
AppendMenu(m,0,0x65,"nach unten verschieben");
AppendMenu(m,0,0x66,"duplizieren");
}
PTSTR p=0;
switch (level) {
case 0: if (level>=0) p="ID ändern"; break;
case 1: if (level>0) p="Zeit ändern"; break;
case 2: p="Wert ändern"; break;
}
if (p) AppendMenu(m,0,0x61,p);
AppendMenu(m,0,0x67,"Neu");
if (p) AppendMenu(m,0,0x68,"Löschen");
ClientToScreen(nm->hwndFrom,&hti.pt);
TrackPopupMenu(m,TPM_RIGHTBUTTON|TPM_RETURNCMD,hti.pt.x,hti.pt.y,0,Wnd,0);
MBox(6);
}
}
}break;
}break;
}break;
case WM_DEVICECHANGE: SetTimer(Wnd,1,1500,NULL); break;
case WM_TIMER: switch (wParam) {
case 1: KillTimer(Wnd,wParam); onComListChange(); break;
}break;
case WM_ENDSESSION: if (wParam) Config.Save(); break;
}
return FALSE;
}
void WinMainCRTStartup() {
ghInstance=GetModuleHandle(0);
INITCOMMONCONTROLSEX icc={sizeof icc,ICC_WIN95_CLASSES|ICC_DATE_CLASSES|ICC_USEREX_CLASSES|ICC_COOL_CLASSES};
InitCommonControlsEx(&icc);
WNDCLASS wc={
CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
DefDlgProc,
0,DLGWINDOWEXTRA,0,
LoadIcon(ghInstance,MAKEINTRESOURCE(1)),
LoadCursor(0,IDC_ARROW),
0,
0,
MAKEINTRESOURCE(1),
};
RegisterClass(&wc);
wc.lpfnWndProc=XYGraph::WndProc;
wc.cbWndExtra=sizeof(XYGraph*);
wc.hIcon=0;
wc.lpszClassName="XYGraph";
RegisterClass(&wc);
LoadString(0,1,MBoxTitle,elemof(MBoxTitle));
ghMainWnd=CreateDialog(0,MAKEINTRESOURCE(1),0,MainWndProc);
Config.Load();
onComListChange();
ShowWindow(ghMainWnd,Config.showCmd?Config.showCmd:SW_SHOWDEFAULT);
MSG Msg;
while (GetMessage(&Msg,0,0,0)) {
if (IsDialogMessage(ghMainWnd,&Msg)) continue;
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
ExitProcess(Msg.wParam);
// return Msg.wParam;
}
extern"C" int _fltused;
int _fltused;
Detected encoding: UTF-8 | 0
|