/*
Ein Hilfsprogramm, um bei unbekanntem Format einer Binär-Messdaten-Datei
die eigentlichen Diagrammdaten auszulesen.
Wenn sich ein sinnvoller Kurvenzug ergibt, wurde der richtige
Angangs-Offset, End-Offset, Inkrement sowie Datentyp gefunden.
Anmerkung: Zumeist werden float-Daten gespeichert (4 Byte pro Wert),
manchmal double (8 Byte pro Wert), zumeist von Matlab.
Hier auch mal eine Demonstration, um ohne Laufzeitbibliothek
einen eigenen "std::vector" als variables Array nachzuahmen.
Nur die unbedingt benötigten Funktionen und ohne Bereichsüberlauftest.
*/
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0501 // WM_THEMECHANGED aktivieren
#include <windows.h>
#include <windowsx.h> // Makros
#include <commdlg.h> // Datei öffnen/speichern
#include <commctrl.h> // Listenfenster für die Zeitschritte
#include <shlwapi.h> // nützliche Funktionen
#include <shellapi.h> // HDROP, DragQueryFile()
#include <mmsystem.h>
#include <stdio.h>
#include <tchar.h>
#include "vector.h"
#define elemof(x) (sizeof(x)/sizeof((x)[0]))
#define T(x) TEXT(x)
#define nobreak
#ifdef _DEBUG
void _cdecl DebugPrintf(PCSTR s,...) {
char buf[256];
va_list va;
va_start(va,s);
_vsnprintf(buf,elemof(buf),s,va);
OutputDebugStringA(buf);
}
# define _debug(x) DebugPrintf x
#else
# define _debug(x)
#endif
HINSTANCE ghInstance;
HWND ghMainWnd;
HWND ghDlgWnd;
HWND DispInfoDlg;
TCHAR StdMBoxTitle[64];
/****************
* aus WUTILS.C *
****************/
//Win32-typische Strukturen mit DWORD-Ausrichtung initialisieren
void _fastcall InitStruct(LPVOID p, UINT len) {
LPUINT p2=(LPUINT)p; // sonst hat C++ Verdauungsstörungen
*p2=len; len/=sizeof(UINT); len--;
if (len) do *++p2=0; while (--len);
}
int vMBox(HWND Wnd, LPCTSTR Text, UINT Type, va_list va) {
TCHAR buf[256],buf2[256];
if (!((DWORD_PTR)Text>>16)) {
LoadString(ghInstance,(UINT)(DWORD_PTR)Text,buf2,elemof(buf2));
Text=buf2;
}
_vsntprintf(buf,elemof(buf),Text,va);
return MessageBox(Wnd,buf,StdMBoxTitle,Type);
}
int _cdecl MBox(HWND Wnd, LPCTSTR Text, UINT Type, ...) {
return vMBox(Wnd,Text,Type,(va_list)(&Type+1));
}
#define WM_OPENFILE (WM_USER+101) // wParam=FilterIndex, HIWORD=Multi-Flag,
// Diese Universalroutine müsste mal „kugelsicher“ und universell geschrieben werden…
// Einmal SDI, einmal MDI
void OnFileOpen(HWND Wnd) {
#define BUFSIZE 8192
OPENFILENAME ofn;
TCHAR sFilter[256];
LPTSTR sFileNames;
sFilter[LoadString(ghInstance,2,sFilter,elemof(sFilter)-1)+1]=0;
sFileNames=(LPTSTR)LocalAlloc(LPTR,BUFSIZE*sizeof(TCHAR));
InitStruct(&ofn,sizeof(ofn));
ofn.hwndOwner=Wnd;
ofn.lpstrFilter=sFilter;
ofn.lpstrFile=sFileNames;
ofn.nMaxFile=BUFSIZE;
ofn.Flags=OFN_ALLOWMULTISELECT|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
if (GetOpenFileName(&ofn)) {
UINT len;
// herausfinden, ob Single- oder Multi-Select
len=lstrlen(sFileNames);
if (sFileNames[len+1]) { // Multi-Select
LPTSTR d,s;
TCHAR FileName[MAX_PATH];
lstrcpyn(FileName,sFileNames,elemof(FileName)); // Pfad kopieren
d=PathAddBackslash(FileName);
s=sFileNames+ofn.nFileOffset;
for (UINT i=0; *s; s+=lstrlen(s)+1, i++) {
lstrcpyn(d,s,(int)(FileName+elemof(FileName)-d));
SendMessage(Wnd,WM_OPENFILE,i,(LPARAM)FileName);
}
}else SendMessage(Wnd,WM_OPENFILE,0,(LPARAM)sFileNames);
}
LocalFree(sFileNames);
#undef BUFSIZE
}
enum eTypeCode {i8,u8,i16,u16,i32,u32,i64,u64,f32,f64};
struct {
UINT a,e; // Anfang und Ende der Daten, in Bytes
UINT g; // Granularität (1 = Byte, 2 = WORD usw.)
eTypeCode t; // Interpretationsweise
} gDispInfo;
struct {
HANDLE f; // Datei-Handle
HANDLE m; // Mapping-Handle
LPVOID p; // Map-Zeiger
DWORD l; // Datei-Länge (in Bytes)
} gFile;
void SetDlgItemHex(HWND Wnd, UINT id, UINT val) {
TCHAR s[32];
_sntprintf(s,elemof(s),T("0x%X"),val);
if (id!=(UINT)-1) SetDlgItemText(Wnd,id,s); else SetWindowText(Wnd,s);
}
bool GetDlgItemHex(HWND Wnd, UINT id, UINT*val) {
TCHAR s[32];
if (id!=(UINT)-1) GetDlgItemText(Wnd,id,s,elemof(s)); else GetWindowText(Wnd,s,elemof(s));
return _stscanf(s,T("%i"),val)==1;
}
BOOL CALLBACK DispInfoDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_INITDIALOG: {
DispInfoDlg=Wnd;
SetDlgItemHex(Wnd,16,gDispInfo.a);
SetDlgItemHex(Wnd,17,gDispInfo.e);
HWND hCombo=GetDlgItem(Wnd,18);
ComboBox_ResetContent(hCombo);
TCHAR s[256],*p;
for (int i=1; i<=32; i<<=1) {
_sntprintf(s,elemof(s),T("%d"),i);
ComboBox_AddString(hCombo,s);
}
SetDlgItemInt(Wnd,18,gDispInfo.g,FALSE);
hCombo=GetDlgItem(Wnd,19);
ComboBox_ResetContent(hCombo);
s[LoadString(ghInstance,3,s,elemof(s)-1)+1]=0;
for(p=s;*p;p+=lstrlen(p)+1) ComboBox_AddString(hCombo,p);
ComboBox_SetCurSel(hCombo,gDispInfo.t);
}return TRUE;
case WM_ACTIVATE: ghDlgWnd=wParam?Wnd:0; break;
case WM_COMMAND: switch (wParam) {
case 1:
case 2: DestroyWindow(Wnd); break;
case MAKELONG(16,EN_CHANGE): {
GetDlgItemHex((HWND)lParam,-1,&gDispInfo.a);
InvalidateRect(ghMainWnd,NULL,TRUE);
}break;
case MAKELONG(17,EN_CHANGE): {
GetDlgItemHex((HWND)lParam,-1,&gDispInfo.e);
InvalidateRect(ghMainWnd,NULL,TRUE);
}break;
case MAKELONG(18,CBN_EDITUPDATE):
case MAKELONG(18,CBN_SELCHANGE): {
GetDlgItemHex((HWND)lParam,-1,&gDispInfo.g);
InvalidateRect(ghMainWnd,NULL,TRUE);
}break;
case MAKELONG(19,CBN_SELCHANGE): {
gDispInfo.t=(eTypeCode)ComboBox_GetCurSel((HWND)lParam);
InvalidateRect(ghMainWnd,NULL,TRUE);
}
}break;
case WM_DESTROY: DispInfoDlg=0; break;
}
return FALSE;
}
void HandleOpenFile(LPTSTR FileName) {
gFile.f=CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0);
if (gFile.f==INVALID_HANDLE_VALUE) return;
gFile.l=GetFileSize(gFile.f,NULL);
if (!gFile.l) return;
gFile.m=CreateFileMapping(gFile.f,NULL,PAGE_READONLY,0,0,NULL);
gFile.p=MapViewOfFile(gFile.m,FILE_MAP_READ,0,0,0);
gDispInfo.a=0;//0x7568;
gDispInfo.e=gFile.l;//0x9560;
gDispInfo.g=1;
gDispInfo.t=u8;
if (ghDlgWnd) PostMessage(ghDlgWnd,WM_INITDIALOG,0,0);
}
union PTYP{
void *v;
char *c;
unsigned char *b;
short *s;
unsigned short *us;
long *l;
unsigned long *ul;
__int64 *ll;
unsigned __int64 *ull;
float *f;
double *lf;
double getDouble(enum eTypeCode);
};
double PTYP::getDouble(enum eTypeCode tc) {
switch (tc) {
case i8: return *c;
case u8: return *b;
case i16: return *s;
case u16: return *us;
case i32: return *l;
case u32: return *ul;
case i64: return (double)*ll;
case u64: return (double)*ull;
case f32: return *f;
case f64: return *lf;
}
return 0;
}
#ifdef _M_IX86
__forceinline __int64 rndint64(double f) {
__int64 i;
_asm fld f
_asm fistp i
return i;
}
#endif
#define rndint(x) (int)rndint64(x)
extern "C" int _fltused;
int _fltused;
void OnPaint(HDC dc) {
RECT r;
GetClientRect(ghMainWnd,&r);
PTYP p;
POINT *pa;
int x;
double ymin,ymax;
if (!gDispInfo.g) return;
if (gDispInfo.a>=gDispInfo.e) return;
vector<POINT>a((gDispInfo.e-gDispInfo.a)/gDispInfo.g); // Anzahl Punkte
ymin=1E100;
ymax=-ymin;
for (p.c=(char*)gFile.p+gDispInfo.a,x=0; x<a.size(); p.c+=gDispInfo.g,x++) {
double y=p.getDouble(gDispInfo.t);
if (ymin>y) ymin=y;
if (ymax<y) ymax=y;
}
ymax-=ymin;
for (pa=a, p.c=(char*)gFile.p+gDispInfo.a, x=0; x<a.size(); p.c+=gDispInfo.g,x++) {
pa->x=MulDiv(x,r.right,a.size());
pa->y=rndint((p.getDouble(gDispInfo.t)-ymin)*r.bottom/ymax);
pa++;
}
Polyline(dc,a,a.size());
WCHAR s[32];
TextOutW(dc,0,0,s,_snwprintf(s,elemof(s),L"%G",ymax));
SetTextAlign(dc,TA_BOTTOM);
TextOutW(dc,0,r.bottom,s,_snwprintf(s,elemof(s),L"%G",ymin));
}
/********************
* Fenster-Prozedur *
********************/
LRESULT CALLBACK MainWndProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_CREATE: {
ghMainWnd=Wnd;
LPCREATESTRUCT cs=(LPCREATESTRUCT)lParam;
if (cs->lpCreateParams) { // Kommandozeile: zerpflücken
LPTSTR arg=PathGetArgs((LPTSTR)cs->lpCreateParams);
if (*arg) SendMessage(Wnd,WM_OPENFILE,0,(LPARAM)arg);
}
}break;
case WM_CLOSE: PostQuitMessage(0); break;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 2: SendMessage(Wnd,WM_CLOSE,0,0); break;
case 101: OnFileOpen(Wnd); break;
case 102: if (DispInfoDlg) SetActiveWindow(DispInfoDlg);
else CreateDialog(ghInstance,MAKEINTRESOURCE(102),Wnd,DispInfoDlgProc);
break;
}break;
case WM_PAINT: {
PAINTSTRUCT ps;
ps.hdc=BeginPaint(Wnd,&ps);
OnPaint(ps.hdc);
EndPaint(Wnd,&ps);
}return 0;
case WM_PRINT:
case WM_PRINTCLIENT: {
OnPaint((HDC)wParam);
}return 0;
case WM_OPENFILE: {
HandleOpenFile((LPTSTR)lParam);
InvalidateRect(Wnd,NULL,TRUE);
}break;
case WM_DROPFILES: {
UINT j=DragQueryFile((HDROP)wParam,(UINT)-1,NULL,0);
for (UINT i=0; i<j; i++) {
TCHAR s[MAX_PATH];
DragQueryFile((HDROP)wParam,i,s,elemof(s));
SendMessage(Wnd,WM_OPENFILE,i,(LPARAM)(LPTSTR)s);
}
DragFinish((HDROP)wParam);
}break;
}
return DefWindowProc(Wnd,Msg,wParam,lParam);
}
/******************************
* Hauptprogramm (lächerlich) *
******************************/
int _stdcall WinMainCRTStartup(void) {
ghInstance=GetModuleHandle(NULL);
WNDCLASSEX wc;
InitStruct(&wc,sizeof(wc));
wc.style=CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc=MainWndProc;
wc.hInstance=ghInstance;
wc.hCursor=LoadCursor(0,IDC_ARROW);
wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName=MAKEINTRESOURCE(100);
wc.lpszClassName=MAKEINTRESOURCE(100);
RegisterClassEx(&wc);
InitCommonControls();
ghMainWnd=CreateWindowEx(WS_EX_ACCEPTFILES,MAKEINTRESOURCE(100),T("bin2graf"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,0,
CW_USEDEFAULT,0,
0,0,ghInstance,GetCommandLine());
ShowWindow(ghMainWnd,SW_SHOWDEFAULT);
MSG Msg;
while (GetMessage(&Msg,0,0,0)) {
if (ghDlgWnd && IsDialogMessage(ghDlgWnd,&Msg)) continue;
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
ExitProcess((UINT)Msg.wParam);
}
Detected encoding: ANSI (CP1252) | 4
|
|