Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

503 lines
16 KiB

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