|
|
1.1 root 1: /*
2: ==============================================================================
3:
4: Application:
5:
6: Microsoft Windows NT (TM) Performance Monitor
7:
8: File:
9: status.c - Status window procedure and supporting routines.
10:
11: This file contains code creating the status window, which is
12: a child of the legend window. The status window shows the
13: time duration of the chart, and the last, avg, min and max
14: of the currently-selected chart line.
15:
16:
17: Copyright 1992, Microsoft Corporation. All Rights Reserved.
18: ==============================================================================
19: */
20:
21:
22: //==========================================================================//
23: // Includes //
24: //==========================================================================//
25:
26:
27: #include <stdio.h>
28: #include <stdlib.h> // for mbstowcs
29:
30:
31: #include "perfmon.h"
32: #include "valuebar.h"
33:
34: #include "grafdata.h" // for CurrentGraphLine
35: #include "graph.h"
36: #include "playback.h" // for PlayingBackLog
37: #include "legend.h"
38: #include "utils.h"
39:
40:
41:
42: //==========================================================================//
43: // Constants //
44: //==========================================================================//
45: HDC hVBarDC ;
46:
47: #define szGraphStatusClass TEXT("PerfmonGraphStatusClass")
48: #define dwGraphStatusClassStyle (CS_HREDRAW | CS_VREDRAW | CS_OWNDC)
49: #define iGraphStatusClassExtra (0)
50: #define iGraphStatusWindowExtra (0)
51: #define dwGraphStatusWindowStyle (WS_CHILD | WS_VISIBLE)
52:
53:
54: #define szStatusValueFormat TEXT("%10.3f")
55: #define szStatusMediumnValueFormat TEXT("%10.0f")
56: #define szStatusLargeValueFormat TEXT("%10.4e")
57: #define eStatusValueTooLarge ((FLOAT) 1.0E+20)
58: #define eStatusValueMax ((FLOAT) 999999.999)
59: #define eStatusLargeValueMax ((FLOAT) 9999999999.0)
60:
61:
62: #define szValueTooHigh TEXT("+ + + +")
63: #define szValueTooLow TEXT("- - - -")
64:
65: #define StatusLastElt 0
66: #define StatusAvgElt 1
67: #define StatusMinElt 2
68: #define StatusMaxElt 3
69: #define StatusTimeElt 4
70:
71: #define StatusNumElts 5
72:
73: #define StatusDrawAvg(hDC, eValue, bForceRedraw) \
74: DrawStatusValue (hDC, StatusAvgElt, eValue, bForceRedraw)
75:
76: #define StatusDrawMax(hDC, eValue, bForceRedraw) \
77: DrawStatusValue (hDC, StatusMaxElt, eValue, bForceRedraw)
78:
79: #define StatusDrawMin(hDC, eValue, bForceRedraw) \
80: DrawStatusValue (hDC, StatusMinElt, eValue, bForceRedraw)
81:
82: //==========================================================================//
83: // Typedefs //
84: //==========================================================================//
85:
86:
87: typedef struct StatusEltStruct
88: {
89: TCHAR szText [20] ;
90: int xTextPos ;
91: int xValuePos ;
92: FLOAT eValue ;
93: } StatusEltType ;
94:
95:
96: // This structure represents the "instance data" for a StatusWindow. The
97: // information is collected in a structure to ease the conversion of this
98: // code when later adding multiple graph windows. For now, one copy of this
99: // struct is defined as local data to this file.
100: typedef struct StatusDataStruct
101: {
102: StatusEltType aElts [StatusNumElts] ;
103: SIZE sizeValue ;
104: int yHeight ;
105: } StatusDataType ;
106:
107:
108:
109: //==========================================================================//
110: // Local Data //
111: //==========================================================================//
112:
113:
114: StatusDataType StatusData ;
115:
116:
117: //==========================================================================//
118: // Macros //
119: //==========================================================================//
120:
121:
122: #define StatusTopMargin() (2)
123: #define StatusBottomMargin() (4)
124:
125: #define StatusLeftMargin() (3)
126: #define StatusTextMargin() (5 + ThreeDPad)
127: #define StatusValueMargin() (3 + ThreeDPad)
128:
129:
130: //==========================================================================//
131: // Local Functions //
132: //==========================================================================//
133:
134:
135: void DrawStatusValue (HDC hDC,
136: int iEltOffset,
137: FLOAT eValue,
138: BOOL bForceRedraw)
139: /*
140: Called By: StatusDrawTime, StatusDrawLast, StatusDrawAvg,
141: StatusDrawMin, StatusDrawMax.
142: */
143: { // DrawStatusValue
144: RECT rectValue ;
145: TCHAR szValue [20] ;
146:
147: if (!bForceRedraw && eValue == StatusData.aElts[iEltOffset].eValue)
148: return ;
149: StatusData.aElts[iEltOffset].eValue = eValue ;
150:
151: rectValue.left = StatusData.aElts[iEltOffset].xValuePos ;
152: rectValue.top = StatusTopMargin () + ThreeDPad + 1;
153: rectValue.right = rectValue.left + StatusData.sizeValue.cx ;
154: rectValue.bottom = rectValue.top + StatusData.sizeValue.cy ;
155:
156:
157: if (eValue > eStatusValueMax)
158: {
159: if (eValue > eStatusValueTooLarge)
160: {
161: lstrcpy (szValue, szValueTooHigh) ;
162: }
163: else
164: {
165: TSPRINTF (szValue,
166: (eValue > eStatusLargeValueMax) ? szStatusLargeValueFormat :
167: szStatusMediumnValueFormat,
168: eValue) ;
169: }
170: }
171: else if (eValue < -eStatusValueMax)
172: lstrcpy (szValue, szValueTooLow) ;
173: else
174: TSPRINTF (szValue, szStatusValueFormat, eValue) ;
175:
176: ExtTextOut (hDC, rectValue.right, rectValue.top, ETO_OPAQUE, &rectValue,
177: szValue, lstrlen (szValue), NULL) ;
178: } // DrawStatusValue
179:
180:
181: //==========================================================================//
182: // Message Handlers //
183: //==========================================================================//
184:
185:
186: //void static OnCreate (HWND hWnd)
187: void OnVBarCreate (HWND hWnd)
188: /*
189: Effect: Perform any actions needed when a status window is created.
190: In particular, set the instance data to initial values,
191: determine the size and placement of the various elements
192: of the status display.
193:
194: Called By: GraphStatusWndProc only, in response to a WM_CREATE message.
195: */
196: { // OnCreate
197: TCHAR szValue [20] ;
198: HDC hDC ;
199: int iLen ;
200: int i ;
201:
202:
203: hDC = hVBarDC = GetDC (hWnd) ;
204: SelectFont (hDC, hFontScales) ;
205: SetBkColor (hDC, ColorBtnFace) ;
206: SetTextAlign (hDC, TA_RIGHT | TA_TOP) ;
207:
208: //=============================//
209: // Load Text Labels //
210: //=============================//
211:
212: StringLoad (IDS_STATUSLAST, StatusData.aElts[StatusLastElt].szText) ;
213: StringLoad (IDS_STATUSAVG, StatusData.aElts[StatusAvgElt].szText) ;
214: StringLoad (IDS_STATUSMIN, StatusData.aElts[StatusMinElt].szText) ;
215: StringLoad (IDS_STATUSMAX, StatusData.aElts[StatusMaxElt].szText) ;
216: StringLoad (IDS_STATUSTIME, StatusData.aElts[StatusTimeElt].szText) ;
217:
218: //=============================//
219: // Determine Status Height //
220: //=============================//
221:
222: StatusData.yHeight = StatusTopMargin () +
223: StatusBottomMargin () +
224: FontHeight (hDC, TRUE) +
225: 2 * ThreeDPad ;
226:
227: //=============================//
228: // Set position/size of elts //
229: //=============================//
230:
231: // Determine the bounding box for each status value by using a max value.
232: iLen = TSPRINTF (szValue, szStatusLargeValueFormat, -eStatusValueMax) ;
233:
234: GetTextExtentPoint (hDC, szValue, lstrlen(szValue), &StatusData.sizeValue) ;
235: for (i = 0 ;
236: i < StatusNumElts ;
237: i++)
238: { // for
239: StatusData.aElts[i].eValue = (FLOAT) 0.0 ;
240:
241: if (i)
242: StatusData.aElts[i].xTextPos =
243: StatusTextMargin () +
244: StatusData.aElts[i - 1].xValuePos +
245: StatusData.sizeValue.cx ;
246: else
247: StatusData.aElts[i].xTextPos = StatusLeftMargin () ;
248: StatusData.aElts[i].xValuePos = StatusData.aElts[i].xTextPos +
249: StatusValueMargin () +
250: TextWidth (hDC, StatusData.aElts[i].szText) ;
251: } // for
252: } // OnCreate
253:
254:
255:
256: void static OnPaint (HWND hWnd)
257: /*
258: Effect: Paint the invalid surface of hWnd. Draw each label, each
259: recessed value box, and each value.
260:
261: Called By: GraphStatusWndProc only, in response to a WM_PAINT message.
262: */
263: {
264: HDC hDC ;
265: PAINTSTRUCT ps ;
266: RECT rectClient ;
267: int i ;
268: PLINESTRUCT pLine;
269:
270: hDC = BeginPaint (hWnd, &ps) ;
271: SetBkMode (hDC, TRANSPARENT) ;
272:
273: GetClientRect (hWnd, &rectClient) ;
274: HLine (hDC, GetStockObject (BLACK_PEN),
275: rectClient.left, rectClient.right,
276: rectClient.bottom - 1) ;
277:
278: if ((pGraphs->gOptions.bStatusBarChecked) &&
279: (pGraphs->gOptions.bLegendChecked))
280: { // if
281: UINT hPrevTextAlign = SetTextAlign (hDC, TA_LEFT | TA_TOP) ;
282:
283: for (i = 0 ;
284: i < StatusNumElts ;
285: i++)
286: { // for
287: // Draw the label
288: TextOut (hDC, StatusData.aElts[i].xTextPos, StatusTopMargin () + ThreeDPad,
289: StatusData.aElts[i].szText,
290: lstrlen (StatusData.aElts[i].szText)) ;
291:
292: // Draw the recesed value box
293: ThreeDConcave1 (hDC,
294: StatusData.aElts[i].xValuePos - ThreeDPad,
295: StatusTopMargin (),
296: StatusData.aElts[i].xValuePos + StatusData.sizeValue.cx + ThreeDPad,
297: StatusTopMargin () + StatusData.sizeValue.cy + 2 * ThreeDPad ) ;
298: } // for
299:
300: // restore TextAlign for drawing values
301: SetTextAlign (hDC, hPrevTextAlign) ;
302:
303: // Draw the values themselves
304:
305: pLine = CurrentGraphLine (hWndGraph) ;
306: StatusDrawTime (hDC, TRUE) ;
307:
308: StatusDrawLast (hDC, pLine, TRUE) ;
309:
310: if (pLine)
311: {
312: StatusDrawAvg (hDC, pLine->lnAveValue, TRUE) ;
313: StatusDrawMin (hDC, pLine->lnMinValue, TRUE) ;
314: StatusDrawMax (hDC, pLine->lnMaxValue, TRUE) ;
315: }
316: else
317: {
318: StatusDrawAvg (hVBarDC, (FLOAT)0.0, TRUE) ;
319: StatusDrawMax (hVBarDC, (FLOAT)0.0, TRUE) ;
320: StatusDrawMin (hVBarDC, (FLOAT)0.0, TRUE) ;
321: }
322: } // if
323:
324: EndPaint (hWnd, &ps) ;
325: } // StatusPaint
326:
327:
328: //==========================================================================//
329: // Exported Functions //
330: //==========================================================================//
331:
332:
333:
334: void StatusDrawTime (HDC hDC, BOOL bForceRedraw)
335: /*
336: Called By: StatusTimer, StatusPaint.
337: */
338: { // StatusDrawTime
339: FLOAT eTimeSeconds ;
340:
341: if (PlayingBackLog ())
342: eTimeSeconds = (FLOAT) PlaybackSelectedSeconds () ;
343: else
344: eTimeSeconds = pGraphs->gOptions.eTimeInterval *
345: (FLOAT) pGraphs->gMaxValues;
346:
347: DrawStatusValue (hDC, StatusTimeElt, eTimeSeconds, bForceRedraw) ;
348: } // StatusDrawTime
349:
350:
351: void StatusDrawLast (HDC hDC, PLINESTRUCT pLine, BOOL bForceRedraw)
352: /*
353: Called By: StatusTimer, StatusPaint.
354: */
355: {
356: INT iKnownValue ;
357: int iMaxValues ;
358: FLOAT eValue ;
359:
360: if (!pLine)
361: eValue = (FLOAT) 0.0 ;
362: else
363: {
364: iKnownValue = pGraphs->gKnownValue ;
365: iMaxValues = pGraphs->gMaxValues ;
366: eValue = pLine->lnValues [iKnownValue % iMaxValues] ;
367: }
368:
369: DrawStatusValue (hDC, StatusLastElt, eValue, bForceRedraw) ;
370: }
371:
372: #if 0
373: void StatusDrawAvg (HDC hDC, PLINESTRUCT pLine, BOOL bForceRedraw)
374: /*
375: Called By: StatusTimer, StatusPaint.
376: */
377: {
378: FLOAT eValue ;
379:
380: if (!pLine)
381: eValue = (FLOAT) 0.0 ;
382: else
383: eValue = pLine->lnAveValue ;
384:
385: DrawStatusValue (hDC, StatusAvgElt, eValue, bForceRedraw) ;
386: }
387:
388:
389: void StatusDrawMax (HDC hDC, PLINESTRUCT pLine, BOOL bForceRedraw)
390: /*
391: Called By: StatusTimer, StatusPaint.
392: */
393: {
394: FLOAT eValue ;
395:
396: if (!pLine)
397: eValue = (FLOAT) 0.0 ;
398: else
399: eValue = pLine->lnMaxValue ;
400:
401: DrawStatusValue (hDC, StatusMaxElt, eValue, bForceRedraw) ;
402: }
403:
404:
405: void StatusDrawMin (HDC hDC, PLINESTRUCT pLine, BOOL bForceRedraw)
406: /*
407: Called By: StatusTimer, StatusPaint.
408: */
409: {
410: FLOAT eValue ;
411:
412: if (!pLine)
413: eValue = (FLOAT) 0.0 ;
414: else
415: eValue = pLine->lnMinValue ;
416:
417: DrawStatusValue (hDC, StatusMinElt, eValue, bForceRedraw) ;
418: }
419: #endif
420:
421:
422: LRESULT APIENTRY GraphStatusWndProc (HWND hWnd,
423: WORD wMsg,
424: WPARAM wParam,
425: LPARAM lParam)
426: { // GraphStatusWndProc
427: BOOL bCallDefProc ;
428: LRESULT lReturnValue ;
429:
430:
431: bCallDefProc = FALSE ;
432: lReturnValue = 0L ;
433:
434: switch (wMsg)
435: { // switch
436: case WM_CREATE:
437: //OnCreate (hWnd) ;
438: OnVBarCreate (hWnd) ;
439: break ;
440:
441:
442: case WM_PAINT:
443: OnPaint (hWnd) ;
444: break ;
445:
446: case WM_DESTROY:
447: ReleaseDC (hWnd, hVBarDC) ;
448: break ;
449:
450: default:
451: bCallDefProc = TRUE ;
452: } // switch
453:
454:
455: if (bCallDefProc)
456: lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ;
457:
458: return (lReturnValue);
459: } // GraphStatusWndProc
460:
461:
462: int ValuebarHeight (HWND hWnd)
463: /*
464: Effect: A status window has a preferred height, based on the font
465: used in its display. Return the preferred height, determined
466: when the window was created.
467:
468: Assert: OnCreate has already been called, and it set
469: StatusData.yHeight.
470: */
471: {
472: return (StatusData.yHeight) ;
473: }
474:
475:
476: void StatusTimer (HWND hWnd, BOOL bForceRedraw)
477: /*
478: Effect: Perform any status-window actions necessary when a timer
479: tick has been received. In particular, update (redraw)
480: any of the changed values in the status bar.
481:
482: Internals: Each of these called functions compares the value to be
483: displayed with the previous value and doesn't draw if the
484: values are equal.
485: */
486: { // StatusTimer
487: PLINESTRUCT pLine;
488:
489:
490:
491: pLine = CurrentGraphLine (hWndGraph) ;
492:
493: StatusDrawLast (hVBarDC, pLine, bForceRedraw) ;
494:
495: if (pLine)
496: {
497: StatusDrawAvg (hVBarDC, pLine->lnAveValue, bForceRedraw) ;
498: StatusDrawMin (hVBarDC, pLine->lnMinValue, bForceRedraw) ;
499: StatusDrawMax (hVBarDC, pLine->lnMaxValue, bForceRedraw) ;
500: }
501: else
502: {
503: StatusDrawAvg (hVBarDC, (FLOAT)0.0, bForceRedraw) ;
504: StatusDrawMax (hVBarDC, (FLOAT)0.0, bForceRedraw) ;
505: StatusDrawMin (hVBarDC, (FLOAT)0.0, bForceRedraw) ;
506: }
507: } // StatusTimer
508:
509:
510:
511: HWND CreateGraphStatusWindow (HWND hWndGraph)
512: {
513: return (CreateWindow (szGraphStatusClass, // class
514: NULL, // caption
515: dwGraphStatusWindowStyle, // window style
516: 0, 0, // position
517: 0, 0, // size
518: hWndGraph, // parent window
519: NULL, // menu
520: hInstance, // program instance
521: NULL)) ; // user-supplied data
522: }
523:
524:
525:
526:
527: BOOL GraphStatusInitializeApplication (void)
528: /*
529: Called By: GraphInitializeApplication only
530: */
531: {
532: WNDCLASS wc ;
533:
534: wc.style = dwGraphStatusClassStyle ;
535: wc.lpfnWndProc = (WNDPROC) GraphStatusWndProc ;
536: wc.hInstance = hInstance ;
537: wc.cbClsExtra = iGraphStatusClassExtra ;
538: wc.cbWndExtra = iGraphStatusWindowExtra ;
539: wc.hIcon = NULL ;
540: wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
541: wc.hbrBackground = hbLightGray ;
542: wc.lpszMenuName = NULL ;
543: wc.lpszClassName = szGraphStatusClass ;
544:
545: return (RegisterClass (&wc)) ;
546: }
547:
548:
549:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.