home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / perfmon / valuebar.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  17KB  |  559 lines

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