|
|
1.1 ! root 1: /* ! 2: ============================================================================== ! 3: ! 4: Application: ! 5: ! 6: Microsoft Windows NT (TM) Performance Monitor ! 7: ! 8: File: ! 9: legend.c - legend window routines. ! 10: ! 11: This file contains code creating the legend window, which is ! 12: a child of the graph windows. The legend window displays a ! 13: legend line for each line in the associated graph. It also ! 14: includes an area called the label, which are headers for those ! 15: lines. ! 16: ! 17: ! 18: Copyright 1992, Microsoft Corporation. All Rights Reserved. ! 19: ============================================================================== ! 20: */ ! 21: ! 22: ! 23: //==========================================================================// ! 24: // Includes // ! 25: //==========================================================================// ! 26: ! 27: ! 28: #include <stdio.h> // for sprintf ! 29: #include "perfmon.h" ! 30: #include "legend.h" // external declarations for this file ! 31: ! 32: #include "owndraw.h" ! 33: ! 34: #include "alert.h" // for EditAlert ! 35: #include "grafdata.h" // for EditChart ! 36: #include "pmemory.h" // for MemoryXXX (mallloc-type) routines ! 37: #include "utils.h" ! 38: #include "valuebar.h" // for StatusTimer ! 39: #include "playback.h" // for PlayingBackLog() ! 40: ! 41: #define eScaleValueSpace TEXT(">9999999999.0") ! 42: ! 43: //==========================================================================// ! 44: // Constants // ! 45: //==========================================================================// ! 46: ! 47: ! 48: #define dwGraphLegendClassStyle (CS_HREDRAW | CS_VREDRAW) ! 49: #define iGraphLegendClassExtra (0) ! 50: #define iGraphLegendWindowExtra (sizeof (PLEGEND)) ! 51: #define dwGraphLegendWindowStyle (WS_CHILD | WS_VISIBLE) ! 52: ! 53: #define xLegendBorderWidth (xDlgBorderWidth) ! 54: #define yLegendBorderHeight (yDlgBorderHeight) ! 55: ! 56: #define iLabelLen 30 ! 57: #define iLegendColMax 1000 ! 58: ! 59: #define LEFTORIENTATION 1 ! 60: #define CENTERORIENTATION 2 ! 61: #define RIGHTORIENTATION 3 ! 62: ! 63: #define LegendColorCol 0 ! 64: #define LegendScaleCol 1 ! 65: #define LegendCounterCol 2 ! 66: #define LegendInstanceCol 3 ! 67: #define LegendParentCol 4 ! 68: #define LegendObjectCol 5 ! 69: #define LegendSystemCol 6 ! 70: ! 71: #define iLegendNumCols 7 ! 72: ! 73: #define iLegendMaxVisibleItems 8 ! 74: ! 75: #define dwGraphLegendItemsWindowClass TEXT("ListBox") ! 76: #define dwGraphLegendItemsWindowStyle \ ! 77: (LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED | \ ! 78: WS_VISIBLE | WS_CHILD | WS_VSCROLL) ! 79: ! 80: ! 81: //==========================================================================// ! 82: // Typedefs // ! 83: //==========================================================================// ! 84: ! 85: ! 86: typedef struct LEGENDCOLSTRUCT ! 87: { ! 88: TCHAR szLabel [iLabelLen] ; ! 89: int xMinWidth ; ! 90: int xMaxWidth ; ! 91: int xWidth ; ! 92: int xPos ; ! 93: int iOrientation ; ! 94: } LEGENDCOL ; ! 95: ! 96: typedef LEGENDCOL *PLEGENDCOL ; ! 97: ! 98: ! 99: typedef struct LEGENDTRUCT ! 100: { ! 101: HWND hWndItems ; ! 102: HFONT hFontItems ; ! 103: HFONT hFontLabels ; ! 104: int xMinWidth ; ! 105: int yLabelHeight ; ! 106: int yItemHeight ; ! 107: int iNumItemsVisible ; ! 108: LEGENDCOL aCols [iLegendNumCols] ; ! 109: int iLineType ; ! 110: PLINE pCurrentLine ; // current selected line ! 111: } LEGEND ; ! 112: ! 113: typedef LEGEND *PLEGEND ; ! 114: ! 115: ! 116: //==========================================================================// ! 117: // Macros // ! 118: //==========================================================================// ! 119: ! 120: ! 121: #define LabelTopMargin() (2) ! 122: #define LegendLeftMargin() (3 + ThreeDPad) ! 123: ! 124: #define LegendItemTopMargin() (yBorderHeight) ! 125: ! 126: ! 127: #define IsLegendLabelVisible() (TRUE) ! 128: ! 129: #define ColCanGrow(pCol) \ ! 130: (pCol->xMaxWidth > pCol->xWidth) ! 131: ! 132: ! 133: #define LegendHorzMargin() (3) ! 134: ! 135: ! 136: ! 137: //==========================================================================// ! 138: // Local Data // ! 139: //==========================================================================// ! 140: ! 141: ! 142: // LEGEND Legend ; ! 143: PLEGEND pGraphLegendData ; ! 144: PLEGEND pAlertLegendData ; ! 145: ! 146: #define LegendData(hWnd) \ ! 147: ((hWnd == hWndGraphLegend) ? pGraphLegendData : pAlertLegendData ) ! 148: ! 149: //==========================================================================// ! 150: // Local Functions // ! 151: //==========================================================================// ! 152: void LegendSetCurrentLine (PLEGEND pLegend, int iIndex) ! 153: { ! 154: pLegend->pCurrentLine = ! 155: (PLINESTRUCT) LBData (pLegend->hWndItems, iIndex) ; ! 156: ! 157: if (pLegend->pCurrentLine == (PLINESTRUCT) LB_ERR) ! 158: { ! 159: pLegend->pCurrentLine = NULL ; ! 160: } ! 161: } // LegendSetCurrentLine ! 162: ! 163: #if 0 ! 164: PLEGEND LegendData (HWND hWnd) ! 165: { ! 166: return ((PLEGEND) GetWindowLong (hWnd, 0)) ; ! 167: } ! 168: #endif ! 169: ! 170: ! 171: PLEGEND AllocateLegendData (HWND hWnd, BOOL bChartLegend) ! 172: { ! 173: PLEGEND pLegend ; ! 174: ! 175: pLegend = MemoryAllocate (sizeof (LEGEND)) ; ! 176: // SetWindowLong (hWnd, 0, (LONG) pLegend) ; ! 177: ! 178: if (bChartLegend) ! 179: { ! 180: hWndGraphLegend = hWnd ; ! 181: pGraphLegendData = pLegend ; ! 182: } ! 183: else ! 184: { ! 185: hWndAlertLegend = hWnd ; ! 186: pAlertLegendData = pLegend ; ! 187: } ! 188: ! 189: return (pLegend) ; ! 190: } ! 191: ! 192: ! 193: ! 194: void DrawLegendLabel (PLEGEND pLegend, ! 195: HDC hDC, ! 196: HWND hWnd) ! 197: { // DrawLegendLabel ! 198: int i ; ! 199: int xPos ; ! 200: RECT rect ; ! 201: RECT rectLB ; ! 202: INT LocalThreeDPad = ThreeDPad - 1 ; ! 203: ! 204: SetBkColor (hDC, crLightGray) ; ! 205: ! 206: SelectFont (hDC, pLegend->hFontLabels) ; ! 207: ! 208: GetClientRect (hWnd, &rect) ; ! 209: // Fill (hDC, crLightGray, &rect) ; ! 210: ExtTextOut (hDC, rect.left, rect.top, ! 211: ETO_OPAQUE, &(rect), NULL, 0, NULL ) ; ! 212: ! 213: GetWindowRect (pLegend->hWndItems, &rectLB) ; ! 214: ScreenRectToClient (hWnd, &rectLB) ; ! 215: ThreeDConcave1 (hDC, ! 216: rectLB.left - LocalThreeDPad, ! 217: rectLB.top - LocalThreeDPad, ! 218: rectLB.right + LocalThreeDPad, ! 219: rectLB.bottom + LocalThreeDPad) ; ! 220: ! 221: for (i = 0 ; ! 222: i < iLegendNumCols ; ! 223: i++) ! 224: { // for ! 225: rect.left = pLegend->aCols[i].xPos ; ! 226: rect.top = yBorderHeight ; ! 227: rect.right = rect.left + pLegend->aCols[i].xWidth - LegendHorzMargin () ; ! 228: rect.bottom = pLegend->yLabelHeight ; ! 229: ! 230: switch (pLegend->aCols[i].iOrientation) ! 231: { // switch ! 232: case LEFTORIENTATION: ! 233: SetTextAlign (hDC, TA_LEFT) ; ! 234: xPos = rect.left ; ! 235: break ; ! 236: ! 237: case CENTERORIENTATION: ! 238: SetTextAlign (hDC, TA_CENTER) ; ! 239: xPos = (rect.left + rect.right) / 2 ; ! 240: break ; ! 241: ! 242: case RIGHTORIENTATION: ! 243: SetTextAlign (hDC, TA_RIGHT) ; ! 244: xPos = rect.right ; ! 245: break ; ! 246: ! 247: default: ! 248: xPos = rect.left ; ! 249: break ; ! 250: } // switch ! 251: ! 252: ExtTextOut (hDC, ! 253: xPos, rect.top, ! 254: ETO_OPAQUE, ! 255: &rect, ! 256: pLegend->aCols[i].szLabel, ! 257: lstrlen (pLegend->aCols[i].szLabel), ! 258: NULL) ; ! 259: } // for ! 260: } // DrawLegendLabel ! 261: ! 262: ! 263: ! 264: void DrawColorCol (PLEGEND pLegend, ! 265: PLINE pLine, ! 266: int iCol, ! 267: HDC hDC, ! 268: int yPos) ! 269: /* ! 270: Effect: Draw the "color" column of a legend entry. The color ! 271: column displays a small sample of the line drawing. ! 272: ! 273: For charts, the sample is a line of the correct style, ! 274: color, and width. Since we are using wide lines, ! 275: the round endcaps of the lines will breach the column. ! 276: Therefore we need to set the clip region. We could ! 277: remove this clipping if we find a way to change the ! 278: end cap design. ! 279: ! 280: For alerts, the sample is a small circle which echos ! 281: the design in the alert log itself. ! 282: */ ! 283: { // DrawColorCol ! 284: HBRUSH hBrush, hBrushPrevious ; ! 285: RECT rect ; ! 286: int yMiddle ; ! 287: int iCircle ; ! 288: ! 289: ! 290: ! 291: rect.left = pLegend->aCols[iCol].xPos - LegendLeftMargin () + 2 ; ! 292: rect.top = yPos + 1 ; ! 293: rect.right = rect.left + pLegend->aCols[iCol].xWidth - LegendHorzMargin () ; ! 294: rect.bottom = yPos + pLegend->yItemHeight - 1 ; ! 295: ! 296: yMiddle = rect.top + (rect.bottom - rect.top) / 2 ; ! 297: iCircle = rect.bottom - rect.top - 2 ; ! 298: ! 299: switch (pLegend->iLineType) ! 300: { // switch ! 301: case LineTypeChart: ! 302: ! 303: if (pLine->Visual.iWidth == 1) ! 304: { ! 305: // simple case with thin pen ! 306: hBrush = SelectBrush (hDC, hbLightGray) ; ! 307: Rectangle (hDC, rect.left, rect.top, rect.right, rect.bottom) ; ! 308: ! 309: HLine (hDC, pLine->hPen, ! 310: rect.left + 1, rect.right - 1, yMiddle) ; ! 311: SelectBrush (hDC, hBrush) ; ! 312: } ! 313: else ! 314: { ! 315: // thicker pen width, have to set ClipRect so ! 316: // it will not draw otherside the rect. ! 317: SaveDC (hDC) ; ! 318: hBrush = SelectBrush (hDC, hbLightGray) ; ! 319: Rectangle (hDC, rect.left, rect.top, rect.right, rect.bottom) ; ! 320: ! 321: IntersectClipRect (hDC, ! 322: rect.left + 1, ! 323: rect.top + 1, ! 324: rect.right - 1, ! 325: rect.bottom - 1) ; ! 326: HLine (hDC, pLine->hPen, ! 327: rect.left + 1, rect.right - 1, yMiddle) ; ! 328: SelectBrush (hDC, hBrush) ; ! 329: RestoreDC (hDC, -1) ; ! 330: } ! 331: break ; ! 332: ! 333: ! 334: case LineTypeAlert: ! 335: hBrushPrevious = SelectBrush (hDC, pLine->hBrush) ; ! 336: ! 337: Ellipse (hDC, ! 338: rect.left + 2, ! 339: rect.top + 2, ! 340: rect.left + 2 + iCircle, ! 341: rect.top + 2 + iCircle) ; ! 342: ! 343: SelectBrush (hDC, hBrushPrevious) ; ! 344: break ; ! 345: } // switch ! 346: ! 347: } // DrawColorCol ! 348: ! 349: ! 350: void DrawLegendCol (PLEGEND pLegend, ! 351: int iCol, ! 352: HDC hDC, ! 353: int yPos, ! 354: LPTSTR lpszValue) ! 355: /* ! 356: Effect: Draw the value lpszValue for the column iCol on hDC. ! 357: ! 358: Assert: The foreground and background text colors of hDC are ! 359: properly set. ! 360: */ ! 361: { // DrawLegendCol ! 362: RECT rect ; ! 363: int xPos ; ! 364: ! 365: rect.left = pLegend->aCols[iCol].xPos - LegendLeftMargin () ; ! 366: rect.top = yPos ; ! 367: rect.right = rect.left + pLegend->aCols[iCol].xWidth - LegendHorzMargin () ; ! 368: rect.bottom = yPos + pLegend->yItemHeight ; ! 369: ! 370: // SetTextAlign (hDC, TA_TOP) ; ! 371: switch (pLegend->aCols[iCol].iOrientation) ! 372: { // switch ! 373: case LEFTORIENTATION: ! 374: SetTextAlign (hDC, TA_LEFT) ; ! 375: xPos = rect.left ; ! 376: break ; ! 377: ! 378: case CENTERORIENTATION: ! 379: SetTextAlign (hDC, TA_CENTER) ; ! 380: xPos = (rect.left + rect.right) / 2 ; ! 381: break ; ! 382: ! 383: case RIGHTORIENTATION: ! 384: SetTextAlign (hDC, TA_RIGHT) ; ! 385: xPos = rect.right ; ! 386: break ; ! 387: ! 388: default: ! 389: xPos = rect.left ; ! 390: break ; ! 391: } // switch ! 392: ! 393: ExtTextOut (hDC, ! 394: xPos, rect.top + LegendItemTopMargin (), ! 395: ETO_OPAQUE | ETO_CLIPPED, ! 396: &rect, ! 397: lpszValue, ! 398: lstrlen (lpszValue), ! 399: NULL) ; ! 400: } // DrawLegendCol ! 401: ! 402: ! 403: void DrawLegendItem (PLEGEND pLegend, ! 404: PLINESTRUCT pLine, ! 405: int yPos, ! 406: HDC hDC) ! 407: { ! 408: TCHAR szValue [256] ; ! 409: TCHAR szInstance [256] ; ! 410: TCHAR szParent [256] ; ! 411: TCHAR szNoName[4] ; ! 412: ! 413: szNoName[0] = szNoName[1] = szNoName[2] = TEXT('-') ; ! 414: szNoName[3] = TEXT('\0') ; ! 415: ! 416: //=============================// ! 417: // Determine Instance, Parent // ! 418: //=============================// ! 419: ! 420: // It's possible that there will be no instance, therefore ! 421: // the lnInstanceName would be NULL. ! 422: ! 423: if (pLine->lnObject.NumInstances > 0) ! 424: { ! 425: // Test for the parent object instance name title index. ! 426: // If there is one, it implies that there will be a valid ! 427: // Parent Object Name and a valid Parent Object Instance Name. ! 428: ! 429: // If the Parent Object title index is 0 then ! 430: // just display the instance name. ! 431: ! 432: lstrcpy (szInstance, pLine->lnInstanceName) ; ! 433: if (pLine->lnInstanceDef.ParentObjectTitleIndex && ! 434: pLine->lnPINName) ! 435: { ! 436: // Get the Parent Object Name. ! 437: lstrcpy (szParent, pLine->lnPINName) ; ! 438: } ! 439: else ! 440: { ! 441: lstrcpy (szParent, szNoName) ; ! 442: } ! 443: } ! 444: else ! 445: { ! 446: lstrcpy (szInstance, szNoName) ; ! 447: lstrcpy (szParent, szNoName) ; ! 448: } ! 449: ! 450: //=============================// ! 451: // Draw Color // ! 452: //=============================// ! 453: ! 454: DrawColorCol (pLegend, pLine, LegendColorCol, hDC, yPos) ; ! 455: ! 456: //=============================// ! 457: // Draw Scale/Value // ! 458: //=============================// ! 459: ! 460: if (pLegend->iLineType == LineTypeChart) ! 461: { ! 462: if (pLine->eScale < (FLOAT) 1.0) ! 463: { ! 464: TSPRINTF (szValue, TEXT("%6.6f"), pLine->eScale) ; ! 465: } ! 466: else ! 467: { ! 468: TSPRINTF (szValue, TEXT("%10.3f"), pLine->eScale) ; ! 469: } ! 470: } ! 471: else ! 472: { ! 473: FLOAT tempAlertValue ; ! 474: ! 475: tempAlertValue = pLine->eAlertValue ; ! 476: if (tempAlertValue < (FLOAT) 0.0) ! 477: { ! 478: tempAlertValue = -tempAlertValue ; ! 479: } ! 480: ! 481: if (tempAlertValue >= (FLOAT) 10000.0) ! 482: { ! 483: if (tempAlertValue < (FLOAT) 1.0E+8) ! 484: { ! 485: TSPRINTF (szValue, TEXT("%c%10.0f"), ! 486: pLine->bAlertOver ? TEXT('>') : TEXT('<'), ! 487: pLine->eAlertValue) ; ! 488: } ! 489: else ! 490: { ! 491: TSPRINTF (szValue, TEXT("%c%10.3e"), ! 492: pLine->bAlertOver ? TEXT('>') : TEXT('<'), ! 493: pLine->eAlertValue) ; ! 494: } ! 495: } ! 496: else ! 497: { ! 498: TSPRINTF (szValue, TEXT("%c%10.4f"), ! 499: pLine->bAlertOver ? TEXT('>') : TEXT('<'), ! 500: pLine->eAlertValue) ; ! 501: } ! 502: } ! 503: ! 504: SetTextAlign (hDC, TA_TOP) ; ! 505: ! 506: DrawLegendCol (pLegend, LegendScaleCol, ! 507: hDC, yPos, szValue) ; ! 508: ! 509: ! 510: //=============================// ! 511: // Draw Counter // ! 512: //=============================// ! 513: ! 514: DrawLegendCol (pLegend, LegendCounterCol, ! 515: hDC, yPos, pLine->lnCounterName) ; ! 516: ! 517: ! 518: //=============================// ! 519: // Draw Instance // ! 520: //=============================// ! 521: ! 522: DrawLegendCol (pLegend, LegendInstanceCol, ! 523: hDC, yPos, szInstance) ; ! 524: ! 525: //=============================// ! 526: // Draw Parent // ! 527: //=============================// ! 528: ! 529: DrawLegendCol (pLegend, LegendParentCol, ! 530: hDC, yPos, szParent) ; ! 531: ! 532: //=============================// ! 533: // Draw Object // ! 534: //=============================// ! 535: ! 536: DrawLegendCol (pLegend, LegendObjectCol, ! 537: hDC, yPos, pLine->lnObjectName) ; ! 538: ! 539: //=============================// ! 540: // Draw System // ! 541: //=============================// ! 542: ! 543: DrawLegendCol (pLegend, LegendSystemCol, ! 544: hDC, yPos, pLine->lnSystemName) ; ! 545: ! 546: } ! 547: ! 548: ! 549: //==========================================================================// ! 550: // Message Handlers // ! 551: //==========================================================================// ! 552: ! 553: ! 554: BOOL OnLegendCreate (HWND hWnd, LPCREATESTRUCT lpCS) ! 555: { ! 556: PLEGEND pLegend ; ! 557: HDC hDC ; ! 558: int iCol ; ! 559: BOOL bChartLegend ; ! 560: ! 561: bChartLegend = (lpCS->lpCreateParams) == (LPVOID) TRUE ; ! 562: ! 563: pLegend = AllocateLegendData (hWnd, bChartLegend) ; ! 564: ! 565: if (!pLegend) ! 566: return (FALSE) ; ! 567: ! 568: if (bChartLegend) ! 569: { ! 570: pLegend->iLineType = LineTypeChart ; ! 571: } ! 572: else ! 573: { ! 574: pLegend->iLineType = LineTypeAlert ; ! 575: } ! 576: ! 577: pLegend->hFontItems = hFontScales ; ! 578: pLegend->hFontLabels = hFontScalesBold ; ! 579: hDC = GetDC (hWnd) ; ! 580: ! 581: //=============================// ! 582: // Load Labels // ! 583: //=============================// ! 584: ! 585: StringLoad (IDS_LABELCOLOR, pLegend->aCols[LegendColorCol].szLabel) ; ! 586: if (pLegend->iLineType == LineTypeChart) ! 587: StringLoad (IDS_LABELSCALE, ! 588: pLegend->aCols[LegendScaleCol].szLabel) ; ! 589: else ! 590: StringLoad (IDS_LABELVALUE, ! 591: pLegend->aCols[LegendScaleCol].szLabel) ; ! 592: StringLoad (IDS_LABELCOUNTER, pLegend->aCols[LegendCounterCol].szLabel) ; ! 593: StringLoad (IDS_LABELINSTANCE, pLegend->aCols[LegendInstanceCol].szLabel) ; ! 594: StringLoad (IDS_LABELPARENT, pLegend->aCols[LegendParentCol].szLabel) ; ! 595: StringLoad (IDS_LABELOBJECT, pLegend->aCols[LegendObjectCol].szLabel) ; ! 596: StringLoad (IDS_LABELSYSTEM, pLegend->aCols[LegendSystemCol].szLabel) ; ! 597: ! 598: ! 599: //=============================// ! 600: // Label dimensions // ! 601: //=============================// ! 602: ! 603: SelectFont (hDC, pLegend->hFontLabels) ; ! 604: pLegend->yLabelHeight = FontHeight (hDC, TRUE) + 2 * LabelTopMargin () ; ! 605: ! 606: //=============================// ! 607: // Column dimensions // ! 608: //=============================// ! 609: ! 610: for (iCol = 0 ; ! 611: iCol < iLegendNumCols ; ! 612: iCol++) ! 613: { // for ! 614: pLegend->aCols[iCol].iOrientation = LEFTORIENTATION ; ! 615: pLegend->aCols[iCol].xMinWidth = ! 616: TextWidth (hDC, pLegend->aCols[iCol].szLabel) + LegendHorzMargin () ; ! 617: } // for ! 618: ! 619: SelectFont (hDC, pLegend->hFontItems) ; ! 620: pLegend->yItemHeight = FontHeight (hDC, TRUE) + 2 * LegendItemTopMargin () ; ! 621: ! 622: pLegend->aCols[LegendColorCol].xMaxWidth = max (3 * xScrollWidth, ! 623: pLegend->aCols[LegendColorCol].xMinWidth) ; ! 624: ! 625: pLegend->aCols[LegendScaleCol].xMaxWidth = TextWidth (hDC, eScaleValueSpace) ; ! 626: pLegend->aCols[LegendCounterCol].xMaxWidth = iLegendColMax ; ! 627: pLegend->aCols[LegendInstanceCol].xMaxWidth = iLegendColMax ; ! 628: pLegend->aCols[LegendParentCol].xMaxWidth = iLegendColMax ; ! 629: pLegend->aCols[LegendObjectCol].xMaxWidth = iLegendColMax ; ! 630: pLegend->aCols[LegendSystemCol].xMaxWidth = iLegendColMax ; ! 631: ! 632: pLegend->aCols[LegendColorCol].iOrientation = LEFTORIENTATION ; ! 633: pLegend->aCols[LegendScaleCol].iOrientation = RIGHTORIENTATION ; ! 634: ! 635: ReleaseDC (hWnd, hDC) ; ! 636: ! 637: //=============================// ! 638: // Create Legend Items Listbox // ! 639: //=============================// ! 640: ! 641: pLegend->hWndItems = ! 642: CreateWindow (TEXT("ListBox"), // window class ! 643: NULL, // window caption ! 644: dwGraphLegendItemsWindowStyle, // window style ! 645: 0, 0, 0, 0, // window size and pos ! 646: hWnd, // parent window ! 647: NULL, // menu ! 648: hInstance, // program instance ! 649: (LPVOID) TRUE) ; // user-supplied data ! 650: } // OnLegendCreate ! 651: ! 652: ! 653: void static OnSize (HWND hWnd, int xWidth, int yHeight) ! 654: /* ! 655: Effect: Perform all actions necessary when the legend window is ! 656: being resized. In particular, set the width and starting ! 657: position for each column of the legend list and labels. ! 658: ! 659: Internals: What we do is determine the amount of space in the ! 660: width that is greater than the minimum, and allocate ! 661: that space among each of the columns that is willing to ! 662: be larger than minimum. If there is not enough room for ! 663: the minimum, don't bother with calculations. ! 664: */ ! 665: ! 666: { // OnSize ! 667: PLEGEND pLegend ; ! 668: PLEGENDCOL pCol ; ! 669: int xMin ; ! 670: int xSlack ; ! 671: int iColsToGrow ; ! 672: int iCol ; ! 673: ! 674: pLegend = LegendData (hWnd) ; ! 675: ! 676: //=============================// ! 677: // Resize Legend Items // ! 678: //=============================// ! 679: ! 680: if (IsLegendLabelVisible ()) ! 681: MoveWindow (pLegend->hWndItems, ! 682: LegendLeftMargin (), pLegend->yLabelHeight + ThreeDPad, ! 683: xWidth - 2 * LegendLeftMargin (), ! 684: yHeight - pLegend->yLabelHeight - yLegendBorderHeight, ! 685: TRUE) ; ! 686: else ! 687: MoveWindow (pLegend->hWndItems, ! 688: 0, 0, ! 689: xWidth, yHeight, ! 690: TRUE) ; ! 691: ! 692: ! 693: //=============================// ! 694: // Allocate width to Columns // ! 695: //=============================// ! 696: ! 697: xMin = LegendMinWidth (hWnd) ; ! 698: xSlack = max (xWidth - xMin, 0) ; ! 699: iColsToGrow = 0 ; ! 700: ! 701: for (iCol = 0 ; ! 702: iCol < iLegendNumCols ; ! 703: iCol++) ! 704: { // for ! 705: pCol = &(pLegend->aCols[iCol]) ; ! 706: ! 707: pCol->xWidth = pCol->xMinWidth ; ! 708: if (ColCanGrow (pCol)) ! 709: iColsToGrow++ ; ! 710: } // for ! 711: ! 712: for (iCol = 0 ; ! 713: iCol < iLegendNumCols ; ! 714: iCol++) ! 715: { // for ! 716: pCol = &(pLegend->aCols[iCol]) ; ! 717: ! 718: if (ColCanGrow (pCol)) ! 719: { ! 720: if ((pCol->xWidth + xSlack / iColsToGrow) > ! 721: pCol->xMaxWidth) ! 722: { // if ! 723: pCol->xWidth = pCol->xMaxWidth ; ! 724: xSlack -= (pCol->xMaxWidth - pCol->xMinWidth) ; ! 725: iColsToGrow-- ; ! 726: } // if ! 727: } // if ! 728: } // for ! 729: ! 730: for (iCol = 0 ; ! 731: iCol < iLegendNumCols ; ! 732: iCol++) ! 733: { // for ! 734: pCol = &(pLegend->aCols[iCol]) ; ! 735: ! 736: if (ColCanGrow (pCol)) ! 737: pCol->xWidth += xSlack / iColsToGrow ; ! 738: } // for ! 739: ! 740: if (pLegend->aCols[LegendCounterCol].xWidth < ! 741: pLegend->aCols[LegendCounterCol].xMaxWidth) ! 742: { ! 743: // cut some from the other columns and give them to CounterCol ! 744: if (pLegend->aCols[LegendColorCol].xWidth - xScrollWidth >= ! 745: pLegend->aCols[LegendColorCol].xMinWidth) ! 746: { ! 747: pLegend->aCols[LegendColorCol].xWidth -= xScrollWidth ; ! 748: pLegend->aCols[LegendCounterCol].xWidth += xScrollWidth ; ! 749: } ! 750: if (pLegend->aCols[LegendInstanceCol].xWidth - xScrollWidth >= ! 751: pLegend->aCols[LegendInstanceCol].xMinWidth) ! 752: { ! 753: pLegend->aCols[LegendInstanceCol].xWidth -= xScrollWidth ; ! 754: pLegend->aCols[LegendCounterCol].xWidth += xScrollWidth ; ! 755: } ! 756: if (pLegend->aCols[LegendParentCol].xWidth - xScrollWidth >= ! 757: pLegend->aCols[LegendParentCol].xMinWidth) ! 758: { ! 759: pLegend->aCols[LegendParentCol].xWidth -= xScrollWidth ; ! 760: pLegend->aCols[LegendCounterCol].xWidth += xScrollWidth ; ! 761: } ! 762: } ! 763: ! 764: ! 765: //=============================// ! 766: // Set Column positions // ! 767: //=============================// ! 768: ! 769: pLegend->aCols[0].xPos = LegendLeftMargin () ; ! 770: for (iCol = 1 ; ! 771: iCol < iLegendNumCols ; ! 772: iCol++) ! 773: { // for ! 774: pLegend->aCols[iCol].xPos = ! 775: pLegend->aCols[iCol - 1].xPos + pLegend->aCols[iCol - 1].xWidth ; ! 776: ! 777: if (iCol == LegendCounterCol) ! 778: { ! 779: // add some space between Scale/Value col & Counter col ! 780: pLegend->aCols[LegendCounterCol].xPos += LegendLeftMargin () ; ! 781: } ! 782: } // for ! 783: ! 784: } // OnSize ! 785: ! 786: ! 787: void static OnPaint (HWND hWnd) ! 788: { // OnPaint ! 789: PLEGEND pLegend ; ! 790: HDC hDC ; ! 791: PAINTSTRUCT ps ; ! 792: ! 793: hDC = BeginPaint (hWnd, &ps) ; ! 794: ! 795: if (IsLegendLabelVisible ()) ! 796: { ! 797: pLegend = LegendData (hWnd) ; ! 798: DrawLegendLabel (pLegend, hDC, hWnd) ; ! 799: } ! 800: ! 801: ! 802: EndPaint (hWnd, &ps) ; ! 803: } // OnPaint ! 804: ! 805: ! 806: void OnDrawLegendItem (HWND hWnd, ! 807: LPDRAWITEMSTRUCT lpDI) ! 808: { // OnDrawItem ! 809: HFONT hFontPrevious ; ! 810: HDC hDC ; ! 811: PLEGEND pLegend ; ! 812: PLINESTRUCT pLine ; ! 813: int iLBIndex ; ! 814: COLORREF preBkColor ; ! 815: COLORREF preTextColor ; ! 816: ! 817: ! 818: hDC = lpDI->hDC ; ! 819: iLBIndex = DIIndex (lpDI) ; ! 820: ! 821: pLegend = LegendData (hWnd) ; ! 822: ! 823: if (iLBIndex == -1) ! 824: pLine = NULL ; ! 825: else ! 826: pLine = (PLINESTRUCT) LBData (pLegend->hWndItems, iLBIndex) ; ! 827: ! 828: //=============================// ! 829: // Set DC attributes // ! 830: //=============================// ! 831: ! 832: ! 833: if (DISelected (lpDI)) ! 834: { // if ! 835: preTextColor = SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)) ; ! 836: preBkColor = SetBkColor (hDC, GetSysColor (COLOR_HIGHLIGHT)) ; ! 837: } // if ! 838: ExtTextOut (hDC, lpDI->rcItem.left, lpDI->rcItem.top, ! 839: ETO_OPAQUE, &(lpDI->rcItem), NULL, 0, NULL ) ; ! 840: ! 841: ! 842: //=============================// ! 843: // Draw Legend Item // ! 844: //=============================// ! 845: ! 846: hFontPrevious = SelectFont (hDC, pLegend->hFontItems) ; ! 847: if (pLine) ! 848: DrawLegendItem (pLegend, pLine, lpDI->rcItem.top, hDC) ; ! 849: SelectFont (hDC, hFontPrevious) ; ! 850: ! 851: //=============================// ! 852: // Draw Focus // ! 853: //=============================// ! 854: ! 855: if (DIFocus (lpDI)) ! 856: DrawFocusRect (hDC, &(lpDI->rcItem)) ; ! 857: ! 858: ! 859: if (DISelected (lpDI)) ! 860: { // if ! 861: preTextColor = SetTextColor (hDC, preTextColor) ; ! 862: preBkColor = SetBkColor (hDC, preBkColor) ; ! 863: } // if ! 864: } // OnDrawItem ! 865: ! 866: ! 867: void static OnMeasureItem (HWND hWnd, ! 868: LPMEASUREITEMSTRUCT lpMI) ! 869: { // OnMeasureItem ! 870: PLEGEND pLegend ; ! 871: ! 872: pLegend = LegendData (hWnd) ; ! 873: lpMI->itemHeight = pLegend->yItemHeight ; ! 874: } // OnMeasureItem ! 875: ! 876: ! 877: void static OnDestroy (HWND hWnd) ! 878: { ! 879: PLEGEND pLegend ; ! 880: ! 881: pLegend = LegendData (hWnd) ; ! 882: MemoryFree (pLegend) ; ! 883: } // OnDestroy ! 884: ! 885: ! 886: ! 887: void static OnDoubleClick (HWND hWnd) ! 888: { ! 889: PLEGEND pLegend ; ! 890: ! 891: pLegend = LegendData (hWnd) ; ! 892: if (!pLegend) ! 893: return ; ! 894: ! 895: switch (pLegend->iLineType) ! 896: { // switch ! 897: case LineTypeChart: ! 898: EditChart (hWndMain) ; ! 899: break ; ! 900: ! 901: case LineTypeAlert: ! 902: EditAlert (hWndAlert) ; ! 903: break ; ! 904: } // switch ! 905: } // OnDoubleClick ! 906: ! 907: ! 908: ! 909: void static OnSelectionChanged (HWND hWnd) ! 910: { // OnSelectionChanged ! 911: PLEGEND pLegend ; ! 912: PGRAPHSTRUCT pGraph ; ! 913: int iIndex ; ! 914: ! 915: ! 916: pLegend = LegendData (hWnd) ; ! 917: ! 918: // set the new selected line ! 919: iIndex = LBSelection (pLegend->hWndItems) ; ! 920: ! 921: if (iIndex == LB_ERR) ! 922: return ; ! 923: ! 924: LegendSetCurrentLine (pLegend, iIndex) ; ! 925: ! 926: if (pLegend->iLineType == LineTypeChart) ! 927: { ! 928: pGraph = GraphData (hWndGraph) ; ! 929: ! 930: if (!PlayingBackLog()) ! 931: { ! 932: // update the min, max, & avg of the current line ! 933: UpdateValueBarData (pGraph) ; ! 934: } ! 935: ! 936: // update the valuebar display ! 937: StatusTimer (hWndGraphStatus, TRUE) ; ! 938: ! 939: // change the Current highlighted line if necessary ! 940: if (pGraph && pGraph->HighLightOnOff) ! 941: { ! 942: WindowInvalidate (hWndGraphDisplay) ; ! 943: } ! 944: } ! 945: } // OnSelectionChanged ! 946: ! 947: ! 948: //==========================================================================// ! 949: // Exported Functions // ! 950: //==========================================================================// ! 951: ! 952: ! 953: LRESULT APIENTRY GraphLegendWndProc (HWND hWnd, ! 954: WORD wMsg, ! 955: WPARAM wParam, ! 956: LONG lParam) ! 957: { // GraphLegendWndProc ! 958: BOOL bCallDefProc ; ! 959: LRESULT lReturnValue ; ! 960: ! 961: ! 962: bCallDefProc = FALSE ; ! 963: lReturnValue = 0L ; ! 964: ! 965: switch (wMsg) ! 966: { // switch ! 967: case WM_DELETEITEM: ! 968: break ; ! 969: ! 970: case WM_COMMAND: ! 971: switch (HIWORD (wParam)) ! 972: { // switch ! 973: case LBN_DBLCLK: ! 974: OnDoubleClick (hWnd) ; ! 975: break ; ! 976: ! 977: case LBN_SELCHANGE: ! 978: OnSelectionChanged (hWnd) ; ! 979: break ; ! 980: ! 981: default: ! 982: break ; ! 983: } // switch ! 984: break ; ! 985: ! 986: case WM_CREATE: ! 987: OnLegendCreate (hWnd, (LPCREATESTRUCT) lParam) ; ! 988: break ; ! 989: ! 990: case WM_DESTROY: ! 991: OnDestroy (hWnd) ; ! 992: break ; ! 993: ! 994: case WM_DRAWITEM: ! 995: OnDrawLegendItem (hWnd, (LPDRAWITEMSTRUCT) lParam) ; ! 996: break ; ! 997: ! 998: case WM_MEASUREITEM: ! 999: OnMeasureItem (hWnd, (LPMEASUREITEMSTRUCT) lParam) ; ! 1000: break ; ! 1001: ! 1002: case WM_PAINT: ! 1003: OnPaint (hWnd) ; ! 1004: break ; ! 1005: ! 1006: case WM_SIZE: ! 1007: OnSize (hWnd, LOWORD (lParam), HIWORD (lParam)) ; ! 1008: break ; ! 1009: ! 1010: default: ! 1011: bCallDefProc = TRUE ; ! 1012: } // switch ! 1013: ! 1014: ! 1015: if (bCallDefProc) ! 1016: lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ; ! 1017: ! 1018: return (lReturnValue); ! 1019: } // GraphLegendWndProc ! 1020: ! 1021: ! 1022: int LegendMinWidth (HWND hWnd) ! 1023: { ! 1024: PLEGEND pLegend ; ! 1025: int iCol ; ! 1026: int xMinWidth ; ! 1027: ! 1028: pLegend = LegendData (hWnd) ; ! 1029: xMinWidth = 0 ; ! 1030: ! 1031: for (iCol = 0 ; ! 1032: iCol < iLegendNumCols ; ! 1033: iCol++) ! 1034: { // for ! 1035: xMinWidth += pLegend->aCols[iCol].xMinWidth ; ! 1036: } // for ! 1037: ! 1038: return (xMinWidth) ; ! 1039: } ! 1040: ! 1041: ! 1042: int LegendMinHeight (HWND hWnd) ! 1043: { ! 1044: PLEGEND pLegend ; ! 1045: ! 1046: pLegend = LegendData (hWnd) ; ! 1047: ! 1048: if (IsLegendLabelVisible ()) ! 1049: return (pLegend->yLabelHeight + pLegend->yItemHeight) ; ! 1050: else ! 1051: return (pLegend->yItemHeight) ; ! 1052: } ! 1053: ! 1054: ! 1055: int LegendHeight (HWND hWnd, int yGraphHeight) ! 1056: /* ! 1057: Effect: Return the best height for the Legend window given the ! 1058: number of items and label visibility of the legend, as ! 1059: well as the overall height of the graph. ! 1060: */ ! 1061: { // LegendHeight ! 1062: PLEGEND pLegend ; ! 1063: int yPreferredHeight ; ! 1064: ! 1065: pLegend = LegendData (hWnd) ; ! 1066: ! 1067: yPreferredHeight = yLegendBorderHeight + ! 1068: pLegend->yItemHeight * ! 1069: PinInclusive (LBNumItems (pLegend->hWndItems), ! 1070: 1, iLegendMaxVisibleItems) ; ! 1071: if (IsLegendLabelVisible ()) ! 1072: yPreferredHeight += pLegend->yLabelHeight ; ! 1073: ! 1074: return (min (yPreferredHeight, yGraphHeight / 2)) ; ! 1075: } // LegendHeight ! 1076: ! 1077: ! 1078: ! 1079: int LegendFullHeight (HWND hWnd, HDC hDC) ! 1080: /* ! 1081: Effect: Return the best height for the Legend window given the ! 1082: number of items and label visibility of the legend, as ! 1083: well as the overall height of the graph. ! 1084: */ ! 1085: { // LegendHeight ! 1086: PLEGEND pLegend ; ! 1087: int yPreferredHeight ; ! 1088: ! 1089: pLegend = LegendData (hWnd) ; ! 1090: ! 1091: yPreferredHeight = yLegendBorderHeight + ! 1092: pLegend->yItemHeight * ! 1093: LBNumItems (pLegend->hWndItems) ; ! 1094: if (IsLegendLabelVisible ()) ! 1095: yPreferredHeight += pLegend->yLabelHeight ; ! 1096: ! 1097: return (yPreferredHeight) ; ! 1098: } // LegendFullHeight ! 1099: ! 1100: ! 1101: ! 1102: ! 1103: HWND CreateGraphLegendWindow (HWND hWndGraph) ! 1104: { ! 1105: return (CreateWindow (szGraphLegendClass, // class ! 1106: NULL, // caption ! 1107: dwGraphLegendWindowStyle, // window style ! 1108: 0, 0, // position ! 1109: 0, 0, // size ! 1110: hWndGraph, // parent window ! 1111: NULL, // menu ! 1112: hInstance, // program instance ! 1113: (LPVOID) TRUE)) ; // user-supplied data ! 1114: } ! 1115: ! 1116: ! 1117: BOOL GraphLegendInitializeApplication (void) ! 1118: /* ! 1119: Called By: GraphInitializeApplication only ! 1120: */ ! 1121: { ! 1122: WNDCLASS wc ; ! 1123: ! 1124: wc.style = dwGraphLegendClassStyle ; ! 1125: wc.lpfnWndProc = (WNDPROC) GraphLegendWndProc ; ! 1126: wc.hInstance = hInstance ; ! 1127: wc.cbClsExtra = iGraphLegendClassExtra ; ! 1128: wc.cbWndExtra = iGraphLegendWindowExtra ; ! 1129: wc.hIcon = NULL ; ! 1130: wc.hCursor = LoadCursor (NULL, IDC_ARROW) ; ! 1131: wc.hbrBackground = hbLightGray ; ! 1132: wc.lpszMenuName = NULL ; ! 1133: wc.lpszClassName = szGraphLegendClass ; ! 1134: ! 1135: return (RegisterClass (&wc)) ; ! 1136: } ! 1137: ! 1138: ! 1139: BOOL LegendAddItem (HWND hWnd, PLINESTRUCT pLine) ! 1140: /* ! 1141: Effect: Add a legend entry for the line pLine. Don't select ! 1142: the line as current entry here, because this will cause ! 1143: the scroll bar to unneccesarily appear for a moment. ! 1144: If you want this line to be the current line, resize ! 1145: the legend first, then set as current line. ! 1146: ! 1147: See Also: ChartInsertLine, AlertInsertLine. ! 1148: */ ! 1149: { // LegendAddItem ! 1150: PLEGEND pLegend ; ! 1151: ! 1152: pLegend = LegendData (hWnd) ; ! 1153: LBAdd (pLegend->hWndItems, pLine) ; ! 1154: ! 1155: return (TRUE) ; ! 1156: } // LegendAddItem ! 1157: ! 1158: ! 1159: void LegendDeleteItem (HWND hWndLegend, ! 1160: PLINE pLine) ! 1161: { // LegendDeleteItem ! 1162: PLEGEND pLegend ; ! 1163: int iIndex ; ! 1164: int iNextIndex ; ! 1165: int iNumItems ; ! 1166: PGRAPHSTRUCT pGraph ; ! 1167: ! 1168: pLegend = LegendData (hWndLegend) ; ! 1169: if (!pLegend) ! 1170: return ; ! 1171: ! 1172: iNumItems = LBNumItems (pLegend->hWndItems) ; ! 1173: ! 1174: iIndex = LBFind (pLegend->hWndItems, pLine) ; ! 1175: ! 1176: if (iIndex != LB_ERR) ! 1177: { ! 1178: LBDelete (pLegend->hWndItems, iIndex) ; ! 1179: } ! 1180: ! 1181: // no need to do anything if iNumItems is 1 to begin with ! 1182: if (iNumItems != LB_ERR && iNumItems > 1) ! 1183: { ! 1184: if (iIndex == iNumItems - 1) ! 1185: { ! 1186: // deleting the last line, then set selection ! 1187: // to the previous legend line ! 1188: iNextIndex = iIndex - 1 ; ! 1189: } ! 1190: else ! 1191: { ! 1192: // set the selection to the next legend line ! 1193: iNextIndex = iIndex ; ! 1194: } ! 1195: ! 1196: LBSetSelection (pLegend->hWndItems, iNextIndex) ; ! 1197: LegendSetCurrentLine (pLegend, iNextIndex) ; ! 1198: ! 1199: if (pLegend->iLineType == LineTypeChart) ! 1200: { ! 1201: // update the min, max, & avg of the current line ! 1202: pGraph = GraphData (hWndGraph) ; ! 1203: ! 1204: if (!PlayingBackLog()) ! 1205: { ! 1206: // update the min, max, & avg of the current line ! 1207: UpdateValueBarData (pGraph) ; ! 1208: } ! 1209: ! 1210: // update the valuebar display ! 1211: StatusTimer (hWndGraphStatus, TRUE) ; ! 1212: } ! 1213: } ! 1214: ! 1215: } // LegendDeleteItem ! 1216: ! 1217: ! 1218: PLINE LegendCurrentLine (HWND hWndLegend) ! 1219: { // LegendCurrentLine ! 1220: PLEGEND pLegend ; ! 1221: ! 1222: pLegend = LegendData (hWndLegend) ; ! 1223: ! 1224: if (!pLegend) ! 1225: return (NULL) ; ! 1226: ! 1227: return (pLegend->pCurrentLine) ; ! 1228: ! 1229: } // LegendCurrentLine ! 1230: ! 1231: ! 1232: ! 1233: int LegendNumItems (HWND hWndLegend) ! 1234: { // LegendNumItems ! 1235: PLEGEND pLegend ; ! 1236: ! 1237: pLegend = LegendData (hWndLegend) ; ! 1238: ! 1239: return (LBNumItems (pLegend->hWndItems)) ; ! 1240: } // LegendNumItems ! 1241: ! 1242: ! 1243: ! 1244: void LegendSetSelection (HWND hWndLegend, int iIndex) ! 1245: { // LegendSetSelection ! 1246: PLEGEND pLegend ; ! 1247: ! 1248: pLegend = LegendData (hWndLegend) ; ! 1249: LBSetSelection (pLegend->hWndItems, iIndex) ; ! 1250: LegendSetCurrentLine (pLegend, iIndex) ; ! 1251: } // LegendSetSelection ! 1252: ! 1253: ! 1254: ! 1255: #ifdef KEEP_PRINT ! 1256: ! 1257: void PrintLegend (HDC hDC, PGRAPHSTRUCT pGraph, HWND hWndLegend, ! 1258: RECT rectLegend) ! 1259: { ! 1260: PLEGEND pLegend ; ! 1261: int yItemHeight ; ! 1262: HFONT hFontItems ; ! 1263: PLINE pLine ; ! 1264: int iIndex ; ! 1265: int iIndexNum ; ! 1266: ! 1267: ! 1268: pLegend = LegendData (hWndLegend) ; ! 1269: ! 1270: yItemHeight = pLegend->yItemHeight ; ! 1271: hFontItems = pLegend->hFontItems ; ! 1272: ! 1273: pLegend->hFontItems = hFontPrinterScales ; ! 1274: SelectFont (hDC, pLegend->hFontItems) ; ! 1275: ! 1276: pLegend->yItemHeight = FontHeight (hDC, TRUE) ; ! 1277: ! 1278: iIndexNum = LBNumItems (pLegend->hWndItems) ; ! 1279: for (iIndex = 0 ; ! 1280: iIndex < iIndexNum ; ! 1281: iIndex++) ! 1282: { // for ! 1283: pLine = (PLINE) LBData (pLegend->hWndItems, iIndex) ; ! 1284: DrawLegendItem (pLegend, pLine, iIndex * pLegend->yItemHeight, hDC) ; ! 1285: } // for ! 1286: ! 1287: pLegend->hFontItems = hFontItems ; ! 1288: pLegend->yItemHeight = yItemHeight ; ! 1289: ! 1290: ! 1291: SelectBrush (hDC, GetStockObject (HOLLOW_BRUSH)) ; ! 1292: SelectPen (hDC, GetStockObject (BLACK_PEN)) ; ! 1293: Rectangle (hDC, 0, 0, ! 1294: rectLegend.right - rectLegend.left, ! 1295: rectLegend.bottom - rectLegend.top) ; ! 1296: } ! 1297: #endif ! 1298: ! 1299: ! 1300: void ClearLegend (HWND hWndLegend) ! 1301: { ! 1302: PLEGEND pLegend ; ! 1303: ! 1304: pLegend = LegendData (hWndLegend) ; ! 1305: if (!pLegend) ! 1306: return ; ! 1307: ! 1308: LBReset (pLegend->hWndItems) ; ! 1309: pLegend->pCurrentLine = NULL ; ! 1310: } ! 1311: ! 1312: void LegendSetRedraw (HWND hWndLegend, BOOL bRedraw) ! 1313: { ! 1314: PLEGEND pLegend ; ! 1315: ! 1316: pLegend = LegendData (hWndLegend) ; ! 1317: if (!pLegend) ! 1318: return ; ! 1319: ! 1320: LBSetRedraw (pLegend->hWndItems, bRedraw) ; ! 1321: } ! 1322: ! 1323:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.