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.

1084 lines
29 KiB

  1. /*
  2. ==============================================================================
  3. Application:
  4. Microsoft Windows NT (TM) Performance Monitor
  5. File:
  6. intrline.c -- IntervalLine custom control.
  7. Copyright 1992, Microsoft Corporation. All Rights Reserved.
  8. ==============================================================================
  9. */
  10. /*
  11. Basic Information
  12. -----------------
  13. An ILine (Interval Line) control is a horizontally-sliding device; the user
  14. can slide the start position and end position independently by dragging
  15. either "grab" bar, or move them simultaneously by dragging the center grab
  16. bar. An ILine control is used in the Input Log dialog of Perfmon, but could
  17. be used anywhere. The control allows the user to specify the start, end and
  18. duration of playback within the range of previously-logged data.
  19. ILine Parts
  20. -----------
  21. iBeginValue iEndValue
  22. | iStartValue iStopValue |
  23. | | | |
  24. v v v v
  25. +------+-+---------------------------------------+-+-----------+
  26. | |X| |X| |
  27. | |X| |X| |
  28. +------+-+---------------------------------------+-+-----------+
  29. ^ ^ ^
  30. Start grab bar Center grab bar Stop grab bar
  31. ILine Terminology
  32. -----------------
  33. All external routines are designated by the prefix ILine-.
  34. Internal routines are designated by the prefix IL-.
  35. The suffix -Value represents an integer in the user-supplied domain.
  36. The suffix -Pixel represents an integer location on the screen.
  37. Note that the range of the IntervalLine is represented by "Begin" and
  38. "End", while the the currently selected interval is represented by
  39. "Start" and "Stop".
  40. Implementation Notes
  41. --------------------
  42. ILine is a custom control, but does not have all the messages
  43. normally associated with a full-fledged control type like "button".
  44. In particular, it doesn't have a keyboard interface or ask it's parent
  45. for color choices. It also doesn't have the functions needed for interfacing
  46. with the dialog editor custom control menu.
  47. An ILine control is designed to work with an integer range of values
  48. specified by the user of the control. These values should have meaning to
  49. the caller. The caller can specify the minimum value of the range
  50. (iBeginValue), the maximum value of the range (iEndValue), and the current
  51. starting and stopping values (iStartValue and iStopValue).
  52. These values are set with a function-based interface. (ILSetXXX).
  53. The code distinguishes between the *values* for the begin, end, start, and
  54. stop, and the *pixels* which represent locations on the control for these
  55. values.
  56. Various bits of the control style allow for changing the control's
  57. behavior.
  58. To allow for multiple ILine controls, all data used by each ILine
  59. instance is allocated from the heap and associated with the control.
  60. The allocation is done in OnCreate and the freeing in OnDestroy. The
  61. instance data is contained in the ILINE structure. Each message handler
  62. retrieves this instance data with the ILData function.
  63. */
  64. //==========================================================================//
  65. // Includes //
  66. //==========================================================================//
  67. #include "perfmon.h"
  68. #include "utils.h"
  69. #include "intrline.h"
  70. #include "pmemory.h" // for MemoryXXX (mallloc-type) routines
  71. BOOL IntrLineFocus ;
  72. //==========================================================================//
  73. // Constants //
  74. //==========================================================================//
  75. #define dwILineClassStyle (CS_HREDRAW | CS_VREDRAW)
  76. #define iILineClassExtra (0)
  77. #define iILineWindowExtra (sizeof (PILINE))
  78. #define dwILineWindowStyle (WS_CHILD | WS_VISIBLE)
  79. #define ILModeNone 0
  80. #define ILModeLeft 1
  81. #define ILModeCenter 2
  82. #define ILModeRight 3
  83. #define TO_THE_END 0x7FFFFFFFL
  84. //==========================================================================//
  85. // Typedefs //
  86. //==========================================================================//
  87. // The instance data for each IL window. One of these is allocated for each
  88. // window in the window's OnCreate processing and free'd in OnDestroy.
  89. typedef struct ILINESTRUCT
  90. { // ILINE
  91. int iBeginValue ; // user-supplied lowest range
  92. int iEndValue ; // user-supplied highest range
  93. int iStartValue ; // current start of selected interval
  94. int iStopValue ; // current end of selected interval
  95. int iGranularityValue ;
  96. int iMinimumRangeValue ;
  97. RECT rectBorder ;
  98. RECT rectLeftBk ;
  99. RECT rectLeftGrab ;
  100. RECT rectCenterGrab ;
  101. RECT rectRightGrab ;
  102. RECT rectRightBk ;
  103. HBRUSH hBrushBk ;
  104. POINTS ptsMouse ;
  105. int iMode ; // who is being tracked?
  106. } ILINE ;
  107. typedef ILINE *PILINE ;
  108. //==========================================================================//
  109. // Macros //
  110. //==========================================================================//
  111. // Width of the start and stob grab bars
  112. #define ILGrabWidth() \
  113. (xScrollThumbWidth)
  114. // A rectangle is "drawable" if it has both nonzero width and height
  115. #define RectDrawable(lpRect) \
  116. ((lpRect->right - lpRect->left) && \
  117. (lpRect->bottom - lpRect->top))
  118. //======================================//
  119. // ILine Accessor Macros //
  120. //======================================//
  121. // These macros reference fields in the ILine structure and should be
  122. // used in place of direct reference to the fields. This makes the code
  123. // easier to read and allows modification of the underlying structure.
  124. // You can use these macros to both get and set the fields.
  125. #define ILBegin(pILine) \
  126. (pILine->iBeginValue)
  127. #define ILEnd(pILine) \
  128. (pILine->iEndValue)
  129. #define ILStart(pILine) \
  130. (pILine->iStartValue)
  131. #define ILStop(pILine) \
  132. (pILine->iStopValue)
  133. #define ILMode(pILine) \
  134. (pILine->iMode)
  135. //======================================//
  136. // ILine Pseudo-Accessor Macros //
  137. //======================================//
  138. // These macros are used to get values which don't correspond to a single
  139. // field. You can get the value with these macros but can't set it.
  140. #define ILWidth(pILine) \
  141. (pILine->rectBorder.right)
  142. #define ILRange(pILine) \
  143. (ILEnd (pILine) - ILBegin (pILine))
  144. #define ILStartPixel(pILine) \
  145. (pILine->rectLeftGrab.left)
  146. #define ILStopPixel(pILine) \
  147. (pILine->rectRightGrab.right)
  148. //==========================================================================//
  149. // Local Functions //
  150. //==========================================================================//
  151. void static ILNotifyChange (HWND hWnd,
  152. PILINE pILine)
  153. { // ILNotifyChange
  154. HWND hWndParent ;
  155. hWndParent = WindowParent (hWnd) ;
  156. if (hWndParent)
  157. SendMessage (hWndParent, WM_COMMAND,
  158. (WPARAM) WindowID (hWnd),
  159. (LPARAM) hWnd) ;
  160. } // ILNotifyChange
  161. BOOL ILGrabRect (IN PILINE pILine,
  162. OUT LPRECT lpRect)
  163. /*
  164. Effect: Return in lpRect the rectangle representing the position
  165. of the grab bar currently being tracked.
  166. */
  167. { // ILGrabRect
  168. switch (ILMode (pILine))
  169. { // switch
  170. case ILModeLeft:
  171. *lpRect = pILine->rectLeftGrab ;
  172. return (TRUE) ;
  173. break ;
  174. case ILModeRight:
  175. *lpRect = pILine->rectRightGrab ;
  176. return (TRUE) ;
  177. break ;
  178. case ILModeCenter:
  179. *lpRect = pILine->rectCenterGrab ;
  180. return (TRUE) ;
  181. break ;
  182. case ILModeNone:
  183. lpRect->left = 0 ;
  184. lpRect->top = 0 ;
  185. lpRect->right = 0 ;
  186. lpRect->bottom = 0 ;
  187. return (FALSE) ;
  188. break ;
  189. } // switch
  190. // return FALSE if it falls through to here
  191. return FALSE;
  192. } // ILGrabRect
  193. PILINE ILData (HWND hWndIL)
  194. {
  195. return ((PILINE) GetWindowLongPtr (hWndIL, 0)) ;
  196. }
  197. PILINE AllocateILData (HWND hWndIL)
  198. {
  199. PILINE pILine ;
  200. pILine = MemoryAllocate (sizeof (ILINE)) ;
  201. SetWindowLongPtr (hWndIL, 0, (LONG_PTR) pILine) ;
  202. return (pILine) ;
  203. }
  204. void static DrawGrab (HDC hDC,
  205. LPRECT lpRectGrab,
  206. BOOL bDown)
  207. { // DrawGrab
  208. if (!RectDrawable (lpRectGrab))
  209. return ;
  210. if (bDown)
  211. ThreeDConcave1 (hDC,
  212. lpRectGrab->left,
  213. lpRectGrab->top,
  214. lpRectGrab->right,
  215. lpRectGrab->bottom) ;
  216. else
  217. ThreeDConvex1 (hDC,
  218. lpRectGrab->left,
  219. lpRectGrab->top,
  220. lpRectGrab->right,
  221. lpRectGrab->bottom) ;
  222. } // DrawGrab
  223. int ILValueToPixel (PILINE pILine,
  224. int iValue)
  225. {
  226. int xPixel ;
  227. if (ILRange (pILine))
  228. xPixel = MulDiv (iValue, ILWidth (pILine), ILRange (pILine)) ;
  229. else
  230. xPixel = 0 ;
  231. return (PinExclusive (xPixel, 0, pILine->rectBorder.right)) ;
  232. }
  233. int ILPixelToValue (PILINE pILine,
  234. int xPixel)
  235. {
  236. int iValue ;
  237. if (ILWidth (pILine))
  238. iValue = MulDiv (xPixel, ILRange (pILine), ILWidth (pILine)) ;
  239. else
  240. iValue = 0 ;
  241. return (PinInclusive (iValue, ILBegin (pILine), ILEnd (pILine))) ;
  242. }
  243. void static ILCalcPositions (HWND hWnd,
  244. PILINE pILine)
  245. /*
  246. Effect: Determine and set all of the physical rectangles of ILine,
  247. based on the current size of the ILine window and the
  248. current logical Start, Stop, Begin, and End values.
  249. */
  250. { // ILCalcPositions
  251. int xStart, xStop ;
  252. int yHeight ;
  253. GetClientRect (hWnd, &pILine->rectBorder) ;
  254. yHeight = pILine->rectBorder.bottom ;
  255. xStart = ILValueToPixel (pILine, ILStart (pILine)) ;
  256. xStop = ILValueToPixel (pILine, ILStop (pILine)) ;
  257. pILine->rectLeftBk.left = 1 ;
  258. pILine->rectLeftBk.top = 1 ;
  259. pILine->rectLeftBk.right = xStart ;
  260. pILine->rectLeftBk.bottom = yHeight - 1 ;
  261. pILine->rectLeftGrab.left = xStart ;
  262. pILine->rectLeftGrab.top = 1 ;
  263. pILine->rectLeftGrab.right = xStart + ILGrabWidth () ;
  264. pILine->rectLeftGrab.bottom = yHeight - 1 ;
  265. pILine->rectRightBk.left = xStop ;
  266. pILine->rectRightBk.top = 1 ;
  267. pILine->rectRightBk.right = pILine->rectBorder.right - 1 ;
  268. pILine->rectRightBk.bottom = yHeight - 1 ;
  269. pILine->rectRightGrab.left = xStop - ILGrabWidth () ;
  270. pILine->rectRightGrab.top = 1 ;
  271. pILine->rectRightGrab.right = xStop ;
  272. pILine->rectRightGrab.bottom = yHeight - 1 ;
  273. pILine->rectCenterGrab.left = pILine->rectLeftGrab.right ;
  274. pILine->rectCenterGrab.top = 1 ;
  275. pILine->rectCenterGrab.right = pILine->rectRightGrab.left ;
  276. pILine->rectCenterGrab.bottom = yHeight - 1 ;
  277. if (pILine->rectLeftGrab.right > pILine->rectRightGrab.left)
  278. {
  279. pILine->rectLeftGrab.right = pILine->rectLeftGrab.left +
  280. (xStop - xStart) / 2 ;
  281. pILine->rectRightGrab.left = pILine->rectLeftGrab.right ;
  282. pILine->rectCenterGrab.left = 0 ;
  283. pILine->rectCenterGrab.right = 0 ;
  284. }
  285. } // ILCalcPositions
  286. void static ILDraw (HDC hDC,
  287. PILINE pILine,
  288. LPRECT lpRectUpdate)
  289. /*
  290. Effect: Draw the image of pILine on hDC. Draw at least the
  291. portions within rectUpdate.
  292. Called By: OnPaint, OnMouseMove.
  293. */
  294. { // ILDraw
  295. HBRUSH hBrush = GetStockObject (BLACK_BRUSH);
  296. if (!hBrush)
  297. return;
  298. //=============================//
  299. // Draw Border //
  300. //=============================//
  301. FrameRect (hDC, &pILine->rectBorder, hBrush);
  302. //=============================//
  303. // Draw Background //
  304. //=============================//
  305. FillRect (hDC, &pILine->rectLeftBk, pILine->hBrushBk) ;
  306. FillRect (hDC, &pILine->rectRightBk, pILine->hBrushBk) ;
  307. //=============================//
  308. // Draw Range Grabs //
  309. //=============================//
  310. DrawGrab (hDC, &pILine->rectLeftGrab,
  311. ILMode (pILine) == ILModeLeft) ;
  312. DrawGrab (hDC, &pILine->rectRightGrab,
  313. ILMode (pILine) == ILModeRight) ;
  314. //=============================//
  315. // Draw Center Grab //
  316. //=============================//
  317. DrawGrab (hDC, &pILine->rectCenterGrab,
  318. ILMode (pILine) == ILModeCenter) ;
  319. } // ILDraw
  320. #if 0
  321. void ILPageLeftRight (HWND hWnd,
  322. PILINE pILine,
  323. BOOL bLeft)
  324. { // ILPageLeftRight
  325. int iStart, iStop, iMove ;
  326. HDC hDC ;
  327. iStart = ILStart (pILine) ;
  328. iStop = ILStop (pILine) ;
  329. if (ILRange (pILine) >= 10)
  330. iMove = ILRange (pILine) / 10 ;
  331. else
  332. iMove = 1 ;
  333. if (bLeft)
  334. iMove = -iMove ;
  335. iStart += iMove ;
  336. iStop += iMove ;
  337. ILineSetStart (hWnd, iStart) ;
  338. ILineSetStop (hWnd, iStop) ;
  339. hDC = GetDC (hWnd) ;
  340. ILDraw (hDC, pILine, &pILine->rectBorder) ;
  341. ReleaseDC (hWnd, hDC) ;
  342. ILNotifyChange (hWnd, pILine) ;
  343. } // ILPageLeftRight
  344. #endif
  345. void ILMoveLeftRight (HWND hWnd,
  346. BOOL bStart,
  347. BOOL bLeft,
  348. int MoveAmt)
  349. { // ILPageLeftRight
  350. int iStart, iStop, iMove ;
  351. int iBegin, iEnd ;
  352. HDC hDC ;
  353. PILINE pILine ;
  354. pILine = ILData (hWnd) ;
  355. iStart = ILStart (pILine) ;
  356. iStop = ILStop (pILine) ;
  357. iBegin = ILBegin (pILine) ;
  358. iEnd = ILEnd (pILine) ;
  359. iMove = MoveAmt ;
  360. if (bLeft)
  361. iMove = -iMove ;
  362. if (bStart)
  363. {
  364. if (MoveAmt == TO_THE_END)
  365. {
  366. iStart = iBegin ;
  367. }
  368. else
  369. {
  370. iStart += iMove ;
  371. if (iStart >= iStop)
  372. {
  373. return;
  374. }
  375. }
  376. ILineSetStart (hWnd, iStart) ;
  377. }
  378. else
  379. {
  380. if (MoveAmt == TO_THE_END)
  381. {
  382. iStop = iEnd ;
  383. }
  384. else
  385. {
  386. iStop += iMove ;
  387. if (iStart >= iStop)
  388. {
  389. return;
  390. }
  391. }
  392. ILineSetStop (hWnd, iStop) ;
  393. }
  394. hDC = GetDC (hWnd) ;
  395. if (hDC) {
  396. ILDraw (hDC, pILine, &pILine->rectBorder) ;
  397. ReleaseDC (hWnd, hDC) ;
  398. }
  399. ILNotifyChange (hWnd, pILine) ;
  400. } // ILMoveLeftRight
  401. static BOOL OnKeyDown (HWND hWnd,
  402. WPARAM wParam)
  403. {
  404. BOOL bHandle = TRUE ;
  405. BOOL bStart ;
  406. BOOL bLeftDirection ;
  407. BOOL bShiftKeyDown ;
  408. if (wParam == VK_LEFT || wParam == VK_RIGHT)
  409. {
  410. bShiftKeyDown = (GetKeyState (VK_SHIFT) < 0) ;
  411. if (!bShiftKeyDown)
  412. {
  413. if (wParam == VK_LEFT)
  414. {
  415. // Left Arrow --> move Start Edge Left
  416. bStart = TRUE ;
  417. bLeftDirection = TRUE ;
  418. }
  419. else
  420. {
  421. // Right Arrow --> move Stop Edge Right
  422. bStart = FALSE ;
  423. bLeftDirection = FALSE ;
  424. }
  425. }
  426. else
  427. {
  428. if (wParam == VK_LEFT)
  429. {
  430. // Shift Left Arrow --> move Stop Edge Left
  431. bStart = FALSE ;
  432. bLeftDirection = TRUE ;
  433. }
  434. else
  435. {
  436. // Shift Right Arrow --> move Start Edge Right
  437. bStart = TRUE ;
  438. bLeftDirection = FALSE ;
  439. }
  440. }
  441. ILMoveLeftRight (hWnd, bStart, bLeftDirection, 1) ;
  442. }
  443. else if (wParam == VK_HOME)
  444. {
  445. // move iStart all the way the Left
  446. ILMoveLeftRight (hWnd, TRUE, TRUE, TO_THE_END) ;
  447. }
  448. else if (wParam == VK_END)
  449. {
  450. // move iStop all the way the right
  451. ILMoveLeftRight (hWnd, FALSE, FALSE, TO_THE_END) ;
  452. }
  453. else
  454. {
  455. bHandle = FALSE ;
  456. }
  457. return (bHandle) ;
  458. } // OnKeyDown
  459. void StartGrab (HWND hWnd,
  460. PILINE pILine)
  461. { // StartGrab
  462. RECT rectUpdate ;
  463. HDC hDC ;
  464. SetCapture (hWnd) ;
  465. ILGrabRect (pILine, &rectUpdate) ;
  466. hDC = GetDC (hWnd) ;
  467. if (hDC) {
  468. ILDraw (hDC, pILine, &rectUpdate) ;
  469. ReleaseDC (hWnd, hDC) ;
  470. } // StartGrab
  471. }
  472. void EndGrab (HWND hWnd,
  473. PILINE pILine)
  474. /*
  475. Internals: Set the mode to null after getting the grab rectangle
  476. so ILGrabRect knows which grab bar to get.
  477. */
  478. {
  479. RECT rectUpdate ;
  480. HDC hDC ;
  481. ReleaseCapture () ;
  482. ILGrabRect (pILine, &rectUpdate) ;
  483. ILMode (pILine) = ILModeNone ;
  484. hDC = GetDC (hWnd) ;
  485. if (hDC) {
  486. ILDraw (hDC, pILine, &rectUpdate) ;
  487. ReleaseDC (hWnd, hDC) ;
  488. }
  489. }
  490. //==========================================================================//
  491. // Message Handlers //
  492. //==========================================================================//
  493. void static OnPaint (HWND hWnd)
  494. {
  495. PAINTSTRUCT ps ;
  496. HDC hDC ;
  497. PILINE pILine ;
  498. pILine = ILData (hWnd) ;
  499. hDC = BeginPaint (hWnd, &ps) ;
  500. ILDraw (hDC, pILine, &ps.rcPaint) ;
  501. EndPaint (hWnd, &ps) ;
  502. }
  503. void static OnCreate (HWND hWnd)
  504. {
  505. PILINE pILine ;
  506. pILine = AllocateILData (hWnd) ;
  507. ILBegin (pILine) = 0 ;
  508. ILEnd (pILine) = 100 ;
  509. ILStart (pILine) = 0 ;
  510. ILStop (pILine) = 100 ;
  511. ILMode (pILine) = ILModeNone ;
  512. pILine->hBrushBk = CreateSolidBrush (crBlue) ;
  513. ILCalcPositions (hWnd, pILine) ;
  514. }
  515. void static OnDestroy (HWND hWnd)
  516. {
  517. PILINE pILine ;
  518. pILine = ILData (hWnd) ;
  519. IntrLineFocus = FALSE ;
  520. DeleteBrush (pILine->hBrushBk) ;
  521. MemoryFree (pILine) ;
  522. }
  523. void static OnLButtonUp (HWND hWnd)
  524. { // OnLButtonUp
  525. PILINE pILine ;
  526. pILine = ILData (hWnd) ;
  527. if (ILMode (pILine) == ILModeNone)
  528. return ;
  529. EndGrab (hWnd, pILine) ;
  530. } // OnLButtonUp
  531. void static OnMouseMove (HWND hWnd,
  532. POINTS ptsMouse)
  533. /*
  534. Effect: Handle any actions needed when the mouse moves in the
  535. ILine hWnd's client area or while the mouse is captured.
  536. In particular, if we are tracking one of the grab bars,
  537. determine if the mouse movement represents a logical value
  538. change and move the grab bar accordingly.
  539. Called By: ILineWndProc, in response to a WM_MOUSEMOVE message.
  540. See Also: OnLButtonDown, OnLButtonUp.
  541. Note: This function has multiple return points.
  542. Note: Since we have captured the mouse, we receive mouse msgs
  543. even when the mouse is outside our client area, but still
  544. in client coordinates. Thus we can have negative mouse
  545. coordinates. That is why we convert the lParam of the
  546. mouse msg into a POINTS structure rather than 2 WORDS.
  547. Internals: Remember that an IntervalLine can only take on integral
  548. values in the user-supplied range. Therefore we do our
  549. movement calculation in user values, not pixels. We
  550. determine what the logical value would be for the previous
  551. (last mouse move) and current mouse position. If these
  552. LOGICAL values differ, we attempt an adjustment of the
  553. grab bar by that logical amount. This way the grab
  554. values assume on integral positions and the calculations
  555. are simplified.
  556. If we calculated by pixel movement, and then shifted the
  557. bar into the nearest integal position, we would encounter
  558. rounding problems. In particular, when tracking the center
  559. grab bar, if we moved both start and stop by the same
  560. amount of PIXELS, then converted to LOGICAL values, we
  561. might find our center bar shrinking and growing while
  562. the bar moves.
  563. */
  564. {
  565. int iMousePrevious, iMouseCurrent ;
  566. int iMouseMove ;
  567. PILINE pILine ;
  568. HDC hDC ;
  569. //=============================//
  570. // Are we tracking? //
  571. //=============================//
  572. pILine = ILData (hWnd) ;
  573. if (ILMode (pILine) == ILModeNone)
  574. return ;
  575. //=============================//
  576. // Calc LOGICAL mouse movement //
  577. //=============================//
  578. ptsMouse.x = PinInclusive ((INT)ptsMouse.x,
  579. (INT)pILine->rectBorder.left,
  580. (INT)pILine->rectBorder.right) ;
  581. iMousePrevious = ILPixelToValue (pILine, pILine->ptsMouse.x) ;
  582. iMouseCurrent = ILPixelToValue (pILine, ptsMouse.x) ;
  583. iMouseMove = iMouseCurrent - iMousePrevious ;
  584. if (!iMouseMove)
  585. return ;
  586. //=============================//
  587. // Move grab bar positions //
  588. //=============================//
  589. switch (ILMode (pILine))
  590. { // switch
  591. case ILModeLeft:
  592. ILStart (pILine) += iMouseMove ;
  593. ILStart (pILine) = min (ILStart (pILine), ILStop (pILine) - 1) ;
  594. break ;
  595. case ILModeCenter:
  596. // Before we slide the center grab bar we need to see if the
  597. // desired movement amount would send either end out of bounds,
  598. // and reduce the movement accordingly.
  599. if (ILStart (pILine) + iMouseMove < ILBegin (pILine))
  600. iMouseMove = ILBegin (pILine) - ILStart (pILine) ;
  601. if (ILStop (pILine) + iMouseMove > ILEnd (pILine))
  602. iMouseMove = ILEnd (pILine) - ILStop (pILine) ;
  603. ILStart (pILine) += iMouseMove ;
  604. ILStop (pILine) += iMouseMove ;
  605. break ;
  606. case ILModeRight:
  607. ILStop (pILine) += iMouseMove ;
  608. ILStop (pILine) = max (ILStart (pILine) + 1, ILStop (pILine)) ;
  609. break ;
  610. } // switch
  611. //=============================//
  612. // Keep grab bars in range //
  613. //=============================//
  614. ILStart (pILine) = PinInclusive (ILStart (pILine),
  615. ILBegin (pILine), ILEnd (pILine)) ;
  616. ILStop (pILine) = PinInclusive (ILStop (pILine),
  617. ILBegin (pILine), ILEnd (pILine)) ;
  618. //=============================//
  619. // Determine pixel pos, draw //
  620. //=============================//
  621. ILCalcPositions (hWnd, pILine) ;
  622. hDC = GetDC (hWnd) ;
  623. if (hDC) {
  624. ILDraw (hDC, pILine, &pILine->rectBorder) ;
  625. ReleaseDC (hWnd, hDC) ;
  626. }
  627. pILine->ptsMouse = ptsMouse ;
  628. ILNotifyChange (hWnd, pILine) ;
  629. } // OnMouseMove
  630. void static OnLButtonDown (HWND hWnd,
  631. POINTS ptsMouse)
  632. {
  633. PILINE pILine ;
  634. POINT ptMouse ;
  635. pILine = ILData (hWnd) ;
  636. pILine->ptsMouse = ptsMouse ;
  637. ptMouse.x = ptsMouse.x ;
  638. ptMouse.y = ptsMouse.y ;
  639. #if 0
  640. // Russ said this is bad, so don't do it
  641. if (PtInRect (&pILine->rectLeftBk, ptMouse))
  642. ILPageLeftRight (hWnd, pILine, TRUE) ;
  643. else if (PtInRect (&pILine->rectRightBk, ptMouse))
  644. ILPageLeftRight (hWnd, pILine, FALSE) ;
  645. else if (PtInRect (&pILine->rectLeftGrab, ptMouse))
  646. #endif
  647. if (PtInRect (&pILine->rectLeftGrab, ptMouse) ||
  648. PtInRect (&pILine->rectLeftBk, ptMouse))
  649. {
  650. ILMode (pILine) = ILModeLeft ;
  651. StartGrab (hWnd, pILine) ;
  652. }
  653. else if (PtInRect (&pILine->rectRightGrab, ptMouse) ||
  654. PtInRect (&pILine->rectRightBk, ptMouse))
  655. {
  656. ILMode (pILine) = ILModeRight ;
  657. StartGrab (hWnd, pILine) ;
  658. }
  659. else if (PtInRect (&pILine->rectCenterGrab, ptMouse))
  660. {
  661. ILMode (pILine) = ILModeCenter ;
  662. StartGrab (hWnd, pILine) ;
  663. }
  664. }
  665. void static OnSize (HWND hWnd, WORD xWidth, WORD yHeight)
  666. { // OnSize
  667. PILINE pILine ;
  668. pILine = ILData (hWnd) ;
  669. ILCalcPositions (hWnd, pILine) ;
  670. } // OnSize
  671. //==========================================================================//
  672. // Exported Functions //
  673. //==========================================================================//
  674. LRESULT
  675. FAR
  676. PASCAL
  677. ILineWndProc (
  678. HWND hWnd,
  679. unsigned msg,
  680. WPARAM wParam,
  681. LPARAM lParam
  682. )
  683. /*
  684. Note: This function must be declared in the application's
  685. linker-definition file, perfmon.def file.
  686. */
  687. { // ILineWndProc
  688. BOOL bCallDefWindowProc ;
  689. POINTS ptsMouse ;
  690. LRESULT lReturnValue ;
  691. bCallDefWindowProc = FALSE ;
  692. lReturnValue = 0L ;
  693. switch (msg)
  694. { // switch
  695. case WM_CREATE:
  696. OnCreate (hWnd) ;
  697. break ;
  698. case WM_DESTROY:
  699. OnDestroy (hWnd) ;
  700. break ;
  701. case WM_LBUTTONDOWN:
  702. // See the note in OnMouseMove for why we are using POINTS
  703. SetFocus (hWnd) ;
  704. ptsMouse = MAKEPOINTS (lParam) ;
  705. OnLButtonDown (hWnd, ptsMouse) ;
  706. break ;
  707. case WM_LBUTTONUP:
  708. OnLButtonUp (hWnd) ;
  709. break ;
  710. case WM_SETFOCUS:
  711. case WM_KILLFOCUS:
  712. {
  713. PILINE pILine ;
  714. IntrLineFocus = (msg == WM_SETFOCUS) ;
  715. pILine = ILData (hWnd) ;
  716. ILNotifyChange (hWnd, pILine) ;
  717. }
  718. return 0 ;
  719. case WM_MOUSEMOVE:
  720. // See the note in OnMouseMove for why we are using POINTS
  721. ptsMouse = MAKEPOINTS (lParam) ;
  722. OnMouseMove (hWnd, ptsMouse) ;
  723. break ;
  724. case WM_KEYDOWN:
  725. if (!OnKeyDown (hWnd, wParam))
  726. {
  727. bCallDefWindowProc = TRUE ;
  728. }
  729. break ;
  730. case WM_GETDLGCODE:
  731. // We want to handle Arrow keys input. If we don't specify this
  732. // the dialog will not pass arrow keys to us.
  733. return (DLGC_WANTARROWS) ;
  734. break ;
  735. case WM_PAINT:
  736. OnPaint (hWnd) ;
  737. break ;
  738. case WM_SIZE:
  739. OnSize (hWnd, LOWORD (lParam), HIWORD (lParam)) ;
  740. default:
  741. bCallDefWindowProc = TRUE ;
  742. } // switch
  743. if (bCallDefWindowProc)
  744. lReturnValue = DefWindowProc (hWnd, msg, wParam, lParam) ;
  745. return (lReturnValue) ;
  746. } // ILineWndProc
  747. BOOL ILineInitializeApplication (void)
  748. /*
  749. Effect: Perform all initializations required before an application
  750. can create an IntervalLine. In particular, register the
  751. IntervalLine window class.
  752. Called By: The application, in its InitializeApplication routine.
  753. Returns: Whether the class could be registered.
  754. */
  755. { // ILineInitializeApplication
  756. WNDCLASS wc ;
  757. wc.style = dwILineClassStyle ;
  758. wc.lpfnWndProc = ILineWndProc ;
  759. wc.cbClsExtra = iILineClassExtra ;
  760. wc.cbWndExtra = iILineWindowExtra ;
  761. wc.hInstance = hInstance ;
  762. wc.hIcon = NULL ;
  763. wc.hCursor = LoadCursor (NULL, IDC_ARROW) ;
  764. wc.hbrBackground = NULL ;
  765. wc.lpszMenuName = NULL ;
  766. wc.lpszClassName = szILineClass ;
  767. return (RegisterClass (&wc)) ;
  768. } // ILineInitializeApplication
  769. void ILineSetRange (HWND hWnd, int iBegin, int iEnd)
  770. { // ILineSetRange
  771. PILINE pILine ;
  772. pILine = ILData (hWnd) ;
  773. ILBegin (pILine) = iBegin ;
  774. ILEnd (pILine) = iEnd ;
  775. ILCalcPositions (hWnd, pILine) ;
  776. } // ILineSetRange
  777. void ILineSetStart (HWND hWnd, int iStart)
  778. { // ILineSetStart
  779. PILINE pILine ;
  780. pILine = ILData (hWnd) ;
  781. iStart = PinInclusive (iStart, ILBegin (pILine), ILEnd (pILine)) ;
  782. ILStart (pILine) = iStart ;
  783. ILCalcPositions (hWnd, pILine) ;
  784. } // ILineSetStart
  785. void ILineSetStop (HWND hWnd, int iStop)
  786. { // ILineSetStop
  787. PILINE pILine ;
  788. pILine = ILData (hWnd) ;
  789. iStop = PinInclusive (iStop, ILBegin (pILine), ILEnd (pILine)) ;
  790. ILStop (pILine) = iStop ;
  791. ILCalcPositions (hWnd, pILine) ;
  792. } // ILineSetStop
  793. int ILineXStart (HWND hWnd)
  794. {
  795. PILINE pILine ;
  796. pILine = ILData (hWnd) ;
  797. return (pILine->rectLeftGrab.left) ;
  798. }
  799. int ILineXStop (HWND hWnd)
  800. {
  801. PILINE pILine ;
  802. pILine = ILData (hWnd) ;
  803. return (pILine->rectRightGrab.right) ;
  804. }
  805. int ILineStart (HWND hWnd)
  806. {
  807. PILINE pILine ;
  808. pILine = ILData (hWnd) ;
  809. return (ILStart (pILine)) ;
  810. }
  811. int ILineStop (HWND hWnd)
  812. {
  813. PILINE pILine ;
  814. pILine = ILData (hWnd) ;
  815. return (ILStop (pILine)) ;
  816. }