File: DIFRKMTY\D_EXTERN.CPP
1 //##############################################################################
2 // //
3 // D_EXTERN.CPP //
4 // //
5 // Subsystem: Diffraktometrie/ Reflektometrie //
6 // DIE MDI-Fensterbasisklasse //
7 // Benutzung durch andere Subsysteme erforderlich: NEIN //
8 // //
9 //##############################################################################
10 //! Kommentierung und Aenderungen B. Buss, 2000/2001, HUB IfI
11
12 #include <direct.h>
13
14 #include "internls\evrythng.h" // GermanVersion
15 #include "winresrc\rc_def.h" // Ressourcen-IDs
16 #pragma hdrstop
17
18 #include "difrkmty\d_extern.h" // SCHNITTSTELLE für diese Datei
19 #include "motrstrg\motrstrg.h" // für Motor-C-Interface
20
21 //--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--//--||--\\--||--
22
23 //! Kurvendatenbasis
24 __declspec(dllimport) LPDataBase lpDBase;
25
26 //#############################################################################
27 // globale Typen und Konstanten
28 //#############################################################################
29
30 //! Anzahl der max. unterschiedlichen Schrittweiten (dyn. Schrittweite)
31 const int MaxScaleCount= 10;
32
33 const UINT tiles_x_achse= 5;
34 const UINT tiles_y_achse= 5;
35
36 const UINT Mindxpos= 200;
37 const UINT Maxdxpos= 700;
38 const UINT Mindypos= 200;
39 const UINT Maxdypos= 700;
40
41 const UINT XBNorm= 85;
42 const UINT YBNorm= 62;
43
44 //#############################################################################
45 // sprachspezifische Konstanten
46 //#############################################################################
47
48 #ifdef GermanVersion
49 static const char szMsgLine600[]= "Scanachse ???";
50 static const char szMsgLine601[]= "ausserhalb des Bereichs";
51 static const char szMsgLine604[]= "Vergleichs-Scan speichern...";
52 static const char szMsgLine605[]= "Vergleichs-Scan (*.bk)|*.bk||";
53 static const char szMsgLine606[]= "[Header]\nVergleichs-Scan \n";
54 static const char szMsgLine607[]= "Linie von (%.*f, %.*f) bis (%.*f, %.*f)";
55 static const char szMsgLine608[]= "Theta:%.*f (D:%.3f) Omega:%.*f (D:%.3f) Int.:%.*f Zeile:%d Spalte:%d";
56 static const char szMsgLine609[]= "X:%.*f Y:%.*f Theta:%.3f Omega:%.3f Int.:%.*f Zeile:%d Spalte:%d";
57 static const char strMessage14[]= "Datei wurde bereits gespeichert !";
58
59 static const char szIntensLi[]= "Intensitäten\nlinear skaliert";
60 static const char szIntensLiEZ[]= "linear skaliert";
61 static const char szIntensLo[]= "Intensitäten\nlog10 skaliert";
62 static const char szIntensLoEZ[]= "log10 skaliert";
63 #else
64 static const char szMsgLine600[]= "Scanaxis ???";
65 static const char szMsgLine601[]= "out of Range";
66 static const char szMsgLine604[]= "Save Comparison-Scan...";
67 static const char szMsgLine605[]= "Comparison-Scan (*.bk)|*.bk||";
68 static const char szMsgLine606[]= "[Header]\nComparison-Scan \n";
69 static const char szMsgLine607[]= "Line from (%.*f, %.*f) to (%.*f, %.*f)";
70 static const char szMsgLine608[]= "Theta:%.*f (D:%.3f) Omega:%.*f (D:%.3f) Int.:%.*f Row:%d Column:%d";
71 static const char szMsgLine609[]= "X:%.*f Y:%.*f Theta:%.3f Omega:%.3f Int.:%.*f Row:%d Column:%d";
72 static const char strMessage14[]= "File was already saved !";
73
74 static const char szIntensLi[]= "Intensities\nlinear scaling";
75 static const char szIntensLiEZ[]= "linear scaling";
76 static const char szIntensLo[]= "Intensities\nlog10 scaling";
77 static const char szIntensLoEZ[]= "log10 scaling"; 78 #endif
79
80 //##############################################################################
81 // TPlotWindow
82 //##############################################################################
83
84 //! Konstruktor TPlotWindow
85 TPlotWindow::TPlotWindow(HINSTANCE aInstance) : TFileWindow(aInstance), BSource(0), MainCurve(0), SecondCurve(0), hFont(0), DragDC(0)
86 {
87 m_Dotted= FALSE;
88 m_HasFilter= FALSE;
89 m_FilterStrength= 0.0;
90 bEnablePaint= FALSE; // siehe EnablePaint() und DisablePaint()
91 WindowType= wtUnknown;
92 bMeasurementActive= FALSE;
93 bSecondaryCoor= FALSE;
94
95 //! durch einen Aufruf von set_new_handler(0) wird das traditionelle
96 //! new-Verhalten wiederhergestellt, bei dem keine Exception ausgeloest wird
97 set_new_handler(0);
98 //! xST/yST/zST darin als TScaleType (comhead.h) def.
99 LowerBound= (float)1e-1; //! gibt beim ersten Aufruf MinIntensitaet vor
100 UpperBound= (float)1e5; //! gibt beim ersten Aufruf MaxIntensitaet vor
101
102 eOutputType= otCurve;
103
104 CoorSys.xMin= 0.01;
105 CoorSys.xMax= 100.0;
106 CoorSys.xScal= sLinear;
107 CoorSys.yMax= UpperBound;
108 CoorSys.yMin= LowerBound;
109 CoorSys.yScal= sLogarithmic;
110 CoorSys.zMax= UpperBound;
111 CoorSys.zMin= LowerBound;
112 CoorSys.zScal= sLinear;
113 //! CoorSys wird in AltCoorSys gesichert
114 AltCoorSys= CoorSys;
115 bAltCoorSystem= FALSE;
116
117 bXY_Scaling= FALSE;
118 bButtonDown= FALSE;
119
120 //! Screen - Typ TScreen (m_data.h)
121 Screen.x0= 0;
122 Screen.x1= stdx - 1;
123 Screen.dx= stdx;
124 Screen.y0= 0;
125 Screen.y1= stdy - 1;
126 Screen.dy= stdy;
127 //! SecondCurve - Typ TCurve (m_curve.h)
128 SecondCurve= (TCurve *) new TCurve;
129
130 //! Font - Def. in windows.h
131 LOGFONT lf;
132 // LogFont spezifizieren...
133 memset(&lf, 0, sizeof(LOGFONT));
134 lf.lfHeight= -13;
135 lf.lfWidth= 0; // wird automatisch entsprechend der Hoehe gesetzt
136 lf.lfWeight= 400;
137 lf.lfUnderline= FALSE;
138 lstrcpy(lf.lfFaceName, "Times New Roman");
139 //! the CreateFontIndirect function creates a logical font that has
140 //! the characteristics specified in the specified structure
141 hFont= CreateFontIndirect(&lf);
142
143 HCURSOR hOldCursor= SetDefaultCursor( IDC_WAIT );
144 switch ( eOutputType ) { // notify type TOutputType
145 case otReciprokeLatticeBitmap:
146 case otMatrixBitmap:
147 new TBitmapSource(this); // registriert sich selbst für dieses Fenster
148 BSource->FormatDBaseToBitmapSource();
149 break;
150
151 default:
152 //! setze neue Koordinatensystembereiche
153 SetRanges();
154 }
155 SetCursor(hOldCursor); // restore cursor before waiting cursor
156
157 //! setze Bool-Variable bEnablePaint auf TRUE (m_data.h)
158 EnablePaint();
159 //! noch keine alten Daten geladen...
160 SetLoadFormat(ffUnknown);
161 strcpy(abzisse, szMsgLine600);
162
163 VisualDB.bPsd=FALSE; VisualDB.dThetaWindow= VisualDB.dMoveRelation= VisualDB.dOmegaMin= VisualDB.dOmegaMax= VisualDB.dThetaMinFirst= VisualDB.dThetaMaxFirst= VisualDB.dThetaMinLast= VisualDB.dThetaMaxLast= 0; VisualDB.fAngleRange= VisualDB.fAngleStep= 0;
164 eLoadFormat= ffUnknown;
165 xo= yo= 0;
166
167 // Motorkoordinaten nur bei AreaScan umrechnen
168 m_MotorUnit= utNone;
169 m_DetectorUnit= utNone;
170
171 // ehemalig extern-Verweise aus D_INTERN.CPP
172 tilesx= tiles_x_achse;
173 tilesy= tiles_y_achse;
174 scrolldyposmin= Mindypos;
175 scrolldyposmax= Maxdypos;
176 scrolldxposmin= Mindxpos;
177 scrolldxposmax= Maxdxpos;
178 xBorder= XBNorm;
179 yBorder= YBNorm;
180 RLdx= 400;
181 RLdy= 400;
182 bIncreasePP= FALSE;
183 MinIntensitaet= (float)1e-5;
184 MaxIntensitaet= (float)1e10;
185 mPoint1.x= mPoint1.y= mPoint2.x= mPoint2.y= 0; //! zum Aufzeichnen der Mausbewegungen beim Ziehen einer Linie mit der Maus
186 DataaquisitionActive= false;
187 };
188 //*****************************************************************************
189
190 //! Destruktor TPlotWindow
191 TPlotWindow::~TPlotWindow()
192 {
193 //! loesche SecondCurve - Typ TCurve (m_curve.h)
194 _FREEOBJ(SecondCurve);
195 _FREEOBJ(BSource);
196 if ( hFont ) {
197 DeleteObject(hFont);
198 hFont= 0;
199 }
200 };
201 //*****************************************************************************
202
203 BOOL TPlotWindow::New(void)
204 {
205 //! wenn ReciprokeLatticeBitmap oder MatrixBitmap dann generiere
206 //! gleich auch neue BSource - Typ TBitmapSource (m_data.h)
207 if ( eOutputType==otReciprokeLatticeBitmap || eOutputType==otMatrixBitmap )
208 BSource->New();
209
210 bMeasurementActive= FALSE;
211 return TFileWindow::New();
212 }
213 //*****************************************************************************
214
215 //! berechnet neue Groesse fuer Ausgabefenster, wenn mit Mouse geaendert
216 //! keine Groessenanpassung mehr vorgesehen...
217 /* Fehler 12
218 void TPlotWindow::Size(HWND hWnd,WPARAM,LPARAM)
219 //! berechne Groeße des Screens
220 {
221 //! the GetClientRect function retrieves the coordinates
222 //! of a window's client area
223 //! hWnd - handle of window; &WndRect - address of Rect structure for
224 //! client coordinates
225 GetClientRect(hWnd,&WndRect);
226 //! nicht hBitmap (Bitmap-windows.h) und
227 //! ReciprokeLatticeBitmap oder MatrixBitmap
228 if(!::hBitmap && (eOutputType <= MatrixBitmap))
229 {
230 //! berechne Groeße des Screens und setze Struct-Variablen
231 //! woher kommen ominoese Multiplikatoren fuer dx und dy ???
232 Screen.dx= (WndRect.right - WndRect.left) - xBorder;
233 Screen.x0= 0;
234 Screen.x1= Screen.dx;
235 Screen.dx*= 0.8;
236 Screen.dy= (WndRect.bottom - WndRect.top) - yBorder;
237 Screen.y0= 0;
238 Screen.y1= Screen.dy;
239 Screen.dy*= 0.9;
240 }
241 };
242 //******************************************************************************/
243
244 //! setze neue Koordinatensystembereiche
245 void TPlotWindow::SetRanges()
246 {
247 //! nur RecipokeLatticeBitmap und MatrixBitmap haben x,y,z Koordinatensystem
248 if ( eOutputType==otReciprokeLatticeBitmap || eOutputType==otMatrixBitmap )
249 {
250 CoorSys.xMin= 0.01;
251 CoorSys.xMax= 100.0;
252 CoorSys.yMin= 0.01;
253 CoorSys.yMax= 100.0;
254 CoorSys.zMax= UpperBound;
255 CoorSys.zMin= LowerBound;
256 } else {
257 /*Kullmann, Reinecker: ATOS-Testfall MS.2 Fehlerbehebung
258 CoorSys.xMin= 0.01;
259 CoorSys.xMax= 100.0;*/
260 CoorSys.yMax= UpperBound;
261 CoorSys.yMin= LowerBound;
262 }
263 };
264 //*****************************************************************************
265
266 //! behandelt Kommando: linke Maustaste wurde gedrueckt
267 //! gibt x und y Werte in der untersten Statuszeile aus, wenn linke
268 //! Maustaste kurzzeitig gedrueckt, in einem Koord.system
269 void TPlotWindow::OnLButtonDown(WPARAM, LPARAM lParam)
270 {
271 char buf[MaxString];
272 int nk1, nk2, nk3;
273 TCoorSystem *pCoorSys;
274
275 LPCurve Scan;
276 LPCurve ScanReport;
277 float x, y, z, offset, temp_xo, ODelta, TDelta;
278 double Omega, Theta;
279 int row, column;
280
281 bButtonDown= TRUE;
282 //! the GetDC function retrieves a handle of a display device context (DC)
283 //! for the client area of the specified window
284 //! DragDC - Typ HDC (m_data.h) - Handle auf ein DC (dc.h)
285 DragDC= GetDC( GetHandle() );
286 //! setzt den Mausfang auf das aktuelle Fenster
287 SetCapture(GetHandle());
288 switch (eOutputType)
289 {
290 case otReciprokeLatticeBitmap:
291 case otMatrixBitmap:
292 pCoorSys= &AltCoorSys;
293 break;
294
295 default:
296 pCoorSys= &CoorSys;
297 }
298
299 /*//! switch Anweisung folgt dem, wohin, mit der Maus geklickt wurde
300 int xi, yi;
301 //! bzw welche Optionen an waren...
302 switch (eOutputType)
303 {
304 case otReciprokeLatticeBitmap:
305 case otMatrixBitmap:
306 xi= LOWORD(lParam) - xBorder;
307 break;
308
309 default:
310 xi= LOWORD(lParam) - xBorder;
311 }
312 xo= ((float)xi * pCoorSys->xSF) + pCoorSys->xMin;
313
314
315 switch (eOutputType)
316 {
317 case otReciprokeLatticeBitmap:
318 case otMatrixBitmap:
319 yi= Screen.y1 - HIWORD(lParam) - yBorder;
320 break;
321
322 default:
323 yi= Screen.y1 - HIWORD(lParam);
324 }
325 switch (pCoorSys->yScal)
326 {
327 case sLogarithmic:
328 y= yi * pCoorSys->ySF;
329 if (y > 7.0)
330 y= yi * log10(pCoorSys->yMax / pCoorSys->yMin) / Screen.dx;
331 yo= pow((float)10, y) * pCoorSys->yMin;
332 break;
333
334 case sLinear:
335 yo= (yi * pCoorSys->ySF) + pCoorSys->yMin;
336 break;
337 }*/
338 float valueZ= 0;
339 Screen2Title(LOWORD(lParam) - xBorder, (eOutputType==otCurve) ? (Screen.y1 - HIWORD(lParam)) : (Screen.y1 - HIWORD(lParam) - yBorder),
340 xo, yo, valueZ, false);
341
342 ScanReport= lpDBase->GetScanReport();
343
344
345 //! ThetaOffset muss in Koordinatenausgabe beruecksichtigt werden
346 if ( eOutputType==otMatrixBitmap )
347 {
348 row= ScanReport->GetValueByValue(yo, x, y);
349 offset= GetThetaOffset(row) - VisualDB.dThetaMinFirst;
350 temp_xo= xo;
351
352 if (VisualDB.bPsd)
353 {
354 xo= xo - pCoorSys->xMin;
355 xo= xo - offset;
356 }
357 }
358 else
359 temp_xo= xo;
360
361 mPoint1.x= temp_xo;
362 mPoint1.y= yo;
363
364 //! zeige X,Y,Intensitaet,Row,Column in Statuszeile
365 //! - wenn in Koordinatensystem geklickt
366 float xMin= pCoorSys->xMin;
367 float xMax= pCoorSys->xMax;
368 if ( eOutputType!=otMatrixBitmap && !bSecondaryCoor ) { //! im Falle von Winkelbeschriftung
369 xMin= CalcValueInUnit( m_DetectorUnit, CalcValueFromUnit(m_MotorUnit, xMin) );
370 xMax= CalcValueInUnit( m_DetectorUnit, CalcValueFromUnit(m_MotorUnit, xMax) );
371 }
372 if ( yo>=pCoorSys->yMin && yo<=pCoorSys->yMax &&
373 temp_xo>=xMin && temp_xo<=xMax )
374 {
375 switch (eOutputType)
376 {
377 case otReciprokeLatticeBitmap: //! Zeile und Spalte im Bitmap berechnen
378 row= (yo - pCoorSys->yMin) / pCoorSys->ySF;
379 column= (xo - pCoorSys->xMin) / pCoorSys->xSF;
380 //! Omega und Theta aus dem "Daten"Feld holen
381 if ( BSource->IsDatenInited() )
382 {
383 Omega= BSource->GetOmega(row, column);
384 Theta= BSource->GetTheta(row, column);
385 } else {
386 Omega= 0;
387 Theta= 0;
388 }
389
390 //! nur die Vorinitialisierung des "Daten"feldes abfangen
391 if ( (Omega && Theta) != row*row - column*column )
392 {
393 //! Zeile und Spalte in der Areascan-Datenbasis holen und Pointer darauf setzen
394 row= ScanReport->GetValueByValue(Omega, x, y);
395 Scan= lpDBase->GetCurve(row);
396 //** pick out the intensity
397 column= Scan->GetValueByValue(Theta, x, y);
398 Scan->SetPP(column);
399 //! Intensitaet holen
400 Scan->PGet(x, y, z); //07.05.2004 FastP...
401 //! zur Ausgabe in der Statuszeile Thetaoffset aufaddieren
402 //! diese Unterscheidung, da 0-dim. andere Datenbasisspeicherung als
403 //! 1-dim Areascans (ThetaOffset mitgespeichert/nichtgespeichert)
404 if (VisualDB.bPsd)
405 Theta= Theta + GetThetaOffset(row);
406 } else Omega= Theta= row= column= 0;
407 break;
408
409 case otMatrixBitmap:
410 Omega= yo;
411 Theta= xo;
412 //! Zeile und Spalte in der Areascan-Datenbasis holen und Pointer darauf setzen
413 row= ScanReport->GetValueByValue(Omega, ODelta, y);
414 Scan= lpDBase->GetCurve(row);
415 //** pick out the intensity
416 column= Scan->GetValueByValue(Theta, TDelta, y);
417 Scan->SetPP(column);
418 //! Intensitaet holen
419 Scan->PGet(x, y, z); //07.05.2004 FastP...
420 xo= temp_xo;
421 break;
422 }
423 //! hier Unterscheidung nach benoetigter Genauigkeit eingebaut - Fehler 6
424 nk1= GetNachkommaStelle(pCoorSys, 1, 0);
425 nk2= GetNachkommaStelle(pCoorSys, 0, 1);
426 if (y >= 1000)
427 nk3= 0;
428 else if (y >= 100)
429 nk3= 1;
430 else if (y >= 10)
431 nk3= 2;
432 else
433 nk3= 3;
434
435 //! Standardausgabe
436 sprintf(buf, "X: %.*f Y: %.*f", nk1, temp_xo, nk2, yo);
437 if (row && column) switch (eOutputType)
438 {
439 case otReciprokeLatticeBitmap:
440 sprintf(buf, szMsgLine609,
441 nk1, xo, nk2, yo, Theta, Omega, nk3, y, row, column);
442 break;
443
444 case otMatrixBitmap:
445 sprintf(buf, szMsgLine608,
446 nk1, xo, TDelta, nk2, yo, ODelta, nk3, y, row, column);
447 break;
448 }
449 //! buf in Statuszeile anzeigen
450 SetInfo(buf);
451 } else SetInfo(szMsgLine601);
452 };
453 //*****************************************************************************
454
455 void TPlotWindow::OnMouseMove(WPARAM, LPARAM lParam)
456 //! diese Fkt. gibt in der Statuszeile dx und dy Werte aus
457 //! wenn mit gedrueckter linker Maustaste ueber ein Koord.system gefahren wird
458 {
459 char buf[MaxString];
460 int xi, yi, temp1, temp2;
461 float x, y;
462 TCoorSystem *pCoorSys;
463
464 //! wenn Button nicht gedrueckt gehe zurueck...
465 if ( !bButtonDown )
466 return;
467
468 switch (eOutputType)
469 {
470 case otReciprokeLatticeBitmap:
471 case otMatrixBitmap:
472 xi= LOWORD(lParam) - xBorder;
473 yi= Screen.y1 - HIWORD(lParam) - yBorder;
474 pCoorSys= &AltCoorSys;
475 break;
476
477 default:
478 xi= LOWORD(lParam) - xBorder;
479 yi= Screen.y1 - HIWORD(lParam);
480 pCoorSys= &CoorSys;
481 }
482 //! Abzisse immer linear skaliert
483 x= (xi * pCoorSys->xSF) + pCoorSys->xMin;
484 //! Ordinate linear oder log skaliert
485 switch (pCoorSys->yScal)
486 {
487 case sLogarithmic:
488 y= yi * pCoorSys->ySF;
489 if (y > 7.0)
490 y= yi * log10(pCoorSys->yMax / pCoorSys->yMin) / Screen.dx;
491 y= pow((float)10, y) * pCoorSys->yMin;
492 break;
493
494 case sLinear:
495 y= (yi * pCoorSys->ySF) + pCoorSys->yMin;
496 break;
497
498 default:
499 y=0;
500 }
501 //! zeige dX,dY in Statuszeile - wenn in Koordinatensystem geklickt
502 if ( mPoint1.y <= pCoorSys->yMax && mPoint1.y >= pCoorSys->yMin &&
503 mPoint1.x <= pCoorSys->xMax && mPoint1.x >= pCoorSys->xMin &&
504 y <= pCoorSys->yMax && y >= pCoorSys->yMin &&
505 x <= pCoorSys->xMax && x >= pCoorSys->xMin)
506 {
507 //! hier Unterscheidung nach benoetigter Genauigkeit eingebaut - Fehler 6
508 temp1= GetNachkommaStelle(pCoorSys, 1, 0);
509 temp2= GetNachkommaStelle(pCoorSys, 0, 1);
510 if ( DataaquisitionActive ) { //! wenn DataAquisition aktiv
511 mPoint2.x= x;
512 mPoint2.y= y;
513 sprintf(buf, szMsgLine607,
514 temp1, mPoint1.x, temp2, mPoint1.y,
515 temp1, mPoint2.x, temp2, mPoint2.y);
516 } else sprintf(buf, "dX= %.*f dY= %.*f", temp1, x - xo, temp2, y - yo);
517 //! in Statuszeile ausgeben
518 SetInfo(buf);
519 }
520 else
521 SetInfo(szMsgLine601);
522 };
523 //*****************************************************************************
524
525 void TPlotWindow::OnLButtonUp(WPARAM, LPARAM)
526 //! nur dazu da, um das Loslassen der linken Maustaste zu registrieren
527 {
528 bButtonDown= FALSE;
529 if ( DragDC ) {
530 ReleaseDC(GetHandle(), DragDC);
531 ReleaseCapture();
532 DragDC= 0;
533 }
534 };
535 //*****************************************************************************
536
537 //! fuelle TKSystem mit Standardwerten
538 BOOL TPlotWindow::SetMeasurementArea(TKSystem &ks)
539 {
540 ks[0].x= 1.0;
541 ks[0].y= 1.0;
542 ks[0].Ord= 0;
543
544 ks[1].x= 10.0;
545 ks[1].y= 1.0;
546 ks[1].Ord= 1;
547
548 ks[2].x= 10.0;
549 ks[2].y= 10.0;
550 ks[2].Ord= 2;
551
552 ks[3].x= 1.0;
553 ks[3].y= 10.0;
554 ks[3].Ord= 3;
555 return TRUE;
556 };
557 //*****************************************************************************
558
559 void TPlotWindow::OnRenderFormat(WPARAM wParam, LPARAM)
560 //! the WM_RENDERFORMAT message is sent to the clipboard owner
561 //! when a particular format with delayed rendering needs to be rendered
562 //! HANDLE SetClipboardData(uint format, HANDLE handle);
563 //! bei erfolgreicher Ausfuehrung ist der Rueckgabewert ein Handle auf die Daten
564 {
565 HANDLE hClip;
566
567 if (eOutputType==otCurve)
568 return;
569 switch (wParam)
570 {
571 case CF_BITMAP:
572 hClip= (HANDLE)BSource->CreateGDIObject(GetDC(GetHandle()));
573 SetClipboardData(CF_BITMAP, hClip);
574 break;
575
576 case CF_PALETTE:
577 hClip= (HANDLE)CreatePalette(BSource->GetPalette());
578 SetClipboardData(CF_PALETTE, hClip);
579 break;
580
581 case CF_DIB:
582 hClip= BSource->RenderDIB();
583 SetClipboardData(CF_DIB, hClip);
584 break;
585 }
586 };
587 //*****************************************************************************
588
589 void TPlotWindow::OnRenderAllFormats(WPARAM, LPARAM)
590 //! the WM_RENDERALLFORMATS message is sent to the clipboard owner
591 //! when the owner application is being destroyed
592 {
593 UINT uFormat= 0;
594
595 OpenClipboard(GetHandle());
596 // hier stand ein =, was soll das?
597 while (NULL != (uFormat= EnumClipboardFormats(uFormat)))
598 SendMessage(GetHandle(), WM_RENDERFORMAT, uFormat, 0L);
599 CloseClipboard();
600 };
601 //*****************************************************************************
602
603 void TPlotWindow::DoCopy(void)
604 //! Kopieren mit Hilfe der Zwischeablage - Typen: CF_DIB, CF_PALETTE
605
606 {
607 //! OpenClipboard(hWnd) - oeffnet die Zwischenablage und hindert
608 //! andere Anwendungen daran, den Inhalt der Zwischenablage zu veraendern
609 //! (Ausgabetyp ist nicht Matrix- oder RL Bitmap) oder Zwischenablage
610 //! geht nicht auf ---> denn zurueck...
611 if ( (eOutputType==otCurve) || !OpenClipboard(GetHandle()) )
612 return;
613
614 //! EmptyClipBoard() - Leert die Zwischenablage
615 //! und gibt alle Handles auf die Daten der Zwischenablage frei
616 EmptyClipboard();
617
618 //! SetClipBoardData(...) - setzt ein Handle auf den Datenblock
619 //! an der durch handle angezeigten Position
620 SetClipboardData(CF_DIB, NULL);
621 SetClipboardData(CF_PALETTE, NULL);
622
623 //! schließt die Zwischenablage
624 CloseClipboard();
625 };
626 //*****************************************************************************
627
628 void TPlotWindow::Screen2Title(float aScreenX, float aScreenY, float &resultX, float &resultY, float &resultZ, bool aChannel5Steps) {
629 TCoorSystem *pCoorSys;
630 switch (eOutputType)
631 {
632 case otReciprokeLatticeBitmap:
633 case otMatrixBitmap:
634 pCoorSys= &AltCoorSys;
635 break;
636
637 default:
638 pCoorSys= &CoorSys;
639 }
640
641 // x-Achse
642 if ( eOutputType==otMatrixBitmap && bSecondaryCoor ) { // MatrixBitmap und Winkeldarstellung
643 float xMin= MainCurve->GetMin( P_Z );
644 float xMax= (MainCurve->GetMax( P_Z ) * pCoorSys->xMax) / (MainCurve->GetMax( P_X ) + GetThetaOffset(0));
645 float xSF= (xMax - xMin) / Screen.dx;
646 resultX= xMin + aScreenX*xSF;
647 } else {
648 resultX= pCoorSys->xMin + aScreenX * pCoorSys->xSF;
649 if ( bSecondaryCoor ) { //! im Falle von Kanalbeschriftung
650 if ( aChannel5Steps ) { // sonst treten an x-Achse zwei identische Beschriftungen auf
651 // in 5er Schritten runden
652 long chann= long(resultX);
653 if ( chann % 5 == 0 ) /*perfekt*/;
654 else if ( (chann-1) % 5 == 0 ) chann-= 1; // na gut, Verschiebung um -1
655 else if ( (chann+1) % 5 == 0 ) chann+= 1; // na gut, Verschiebung um +1
656 else if ( (chann-2) % 5 == 0 ) chann-= 2; // na gut, Verschiebung um -2
657 else if ( (chann+2) % 5 == 0 ) chann+= 2; // na gut, Verschiebung um +2
658 resultX= chann;
659 }
660 } else if ( m_DetectorUnit!=utNone && m_MotorUnit!=utNone ) resultX= CalcValueInUnit( m_DetectorUnit, CalcValueFromUnit(m_MotorUnit, resultX) ); //! im Falle von Winkelbeschriftung
661 }
662
663 // y-Achse
664 switch (pCoorSys->yScal)
665 {
666 case sLinear:
667 resultY= pCoorSys->yMin + aScreenY*pCoorSys->ySF;
668 break;
669
670 default:
671 resultY= pCoorSys->yMin * pow((double)10, (double)(aScreenY)*pCoorSys->ySF);
672 }
673
674 // x-Achse (zweizeilige Beschriftung; nur DTN-File)
675 if (eLoadFormat == ffDtnFile) resultZ= pCoorSys->zMin + aScreenX*pCoorSys->zSF;
676 else resultZ= 0;
677 }
678
679 void TPlotWindow::GetTitleX(int i, int titlesx, char *buf, bool reduceLines) {
680 TCoorSystem *pCoorSys;
681 switch (eOutputType)
682 {
683 case otReciprokeLatticeBitmap:
684 case otMatrixBitmap:
685 pCoorSys= &AltCoorSys;
686 break;
687
688 default:
689 pCoorSys= &CoorSys;
690 }
691
692 // an der Achse darzustellende(r) Zahlenwert(e)
693 float valueX, valueY, valueZ;
694 float x= float(i) / float(tilesx)*Screen.dx;
695 Screen2Title(x, 0/*y-Achse nicht berechnen*/,
696 valueX, valueY, valueZ, fabs(pCoorSys->xMax-pCoorSys->xMin) >= tilesx*5);
697 if ( eOutputType==otMatrixBitmap && bSecondaryCoor ) Double2String(buf, valueX, 0, TRUE, _DECIMAL, _THOUSAND); // MatrixBitmap und Winkeldarstellung
698 else if ( bSecondaryCoor ) Double2String(buf, valueX, 0, TRUE, _DECIMAL, _THOUSAND); //! im Falle von Kanalbeschriftung
699 else Double2String(buf, valueX, GetNachkommaStelle(pCoorSys, 1, 0), TRUE, _DECIMAL, _THOUSAND); // sprintf(buf, "%.*f", GetNachkommaStelle(pCoorSys, 1, 0), fval); //! im Falle von Winkelbeschriftung
700
701 // dtn-Abszissenbeschr. (zweizeilige Zahlenwerte)
702 if (eLoadFormat == ffDtnFile) {
703 char buf2[MaxString];
704 Double2String(buf2, valueZ, GetNachkommaStelle(pCoorSys, 1, 0), TRUE, _DECIMAL, _THOUSAND); // sprintf(buf, "%.*f", GetNachkommaStelle(pCoorSys, 1, 0), fval);
705 strcat(buf, "\n");
706 strcat(buf, buf2);
707 }
708 }
709
710 void TPlotWindow::GetTitleY(int i, int titlesy, char *buf, bool reduceLines) {
711 TCoorSystem *pCoorSys;
712 switch (eOutputType)
713 {
714 case otReciprokeLatticeBitmap:
715 case otMatrixBitmap:
716 pCoorSys= &AltCoorSys;
717 break;
718
719 default:
720 pCoorSys= &CoorSys;
721 }
722
723 // an der Achse darzustellende(r) Zahlenwert(e)
724 float valueX= 0, valueY= 0, valueZ= 0;
725 float y= float(i) / float(titlesy)*Screen.dy;
726 Screen2Title(0/*x-Achse nicht berechnen*/, y,
727 valueX, valueY, valueZ, false);
728 if ( valueY==0 )
729 Double2String(buf, 0, 2, TRUE, _DECIMAL, _THOUSAND); // sprintf(buf, "0.00");
730 else
731 Double2String(buf, valueY, GetNachkommaStelle(pCoorSys, 0, 1), TRUE, _DECIMAL, _THOUSAND); // sprintf(buf, "%.*f", GetNachkommaStelle(pCoorSys, 0, 1), fval);
732
733 // letzte Beschriftung = Beschriftung der Ordinaten-Achse mit Skalierungstyp
734 if ( i==tilesy )
735 if ( eOutputType==otCurve ) {
736 if ( reduceLines ) {
737 if ( pCoorSys->yScal==sLinear ) sprintf(buf, szIntensLiEZ);
738 else if ( pCoorSys->yScal==sLogarithmic ) sprintf(buf, szIntensLoEZ);
739 } else {
740 if ( pCoorSys->yScal==sLinear ) sprintf(buf, szIntensLi);
741 else if ( pCoorSys->yScal==sLogarithmic ) sprintf(buf, szIntensLo);
742 }
743 }
744 }
745
746 BOOL TPlotWindow::GetTextExtentPointEx(HDC hdc, LPCTSTR lpString, int cbString, LPSIZE lpSize)
747 {
748 BOOL result= TRUE; // falls Leerstring
749 lpSize->cx= 0;
750 lpSize->cy= 0;
751 SIZE tagS;
752 GetTextExtentPoint(hdc, "Qq", strlen("Qq"), &tagS);
753
754 char *buf= new char[ strlen(lpString)+1 ];
755 strcpy(buf, lpString);
756
757 char *actual= strtok( buf, "\n\r" ); // erste "Zeile" auslesen
758 while ( actual ) { // ausgeben der "Zeilen"
759 SIZE tagT;
760 if ( !GetTextExtentPoint(hdc, actual, strlen(actual), &tagT) ) result= FALSE;
761 lpSize->cx= max(lpSize->cx, tagT.cx);
762 lpSize->cy+= tagS.cy;
763 actual= strtok( NULL, "\n\r" ); // nächste "Zeile"
764 }
765
766 _FREELIST(buf);
767 return result;
768 };
769
770
771 void TPlotWindow::TextOutEx(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString, EHAlign hAlign, EVAlign vAlign)
772 {
773 char *buf= new char[ strlen(lpString)+1 ];
774 strcpy(buf, lpString);
775 SIZE tagO;
776 GetViewportExtEx(hdc, &tagO);
777 bool bTopDown= tagO.cy>=0; // bei Sichtweise von oben nach unten: Koordinaten werden größer
778 bool bLeftRight= tagO.cx>=0; // bei Sichtweise von links nach rechts: Koordinaten werden größer
779 SIZE tagS;
780 GetTextExtentPoint(hdc, "Qq", strlen("Qq"), &tagS);
781 SIZE tagG;
782 GetTextExtentPointEx(hdc, lpString, strlen(lpString), &tagG);
783
784 int y= nYStart;
785 if ( vAlign==vaCenter ) {
786 if ( bTopDown ) y= nYStart - tagG.cy/2;
787 else y= nYStart + tagG.cy/2;
788 } else if ( vAlign==vaBottom ) {
789 if ( bTopDown ) y= nYStart - tagG.cy;
790 else y= nYStart + tagG.cy;
791 }
792 char *actual= strtok( buf, "\n\r" ); // erste "Zeile" auslesen
793 while ( actual ) { // ausgeben der "Zeilen"
794 SIZE tagT;
795 GetTextExtentPoint(hdc, actual, strlen(actual), &tagT);
796 int x= nXStart;
797 if ( hAlign==haCenter ) {
798 if ( bLeftRight ) x= nXStart - tagT.cx/2;
799 else x= nXStart + tagT.cx/2;
800 } else if ( hAlign==haRight ) {
801 if ( bLeftRight ) x= nXStart - tagT.cx;
802 else x= nXStart + tagT.cx;
803 }
804 TextOut(hdc, x, y, actual, strlen(actual));
805
806 if ( bTopDown ) y+= tagS.cy;
807 else y-= tagS.cy;
808 actual= strtok( NULL, "\n\r" ); // nächste "Zeile"
809 }
810
811 _FREELIST(buf);
812 }
813
814 void TPlotWindow::DrawCoordinateSystem(HDC hdc)
815 //! zeichnet Koord.System - oder was soll der Name sonst :-)
816 {
817 //! der Datentyp, der das Handle auf eine physikalische Schrift repraesentiert
818 HFONT hOldFont;
819 //! der Windows-Datentyp, der Handles fuer logische Stifte repraesentiert
820 HPEN hOldPen, hPenDot, hPenBlack;
821 //! the SIZE structure specifies the width and height of a rectangle
822 SIZE tagS;
823 //! the POINT structure defines the x- and y- coordinates of a point
824 POINT egde[5];
825 char buf[MaxString];
826 float dist, offset;
827 int i;
828
829 CoorSys.xSF= (CoorSys.xMax - CoorSys.xMin) / Screen.dx;
830 CoorSys.ySF= (CoorSys.yMax - CoorSys.yMin) / Screen.dy;
831
832 // inquire scaling parameters
833 CoorSys.xSF= (CoorSys.xMax - CoorSys.xMin) / Screen.dx;
834 if ( eOutputType!=otCurve || CoorSys.yScal==sLinear ) CoorSys.ySF= (CoorSys.yMax - CoorSys.yMin) / Screen.dy; // Bitmaps sind nur linear skaliert
835 else CoorSys.ySF= log10(CoorSys.yMax / CoorSys.yMin) / Screen.dy;
836
837 hPenBlack= CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
838 hPenDot= CreatePen(PS_DOT, 1, RGB(0, 0, 0));
839 hOldFont= (HFONT)SelectObject(hdc, hFont);
840 hOldPen= (HPEN)SelectObject(hdc, hPenBlack);
841
842 // wie viele Zeilen benötigt die höchste x-Achsenbeschriftung; ausführliche Beschreibung zulassen?
843 GetTextExtentPoint(hdc, "Qq", strlen("Qq"), &tagS);
844 int rowHeight= tagS.cy;
845 int rows= 1; // Beschriftung muss in so vielen Zeilen angezeigt werden, damit es keine Überschneidungen gibt
846 int heightY= 0; // so hoch sind die Beschriftungen insgesamt für das aktuelle <rows>
847 for (int reduceLinesX= 0; reduceLinesX<2; reduceLinesX++) {
848 int rowStep= 1; // wie viele Zeilen belegt die höchste Bezeichnung
849 for (i= 0; i<=tilesx; i++) {
850 GetTitleX(i, tilesx, buf, reduceLinesX!=0);
851 GetTextExtentPointEx(hdc, buf, strlen(buf), &tagS);
852 rowStep= max(rowStep, min((yBorder-2)/rowHeight, tagS.cy/rowHeight) ); // die Beschriftung darf nicht mehr als den verfügbaren Platz ver(sch)wenden
853 }
854
855 // In wie vielen Ebenen muss die X-Achse beschriftet werden, damit sich die Beschriftungen nicht überschneiden?
856 rows= 1;
857 bool ueberschneid, lastLoop= false;
858 do {
859 ueberschneid= false;
860 heightY= 0;
861 int platz= float(Screen.dx) / float(tilesx) * float(rows); // max. Pixelanzahl zwischen zwei Beschriftungen auf gleicher Ebene (wird diese Anzahl überschritten, kommt es zu Überschneidungen)
862 for (int row=0; row<rows; row++) { // jede Zeile auf Überschneidungen prüfen
863 int dy= 0;
864 int lastWid= 0;
865 for (i= 0; i<=tilesx; i++) {
866 if ( (i%rows)!=row ) continue;
867
868 // diese Beschriftung kommt in Zeile <row>
869 GetTitleX(i, tilesx, buf, reduceLinesX!=0);
870 GetTextExtentPointEx(hdc, buf, strlen(buf), &tagS);
871 int thisWid= tagS.cx;
872 if ( i!=tilesx ) thisWid/= 2; // bis auf den letzten Abschnitt (rechtsbündig) ist alles zentriert; belegt nur die halbe Breite
873 if ( lastWid+thisWid > platz-max(5, float(platz)*0.02) ) ueberschneid= true;
874 lastWid= thisWid;
875 dy= max(dy, tagS.cy);
876 }
877 heightY+= dy;
878 }
879 if ( lastLoop ) break;
880 if ( ueberschneid ) {
881 rows+= 1;
882 if ( heightY > yBorder-max(5, float(yBorder)*0.02) ) { // reicht der Platz zwischen x-Achse und sichtbarem Bereich?
883 rows= max(1, rows-1);
884 lastLoop= true; // Schleife mit neuem <rows> wiederholen und <heightX> berechnen; dann soft beenden
885 }
886 }
887 } while ( ueberschneid );
888 if ( !ueberschneid ) break; // reduceLinesX muss nicht eingeschaltet werden
889 }
890
891 // ermitteln, ob y-Achsenbeschriftung ausführlich oder einzeilig
892 bool reduceLinesY= false;
893 int platz= float(Screen.dy-Screen.y0)/tilesy;
894 int lastHei= 0;
895 for (i= 0;i <= tilesy; i++) {
896 GetTitleY(i, tilesy, buf, false);
897 GetTextExtentPointEx(hdc, buf, strlen(buf), &tagS);
898 int thisHei= tagS.cy;
899 if ( i!=tilesy ) thisHei/= 2; // bis auf letzten Abschnitt (oben) alles mittig ausgerichtet
900 if ( lastHei+thisHei > platz-max(5, platz*0.02) ) { // ausführliche Beschreibung ist zu hoch
901 reduceLinesY= true;
902 break;
903 }
904 lastHei= thisHei;
905 }
906
907 // Rahmen zeichnen
908 egde[0].x= egde[3].x= Screen.x0;
909 egde[1].x= egde[2].x= Screen.x0 + Screen.dx;
910 egde[0].y= egde[1].y= Screen.y0;
911 egde[2].y= egde[3].y= Screen.y0 + Screen.dy;
912 egde[4]= egde[0];
913 Polyline(hdc, egde, 5);
914
915 //************ Absizze (x) *************************************************
916 SelectObject(hdc, hPenBlack);
917 SelectObject(hdc, hPenDot);
918
919 TCoorSystem *pCoorSys;
920 switch (eOutputType)
921 {
922 case otReciprokeLatticeBitmap:
923 case otMatrixBitmap:
924 pCoorSys= &AltCoorSys;
925 break;
926
927 default:
928 pCoorSys= &CoorSys;
929 }
930
931 //! dient zur Unterscheidung, um ThetaOffset in RawMatrix bei
932 //! Winkeldarstellung zu beruecksichtigen
933 if ( eOutputType==otMatrixBitmap && bSecondaryCoor )
934 {
935 offset= VisualDB.dThetaMinLast - VisualDB.dThetaMinFirst; //GetThetaOffset(lpDBase->GetCNumber()-1)-GetThetaOffset(0);
936 offset= offset / pCoorSys->xSF;
937 i= 0;
938 } else {
939 offset= 0;
940 i= 1;
941 }
942
943 for (i;i < tilesx;i++)
944 {
945 //! zeichnet Verbindungslinien ein...
946 egde[0].x= Screen.x0 + i / tilesx * (Screen.dx);
947 egde[1].x= Screen.x0 + offset + i / tilesx * (Screen.dx);
948 egde[0].y= Screen.y0;
949 egde[1].y= Screen.y0 + Screen.dy;
950
951 //! falls Hilfslinien ausserhalb des Screens fallen, berechne Anstieg der Geraden
952 //! und zugehoerigen y-Wert
953 if (egde[1].x > Screen.dx + Screen.x0)
954 {
955 egde[1].x= Screen.dx + Screen.x0;
956 egde[1].y= (Screen.dx + Screen.x0 - egde[0].x) * ((Screen.dy - Screen.y0) / offset);
957 }
958 Polyline(hdc, egde, 2);
959 }
960
961 //! eingefuegt fuer dtn-File Abzissenbeschriftung
962 if (eLoadFormat == ffDtnFile)
963 pCoorSys->zSF= (pCoorSys->zMax - pCoorSys->zMin) / Screen.dx;
964
965 //! zeichnet die Markierungen an der x-Achse
966 for (i= 0; i<=tilesx; i++)
967 {
968 // Verbindungslinien und Markierungen
969 dist= i / tilesx * Screen.dx;
970 egde[0].x= egde[1].x= Screen.x0 + dist + offset;
971 egde[0].y= Screen.y0 + Screen.dy;
972 egde[1].y= Screen.y0 + Screen.dy - 5;
973 if (egde[1].x < Screen.dx + Screen.x0)
974 Polyline(hdc, egde, 2);
975
976 egde[0].x= egde[1].x= Screen.x0 + dist;
977 egde[0].y= Screen.y0 + 5;
978 egde[1].y= Screen.y0;
979 Polyline(hdc, egde, 2);
980 }
981
982 // Beschriftungen
983 int y= -yBorder/2 + heightY/2;
984 for (int r= 0; r<rows; r++)
985 {
986 int dy= 0;
987 for (i= 0; i<=tilesx; i++) if ( i%rows==r )
988 {
989 GetTitleX(i, tilesx, buf, reduceLinesX!=0);
990 GetTextExtentPointEx(hdc, buf, strlen(buf), &tagS);
991 TextOutEx(hdc, Screen.x0 + float(i) / tilesx * Screen.dx, y - tagS.cy/2, buf, strlen(buf), (i==tilesx) ? haRight : haCenter, vaCenter);
992 dy= max(dy, tagS.cy);
993 }
994 y-= dy;
995 }
996
997 //************ Ordinate (y) **************************************************
998 SelectObject(hdc, hPenDot);
999 for (i= 1;i < tilesy;i++)
1000 {
1001 //! zeichnet Verbindungslinien ein...
1002 egde[0].y= egde[1].y= 1 + i / tilesy * Screen.dy + Screen.y0;
1003 egde[0].x= Screen.x0;
1004 egde[1].x= Screen.x0 + Screen.dx;
1005 Polyline(hdc, egde, 2);
1006 }
1007
1008 SelectObject(hdc, hPenBlack);
1009 for (i= 0;i <= tilesy;i++)
1010 {
1011 // Markierungen
1012 dist= i / tilesy * Screen.dy;
1013 egde[0].y= egde[1].y= Screen.x0 + dist;
1014 egde[0].x= Screen.x0 + Screen.dx;
1015 egde[1].x= Screen.x0 + Screen.dx - 5;
1016 Polyline(hdc, egde, 2);
1017
1018 egde[0].x= Screen.x0 + 5;
1019 egde[1].x= Screen.x0;
1020 Polyline(hdc, egde, 2);
1021
1022 // Beschriftung
1023 GetTitleY(i, tilesy, buf, reduceLinesY);
1024 SetTextAlign(hdc, TA_LEFT);
1025 TextOutEx(hdc, -0.5*xBorder, egde[0].y, (LPSTR)buf, strlen(buf), haCenter, (i==tilesy) ? vaTop : vaCenter);
1026 }
1027
1028 //****************************************************************************
1029 //! loesche hPenBlack,hPenDot und krame hOldPen, hOldFont wieder hervor
1030 SelectObject(hdc, hOldPen);
1031 SelectObject(hdc, hOldFont);
1032 DeleteObject(hPenBlack);
1033 DeleteObject(hPenDot);
1034 };
1035 //*****************************************************************************
1036
1037 int TPlotWindow::GetNachkommaStelle(TCoorSystem* pCoorSys, int x, int y)
1038 //! neue Funktion, die die benoetigte Nachkommastellengenauigkeit
1039 //! berechnet und die noetigen Nachkommastellen als int zurueckliefert
1040 //! wenn x=1 dann fuer x-Achse / wenn y=1 dann fuer y-Achse
1041 //! gehoert zu Fehler 6
1042 {
1043 float fval;
1044
1045 if (y)
1046 fval= fabs(pCoorSys->yMax - pCoorSys->yMin);
1047 if (x)
1048 fval= fabs(pCoorSys->xMax - pCoorSys->xMin);
1049
1050 if (fval < 0.25)
1051 return 5;
1052 else
1053 if (fval < 1)
1054 return 4;
1055 else
1056 if (fval < 3)
1057 return 3;
1058 else
1059 return 2;
1060 };
1061 //*****************************************************************************
1062
1063 LRESULT TPlotWindow::OnEvent ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
1064 {
1065 if ( message==WM_ERASEBKGND ) return 01; // Durch die Verwendung des hMemDC und der hBitmap in DoPaint braucht der Hintergrund nicht mehr gelöscht werden, sonst flackert es.
1066 else return TFileWindow::OnEvent(hwnd, message, wParam, lParam);
1067 }
1068 //*****************************************************************************
1069
1070 LRESULT TPlotWindow::OnCommand(WPARAM wParam, LPARAM lParam)
1071 {
1072 TModalDlg *dlg;
1073 WPARAM Cmd;
1074 Cmd= GET_WM_COMMAND_ID(wParam, lParam);
1075 switch ( Cmd ) {
1076 case cm_Open:
1077 LoadOldData();
1078 SetRanges();
1079 return 0l;
1080
1081 case cm_SaveSecondCurve:
1082 SaveSecondCurve();
1083 return 0l;
1084
1085 case cm_KillSecondCurve:
1086 KillSecondCurve();
1087 return 0l;
1088
1089 case cm_FreezeCurve:
1090 FreezeCurve();
1091 return 0l;
1092
1093 case cm_ShowCurveParam:
1094 dlg= (TCurveShowParamDlg *)new TCurveShowParamDlg(this);
1095 if ( dlg ) dlg->ExecuteDialog(GetHandle());
1096 _FREEOBJ(dlg);
1097 UpdateWnd();
1098 return 0l;
1099
1100 case cm_MoveScanReady:
1101 TCurve *crv= new TCurve();
1102 //07.05.2004 crv->FastOpen();
1103 float x, y, z;
1104 LPLONG data;
1105 data= mGetMoveScan();
1106 long yo;
1107 yo= data[0];
1108 int cnt;
1109 for (cnt= 0;cnt < mGetScanSize();cnt++)
1110 {
1111 x= z= cnt;
1112 y= (data[cnt] - yo);
1113 crv->PAdd(x, y, z); //07.05.2004 FastP...
1114 }
1115 //07.05.2004 crv->FastClose();
1116 TKSProperties ksp;
1117 ksp.bLogarithmicY= FALSE;
1118 ksp.fMinX= 0.0f;
1119 ksp.fMaxX= (float)mGetScanSize() * 1.1;
1120 ksp.fMinY= 0.01f;
1121 ksp.fMaxY= (float)(data[cnt - 1] - yo) * 1.3;
1122 SetKSProperties(&ksp);
1123 PickUpData((LPARAM)(TCurve*)crv);
1124 // SendMessage(Main.hScanWindow,WM_COMMAND,cm_PlotCurve,(LPARAM)(TCurve*)crv);
1125 char Msg[MaxString];
1126 sprintf(Msg, "MoveFinish: %ld >>> Letzter Wert: %ld", data[mGetMoveFinishIdx()] - yo, data[mGetScanSize() - 1] - yo);
1127 SetInfo(Msg);
1128 _FREEOBJ(crv);
1129 SendMessage(GetHandle(), WM_SETFOCUS, 0, 0l);
1130 return 0l;
1131 }
1132 return TFileWindow::OnCommand(wParam, lParam);
1133 }
1134 //*****************************************************************************
1135
1136 //! Paint, das von Basisklassen aufgerufen wird, wenn diese auf eine WM_PAINT-
1137 //! Botschaft reagieren
1138 void TPlotWindow::DoPaint(HDC hdc, PAINTSTRUCT *)
1139 {
1140 BOOL PaintHole= TRUE;
1141 if ( bUserPaint ) {
1142 //! nur bei bEnablePaint zeichnen
1143 if (!bEnablePaint)
1144 return;
1145
1146 //30.06.2004 bei Ausgabe auf MemDC geht nur noch PaintHole PaintHole= WholeWnd(); //! WholeWnd() gibt an, dass für dieses Paint() nicht bPaintPoint gesetzt ist
1147 bUserPaint= false; // nächster Aufruf könnte WM_PAINT sein
1148 }
1149
1150 // Bestimmen der Ausdehnung in Pixeln des Zeichen-Fensters
1151 RECT rect;
1152 GetClientRect(GetHandle(), (LPRECT)&rect);
1153
1154 // Bitmap und DC im Speicher erzeugen, dann darauf zeichnen
1155 HBITMAP hBitmap= CreateCompatibleBitmap(hdc, rect.right-rect.left, rect.bottom-rect.top);
1156 HDC hMemDC= CreateCompatibleDC(hdc);
1157 HGDIOBJ OldBitmap= SelectObject(hMemDC, hBitmap);
1158
1159 // Hintergrund löschen (bevor neues Koordinatensystem gesetzt wird!)
1160 if ( PaintHole ) {
1161 HBRUSH brush= CreateSolidBrush(RGB(255, 255, 255));
1162 FillRect(hMemDC, &rect, brush);
1163 DeleteObject(brush);
1164 }
1165
1166 switch (eOutputType)
1167 {
1168 case otReciprokeLatticeBitmap:
1169 case otMatrixBitmap: {
1170 //! eigentliche Bitmap
1171 BSource->DrawBitmap(hMemDC, 0, -Screen.dy, Screen);
1172 //! Legende (ColorTable)
1173 BSource->DrawBitmapFrame(hMemDC, Screen);
1174 // Koordinatensystem (erst nach DrawBitmapFrame!)
1175 DrawCoordinateSystem(hMemDC);
1176
1177 // jetzt die Bitmap auf <hdc> zeichnen
1178 StretchBlt( hdc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
1179 hMemDC, -xBorder, (rect.bottom-rect.top)-yBorder, rect.right-rect.left, -(rect.bottom-rect.top), SRCCOPY ); // BitBlt kann nicht verwendet werden, weil hMemDC eine andere Koordinatenskalierung besitzt
1180 break;
1181 }
1182
1183 //! dies und viele folgende Sachen nur im Falle von Kurve zu tun...
1184 case otCurve:
1185 if (bAltCoorSystem)
1186 {
1187 CoorSys= AltCoorSys;
1188 bAltCoorSystem= FALSE;
1189 }
1190 else
1191 //! setze neue Koordinatensystembereiche
1192 SetRanges();
1193
1194 // Daten-Bereich festlegen
1195 Screen.dx= (rect.right - rect.left) - xBorder;
1196 Screen.x0= 0;
1197 Screen.x1= Screen.dx;
1198 Screen.dy= (rect.bottom - rect.top) - yBorder;
1199 Screen.y0= 0;
1200 Screen.y1= Screen.dy;
1201
1202 //! Koordinatenursprung und -skalierung ändern, damit die ständigen Koordinatenumrechnungen entfallen
1203 SIZE tagS;
1204 POINT tagP;
1205 SetMapMode(hMemDC, MM_ANISOTROPIC); // wir wollen die Ausdehnung der x- und y-Achse selbst bestimmen
1206 SetWindowExtEx(hMemDC, Screen.dx + xBorder, Screen.dy + yBorder, &tagS); // setze neue x- und y-Ausdehnung
1207 SetViewportExtEx(hMemDC, Screen.dx + xBorder, -(Screen.dy + yBorder), &tagS); // nur in diesem Bereich wollen wir zeichnen
1208 SetWindowOrgEx(hMemDC, 0, 0, &tagP); // folgende Koordinaten als -ursprung des Fensters
1209 SetViewportOrgEx(hMemDC, xBorder, Screen.dy, &tagP); // folgende Koordinaten als -ursprung des sichtbaren Bereiches
1210
1211 if ( PaintHole ) // Koordinatensystem zeichnen (erst nachdem neues Koordinatensystem gesetzt und CoorSys ermittelt wurde!)
1212 DrawCoordinateSystem(hMemDC); // redraw coordinate system
1213
1214 int cnt= 0;
1215 //! Windows-Datentyp, der Handles fuer logische Stifte repraesentiert
1216 HPEN hOldPen, hPen;
1217 //! 32 bit Zeiger
1218 //! the POINT structure defines the x- and y-coordinates of a point
1219 LPPOINT lpPoints;
1220
1221 //! wenn zweite Kurve nicht leer: Kurve komplett zeichnen
1222 if ( SecondCurve->GetPNumber()>1 ) //! 1 < letzter Eintrag + 1
1223 {
1224 lpPoints= (LPPOINT)new POINT[ SecondCurve->GetPNumber() ];
1225 //! setzt ActualIdx auf pos oder auf MaxPointIdx, wenn pos>MaxPointidx
1226 //! hier ActualIdx=0
1227 SecondCurve->SetPP();
1228 //! fuellt die Struktur lpPoints mit den Werten fuer eine Kurve...
1229 FormatCurveToPLine(SecondCurve, lpPoints, cnt);
1230 //! ...um damit spaeter dann die Kurve darzustellen
1231 hPen= CreatePen(PS_SOLID, 1, RGB(0, 0, 255));
1232 hOldPen= (HPEN)SelectObject(hMemDC, hPen);
1233 if ( m_HasFilter )
1234 FilterPLine(lpPoints, cnt);
1235 if ( m_Dotted ) {
1236 HBRUSH hBrush= CreateSolidBrush(RGB(0, 0, 255));
1237 HBRUSH hOldBrush= (HBRUSH)SelectObject(hMemDC, hBrush);
1238 Dottedline(hMemDC, lpPoints, cnt);
1239 SelectObject(hMemDC, hOldBrush);
1240 DeleteObject(hBrush);
1241 } else Polyline(hMemDC, lpPoints, cnt);
1242 SelectObject(hMemDC, hOldPen);
1243 DeleteObject(hPen);
1244 _FREELIST(lpPoints);
1245 }
1246 //! wenn erste Kurve nicht leer: diese [auch] zeichnen
1247 if ( MainCurve->GetPNumber()>1 ) //! 1 < letzter Eintrag + 1
1248 {
1249 if (PaintHole)
1250 { // alle Punkte der Kurve zeichnen, dazu PP auf Index 0 setzen
1251 lpPoints= (LPPOINT)new POINT[ MainCurve->GetPNumber() ];
1252 //! letzter ActualIdx auf Anfang
1253 MainCurve->SetPP();
1254 }
1255 else
1256 { // nur den letzten Punkt zeichnen, Index um eine Position zurücksetzen
1257 lpPoints= (LPPOINT)new POINT [2];
1258 //! setzt ActualIdx vor-letztes MaxPointIdx
1259 MainCurve->SetPPLast();
1260 MainCurve->BackStep();
1261 }
1262 //! fuellt die Struktur lpPoints mit den Werten fuer eine Kurve...
1263 FormatCurveToPLine(MainCurve, lpPoints, cnt);
1264
1265 //! ...um damit spaeter dann die Kurve darzustellen
1266 hPen= CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
1267 hOldPen= (HPEN)SelectObject(hMemDC, hPen);
1268 if ( m_HasFilter )
1269 FilterPLine(lpPoints, cnt);
1270 if ( m_Dotted ) {
1271 HBRUSH hBrush= CreateSolidBrush(RGB(255, 0, 0));
1272 HBRUSH hOldBrush= (HBRUSH)SelectObject(hMemDC, hBrush);
1273 Dottedline(hMemDC, lpPoints, cnt);
1274 SelectObject(hMemDC, hOldBrush);
1275 DeleteObject(hBrush);
1276 } else Polyline(hMemDC, lpPoints, cnt);
1277 SelectObject(hMemDC, hOldPen);
1278 DeleteObject(hPen);
1279 _FREELIST(lpPoints);
1280 }
1281
1282 // jetzt die Bitmap auf <hdc> zeichnen und alles aufräumen
1283 StretchBlt( hdc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
1284 hMemDC, -xBorder, Screen.dy, xBorder+Screen.dx, -(yBorder+Screen.dy), SRCCOPY ); // BitBlt kann nicht verwendet werden, weil hMemDC eine andere Koordinatenskalierung besitzt
1285 break;
1286 } // switch
1287
1288 // alles aufräumen
1289 SelectObject(hMemDC, OldBitmap);
1290 DeleteObject(hBitmap);
1291 DeleteDC(hMemDC);
1292 };
1293 //*****************************************************************************
1294
1295 void TPlotWindow::Dottedline(HDC hdc, const POINT *lppt, int cPoints)
1296 {
1297 for (int i= 0; i<cPoints; i++) {
1298 Ellipse(hdc, lppt[i].x-1, lppt[i].y-1, lppt[i].x+1, lppt[i].y+1);
1299 }
1300 }
1301 //*****************************************************************************
1302
1303 HICON TPlotWindow::GetIcon ( void ) const
1304 {
1305 return (HICON)LoadImage( GetMainInstance(), MAKEINTRESOURCE(icon_ScanWindow),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
1306 };
1307 //*****************************************************************************
1308
1309 void TPlotWindow::SetLoadFormat(EFileFormat type)
1310 {
1311 eLoadFormat= type;
1312 };
1313 //*****************************************************************************
1314
1315 BOOL TPlotWindow::SaveFile(EAskType ask) {
1316 char NewFilename[ _MAX_PATH ];
1317 char dir[_MAX_DIR], drv[_MAX_DRIVE], name[_MAX_FNAME], ext[_MAX_EXT];
1318 OFSTRUCT of;
1319 int nNumber= 0, hFile;
1320 HFILE ht;
1321
1322 //! ht= _lopen("test",READ_WRITE);
1323 ht= _lopen("test", OF_READWRITE);
1324 _lclose(ht);
1325 _chdir(szDataPath);
1326 switch (ask)
1327 {
1328 case atNoAsk:
1329 // Test ob File beschrieben werden kann
1330 _splitpath(FileName, drv, dir, name, ext);
1331 _makepath(NewFilename, "", "", name, szExtension);
1332 hFile= OpenFile(NewFilename, &of, OF_CREATE);
1333 if (hFile==HFILE_ERROR)
1334 do {
1335 sprintf(NewFilename, "%sscan%03d.%s", szDataPath, nNumber++, szExtension);
1336 hFile= OpenFile(NewFilename, &of, OF_EXIST);
1337 } while ( hFile!=HFILE_ERROR && nNumber<10000 );
1338 _lclose(hFile);
1339 break;
1340
1341 case atNewName:
1342 sprintf(NewFilename, "*.%s", szExtension);
1343 if ( !FileSaveDialog("Sichern unter ...", szFilter, NewFilename, szDataPath) ) return FALSE; // 'Abbruch' geklickt
1344 if ( strlen(NewFilename)==0 || strcmp(NewFilename, "*")==0 )
1345 return FALSE;
1346 break;
1347
1348 default:
1349 if (!bFileChanged)
1350 {
1351 SetInfo(strMessage14);
1352 return FALSE;
1353 }
1354 if (!bIsNewFile)
1355 {
1356 _splitpath(FileName, drv, dir, name, ext);
1357 _makepath(NewFilename, "", "", name, szExtension);
1358 }
1359 else
1360 sprintf(NewFilename, "*.%s", szExtension);
1361 if ( !FileSaveDialog("Sichern als ...", szFilter, NewFilename, szDataPath) ) return FALSE; // 'Abbruch' wurde geklickt
1362 if ( strlen(NewFilename)==0 || strcmp(NewFilename, "*")==0 )
1363 return FALSE;
1364 }
1365 _splitpath(NewFilename, drv, dir, name, ext);
1366 _makepath(FileName, drv, dir, name, szExtension);
1367 bIsNewFile= FALSE;
1368 // bOldDataLoaded= FALSE;
1369 bFileChanged= FALSE;
1370 _chdir(szDataPath);
1371 SetTitle();
1372 return TRUE;
1373 }
1374 // ---------------------------------------------------------------------------
1375 // 15.06.2004 Kullmann/Reinecker: neue Methode zur uebersichtlicheren Kurvendarstellung
1376 void TPlotWindow::FilterPLine(LPPOINT lpPoints, int &idx)
1377 {
1378 bool found = false;
1379 POINT FilterLevel;
1380 LPPOINT YAccumulation = (LPPOINT)new POINT[idx+1];
1381
1382 m_FilterStrength = max(0.0, min(100.0, m_FilterStrength));
1383
1384 for (int i = 0; i <= idx; i++)
1385 {
1386 YAccumulation[i].x = -1; // die Häufigkeit des Auftretens
1387 YAccumulation[i].y = -1; // die gemessenen Intensitaet
1388 }
1389 FilterLevel.x = -1;
1390 FilterLevel.y = -1;
1391 for (i = 0; i <= idx; i++)
1392 {
1393 found = false;
1394 // ob schon mal gezählt
1395 for (int j = 0; j <= idx; j++)
1396 {
1397 if ( lpPoints[i].y == YAccumulation[j].y )
1398 {
1399 (YAccumulation[j].x)++;
1400 found = true;
1401 break;
1402 }
1403 }
1404 // wenn neu dann aufnehmen
1405 if (!found)
1406 {
1407 YAccumulation[i].y = lpPoints[i].y;
1408 YAccumulation[i].x = 1;
1409 }
1410 }
1411 // Niveau der groesste Haeufigkeit bestimmen
1412 for (i = 0; i <= idx; i++)
1413 {
1414 if (FilterLevel.x < YAccumulation[i].x)
1415 {
1416 FilterLevel.x = YAccumulation[i].x;
1417 FilterLevel.y = YAccumulation[i].y;
1418 };
1419 };
1420 float MaxAcc = FilterLevel.x; // Maximale Häufigkeit merken
1421 // optimale Haeufigkeit für Y-Wert oberhalb der groessten Haeufigkeit finden
1422 for (i = 0; i <= idx; i++)
1423 {
1424 if ( (YAccumulation[i].y > FilterLevel.y) && ((MaxAcc-((MaxAcc/100)*m_FilterStrength)) < YAccumulation[i].x) ) // naechst kleinere Haufigkeit
1425 {
1426 FilterLevel.x = YAccumulation[i].x;
1427 FilterLevel.y = YAccumulation[i].y;
1428 };
1429 };
1430 // alle Y-Werte auf dieses Niveau anheben
1431 for (i = 0; i <= idx; i++)
1432 if (lpPoints[i].y < FilterLevel.y) lpPoints[i].y = FilterLevel.y;
1433 };
1434
1435 // ---------------------------------------------------------------------------
1436 // 15.06.2004 Kullmann/Reinecker: verkuerzte und korrigierte Methode zur Skalierung der Y-Werte
1437 // fuellt die Struktur lpPoints mit den Werten fuer eine Kurve
1438 void TPlotWindow::FormatCurveToPLine(TCurve *crv, LPPOINT lpPoints, int &idx)
1439 {
1440 idx = 0;
1441 float x; // x-Wert = Thetamotorwinkel
1442 float y; // y-wert = gemessene Intensitaet des Detektors in dieser Position
1443 float z; // z-wert = Kanal
1444 float offset= GetThetaOffset(0);
1445
1446 // FastPGet(x,y,z) holt Werte der Kurve und setzt Kurvenindex weiter
1447 while (crv->PGet(x, y, z)) //07.05.2004 FastP...
1448 {
1449 // wenn X-Achse mit Theta-Winkel Beschriftung
1450 if (!bSecondaryCoor)
1451 {
1452 x += offset; // Theta-Offset beruecksichtigen
1453 lpPoints[idx].x= (x - CoorSys.xMin) / CoorSys.xSF;
1454 } else lpPoints[idx].x= (z - CoorSys.xMin) / CoorSys.xSF; // Beschriftung mit Kanaelen
1455
1456 //if (fabs(z - x) == 0.0) continue; // 15.06.2004 Fehler: was soll Kanaele - Winkel bringen ???
1457
1458 if (y > CoorSys.yMin) // Ok, Wert ist oberhalb X-Achse
1459 {
1460 if (CoorSys.yScal == sLinear)
1461 lpPoints[idx].y= (y - CoorSys.yMin) / CoorSys.ySF;
1462 else
1463 lpPoints[idx].y= log10(y / CoorSys.yMin) / CoorSys.ySF;
1464 }
1465 else // sonst auf Niveau der X-Achse setzen
1466 lpPoints[idx].y= 0;
1467
1468 if ( idx != 0 ) {
1469 if ( !m_Dotted ) {
1470 // ehem. Fehler: Bei gleichem durch Skalierung entstandenem X-Wert
1471 // wurde der Y-Wert des Vorgaengers einfach ueberschrieben.
1472 // so koennte z.B. das abs. Maximum verlorengehen!!!
1473 // Korrektur durch Abfrage
1474 if ( (lpPoints[idx - 1].x == lpPoints[idx].x) ) {
1475 lpPoints[idx - 1].y = max( lpPoints[idx - 1].y, lpPoints[idx].y ); // bei gleichen x-Werten max. y-Wert nehmen
1476 continue;
1477 }
1478 } else
1479 if ( (lpPoints[idx - 1].x == lpPoints[idx].x) && (lpPoints[idx - 1].y == lpPoints[idx].y) ) continue; // nie zwei genau gleiche Punkte in die Liste aufnehmen
1480 }
1481 idx++;
1482 };
1483 };
1484 // ---------------------------------------------------------------------------
1485 //! sichert Koordinatensystem in AltCoorsys
1486 //! m_main.cpp im Falle von cm_MoveScanReady
1487 void TPlotWindow::SetKSProperties(TKSProperties* ksp)
1488 {
1489 if (!ksp)
1490 return;
1491
1492 AltCoorSys.yMin= ksp->fMinY;
1493 AltCoorSys.yMax= ksp->fMaxY;
1494 AltCoorSys.xMin= ksp->fMinX;
1495 AltCoorSys.xMax= ksp->fMaxX;
1496 if (ksp->bLogarithmicY)
1497 AltCoorSys.yScal= sLogarithmic;
1498 else
1499 AltCoorSys.yScal= sLinear;
1500
1501 AltCoorSys.xScal= sLinear; // Logarithmic; geaendert, weil xST meiner Meinung nach nie Logarithmic
1502 bAltCoorSystem= TRUE;
1503 };
1504 //*****************************************************************************
1505
1506 void TPlotWindow::PickUpData(LPARAM data)
1507 //! wird nur in m_main.cpp im Falle von cm_MoveScanReady benoetigt
1508 //! sichert Daten in der SecondCurve
1509 {
1510 *SecondCurve= *((TCurve *)data);
1511 };
1512 //*****************************************************************************
1513
1514 //! wird aufgerufen aus dem Scan-Fenster-Menue unter Scan -> Loeschen
1515 //! bei gesendetem cm_KillSecondCurve
1516 //! setzt SecondCurve auf Initialwerte zurück (loeschen aller Messtripel)
1517 //! zeichnet Scan-Fenster neu
1518 void TPlotWindow::KillSecondCurve(void)
1519 //! SecondCurve wird mit Standardwerten ueberschrieben
1520 {
1521 SecondCurve->New();
1522 //! Update des ClientWindows durch
1523 UpdateWnd();
1524 };
1525 //*****************************************************************************
1526
1527 //! wird aufgerufen aus dem Scan-Fenster-Menue unter Scan -> Fixieren
1528 //! bei gesendetem Kommando cm_FreezeCurve
1529 //! fixiert die aktuelle Hauptkurve -> setzt Pointer von SecondCurve auf MainCurve
1530 void TPlotWindow::FreezeCurve(void)
1531 //! speichert Objektzustand von MainCurve in SecondCurve
1532 {
1533 if (1 > MainCurve->GetPNumber())
1534 return;
1535 *SecondCurve= *MainCurve;
1536 };
1537 //*****************************************************************************
1538
1539 //! wird aufgerufen aus dem Scan-Fenster-Men' unter Scan -> Speichern
1540 //! bei gesendetem Kommando cm_SaveSecondCurve
1541 //! speichert fixierte Kurve (SecondCurve) unter auszuwaehlendem Dateinamen
1542 //! mit Extension *.bk
1543 void TPlotWindow::SaveSecondCurve(void)
1544 //! speichert die SecondCurve
1545 {
1546 char NewFilename[ _MAX_PATH ];
1547 OFSTRUCT of;
1548 int hFile;
1549 float x, y, z;
1550 char buf[MaxString];
1551
1552 // 'Datei Speichern'-Dialog anzeigen und ausgewählte Datei auswerten
1553 char Extension[]= "bk";
1554 sprintf(NewFilename, "*.%s", Extension);
1555 char temp[_MAX_PATH];
1556 strcpy(temp, szMsgLine605); // szMsgLine605 nicht direkt angeben, weil const
1557 if ( !FileSaveDialog(szMsgLine604, temp, NewFilename, "") ) return; // Abbruch wurde geklickt
1558 if ( strlen(NewFilename)==0 || strcmp(NewFilename, "*")==0 ) return;
1559 char dir[_MAX_DIR], drv[_MAX_DRIVE], name[_MAX_FNAME], ext[_MAX_EXT];
1560 _splitpath(NewFilename, drv, dir, name, ext);
1561 _makepath(FileName, drv, dir, name, Extension);
1562
1563 //! erstellen der Datei mit ausgewaehltem Namen + Test, ob dies moeglich
1564 //! wenn nicht, Fehlermeldung + Abbruch
1565 hFile= OpenFile(FileName, &of, OF_CREATE);
1566 if ( hFile==HFILE_ERROR )
1567 {
1568 MessageBox(sth_CannotCreateFile, "Fehler/Error", MBSTOP);
1569 return;
1570 }
1571 //! Wait-Mauszeiger setzen
1572 HCURSOR hOldCursor= SetDefaultCursor( IDC_WAIT );
1573
1574 strcpy(buf, szMsgLine606);
1575 //! FileType mit eingefuehrt - TScanWindow.eSaveFormat= bkFile (beim Einlesen)
1576 strcat(buf, "FileType=Comparison\n");
1577 strcat(buf, "X >> Intensity >> Z\n[Data]\n");
1578 _lwrite(hFile, (LPSTR)buf, strlen(buf));
1579
1580 //! an Anfang der Kurve gehen + Speicher der Punkte fixieren
1581 //! setzt ActualIdx auf 0 oder auf MaxPointIdx, wenn pos>MaxPointidx
1582 //! hier ActualIdx=0
1583 SecondCurve->SetPP();
1584
1585 //! folgendes wird mit FastOpen aktualisiert (betrifft Klasse Curve...)
1586 //! BOOL* lpPV; // Zeiger auf Datenfeld von Validate
1587 //07.05.2004 SecondCurve->FastOpen();
1588
1589 //! FastPGet(x,y,z) holt Werte der Kurve und setzt ActualIdx++ (m_curve.cpp)
1590 //! Kurve Tripel für Tripel auslesen und zeilenweise in der Datei ablegen
1591 while ( SecondCurve->PGet(x, y, z) ) //07.05.2004 FastP...
1592 { //! FIX Fehler 2 Diff/Refl
1593 sprintf(buf, "%.3f %.3f %.3f", x, y, z);
1594 strcat(buf, EOL);
1595 _lwrite(hFile, (LPSTR)buf, strlen(buf));
1596 }
1597 //! Schliežen der Datei + Fixieren des Speichers der Kurve aufheben
1598 //! Wait-Mauszeiger ausschalten
1599 _lclose(hFile);
1600 //! GlobalUnlock(hMemX);GlobalUnlock(hMemY);GlobalUnlock(hMemZ);
1601 //! GlobalUnlock(hMemV);bStreamOpen= FALSE; - Fkt. FastClose();
1602 // 07.05.2004 SecondCurve->FastClose();
1603 SetCursor(hOldCursor);
1604 return;
1605 };
1606