|
|
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.