*-------------------------------------------------------------------------------------------------------------------------------------------------------- * (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!! *-------------------------------------------------------------------------------------------------------------------------------------------------------- *< FOXBIN2PRG: Version="1.21" SourceFile="foxchartsbeta.vcx" CPID="1251" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries) * * DEFINE CLASS _legend AS label && Internal use. Not to be used directly ! *< CLASSDATA: Baseclass="label" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: caption_assign *m: reset && Resets the legend GDI+ objects *m: rotation_assign *m: _drawstring *m: _setup *m: _updatemeasures *m: _value_assign *p: backcoloralpha *p: forecoloralpha *p: format && Specifies the input and output formatting of a control's Value property. *p: isparent *p: ogfx *p: rotationcenter *p: _forceformat *p: _height *p: _initialized *p: _memberdata && XML Metadata for customizable properties *p: _obrush *p: _ofont *p: _orectangle *p: _ostringformat *p: _transfcaption *p: _value *p: _vartype *p: _width * HIDDEN AddProperty,Anchor,AutoSize,BackStyle,BorderStyle,Click,CloneObject,ColorScheme,ColorSource,Comment,DblClick,Destroy,DisabledBackColor,DisabledForeColor,DragDrop,DragIcon,DragMode,DragOver,Drag,Error,FontCondense,FontExtend,FontOutline,FontShadow,GotFocus,HelpContextID,Init,LostFocus,MiddleClick,MouseDown,MouseEnter,MouseIcon,MouseLeave,MouseMove,MousePointer,MouseUp,MouseWheel,Move,OLECompleteDrag,OLEDragDrop,OLEDragMode,OLEDragOver,OLEDragPicture,OLEDrag,OLEDropEffects,OLEDropHasData,OLEDropMode,OLEGiveFeedback,OLESetData,OLEStartDrag,ParentClass,Parent,ReadExpression,ReadMethod,Refresh,ResetToDefault,RightClick,RightToLeft,SaveAsClass,ShowWhatsThis,StatusBarText,Style,TabIndex,TabStop,Tag,UIEnable,WhatsThisHelpID,WordWrap,WriteExpression,WriteMethod,ZOrder * AutoSize = .T. backcoloralpha = 0 Caption = "Legend" DragIcon = ..\..\foxcharts\ forecoloralpha = 255 format = Height = 17 isparent = .F. Name = "_legend" ogfx = .F. OLEDragPicture = ..\..\foxcharts\ rotationcenter = 0 Width = 44 _forceformat = _height = 0 _initialized = .F. _memberdata = _obrush = _ofont = _orectangle = _ostringformat = _transfcaption = _value = _vartype = _width = 0 * HIDDEN PROCEDURE caption_assign LPARAMETERS tuCaption LOCAL lcType m.lcType = VARTYPE(m.tuCaption) IF m.lcType $ "DLTN" && Logical, Date, DateTime, Numeric m.tuCaption = TRANSFORM(m.tuCaption) ENDIF This.Caption = m.tuCaption This._UpdateMeasures(.F.) && Character passed *!* C Character, Memo, Varchar, Varchar (Binary) *!* D Date *!* G General *!* L Logical *!* N Numeric, Float, Double, or Integer *!* O Object *!* Q Blob, Varbinary *!* T DateTime *!* U Unknown or variable does not exist *!* X Null *!* Y Currency ENDPROC HIDDEN PROCEDURE Init THIS.IsParent = TYPE('this.Parent.Name')='C' IF THIS.IsParent AND VARTYPE(THIS.PARENT.oGfx)='O' THIS.oGfx = THIS.PARENT.oGfx ENDIF ENDPROC PROCEDURE reset && Resets the legend GDI+ objects This._Setup() This._UpdateMeasures() ENDPROC PROCEDURE rotation_assign LPARAMETERS tnRotation THIS.Rotation = tnRotation + IIF( tnRotation < 0, 360, 0 ) ENDPROC PROCEDURE _drawstring LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, toGfx LOCAL x1, y1, lnAlign, lnMode, xBack, llBar llBar = IIF(THIS.IsParent AND THIS.PARENT.NAME = "ShapeLegend",.T., .F.) lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates lnAlign = THIS.ALIGNMENT * 0 = Left 1 = Right 2 = Center LOCAL loGfx AS xfcGraphics loGfx = IIF(VARTYPE(toGfx)='O', toGfx, THIS.oGfx) IF VARTYPE(THIS.oGfx)#'O' AND THIS.IsParent THIS.oGfx = THIS.PARENT.oGfx loGfx = THIS.oGfx ENDIF WITH _SCREEN.SYSTEM.Drawing DO CASE CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN" lnMode = 1 * Create a STRINGFORMAT object in order to draw the string centered in the image LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign IF tlVertical loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical loStringFmt.LineAlignment = .StringAlignment.CENTER ENDIF LOCAL loSize AS xfcSize IF THIS.IsParent AND tlVertical loSize = .SIZE.New(THIS.PARENT.WIDTH, THIS.PARENT.HEIGHT) ELSE loSize = .SIZE.New(tnWidth, tnHeight) ENDIF loSize = loGfx.MeasureString( THIS._TransfCaption, THIS._oFont, loSize, loStringFmt ) THIS._Height = CEILING(loSize.HEIGHT) THIS._Width = CEILING(loSize.WIDTH) LOCAL loRect AS xfcRectangle loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height) x1 = tnX y1 = tnY IF tlVertical xBack = tnX + tnWidth / 2 - (THIS._Width / 2) DO CASE CASE lnAlign = 0 && Left y1 = tnY CASE lnAlign = 1 && Right y1 = tnY + tnHeight - THIS._Height CASE lnAlign = 2 && Center y1 = tnY + (tnHeight - THIS._Height) / 2 ENDCASE ELSE DO CASE CASE lnAlign = 0 && Left xBack = tnX CASE lnAlign = 1 && Right xBack = tnX + tnWidth - THIS._Width CASE lnAlign = 2 && Center xBack = tnX + (tnWidth - THIS._Width) / 2 ENDCASE ENDIF CASE lnAlign = 0 && Left STORE tnX TO x1, xBack y1 = tnY CASE lnAlign = 1 && Right x1 = tnX - THIS._Width xBack = x1 y1 = tnY CASE lnAlign = 2 && Center x1 = tnX - (THIS._Width / 2) xBack = x1 y1 = tnY ENDCASE LOCAL lnRotation lnRotation = THIS.ROTATION IF lnRotation <> 0 WITH _SCREEN.SYSTEM.Drawing LOCAL loPointF AS xfcPointF, loMatrix AS xfcMatrix loMatrix = .Drawing2D.Matrix.New() IF lnMode = 1 loPointF = .PointF.New(tnX, tnY) && this is the point of rotation ELSE DO CASE CASE lnAlign = 0 && Left loPointF = .PointF.New(x1 + 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 1 && Right loPointF = .PointF.New(x1 + THIS._Width - 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 2 && Center loPointF = .PointF.New(x1 + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation ENDCASE ENDIF loMatrix.RotateAt(lnRotation, loPointF) loGfx.MultiplyTransform(loMatrix) ENDWITH ENDIF lnRotationCenter = THIS.RotationCenter * Center Rotation IF lnRotationCenter <> 0 WITH _SCREEN.SYSTEM.Drawing LOCAL loPointFC AS xfcPointF, loMatrixC AS xfcMatrix loMatrixC = .Drawing2D.Matrix.New() * loPointFC = .PointF.New(x1 + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation loMatrixC.RotateAt(lnRotationCenter, loPointFC) loGfx.MultiplyTransform(loMatrixC) ENDWITH ENDIF IF THIS.BackColorAlpha > 0 * Draw the BackGround Rectangle WITH _SCREEN.SYSTEM.Drawing IF lnMode = 0 && default loGfx.FillRectangle( ; .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha, THIS.BACKCOLOR)), ; x1, y1, THIS._Width, THIS._Height) ELSE loGfx.FillRectangle( ; .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha, THIS.BACKCOLOR)), ; xBack, y1, THIS._Width, THIS._Height) ENDIF ENDWITH ENDIF * Draw the Text IF lnMode = 0 loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, x1, y1) ELSE IF tlVertical loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height) loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ELSE loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ENDIF ENDIF IF lnRotation <> 0 OR lnRotationCenter <> 0 loGfx.ResetTransform() ENDIF ENDWITH ENDPROC PROCEDURE _setup * Update the FONT object LOCAL liStyle, lcFont liStyle = IIF( THIS.FONTBOLD,1,0) + IIF( THIS.FONTITALIC,2,0) + IIF( THIS.FONTUNDERLINE,4,0) + IIF( THIS.FONTSTRIKETHRU ,8,0) * Prepare the font object lcFont = IIF(THIS.IsParent AND EMPTY(THIS.FONTNAME), THIS.PARENT.FONTNAME, THIS.FONTNAME) * If no font was selected, then take the _Screen one! IF EMPTY(lcFont) lcFont = EVL(_SCREEN.FONTNAME, "Arial") ENDIF WITH _SCREEN.SYSTEM.Drawing LOCAL loFont AS xfcFont loFont = .FONT.New(lcFont, THIS.FONTSIZE, liStyle) THIS._oFont = loFont * Update the BRUSH object LOCAL loColor AS xfcColor, lnColor, loBrush AS xfcSolidBrush lnColor = IIF(THIS.IsParent AND THIS.PARENT.BrushType = 3, 0, THIS.FORECOLOR) loColor = .COLOR.FromArgb(THIS.ForeColorAlpha, lnColor) loBrush = .SolidBrush.New(loColor) THIS._oBrush = loBrush ENDWITH THIS._initialized = .T. ENDPROC PROCEDURE _updatemeasures LPARAMETERS tlNumeric IF VARTYPE(THIS.oGfx)#'O' AND THIS.IsParent THIS.oGfx = THIS.PARENT.oGfx ENDIF IF VARTYPE(THIS.oGfx) <> "O" RETURN ENDIF * Measure the Legend height IF VARTYPE(THIS._oBrush) + VARTYPE(THIS._oFont) <> "OO" OR NOT THIS._initialized THIS._Setup() ENDIF LOCAL lcCaption, lcFormat * _ForceFormat is a forced formatting managed directly from FoxCharts lcFormat = IIF(EMPTY(ALLTRIM(THIS._ForceFormat)), THIS.FORMAT, ALLTRIM(THIS._ForceFormat)) IF tlNumeric IF VARTYPE(THIS._Value) = "C" lcCaption = THIS._Value ELSE IF this.IsParent and EMPTY(lcFormat) lcFormat = "999,999,999,999" + ; IIF(THIS.PARENT._ValueDecimals > 0, ; "." + REPLICATE("9", THIS.PARENT._ValueDecimals), "") ENDIF lcCaption = ALLTRIM(TRANSFORM(THIS._Value, lcFormat)) IF this.IsParent and THIS.PARENT._ValueDecimals>0 lcCaption=RTRIM(RTRIM(lcCaption,'0'),'.') ENDIF ENDIF ELSE lcCaption = STRTRAN(THIS.CAPTION,[CHR(13)+CHR(10)], CHR(13)+CHR(10),-1,-1,1) lcCaption = ALLTRIM(textmerge(lcCaption)) ENDIF LOCAL loSize AS xfcSize loSize = THIS.oGfx.MeasureString(lcCaption, THIS._oFont) &&, This._oStringFormat) THIS._Height = loSize.HEIGHT THIS._Width = CEILING(loSize.WIDTH) THIS._TransfCaption = lcCaption ENDPROC PROCEDURE _value_assign lparameters tuNewValue This._Value = tuNewValue This._UpdateMeasures(.T.) && Value passed ENDPROC ENDDEFINE DEFINE CLASS fields AS collection *< CLASSDATA: Baseclass="collection" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: clear && Clears the contents of a ComboBox or ListBox control. *m: desc_assign *m: isempty *m: new *m: pack *m: setcount *m: type *m: unpack *p: desc *p: packexpr *a: ladesc[1,0] && Fields description * * desc = Height = 23 Name = "fields" packexpr = .F. Width = 23 * PROCEDURE clear && Clears the contents of a ComboBox or ListBox control. LPARAMETERS tnIndex LOCAL lcProp LOCAL lcName, lnCol, lnLine, loMe WITH THIS m.loMe = This FOR m.lnline = EVL(m.tnIndex,1)TO IIF(EMPTY(m.tnIndex),THIS.COUNT,m.tnIndex) FOR m.lnCol=1 TO ALEN(.laDesc,1) m.lcName = 'loMe(m.lnLine).'+ .laDesc(m.lnCol,1) STORE totype('',.laDesc(m.lnCol,2)) TO (m.lcName) NEXT NEXT m.lcProp = '.Parent.'+.Name+'Pack' STORE .pack() TO (m.lcProp) ENDWITH ENDPROC PROCEDURE desc_assign LPARAMETERS vNewVal *To do: Modify this routine for the Assign method LOCAL lnCount, lnLine, la(1) WITH THIS .DESC = UPPER(rtrim(m.vNewVal,CHR(13)+CHR(1))) lnCount = MAX(1,ALINES(la,.DESC)) DIMENSION .laDesc (lnCount,3) FOR lnLine=1 TO ALINES(la,.DESC) .laDesc (lnLine,1) = GETWORDNUM(la(lnLine),1,',') .laDesc (lnLine,2) = GETWORDNUM(la(lnLine),2,',') .laDesc (lnLine,3) = GETWORDNUM(la(lnLine),3,',') NEXT .PackExpr = '' FOR lnLine=1 TO ALEN(.laDesc,1) .PackExpr = IIF(lnLine=1,'',.PackExpr+'^') + [<>] NEXT ENDWITH ENDPROC PROCEDURE isempty LPARAMETERS tnIndex LOCAL loMe, lnCol, lnLine, luVal WITH THIS m.loMe=this FOR m.lnLine = EVL(m.tnIndex,1)TO IIF(EMPTY(m.tnIndex),THIS.COUNT,m.tnIndex) FOR m.lnCol=1 TO ALEN(.laDesc,1) m.luVal = totype(EVALUATE('loMe(m.lnLine).'+ .laDesc(m.lnCol,1)),.laDesc(m.lnCol,2)) IF NOT EMPTY(m.luVal) RETURN .F. ENDIF NEXT NEXT ENDWITH RETURN .T. ENDPROC PROCEDURE new LOCAL lnLine, loData m.loData = CREATEOBJECT("Empty") WITH THIS FOR m.lnLine=1 TO ALEN(.laDesc,1) ADDPROPERTY(m.loData,.laDesc(m.lnLine,1),Totype(.laDesc(m.lnLine,3),.laDesc(m.lnLine,2))) NEXT ENDWITH RETURN m.loData ENDPROC PROCEDURE pack LPARAMETERS tnDeleteIndex LOCAL lcExpr, lcPack, lnLine, loMe IF THIS.IsEmpty () RETURN '' ENDIF tnDeleteIndex=EVL(tnDeleteIndex,0) loMe=THIS lcPack = '' WITH THIS lcExpr = .PackExpr FOR lnLine=1 TO .COUNT IF lnLine # tnDeleteIndex lcPack = lcPack + TEXTMERGE(lcExpr) + IIF(lnLine=.COUNT,'',CHR(13)+CHR(10)) ENDIF NEXT ENDWITH RETURN lcPack ENDPROC PROCEDURE setcount LPARAMETERS tnCnt LOCAL lnLine, lnSelect, loData *--MW-->The stock method handled adding fields to the collection but not removing them. IF THIS.COUNT <> m.tnCnt LOCAL lnIncr, lnFieldNo lnIncr = m.tnCnt - THIS.COUNT DO WHILE THIS.COUNT # m.tnCnt IF lnIncr > 0 *--Adding fields m.loData = THIS.New() THIS.ADD(m.loData) ELSE *--Removing fields lnFieldNo = THIS.COUNT THIS.REMOVE(lnFieldNo) ENDIF ENDDO ENDIF ENDPROC PROCEDURE type LPARAMETERS tcField LOCAL lnLine tcField= UPPER(tcField) FOR lnLine=1 TO ALEN(THIS.laDesc,1) IF tcField== UPPER(THIS.laDesc (lnLine,1)) RETURN THIS.laDesc (lnLine,2) ENDIF NEXT RETURN 'N' ENDPROC PROCEDURE unpack LPARAMETERS lcPack LOCAL lcName, lnCol, lnLine, lnLines, loMe loMe=THIS WITH THIS lnLines = IIF(EMPTY(lcPack),0,ALINES(laPack,lcPack)) .SetCount( lnLines ) FOR lnLine=1 TO lnLines FOR lnCol=1 TO MIN(ALEN(.laDesc,1), ALINES(laCols,laPack(lnLine),'^')) lcName = 'loMe(lnLine).'+ .laDesc(lnCol,1) STORE totype(EVL(laCols(lnCol),.laDesc(lnCol,3)),.laDesc(lnCol,2)) TO (lcName) NEXT NEXT lcName = [.Parent.]+.Name+'Pack' STORE .Pack() TO (lcName) ENDWITH ENDPROC ENDDEFINE DEFINE CLASS figure AS custom *< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: checkmouseposition *m: draw && Repaints a Form object. *m: drawcontour *m: setdimensions *p: arrowheight *p: bartype *p: caption && Specifies the text displayed in an object's caption. *p: chartindex *p: color *p: contour *p: coordnum *p: currentrow *p: front *p: frontview && Передний вид *p: legend *p: matrix *p: parentcoord *p: path *p: pointfc *p: recno *p: rotationcenter *p: rowsum *p: start *p: sweep *p: tilt *p: type *p: value && Specifies the current state of a control. * * arrowheight = 0 bartype = 0 caption = chartindex = 0 color = 0 contour = .F. coordnum = 0 currentrow = 0 front = frontview = .F. legend = matrix = .F. Name = "figure" parentcoord = 0 path = pointfc = .F. recno = 0 rotationcenter = .F. rowsum = 0 start = 0 sweep = 0 tilt = .F. type = value = .F. * PROCEDURE checkmouseposition LPARAMETERS tnX, tnY, tcType IF NOT EMPTY(tcType) AND NOT UPPER(tcType) == UPPER(THIS.TYPE) RETURN .F. ENDIF IF EMPTY(THIS.Contour) RETURN BETWEEN(tnX, THIS.LEFT, THIS.LEFT + THIS.WIDTH) AND BETWEEN(tnY, THIS.TOP, THIS.TOP + THIS.HEIGHT) ELSE RETURN _Screen.FoxChartsHelper.InsidePath(EVL(THIS.Contour,THIS.PATH),tnX,tnY) ENDIF ENDPROC PROCEDURE draw && Repaints a Form object. LPARAMETERS toGfx, toPen, toBrush, tnCanvasLeft, tnCanvastTop, tnRotationCenter LOCAL lnDiag, lnSinAngle tnCanvasLeft = EVL(tnCanvasLeft,This.LEFT) tnCanvastTop = EVL(tnCanvastTop,This.TOP) WITH THIS IF .Tilt OR NOT EMPTY(tnRotationCenter) WITH _SCREEN.SYSTEM.Drawing This.Matrix = .Drawing2D.Matrix.New() This.PointFC = .PointF.New(tnCanvasLeft, tnCanvastTop) && Центр вращения ENDWITH lnDiag = SQRT(.WIDTH^2 + .ArrowHeight^2) lnSinAngle = .ArrowHeight / lnDiag .RotationCenter= iif(EMPTY(tnRotationCenter),RTOD(ASIN(lnSinAngle)),tnRotationCenter) .Matrix.RotateAt(.RotationCenter, .PointFC) toGfx.MultiplyTransform(.Matrix) ENDIF _SCREEN.FoxChartsHelper.DrawPath( toGfx, m.toPen, m.toBrush, .PATH , 0, 0 ) ENDWITH ENDPROC PROCEDURE drawcontour LPARAMETERS toGfx, toPen, toBrush, tnCanvasLeft, tnCanvastTop LOCAL lnDiag, lnSinAngle tnCanvasLeft = EVL(tnCanvasLeft,0) tnCanvastTop = EVL(tnCanvastTop,0) WITH THIS IF .Tilt WITH _SCREEN.SYSTEM.Drawing THIS.Matrix = .Drawing2D.Matrix.New() THIS.PointFC = .PointF.New(THIS.LEFT+tnCanvasLeft, THIS.TOP+tnCanvastTop) && Центр вращения ENDWITH m.lnDiag = SQRT(.WIDTH^2 + .ArrowHeight^2) m.lnSinAngle = .ArrowHeight / m.lnDiag .RotationCenter=RTOD(ASIN(lnSinAngle)) .Matrix.RotateAt(.RotationCenter, .PointFC) toGfx.MultiplyTransform(.Matrix) ENDIF _Screen.FoxChartsHelper.DrawPath( m.toGfx, m.toPen, m.toBrush, .PATH , m.tnCanvasLeft, m.tnCanvastTop ) ENDWITH ENDPROC PROCEDURE setdimensions LPARAMETERS lnLeft,lnTop,lnWidth,lnHeight WITH THIS .LEFT=lnLeft .TOP=lnTop .WIDTH = lnWidth .HEIGHT = lnHeight ENDWITH ENDPROC ENDDEFINE DEFINE CLASS foxcharts AS foxcharts OF "foxcharts.vcx" *< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="Shapes" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="DeltaLegend" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Tips" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Comments" UniqueID="" Timestamp="" /> * *m: chart2report *m: drawcontour *m: fillpathdim *m: getcontourmeasures *m: gettexture *m: getvalue *m: openword *m: rotate *m: toword *m: towriter *m: toxls *m: _drawcomments *m: _drawcone *m: _drawconoid *m: _drawfrustum *m: _drawpyramid *p: backimage *p: bottomvalue *p: column *p: commentssetpack *p: contourgraphics *p: contourpen *p: deltagradient *p: deltaheight *p: deltaposition *p: deltatilt *p: drawarrowsfromsidelegend *p: gradienthorcount *p: gradientvertcount *p: news *p: oldmouseindex *p: readonlyprops *p: row *p: shapelegendtype *p: shapelegendvertalignment *p: showcolcaption *p: showcontour *p: showdecimals *p: showdelta *p: showdeltapercent *p: showrowcaption *p: showvalue *p: sleep *p: texturename *p: texturetheme *p: userightclick *p: value && Specifies the current state of a control. *a: acolors[1,0] *a: acoord[1,0] *a: apalettecolors[1,0] *a: _acolors[1,0] *a: _apoints[1,2] *a: _ashapes[1,0] *a: _asidelegends[1,2] *p: _odimbrush *p: _orightbrush * * backimage = .F. bottomvalue = 0 column = 0 commentssetpack = .F. contourgraphics = .F. contourpen = .F. deltagradient = 0 deltaheight = 24 deltaposition = 1 deltatilt = .F. drawarrowsfromsidelegend = .F. gradienthorcount = 1 gradientvertcount = 1 Height = 264 Name = "foxcharts" news = .F. oldmouseindex = 0 readonlyprops = .F. row = 0 shapelegendtype = 1 shapelegendvertalignment = 2 showcolcaption = .F. showcontour = .T. showdecimals = 0 showdelta = 1 showdeltapercent = .F. showrowcaption = .F. showvalue = .T. sleep = .F. texturename = texturetheme = .F. userightclick = .F. value = 0 versiona = FoxCharts v1.44 Beta Width = 340 _odimbrush = .F. _orightbrush = .F. Title.Name = "Title" SubTitle.Name = "SubTitle" XAxis.Name = "XAxis" YAxis.Name = "YAxis" ScaleLegend.Name = "ScaleLegend" AxisLegend2.Name = "AxisLegend2" ShapeLegend.Name = "ShapeLegend" SideLegend.Name = "SideLegend" ChartCanvas.Name = "ChartCanvas" Fields.Name = "Fields" ToolTip.Name = "ToolTip" YAxis2.Name = "YAxis2" * ADD OBJECT 'Comments' AS _legend WITH ; Alignment = 2, ; BackColor = 247,255,255, ; Caption = "Comments", ; FontSize = 9, ; Left = 113, ; Name = "Comments", ; Top = 236, ; Visible = .F. *< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="label" /> ADD OBJECT 'DeltaLegend' AS _legend WITH ; Alignment = 2, ; BackColor = 247,255,255, ; Caption = "DeltaLegend", ; FontSize = 9, ; Left = 113, ; Name = "DeltaLegend", ; Top = 162, ; Visible = .F. *< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="label" /> ADD OBJECT 'Shapes' AS shapes WITH ; Height = 12, ; Left = 113, ; Name = "Shapes", ; Top = 212, ; Width = 72 *< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="container" /> ADD OBJECT 'Tips' AS tips WITH ; AutoSize = .T., ; Caption = "Tips", ; Height = 17, ; Left = 108, ; Name = "Tips", ; Top = 183, ; Width = 24 *< END OBJECT: ClassLib="foxchartsbeta.vcx" BaseClass="label" /> PROCEDURE afterchart WITH THIS IF NOT EMPTY(.ShowDelta) AND .ChartType = 7 OR (INLIST(.ChartType , 3, 8, 9, 11) AND .ChartsCount=1) PRIVATE lnHalf, loBrush, loGfx, loPen lnArrowHeight= .DeltaHeight lnHalf = lnArrowHeight/2 loGfx=_SCREEN.SYSTEM.Drawing loPen = loGfx.PEN.New(loGfx.COLOR.Black, 1) && Создать карандаш IF .DeltaGradient = 0 m.loBrush = loGfx.SolidBrush.New(loGfx.COLOR.FromARGB(128,228,228,228)) ENDIF loOldObject=.F. FOR EACH loObject IN .Shapes.OBJECTS IF loObject.TYPE = 'Rect' lnValue=0 IF VARTYPE(loOldObject) = 'O' lnX0= INT(loOldObject.LEFT + loOldObject.WIDTH/2) && Left lnY0= ROUND(loOldObject.TOP + loOldObject.HEIGHT - lnArrowHeight,0) DO CASE CASE .DeltaPosition = 1 lnY0= ROUND(loOldObject.TOP + loOldObject.HEIGHT - lnArrowHeight,0) && Bottom CASE .DeltaPosition = 2 lnY0= ROUND(loOldObject.TOP + loOldObject.HEIGHT/2,0) && Middle CASE .DeltaPosition = 3 lnY0= ROUND(loOldObject.TOP - lnHalf,0) && Top OTHERWISE lnY0= ROUND(loOldObject.TOP - lnHalf*4,0) && Over top ENDCASE lcCaption = '' IF .ShowDelta > 0 IF loOldObject.VALUE # 0 AND .ShowDeltaPercent lnValue=(loObject.VALUE - loOldObject.VALUE) / loOldObject.VALUE * 100 lcCaption = ALLTRIM(STR(lnValue,20,1))+'%' ENDIF lnValue=loObject.VALUE - loOldObject.VALUE lcCaption = IIF(EMPTY(lcCaption),'',lcCaption+', ') + TRANSFORM(lnValue) ENDIF lnWidth = loObject.LEFT - lnX0 DO CASE CASE .DeltaPosition=1 lnTop2 = lnY0 CASE .DeltaPosition=2 lnTop2 = INT(loObject.TOP+loObject.HEIGHT/2) CASE .DeltaPosition=3 lnTop2 = INT(loObject.TOP - lnHalf) OTHER lnTop2 = INT(loObject.TOP - lnHalf*4) ENDCASE lnHeight = lnTop2-lnY0 WITH _SCREEN.SYSTEM.Drawing * Gradient brush IF THIS.DeltaGradient > 0 loColor1 = .COLOR.FromARGB(200, loOldObject.COLOR) loColor2 = .COLOR.FromARGB(200, loObject.COLOR) loBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(m.lnX0, m.lnY0, m.lnWidth, m.lnArrowHeight), ; loColor1, loColor2, 0) ENDIF ENDWITH lnEndWidth = 30 lnTextLeft = lnX0 lcPolyGon = _Screen.FoxChartsHelper.Arrows(THIS.ShowDelta, @lnTextLeft, lnY0, lnArrowHeight, lnWidth, lnEndWidth, lnValue ) lcObjectName = 'Shape' + ALLTRIM(STR(.Shapes.OBJECTS.COUNT+1)) THIS.Shapes.ADDOBJECT(lcObjectName,JUSTSTEM(this.Classlibrary)+[.Figure]) WITH EVALUATE('.Shapes.'+lcObjectName) .CoordNum = this.Shapes.OBJECTS.COUNT .SetDimensions( m.lnX0, m.lnY0, m.lnWidth, lnArrowHeight) .ArrowHeight = m.lnHeight .CAPTION = lcCaption .PATH = lcPolyGon .Tilt = THIS.DeltaTilt .TYPE="Delta" .DRAW(THIS.oGfx, m.loPen, m.loBrush, 0,0) .Contour = _Screen.FoxChartsHelper.SimplifyPath(lcPolyGon) IF THIS.DeltaTilt && AND NOT EMPTY(.RotationCenter) .Contour = _Screen.FoxChartsHelper.RotatePath(m.lnX0, m.lnY0, .Contour, .RotationCenter) ENDIF ENDWITH .DeltaLegend._Value = lcCaption .DeltaLegend._DrawString(lnTextLeft, lnY0-CEILING(.DeltaLegend._HEIGHT/2)+1,lnWidth-8,.DeltaLegend._HEIGHT) .oGfx.ResetTransform() ENDIF loOldObject = loObject ENDIF NEXT ENDIF ._DrawComments () ENDWITH ENDPROC PROCEDURE chart2report ** Chart2Report Local lcReportBehaviorOld Local oFoxChart lcReportBehaviorOld = Set("Reportbehavior") Set REPORTBEHAVIOR 90 Private m.oFoxChart && needed by report oFoxChart = This.ChartCanvas Report Form FoxChartsView Preview Nowait Set REPORTBEHAVIOR &lcReportBehaviorOld ENDPROC PROCEDURE chartscount_assign LPARAMETERS tnCount This.ChartsCount = m.tnCount * Prepare the Enumerated properties IF This.OldStyleProperties LOCAL n, lcIndex FOR m.n = 1 TO m.tnCount m.lcIndex = This._Str(m.n) IF m.n > 1 && The enum properties #1 already exists - no need to recreate This.AddProperty("ChartType" + m.lcIndex, 0) This.AddProperty("FieldValue" + m.lcIndex, "") This.AddProperty("Legend" + m.lcIndex, "") This.AddProperty("Color" + m.lcIndex, "") This.AddProperty("Shape" + m.lcIndex, 0) This.AddProperty("ShowValuesOnShape" + m.lcIndex, .T.) This.AddProperty("AxisIndex" + m.lcIndex, 1) ENDIF This.AddProperty("Bartype" + m.lcIndex, 0) ENDFOR ENDIF * Prepare the Fields collection This._SetFieldsCount(m.tnCount) ENDPROC PROCEDURE currlegend_access RETURN IIF(This.CurrIndex = 0, "", EVL(EVALUATE('this.Shapes.Shape'+ALLTRIM(Str(This.CurrIndex))+'.Legend'), cLegend)) ENDPROC PROCEDURE currobjtype_access LOCAL lnIndex, lcObjType lnIndex = This.CurrIndex lcObjType = IIF(lnIndex = 0, "", EVALUATE('this.Shapes.Shape'+ALLTRIM(Str(lnIndex))+'.Type')) RETURN lcObjType ENDPROC PROCEDURE currvalue_access LOCAL lnIndex, lnValue lnIndex = This.CurrIndex lnValue = IIF(EMPTY(lnIndex), 0, EVALUATE('this.Shapes.Shape'+ALLTRIM(Str(lnIndex))+'.Value')) RETURN lnValue ENDPROC PROCEDURE drawchart LPARAMETERS llForceShow LOCAL llSleep * Some setups before drawing for the case of transparent background * When some Image Canvas settings are needed IF THIS.BackColorAlpha < 255 && Transparency active THIS.ChartCanvas.CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.Transparent) THIS.ChartCanvas.RenderMode = 4 && Memory PNG THIS.BACKSTYLE = 0 && Transparent ENDIF IF NOT THIS._Started THIS._InitChart() ENDIF m.llSleep=THIS.Sleep THIS.Sleep = THIS.Sleep AND NOT m.llForceShow THIS.ChartCanvas.DRAW() THIS.Sleep = m.llSleep ENDPROC PROCEDURE drawcontour LPARAMETERS lcLines, tnIndex _Screen.FoxChartsHelper.DrawContour(This, lcLines, tnIndex) ENDPROC PROCEDURE fillpathdim LPARAMETERS loBrush, loPath WITH THIS .oGfx.FillPath(loBrush, loPath) IF VARTYPE(._oDimBrush)='O' .oGfx.FillPath( ._oDimBrush, loPath ) ENDIF ENDWITH ENDPROC PROCEDURE getchartproperties LPARAMETERS tnType, tbWrapper, tlShowDescriptions, tcReadOnlyProps ********************************************************************************************** * Method: GetChartProperties * Author: Jim R. Nelson * Returns the properties and values used to create the current chart * 2009-12-11 CChalom: added parameter #4, for getting the full script ********************************************************************************************** LOCAL lcCRLF, lcCollection, lcDescription, lcItem, lcMember, lcObjMem, lcObjects, lcProperty, lcResult, lcTabs, lcTempResult, ; lnI, lnJ, lnRow, lnTabSpaces, lnType, ; loMember, loPropertiesList * tnType = 1 for all properties * = 2 for non-default properties * = 3 for properties since last call to .SaveChartProperties * = 4 for returning a full script for recreating the chart * tbWrapper = .T. to include code around it ... WITH / ENDWITH IF NOT EMPTY(tcReadOnlyProps) THIS.Readonlyprops = THIS.Readonlyprops + tcReadOnlyProps+',' ENDIF m.lcCRLF = CHR(13) + CHR(10) m.lnTabSpaces = 4 m.lcTabs = SPACE(lnTabSpaces) DO CASE CASE EMPTY (tnType) lnType = 1 CASE tnType = 3 AND ISNULL(THIS._savedchartproperties) * for tnType =2, you must have first invoked method SaveChartProperties ... * the result is then all properties modified after the call to SaveChartProperties lnType = 2 CASE tnType = 4 RETURN THIS._GetChartScript() OTHERWISE lnType = tnType ENDCASE lcResult = "" lcObjects = "" lcCollection = "" m.loPropertiesList = THIS._GetChartProperties() AMEMBERS(laMembers, loPropertiesList, 3) *!* 2009-12-17 *!* CChalom: Changed order of appearance of the properties FOR lnI = 1 TO ALEN (laMembers, 1) m.lcMember = THIS._spellproperty (m.laMembers(lnI,1)) lcDescription = '' lnRow = ASCAN (loPropertiesList._Descriptions, m.lcMember, -1, -1, 1, 9) IF lnRow > 0 lcDescription = loPropertiesList._Descriptions(lnRow, 4) ENDIF DO CASE CASE LOWER(m.lcMember) = '_descriptions' CASE "O" # TYPE ("loPropertiesList." + m.lcMember) && simple properties m.lcResult = m.lcResult + THIS._GetChartProp(m.loPropertiesList, m.lcMember, m.lnType, THIS._savedchartproperties, lcDescription, tlShowDescriptions) CASE "C" = TYPE ("loPropertiesList." + m.lcMember, 1) && collection container FOR lnJ = 1 TO EVALUATE ("loPropertiesList." + m.lcMember + ".Count") m.lcItem = m.lcMember + ".Item(" + TRANSFORM(lnJ) + ")" loMember = EVALUATE ("loPropertiesList." + m.lcItem) AMEMBERS (laObjMembers, loMember) m.lcTempResult = '' FOR EACH m.lcObjMem IN laObjMembers m.lcObjMem = THIS._spellproperty (m.lcObjMem) lcDescription = '' IF tlShowDescriptions AND PEMSTATUS(loMember, "_Descriptions", 5) lnRow = ASCAN (loMember._Descriptions, m.lcObjMem, -1, -1, 1, 9) IF lnRow > 0 lcDescription = loMember._Descriptions(lnRow, 4) ENDIF ENDIF m.lcProperty = THIS._GetChartProp(; m.loPropertiesList, m.lcItem + "." + m.lcObjMem, m.lnType, THIS._savedchartproperties, lcDescription, tlShowDescriptions) m.lcTempResult = m.lcTempResult + m.lcProperty NEXT IF NOT EMPTY (m.lcTempResult) m.lcCollection = m.lcCollection + ; "WITH ." + m.lcMember + "(" + TRANSFORM(lnJ) + ")" + m.lcCRLF + ; STRTRAN(m.lcTempResult, "." + m.lcItem, m.lcTabs)+ "ENDWITH" + m.lcCRLF ENDIF NEXT OTHERWISE && Legend objects loMember = EVALUATE ("loPropertiesList." + m.lcMember) AMEMBERS (laObjMembers, loMember) m.lcTempResult = '' FOR EACH m.lcObjMem IN laObjMembers m.lcObjMem = THIS._spellproperty (m.lcObjMem) lcDescription = '' IF tlShowDescriptions AND PEMSTATUS(loMember, "_Descriptions", 5) lnRow = ASCAN (loMember._Descriptions, m.lcObjMem, -1, -1, 1, 9) IF lnRow > 0 lcDescription = loMember._Descriptions(lnRow, 4) ENDIF ENDIF m.lcTempResult = m.lcTempResult + THIS._GetChartProp (; m.loPropertiesList, m.lcMember + "." + m.lcObjMem, lnType, THIS._savedchartproperties, lcDescription, tlShowDescriptions) NEXT IF NOT EMPTY (m.lcTempResult) m.lcObjects = m.lcObjects + "WITH ." + m.lcMember + m.lcCRLF + ; STRTRAN(m.lcTempResult, "." + m.lcMember, m.lcTabs) + ; "ENDWITH" + m.lcCRLF ENDIF ENDCASE NEXT * Merge all types lcResult = lcResult + lcObjects + lcCollection *!* 2009-02-21 *!* CChalom: Fixed insertion of With/Endwith IF m.tbWrapper LOCAL lcCommand, laLines(1), N m.lcCommand = "" FOR N = 1 TO ALINES(laLines, m.lcResult) m.lcCommand = m.lcCommand + SPACE(3) + laLines(N) + m.lcCRLF NEXT TEXT TO lcResult NOSHOW TEXTMERGE LOCAL loChart as FoxCharts OF "FoxCharts.vcx" m.loChart = CREATEOBJECT("FoxCharts") WITH loChart <> <>loChart.DrawChart() ENDWITH ENDTEXT ENDIF RETURN m.lcResult ENDPROC PROCEDURE getcontourmeasures LPARAMETERS lcContour, tnLeft, tnTop, tnWidth, tnHeight LOCAL lnLine, lnLines, lnVal, laLines(1),la(1),lnCount lnLines = ALINES(laLines,lcContour) FOR lnLine=1 TO lnLines lnCount = ALINES(la,laLines(lnLine),',') lnVal=VAL(la(1)) IF lnLine=1 STORE lnVal TO tnLeft, tnWidth ELSE tnLeft = MIN(tnLeft,lnVal) tnWidth = MAX(tnWidth,lnVal) ENDIF lnVal=VAL(la(2)) IF lnLine=1 STORE lnVal TO tnTop, tnHeight ELSE tnTop = MIN(tnTop,lnVal) tnHeight = MAX(tnHeight,lnVal) ENDIF IF lnCount>5 tnWidth = MAX(tnWidth,VAL(la(1)) +VAL(la(3))) tnHeight = MAX(tnHeight,VAL(la(2)) + VAL(la(4))) ENDIF NEXT tnWidth = tnWidth-tnLeft tnHeight = tnHeight-tnTop ENDPROC PROCEDURE gettexture LPARAMETERS lcTextureTheme,lcPicture LOCAL lcExt, lnDir, lnLine IF VARTYPE(lcPicture)= 'N' lcPicture=TRANSFORM(lcPicture)+'.jpg' ENDIF lcTextureTheme = EVL(lcTextureTheme,THIS.TextureTheme) lcPicture = TRANSFORM(EVL(lcPicture,THIS.TextureName)) DO CASE CASE FILE('Textures\'+ADDBS(lcTextureTheme)+lcPicture) RETURN 'Textures\'+ADDBS(lcTextureTheme)+lcPicture CASE DIRECTORY('Textures\'+ADDBS(lcTextureTheme)) FOR lnLine=1 TO ADIR(la,'Textures\'+ADDBS(lcTextureTheme)+'*.*') lcExt=LOWER(JUSTEXT(la(lnLine,1))) IF lcExt $ [png,jpg,jpeg,gif,bmp] THIS.TextureName = la(lnLine,1) RETU 'Textures\'+ADDBS(lcTextureTheme)+THIS.TextureName EXIT ENDIF NEXT OTHERWISE FOR lnDir=1 TO ADIR(laDir,'Textures\*',"D") IF LEFT(laDir(lnDir,1),1)='.' LOOP ENDIF FOR lnLine=1 TO ADIR(la,'Textures\'+ADDBS(laDir(lnDir,1))+'\*.*') lcExt=LOWER(JUSTEXT(la(lnLine,1))) IF lcExt $ [png,jpg,jpeg,gif,bmp] THIS.TextureName = la(lnLine,1) lcTextureTheme = laDir(lnDir,1) RETURN 'Textures\'+ADDBS(lcTextureTheme)+THIS.TextureName ENDIF NEXT NEXT ENDCASE RETURN '' ENDPROC PROCEDURE getvalue LPARAMETERS tcField LOCAL lcNum WITH THIS GO .ROW IF EMPTY(tcField) lcNum = ALLTRIM(STR(.COLUMN)) .VALUE = NVL(EVALUATE("nValue" + lcNum),0) .BottomValue = IIF(TYPE([Bottom]+lcNum)='N',NVL(EVALUATE("Bottom" + lcNum),0),0 ) ELSE RETURN EVALUATE(tcField) ENDIF ENDWITH ENDPROC PROCEDURE Init IF NOT 'ALIAS FOXCHARTSBETA' $ SET('Class') SET CLASSLIB TO foxchartsBeta.vcx ADDI ENDIF IF TYPE('_Screen.FoxChartsHelper') = 'U' _SCREEN.ADDOBJECT('FoxChartsHelper', 'FoxChartsBeta.FoxChartsHelper') ENDIF DODEFAULT() ENDPROC PROCEDURE MouseDown LPARAMETERS nButton, nShift, nXCoord, nYCoord, toShape LOCAL llGradientInvertColors, llSingle, ; lnAngle, lnDeltaLeft, lnDeltaTop, lnGradientLevel, lnHeight, lnLeft, lnMyLeft, lnMyTop, lnOldBrushType, lnRatio, lnSeconds, lnTop, lnWidth, lnX, lnX1, lnX2, lnY, lnY1, lnY2, ; loGfx, loObject , loPen IF TYPE('thisform.Rect1.Visible')='L' AND THISFORM.Rect1.VISIBLE THISFORM.Rect1.VISIBLE=.F. ENDIF IF TYPE('toShape.Type') # 'C' RETURN ENDIF IF m.nButton=1 AND m.toShape.TYPE='Comments' IF TYPE([thisform.Canvas2])='U' THISFORM.ADDOBJECT ('Canvas2','FoxChartsBeta.Pattern') WITH THISFORM.Canvas2 .oGfx.SmoothingMode = _SCREEN.SYSTEM.Drawing.Drawing2D.SmoothingMode.AntiAlias .PEN = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.Black , 2) .PEN.DASHSTYLE = 3 ENDWITH ENDIF STORE 0 TO m.lnLeft, m.lnTop, m.lnWidth, m.lnHeight =THIS.GetContourmeasures (m.toShape.Contour, @m.lnLeft, @m.lnTop, @m.lnWidth, @m.lnHeight) WITH THISFORM.Canvas2 .ZORDER(0) .BACKSTYLE=0 .LEFT = THIS.LEFT + m.lnLeft .TOP= THIS.TOP + m.lnTop .WIDTH= m.lnWidth+1 .HEIGHT = m.lnHeight+1 .RenderMode = 4 * .CreateOSB() .CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.Transparent) _Screen.FoxChartsHelper.DrawPath(.oGfx, .PEN, , m.toShape.Contour, -m.lnLeft, -m.lnTop) .MyRenderOSB() THISFORM.MOUSEPOINTER = 5 THISFORM.SETALL('MousePointer', 5) .VISIBLE = .T. m.lnMyLeft = .LEFT m.lnMyTop = .TOP m.lnLeft = m.lnMyLeft m.lnTop = m.lnMyTop DO WHILE MDOWN() m.lnLeft = m.lnMyLeft + MCOL(THISFORM.NAME,THISFORM.SCALEMODE) - m.nXCoord m.lnLeft = MAX(THIS.LEFT,MIN(THIS.LEFT+THIS.WIDTH -m.lnWidth-1,m.lnLeft)) m.lnTop = m.lnMyTop + MROW(THISFORM.NAME,THISFORM.SCALEMODE) - m.nYCoord m.lnTop = MAX(THIS.TOP, MIN(THIS.TOP +THIS.HEIGHT-m.lnHeight-1, m.lnTop)) IF m.lnLeft = .LEFT AND m.lnTop = .TOP LOOP ENDIF .LEFT = m.lnLeft .TOP = m.lnTop ENDDO THISFORM.MOUSEPOINTER = 0 THISFORM.SETALL('MousePointer', 0) .VISIBLE=.F. ENDWITH IF m.lnLeft = m.lnMyLeft AND m.lnTop = m.lnMyTop RETURN ENDIF WITH THIS.CommentsSet(m.toShape.ChartIndex) .LEFT = (m.toShape.LEFT + m.lnLeft-m.lnMyLeft) / THIS.WIDTH .TOP = (m.toShape.TOP + m.lnTop-m.lnMyTop) / THIS.HEIGHT ENDWITH THIS.CommentsSetPack = THIS.CommentsSet.PACK() THIS.Drawchart () RETURN ENDIF IF m.nButton=1 AND m.toShape.TYPE='Legend' m.lnSeconds = SECONDS()+1 m.lnX2=-1 m.lnX1=m.nXCoord m.lnY1=m.nYCoord WITH _SCREEN.SYSTEM.Drawing m.loGfx = .Graphics.FromHWnd(THISFORM.HWND) && Create a Graphics object m.loGfx.SmoothingMode=4 m.loPen = .PEN.New(.COLOR.Blue,IIF(INLIST(THIS.ChartType,1,2,7,12),6,3)) && Создать карандаш m.lnOldBrushType= THIS.BrushType m.lnGradientLevel = THIS.GradientLevel m.llGradientInvertColors = THIS.GradientInvertColors THIS.GradientInvertColors =.T. THIS.GradientLevel= 9 IF m.lnOldBrushType=1 THIS.BrushType=2 ENDIF IF m.lnOldBrushType=2 THIS.BrushType=1 ENDIF THIS._PrepareBrushes(0, 0, THIS.WIDTH, THIS.HEIGHT, .T., m.toShape.ChartIndex, .T.) IF m.lnOldBrushType # THIS.BrushType THIS.BrushType=m.lnOldBrushType ENDIF THIS.GradientLevel=m.lnGradientLevel THIS.GradientInvertColors = m.llGradientInvertColors m.loPen.Brush= THIS._oMainBrush m.loPen.StartCap=18 m.loPen.EndCap=20 m.loPen.DASHSTYLE=1 m.llSingle = THIS.Singledata OR THIS.ChartsCount=1 FOR EACH m.loObject IN THIS.Shapes.OBJECTS DO CASE CASE THIS.ChartType<3 && Pie and donut IF m.loObject.TYPE $ 'RectPie' AND m.loObject.Currentrow=m.toShape.VALUE m.lnWidth = m.loObject.WIDTH / 2 m.lnHeight = m.loObject.HEIGHT / 2 m.lnX = m.loObject.LEFT + m.lnWidth m.lnY = m.loObject.TOP + m.lnHeight m.lnAngle = m.loObject.START + m.loObject.Sweep / 2 m.lnAngle = _Screen.FoxchartsHelper.UnAxonometric(m.lnAngle, m.lnWidth, m.lnHeight) m.lnRatio = IIF(THIS.ChartType=1,0.5,THIS.DonutRatio) m.lnRatio = m.lnRatio + (1 - m.lnRatio) / 2 m.lnX2 = m.lnX + COS(DTOR(m.lnAngle)) * m.lnWidth * m.lnRatio m.lnY2 = m.lnY + SIN(DTOR(m.lnAngle)) * m.lnHeight * m.lnRatio m.lnX2=m.lnX2 + OBJTOCLIENT(THIS,2) m.lnY2=m.lnY2 + OBJTOCLIENT(THIS,1) m.loGfx.Drawline(m.loPen, m.lnX1, m.lnY1, m.lnX2, m.lnY2) EXIT ENDIF CASE m.llSingle IF m.loObject.TYPE = 'Rect' AND m.loObject.Currentrow=m.toShape.VALUE m.lnX2 = m.loObject.LEFT + m.loObject.WIDTH/2 + OBJTOCLIENT(THIS,2) m.lnY2 = m.loObject.TOP + m.loObject.HEIGHT/2 + OBJTOCLIENT(THIS,1) m.loGfx.Drawline(m.loPen, m.lnX1, m.lnY1, m.lnX2, m.lnY2) EXIT ENDIF OTHERWISE IF m.loObject.TYPE = 'Rect' AND m.loObject.ChartIndex = m.toShape.ChartIndex IF m.loObject.LEFT=0 AND m.loObject.TOP=0 LOOP ENDIF m.lnX2=m.loObject.LEFT + m.loObject.WIDTH/2 + OBJTOCLIENT(THIS,2) m.lnY2=m.loObject.TOP + m.loObject.HEIGHT/2 + OBJTOCLIENT(THIS,1) m.loGfx.Drawline(m.loPen, m.lnX1, m.lnY1, m.lnX2, m.lnY2) ENDIF ENDCASE NEXT ENDWITH DO WHILE MDOWN() ENDDO ENDIF DO WHILE MDOWN() ENDDO THISFORM.CLS() ENDPROC PROCEDURE MouseUp LPARAMETERS nButton, nShift, nXCoord, nYCoord, toShape ENDPROC PROCEDURE openword * Code from Alex Yudin * 23.11.2013: Koen added code to avoid "Application is Busy" * Parameters from ToWord Lparameters tcDoc, tlInvisible, tcPassWord Local loWord, lnWindow, lcPath, lcPassWord Local loErr As Object #Define wdFormatDocument 0 #Define wdFormatDocument97 0 *!* lcPassWord = IIF(VARTYPE(m.tcPassWord) == 'C', m.tcPassWord, SPACE(0)) Declare Integer SetForegroundWindow In Win32API Long HWnd Declare Long FindWindow In Win32API String lpClassName,String lpWindowName Try loWord=Getobject(,"WORD.APPLICATION") Catch To m.loErr When m.loErr.ErrorNo=1426 loWord=Createobject("WORD.APPLICATION") Finally Endtry ** To avoid "Application is Busy" error messages using OLE Automation. see also - KB240809 Application.OLERequestPendingTimeout = 0 If Type('loWord.ActiveDocument')='O' m.loWord.ActiveDocument.Close Endif lnWindow = FindWindow(.Null., m.loWord.Name) If !Empty(m.tcDoc) tcDoc=Lower(Forceext(Alltrim(m.tcDoc),'DOC')) If File(m.tcDoc) *tcDoc=Fullpath(m.tcDoc) m.loWord.Documents.OpenFullpath(m.tcDoc) Else m.loWord.Documents.Add ("Normal", .F., 0) *lcPath=Justpath(m.tcDoc) If Not Directory(Justpath(m.tcDoc)) Md (Justpath(m.tcDoc)) Endif Try m.loWord.ActiveDocument.SaveAs(m.tcDoc,0,.F.,m.lcPassword) Catch To m.loErr Finally Endtry Endif Endif loWord.Visible=! m.tlInvisible If m.lnWindow # 0 SetForegroundWindow(m.lnWindow) Endif Return m.loWord ENDPROC PROCEDURE rotate LPARAMETERS lnX0,lnY0, lnX, lnY, lnNewAngle LOCAL lnAlfa, lnC, lnX1, lnY1 lnX1=lnX-lnX0 lnY1=lnY-lnY0 lnNewAngle = DTOR(lnNewAngle) * Координаты (lnX1,lnY1) в результате поворота точки (x, y) lnX = lnX1*COS(lnNewAngle)-lnY1*SIN(lnNewAngle) +lnX0 lnY = lnX1*SIN(lnNewAngle)+lnY1*COS(lnNewAngle) +lnY0 ENDPROC PROCEDURE savechartproperties **************************************************************** * Jim Nelson 10/20/2008 * modified 06/30/2009 * Save current settings of Chart Properties so that later comparisons * can determine which properties have changed LPARAMETERS tlSkipIfAlreadySaved IF tlSkipIfAlreadySaved AND "O" = VARTYPE(THIS._SavedChartProperties) RETURN ENDIF IF TYPE('this.CommentsSet.Name')='C' THIS.CommentsSetPack = THIS.CommentsSet.PACK() ENDIF THIS._SavedChartProperties = THIS._GetChartProperties() *!* **************************************************************** *!* * Jim Nelson 10/20/2008 *!* * *!* * Save current settings of Chart Properties so that later comparisons *!* * can determine which properties have changed *!* This._SavedChartProperties = This._GetChartProperties() ENDPROC PROCEDURE shapemouseenter LPARAMETERS nButton, nShift, nXCoord, nYCoord, loShape LOCAL lcLegend, lnChart, lo lnChart=loShape.ChartIndex lcLegend = EVL(loShape.Legend,'') FOR EACH lo IN this.Shapes.Objects IF lo.Type = 'Legend' AND ALLT(EVL(lo.Legend,''))==lcLegend IF TYPE('THISFORM.Rect1')='U' THISFORM.ADDOBJECT('Rect1','Shape') THISFORM.Rect1.BACKSTYLE=0 BINDEVENT(THISFORM.rect1,'MouseDown',THIS.ChartCanvas ,'MouseDown') ENDIF WITH THISFORM.rect1 .LEFT = lo.Left - 1 + OBJTOCLIENT(THIS,2) .WIDTH = lo.Width + 4 .TOP = lo.Top + OBJTOCLIENT(THIS,1)-1 .HEIGHT = lo.Height + 1 .VISIBLE=.T. .BORDERCOLOR = RGB(255,0,0) ENDWITH RETURN TRY LOCAL lcBell lcBell = SET("Bell") SET BELL TO (ADDBS(GETENV('windir')))+"MEDIA\Start.WAV" ?? CHR(7) SET BELL TO (lcBell) CATCH ENDTRY ENDIF NEXT ENDPROC PROCEDURE shapemouseleave LPARAMETERS nButton, nShift, nXCoord, nYCoord, tnValue, tcLegend, tnCoordIndex IF TYPE('thisform.Rect1.Visible')='L' THISFORM.Rect1.VISIBLE=.F. ENDIF ENDPROC PROCEDURE toword * Code from Alex Yudin * History : Koen Piller added codes for Clipboard checking in order to * avoid errors when the clipboard is already in use * Koen changed default saving directory and added "FindFirstFile" * to avoid tcDir contains short a shortfilename Local lcDir, lcFile, lcString, lcTableNum, lcVal, lcWordName, lhClipBMP, lhWndWord, lnChart Local lnColumns, lnEnd, lnLine, lnRows, lnStart, lnStartRows, loTable, loWord, luValue, lcBuffer ** Function FindFirstFile derived from sample code posted by ** AirCon (IS/IT--Manageme) on TekTips.com on May 12, 2003 Declare Long FindFirstFile In Kernel32 As fnFindFirst ; String cFileName, String @WIN32_DATA Declare FindClose In Kernel32 As fnFindClose Long hFile lcDir = GETENV("temp") lcFile = 'Charts.DOC' lcBuffer = Replicate(Chr(0), 318) hFile = fnFindFirst(ADDBS(lcDir)+m.lcFile, @m.lcBuffer) If (m.hFile > 0) lcFile = Substr(m.lcBuffer, 45) lcFile = Left(m.lcFile, At(Chr(0), m.lcFile)-1) fnFindClose(m.hFile) Endif Clear Dlls fnFindFirst, fnFindClose lcWordName = m.lcDir + m.lcFile #Define cf_bitmap 2 #Define cf_dib 8 #Define obj_bitmap 7 Declare Integer CloseClipboard In user32 Declare Integer OpenClipboard In user32 Integer HWnd Declare Integer GetClipboardData In user32 Integer uFormat Declare Integer IsClipboardFormatAvailable In user32 Integer wFormat Declare Integer GetObjectType In gdi32 Integer h *** Local Array laHeaders(This.ChartsCount+1,2) laHeaders(1,1) = This.FieldLegend For lnChart=1 To This.ChartsCount laHeaders(m.lnChart+1,1) = This.Fields(m.lnChart).Fieldvalue laHeaders(m.lnChart+1,2) = Evl(This.Fields(m.lnChart).Legend,'-') Next If This.ChartsCount = 1 laHeaders(1,2) = Evl(This.Fields(1).Legend,'-') laHeaders(2,2) = '-' Else laHeaders(1,2) = '-' Endif loWord = This.OpenWord(m.lcWordName,) lnRows = 1 lnColumns = Alen(m.laHeaders,1) This.oBMP.toClipboard() *= OpenClipboard (0) *= CloseClipboard () With m.loWord lhWndWord = FindWindow("OPUSApp", '') &&"OPUSApp" is the internal name of the MSWord-Class .Selection.WholeStory lhClipBMP = GetClipboardData (cf_bitmap) If m.lhClipBMP = 0 Or GetObjectType(m.lhClipBMP) # obj_bitmap lcFile = Addbs(Getenv('temp')) + Sys(2015) + ".PNG" This.SaveToFile(m.lcFile) .Selection.InlineShapes.AddPicture(m.lcFile,.F.,.T.) Erase (m.lcFile) Else .Selection.paste() Endif .ActiveDocument.Tables.Add(.Selection.Range(), m.lnRows+1, m.lnColumns, .T., .F.) lcTableNum = Evl(m.lcTableNum,1) Select (This.SourceAlias) loTable = .ActiveDocument.Tables(m.lcTableNum) loTable.Select lnStartRows = 1 &&loTable.ROWS.COUNT for multiple use lcString = '' For lnLine = 1 To m.lnColumns lcString = m.lcString+Alltrim(m.laHeaders(m.lnLine,2)) + iif(m.lnLine = m.lnColumns,Chr(13),Chr(9)) Next Select (This.SourceAlias) lnRows = 0 Scan lnRows = m.lnRows + 1 For lnLine = 1 To m.lnColumns lcVal = m.laHeaders(m.lnLine,1) luValue = iif(Type(m.lcVal)=='U','-',Nvl(Evaluate(m.laHeaders(m.lnLine,1)),'-')) lcString = m.lcString + Transform(m.luValue) + iif(m.lnLine = m.lnColumns,Chr(13),Chr(9)) Next Endscan If m.lnRows>1 .Selection.movedown (5, 1) .Selection.insertrows(m.lnRows-1) Endif _Cliptext = m.lcString lnStart = m.loTable.Cell(m.lnStartRows,1).Range.Start lnEnd = m.loTable.Cell(m.lnStartRows + m.lnRows,m.lnColumns).Range.End .ActiveDocument.Range(m.lnStart,m.lnEnd).Paste() .ActiveDocument.Saved = .T. .Visible=.T. * SetWindowPos moves the window to the top, using the window handle Declare SetWindowPos In WIN32API Long HWnd, Long hwndafter, ; LONG x, Long Y, Long cx, Long cy, Long Flags = SetWindowPos(m.lhWndWord, -1, 0,0,0,0, 3) && Moves Word to the topmost = SetWindowPos(m.lhWndWord, -2, 0,0,0,0, 3) && Not topmost * .Selection.TypeParagraph Endwith ENDPROC PROCEDURE towriter * Code from Alex Yudin LOCAL lcVal, lnChart, lnColumns, lnLine, lnRowCount, lnRows, ; loChart, loCoreReflection, loDesktop, loDispatcher, loDocument, loFrame, loRange, loTable, ; luValue LOCAL loWriter, laArgs(4), loProperty TRY m.loWriter = CREATEOBJECT("com.sun.star.ServiceManager") CATCH MESSAGEBOX('Open Office not installed') ENDTRY IF VARTYPE(m.loWriter) # "O" RETURN .F. ENDIF m.loDesktop = m.loWriter.createInstance("com.sun.star.frame.Desktop") m.loDispatcher = m.loWriter.createInstance("com.sun.star.frame.DispatchHelper") m.loCoreReflection = m.loWriter.createInstance("com.sun.star.reflection.CoreReflection") WITH m.loCoreReflection.forName("com.sun.star.beans.PropertyValue") FOR m.lnLine=1 TO ALEN(laArgs,1) m.loProperty =CREATEOBJECT( "Empty" ) .CREATEOBJECT(@m.loProperty) laArgs(m.lnLine)=m.loProperty NEXT ENDWITH RELEASE m.loProperty COMARRAY(m.loDesktop,10) * New document laArgs[1].NAME = "ReadOnly" laArgs[1].VALUE = .F. m.loDocument = m.loDesktop.LoadComponentFromUrl( "private:factory/swriter", "_blank", 0, @laArgs ) m.loFrame = m.loDocument.getCurrentController().getFrame() laArgs(1).NAME = "Text" laArgs(1).VALUE = " " m.loDispatcher.executeDispatch(m.loFrame, ".uno:InsertText", "", 0, @laArgs) *** Insert table SELECT (This.SourceAlias) m.lnRows = RECCOUNT() m.lnColumns = This.ChartsCount+1 m.lnRowCount = m.lnRows+1 LOCAL laArray(lnColumns, lnRowCount), laHeaders(lnColumns) STORE '-' TO m.laArray laHeaders(1) = This.FieldLegend FOR m.lnChart=1 TO This.ChartsCount laHeaders(m.lnChart+1) = This.FIELDS(m.lnChart).Fieldvalue m.laArray(m.lnChart+1,1) = EVL(This.FIELDS(m.lnChart).Legend,'-') NEXT IF This.ChartsCount = 1 m.laArray(2,1) = EVL(This.FIELDS(1).Legend,'-') ENDIF m.lnRows = 0 SCAN m.lnRows = m.lnRows + 1 FOR m.lnLine=1 TO m.lnColumns m.lcVal = laHeaders( m.lnLine) m.luValue = IIF(TYPE(m.lcVal)='U','-',NVL(EVALUATE(m.lcVal),'-')) m.laArray(m.lnLine,m.lnRows+1)= TRANSFORM(m.luValue) NEXT ENDSCAN laArgs(1).NAME = "TableName" laArgs(1).VALUE = "ChartTable" laArgs(2).NAME = "Columns" laArgs(2).VALUE = m.lnColumns laArgs(3).NAME = "Rows" laArgs(3).VALUE = m.lnRows+1 laArgs(4).NAME = "Flags" laArgs(4).VALUE = 9 m.loDispatcher.executeDispatch(m.loFrame, ".uno:InsertTable", "", 0, @laArgs) m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs) m.loTable = m.loDocument.TextTables.getByIndex(0) m.loRange = m.loTable.getCellRangeByPosition(0,0, m.lnColumns-1, m.lnRows) m.loRange.SetDataArray(@m.laArray) m.loDispatcher.executeDispatch(m.loFrame, ".uno:Escape", "", 0, @laArgs) m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs) m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs) THISFORM.ParentForm.Foxcharts1.oBmp.ToClipboard() laArgs[1].NAME = "" laArgs[1].VALUE = "" m.loDispatcher.executeDispatch(m.loFrame, ".uno:Paste", "", 0, @laArgs) m.loDispatcher.executeDispatch(m.loFrame, ".uno:Escape", "", 0, @laArgs) m.loDispatcher.executeDispatch(m.loFrame, ".uno:GoToStartOfDoc", "", 0, @laArgs) m.loFrame.getContainerWindow.setVisible(.T.) ENDPROC PROCEDURE toxls LOCAL lcClip, lcLegend, lcOldCliptext, lcWorkBook, llOK, ; lnChart, lnCount, lnHeight, lnLine, loBook, loSheet, loXls * Trying to attach launched Excel m.llOK=.T. TRY m.loXls=GETOBJECT(,"EXCEL.APPLICATION") CATCH TO loErr m.llOK=.F. ENDTRY IF ! m.llOK m.llOK=.T. TRY m.loXls=CREATEOBJECT("EXCEL.APPLICATION") CATCH TO loErr m.llOK=.F. ENDTRY ENDIF m.lcWorkBook=GETENV("TEMP")+'\Foxcharts.xls' WITH m.loXls .DisplayAlerts=.F. m.loBook=.Workbooks.ADD m.llOK=.T. TRY m.loBook.SAVEAS(m.lcWorkBook) CATCH m.llOK=.F. ENDTRY IF NOT m.llOK .QUIT m.loXls=0 RETURN ENDIF m.lcOldCliptext=_CLIPTEXT * Chart image to Clipboard THIS.oBmp.ToClipboard() * Insert image into Active sheet .activesheet.Paste m.lnHeight=.activesheet.PICTURES(1).HEIGHT m.loSheet=.activesheet FOR m.lnLine=1 TO 1000 IF m.loSheet.cells(m.lnLine,1).TOP>m.lnHeight EXIT ENDIF NEXT m.lnCount = THIS.ChartsCount m.loSheet.cells(m.lnLine,1).SELECT m.lcClip = '-' FOR m.lnChart=1 TO m.lnCount TEXT TO m.lcClip addi <> ENDTEXT NEXT m.lcClip=m.lcClip+CHR(13) SELECT (THIS.sourcealias) m.lcLegend=THIS.FieldLegend SCAN m.lcClip = m.lcClip +ALLT(&lcLegend.)+CHR(9) FOR m.lnChart=1 TO m.lnCount m.lcClip = m.lcClip +TEXTMERGE([<>])+IIF(m.lnChart= THIS.ChartsCount,CHR(13),CHR(9)) NEXT ENDSCAN _CLIPTEXT=m.lcClip m.llOK = .T. .activesheet.Paste _CLIPTEXT=m.lcOldCliptext WITH m.loSheet.RANGE(m.loSheet.cells(m.lnLine,1),m.loSheet.cells(m.lnLine,m.lnCount+1)) .HorizontalAlignment =-4108 .VerticalAlignment=-4108 .WrapText = .T. ENDWITH m.loSheet.COLUMNS("A:A").EntireColumn.AUTOFIT m.loSheet.cells(1,1).SELECT .VISIBLE=.T. * SetWindowPos moves the window to the top, using the window handle DECLARE SetWindowPos IN WIN32API LONG HWND, LONG hwndafter, ; LONG x, LONG Y, LONG cx, LONG cy, LONG FLAGS = SetWindowPos(.HWND, -1, 0,0,0,0, 3) && Moves Excel to the topmost = SetWindowPos(.HWND, -2, 0,0,0,0, 3) && Not topmost ENDWITH ENDPROC PROCEDURE _beforedraw This._Drawing = .T. * Store the current selected table / cursor LOCAL lnSelect m.lnSelect = SELECT() * Initial Settings LOCAL loChart as FoxCharts OF FoxCharts.Vcx m.loChart = This m.loChart.oGfx = This.ChartCanvas.oGfx m.loChart.oBmp = This.ChartCanvas.oBmp * Update quality settings This._UpdateQuality() * Check if the FoxCharts object was created * This is for the case when the user does not create the chart cursor before the form is initialized. IF EMPTY(This.SourceAlias) m.loChart._PrepareBackGround() RETURN ENDIF * Check for the minimum dimensions IF This.ChartCanvas.Width < 30 OR ; This.ChartCanvas.Height < 30 RETURN ENDIF m.loChart._CheckParams() m.loChart._UpdateChartInfo() THIS.Shapes.CLEAR IF NOT m.loChart._SkipPrepareData OR NOT USED(This._DataCursor) * Check if empty cursor IF NOT m.loChart._PrepareData() m.loChart._PrepareBackGround() m.loChart._PrepareTitle() RETURN ENDIF * Make sure to clear some properties to avoid issues if changing the chart type * having the Chart active This._ScaleLegAxis1ForceFormat = "" This._ScaleLegAxis2ForceFormat = "" This.ScaleLegend._ForceFormat = "" m.loChart._PrepareVariables() m.loChart._PrepareColors() ELSE SELECT (This._DataCursor) GO TOP ENDIF * m.loChart._PrepareColors() m.loChart._PrepareBackGround() m.loChart._PrepareTitle() m.loChart._PrepareSideLegend() m.loChart._PrepareLegend() m.loChart._DrawAxis() m.loChart._PrepareTooltip IF m.loChart.ShowValuesOnShapes m.loChart.ShapeLegend._Setup() ENDIF LOCAL lnChartType m.lnChartType = m.loChart.ChartType IF INLIST(m.lnChartType, 6, 9, 14, 11, 10) AND This._HasNegatives MESSAGEBOX("The selected Chart type does not support negative values" + CHR(13) + "The chart will not be drawn", 48, "Invalid Data") ELSE DO CASE *!* Chart Type Values: *!* 1 = Pie ; 2 = Donut ; *!* 3 = Unspecified ; *!* 4 = Point ; 5 = Line ; 6 = Area ; *!* 7 = Simple Bar ; 8 = Multiple Bars ; 9 = Stacked Bars ; 11 = 3D Bars *!* 10 = Stacked Area *!* 12 = Horizontal Bars ; 13 = Horizontal multiple bars ; 14 = Horizontal Stacked Bars CASE This._GeneralType = "Pie" && Pie or Donut Chart m.loChart._DrawPieChart() CASE This._GeneralType = "Bar" && Bar Chart m.loChart._DrawBarChart() CASE INLIST(m.lnChartType, 4, 5, 6, 18) && Line or Area Chart m.loChart._DrawLineChart() CASE INLIST(m.lnChartType, 10, 16) && Stacked Area Chart m.loChart._DrawStackedAreaChart() ENDCASE ENDIF m.loChart._DrawSideLegends() m.loChart.AfterChart() m.loChart._FirstActivate = .F. m.loChart._SkipPrepareData = .F. m.loChart._yAxisWidth = 0 m.loChart._yAxisWidth2 = 0 * Restore the original selected alias SELECT (m.lnSelect) This._GetRelativePositions() ENDPROC PROCEDURE _checkmouseposition LPARAMETERS nButton, nShift, nXCoord, nYCoord, lnValue, lnCoordIndex, toObject * Passed by reference: lnValue LOCAL lcObjectName, llFound, lnChartIndex, lnCoords, lnLeft, lnLine, lnNum, lnRecno, lnRecord, lnSelect, lnTop, lnX, lnY, ; loFirstSlice , loFoundShape, loShape m.toObject = .F. WITH THIS IF TYPE('.Shapes.Shape1.name') <> "C" OR nYCoord < 0 OR nXCoord <0 .MOUSEMOVE(nButton, nShift, nXCoord, nYCoord, toObject) .OldMouseIndex = 0 RETURN ENDIF m.lnLeft = ._xRelative &&+ .Left m.lnTop = ._yRelative &&+ .Top lnX=nXCoord - m.lnLeft lnY=nYCoord - m.lnTop lnCoords = .Shapes.CONTROLCOUNT FOR EACH loShape IN .Shapes.OBJECTS IF loShape.TYPE $ "Title,Subtitle,YaxisCaption,Yaxis2Caption,XaxisCaption,Legend,ScaleLegend,Comments" AND loShape.CheckMousePosition(lnX, lnY) m.toObject = loShape lnValue = loShape.VALUE lnCoordIndex = loShape.CoordNum IF NOT loShape.TYPE = "Legend" =IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum,.DrawContour(loShape.Contour,loShape.CoordNum),.F.) .OldMouseIndex = loShape.CoordNum RETURN ENDIF ENDIF * Проверим "Delta" IF .ShowDelta > 0 AND loShape.CheckMousePosition(lnX,lnY,"Delta") m.toObject = loShape =IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum, .DrawContour(loShape), .F.) .OldMouseIndex = loShape.CoordNum RETURN ENDIF * Проверим "ShapeLegend" IF .ShowValuesOnShapes AND loShape.CheckMousePosition(lnX,lnY,"ShapeLegend") m.toObject = loShape =IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum,.DrawContour(loShape.Contour,loShape.CoordNum),.F.) .OldMouseIndex = loShape.CoordNum RETURN ENDIF NEXT DO CASE CASE ._GeneralType $ "Bar,Point" lnRecord = ._nrecords+1 FOR lnNum=.Shapes.CONTROLCOUNT TO 1 STEP -1 && Reverse in order to catch the first drawing lcObjectName='Shape'+ALLTRIM(STR(lnNum)) loShape=EVALUATE('.Shapes.' + lcObjectName) IF loShape.TYPE = 'Delta' LOOP ENDIF IF NOT loShape.TYPE $ 'Title,Subtitle' lnRecord = lnRecord -1 ENDIF IF loShape.CheckMousePosition(lnX,lnY,'Rect') IF .ShowContour AND .OldMouseIndex # loShape.CoordNum =.DrawContour(EVL(loShape.Front,loShape.Contour),loShape.CoordNum),.F.) ENDIF .OldMouseIndex = loShape.CoordNum ELSE LOOP ENDIF toObject = loShape m.lnValue = loShape.VALUE m.lnCoordIndex = loShape.CoordNum IF m.loShape.TYPE $ "Legend" ._nMouseOnShape = 0 .OldMouseIndex = loShape.CoordNum RETURN ENDIF IF ._nMouseOnShape = 0 ._nMouseOnShape = lnRecord .ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loShape) ELSE IF ._nMouseOnShape # loShape.CoordNum ._nMouseOnShape = loShape.CoordNum .ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loShape) ELSE && Mouse over the shape .ShapeMouseMove(nButton, nShift, nXCoord, nYCoord, m.lnValue, ,m.lnCoordIndex) ENDIF ENDIF .OldMouseIndex = loShape.CoordNum RETURN NEXT IF ._nMouseOnShape # 0 ._nMouseOnShape = 0 .ShapeMouseLeave(nButton, nShift, nXCoord, nYCoord, loShape) ENDIF CASE ._GeneralType = "Pie" * Adapted code from Luis Maria Guayan - VFP MVP from Argentina LOCAL lnX1, lnX2, lnX3, lnY1, lnY2, lnY3, lnStart, lnSweep, lnValue, lnAngle llFound = .F. FOR EACH loFirstSlice IN .Shapes.OBJECTS IF loFirstSlice.TYPE='Pie' .OldMouseIndex = loFirstSlice.CoordNum llFound = .T. EXIT ENDIF NEXT IF NOT llFound RETURN ENDIF * Center of Ellipse m.lnX1 = loFirstSlice.WIDTH / 2 m.lnY1 = loFirstSlice.HEIGHT / 2 * Coordinates inside the Shape IF ._Pie1stDetached m.lnX2 = lnX - m.lnX1 - ._PieX0 m.lnY2 = - (lnY - m.lnY1 - ._PieY0) ELSE m.lnX2 = lnX - m.lnX1 - loFirstSlice.LEFT m.lnY2 = - (lnY - m.lnY1 - loFirstSlice.TOP) ENDIF * Угол в градусах [0°..360°] m.lnAngle = RTOD(ATAN(m.lnY2/m.lnX2)) DO CASE CASE m.lnX2 < 0 m.lnAngle = 180 + m.lnAngle CASE m.lnY2 < 0 m.lnAngle = 360 + m.lnAngle ENDCASE m.lnAngle = 360 - m.lnAngle LOCAL lnFoundShape m.lnFoundShape = 0 * Now we need to find the shape FOR lnLine = loFirstSlice.CoordNum TO lnCoords loFoundShape = EVALUATE('.Shapes.Shape' + ALLTRIM(STR(lnLine))) m.lnStart = EVL(loFoundShape.START, 0) IF loFoundShape.TYPE # 'Pie' OR VARTYPE(m.lnStart) <> "N" LOOP ENDIF m.lnSweep = EVL(loFoundShape.Sweep, 0) IF BETWEEN(m.lnAngle, m.lnStart, m.lnStart + m.lnSweep) OR ; BETWEEN(m.lnAngle + 360, m.lnStart, m.lnStart + m.lnSweep) m.lnFoundShape = lnLine EXIT ENDIF NEXT IF m.lnFoundShape = 0 .OldMouseIndex = 0 RETURN ENDIF * Now we can know exactly the positions in the screen * for the case of detached slices * So, we restart, using the correct information * Center of Shape m.lnX1 = loFoundShape.WIDTH / 2 m.lnY1 = loFoundShape.HEIGHT / 2 * Coordinates inside the Shape m.lnX2 = lnX - m.lnX1 - loFoundShape.LEFT m.lnY2 = -(lnY - m.lnY1 - loFoundShape.TOP) * Percentage in the ellipse m.lnX3 = m.lnX2 / m.lnX1 m.lnY3 = m.lnY2 / m.lnY1 *** NEW ANGLE * Angle in degrees [0°..360°] m.lnAngle = RTOD(ATAN(m.lnY2/m.lnX2)) DO CASE CASE m.lnX2 < 0 m.lnAngle = 180 + m.lnAngle CASE m.lnY2 < 0 m.lnAngle = 360 + m.lnAngle ENDCASE m.lnAngle = 360 - m.lnAngle IF BETWEEN(m.lnAngle, m.lnStart, m.lnStart + m.lnSweep) OR ; BETWEEN(m.lnAngle + 360, m.lnStart, m.lnStart + m.lnSweep) ELSE IF ._nMouseOnShape <> 0 ._nMouseOnShape = 0 .ShapeMouseLeave(nButton, nShift, nXCoord, nYCoord, loShape) ENDIF .OldMouseIndex = 0 RETURN ENDIF *** NEW ANGLE LOCAL lnRatio m.lnRatio = m.lnY3^2 + m.lnX3^2 IF m.lnRatio > 1 OR ; .ChartType = 2 AND m.lnRatio < .DonutRatio / 2 && Doughnut IF ._nMouseOnShape <> 0 ._nMouseOnShape = 0 .ShapeMouseLeave(nButton, nShift, nXCoord, nYCoord, loShape) ENDIF .OldMouseIndex = 0 RETURN ENDIF m.lnValue = loFoundShape.VALUE m.lnCoordIndex = loFoundShape.CoordNum m.toObject = loFoundShape IF ._nMouseOnShape = 0 ._nMouseOnShape = m.lnFoundShape .ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loFoundShape) ELSE IF ._nMouseOnShape <> m.lnFoundShape ._nMouseOnShape = m.lnFoundShape .ShapeMouseEnter(nButton, nShift, nXCoord, nYCoord, loFoundShape) ELSE .ShapeMouseMove(nButton, nShift, nXCoord, nYCoord, loFoundShape) ENDIF ENDIF RETURN ENDCASE IF .ShowAxis FOR EACH loShape IN .Shapes.OBJECTS IF loShape.TYPE $ "BottomSide,LeftSide,RightSide,AxisLegend2" AND loShape.CheckMousePosition(lnX,lnY) m.toObject = loShape =IIF(.ShowContour AND .OldMouseIndex # loShape.CoordNum,.DrawContour(loShape.Contour,loShape.CoordNum),.F.) .OldMouseIndex = loShape.CoordNum RETURN ENDIF NEXT ENDIF IF .OldMouseIndex # 0 THISFORM.CLS() .Tips.VISIBLE=.F. ENDIF .OldMouseIndex= 0 ENDWITH ENDPROC PROCEDURE _checkparams ASSERT BETWEEN(This.AlphaChannel, 0, 255) MESSAGE "AlphaChannel must be between 0-255" ASSERT BETWEEN(This.AxisAlpha, 0, 255) MESSAGE "AxisAlpha must be between 0-255" ASSERT BETWEEN(This.BackGradientMode, 0, 3) MESSAGE "BackGradientMode not available (0-3)" ASSERT BETWEEN(This.BarType, 0, 6) MESSAGE "BarType not available (0-6)" ASSERT BETWEEN(This.BrushType, 1, 5) MESSAGE "BrushType not available (1-5)" ASSERT BETWEEN(This.ChartType, 1, 18) MESSAGE "ChartType not available (1-18)" ASSERT BETWEEN(This.ColorType, 0, 27) MESSAGE "ColorType not available (0-27)" ASSERT BETWEEN(This.DonutRatio, 0, 1) MESSAGE "DonutRatio must be between 0 and 1" ASSERT BETWEEN(This.GradientLevel, -10, +10) MESSAGE "GradientLevel not available (-10, +10)" ASSERT BETWEEN(This.ScaleBackAlpha, 0, 255) MESSAGE "ScaleBackAlpha must be between 0-255" ASSERT BETWEEN(This.ScaleBackBarsType, 0, 3) MESSAGE "ScaleBackBarsType not available (0-3)" ASSERT BETWEEN(This.ScaleBackLinesType, 0, 3) MESSAGE "ScaleBackLinesType not available (0-3)" ASSERT BETWEEN(This.ScaleBackLinesDash, 0, 4) MESSAGE "ScaleBackLinesDash must be between 0-4" ASSERT This.ScaleDivider > 0 MESSAGE "ScaleDivider must be greater than Zero" ASSERT This.BarsPerScale > 0 MESSAGE "BarsPerScale must be greater than Zero" ASSERT This.LegendPosition <=12 MESSAGE "LegendPosition must be between 0-12" ASSERT USED(This.SourceAlias) MESSAGE "The specified source alias - '" + ; This.SourceAlias + "' could not be found!" IF This.ColorType = 3 && Gradient ASSERT (VARTYPE(This.Fields(1).Color) = "N" OR VARTYPE(This.Color1) = "N") ; MESSAGE "You have to define the property .Fields(1).Color to determine the main starting gradient color" ENDIF * GdiPlusX version check LOCAL lnVersion m.lnVersion = 1.10 IF pemstatus(_Screen.System, "Version", 5) m.lnVersion = _Screen.System.Version ENDIF IF m.lnVersion < 1.20 ASSERT (This.ChartType <> 4) ; MESSAGE "Points ChartType #4 is not supported for GdiPlusX System.App versions prior to version 1.20" + CHR(13) + ; "Please make sure to be using at least version 1.20 to be able to use this type of chart" ENDIF ENDPROC PROCEDURE _detachclickedslice LPARAMETERS tnIndex LOCAL lcCursor, ; llOrigDetach, ; lnDetachPixels, lnRecno, lnStep, ; loObject, N IF EMPTY(tnIndex) OR (VARTYPE(tnIndex) <> "N") RETURN ENDIF WITH THIS loObject = EVALUATE('.Shapes.Shape'+ALLTRIM(STR(tnIndex))) ._ChartIndex = loObject.ChartIndex m.lnRecno = loObject.Currentrow m.lcCursor = ._DataCursor SELECT (lcCursor) GO m.lnRecno m.llOrigDetach = lDetach m.lcCursor = (._DataCursor) REPLACE lDetach WITH NOT lDetach FOR RECNO() = m.lnRecno IN &lcCursor IF m.llOrigDetach ._SkipPrepareData = .T. .DrawChart() ELSE ._PieAnimatedRec = m.lnRecno m.lnDetachPixels = .PieDetachPixels m.lnStep = m.lnDetachPixels / MAX(1,.PieDetachAnimationSteps) FOR m.n = m.lnStep TO m.lnDetachPixels STEP m.lnStep ._PieAnimationPix = m.n ._SkipPrepareData = .T. .DrawChart() ENDFOR ENDIF ._PieAnimatedRec = 0 ._PieAnimationPix = 0 ._SkipPrepareData = .F. ENDWITH ENDPROC PROCEDURE _drawaxis LOCAL ln3D, lnMargin, lnYAxisHeight, x0, x1, y0, y1, lnX, lnY m.lnMargin = THIS.MARGIN IF THIS._DeepChart && Point, Line or Area m.ln3D = THIS._3D * THIS.ChartsCount ELSE m.ln3D = THIS._3D ENDIF * Prepare the scale in the Y Axis, populating the ._ScaleW property THIS._GetyLegendSize() IF This.ChartType = 18 AND This.ShowScale && DoubleAxis This._GetyLegendSize(2) ENDIF STORE 0 TO lnYAxisHeight, lnYaxisRight IF THIS.ShowAxis * Draw the main Y Axis caption LOCAL lcYText IF NOT EMPTY(THIS.YAxis.CAPTION) THIS.YAxis.RESET() lnYAxisHeight = CEILING(THIS.YAxis._Height) lnYaxisRight = lnYAxisHeight + THIS.YAxis.Left ENDIF ENDIF * Leaving some extra space for the X Axis legends LOCAL lnMinLeft, lnLeftCaptionWidth IF NOT EMPTY(THIS.FieldAxis2) * Measure the legend width THIS.AxisLegend2._Setup() GO TOP && First Legend THIS.AxisLegend2.CAPTION = cAxis2 && Field text lnLeftCaptionWidth = THIS.AxisLegend2._Width lnMinLeft = lnLeftCaptionWidth &&/ 2 ELSE STORE 0 TO lnMinLeft, lnLeftCaptionWidth ENDIF LOCAL lnEstimatedX, lnXBetween lnEstimatedX = THIS.WIDTH - ; (THIS._Rightoffset + THIS._Scalew + lnYAxisHeight + ln3D) lnXBetween = lnEstimatedX / THIS._nRecords IF lnXBetween > (lnLeftCaptionWidth / 2) lnMinLeft = (lnLeftCaptionWidth / 2) && - lnXBetween ENDIF lnMinLeft = lnMinLeft + THIS.YAxis.Left + IIF(EMPTY(THIS.YAxis.CAPTION),0, THIS.YAxis.Width) IF (NOT THIS.ShowAxis) OR NOT THIS._AllowAxis IF THIS._Orientation = 1 && Vertical THIS._yAxisWidth = 10 + lnMinLeft ELSE && Horizontal THIS._yAxisWidth = MAX(lnMinLeft, 0 + THIS._Scalew) ENDIF THIS._XAxisHeight = THIS._XAxisHeight - THIS.XAxis._Height RETURN ENDIF LOCAL lnTickWidth, loGfx m.lnTickWidth = 4 m.loGfx = THIS.oGfx WITH _SCREEN.SYSTEM.Drawing * Determining Colors, Brushes and Pens LOCAL lnAxisColor, lnAxisBorderColor IF THIS.BrushType = 3 && Monochrome m.lnAxisColor = RGB(255,255,255) && White m.lnAxisBorderColor = 0 && Black ELSE m.lnAxisColor = THIS.AxisColor m.lnAxisBorderColor = THIS.ChangeColor(m.lnAxisColor, -30) ENDIF LOCAL loAxisMainColor AS xfcColor, loAxisBorderColor AS xfcColor, loPen AS xfcPen, loBrush AS xfcSolidBrush loAxisMainColor = .COLOR.FromARGB(THIS.AxisAlpha, m.lnAxisColor) loAxisBorderColor = .COLOR.FromARGB(THIS.AxisAlpha, m.lnAxisBorderColor) m.loPen = .PEN.New(loAxisBorderColor, 1) m.loBrush = .SolidBrush.New(loAxisMainColor) ENDWITH **************** * Рисуем ось Y THIS._DrawYAxis(ln3D, lnMinLeft, lnYAxisHeight, loBrush, loPen, 1) IF THIS.ChartType = 18 && DoubleAxis THIS._DrawYAxis(m.ln3D, m.lnMinLeft, m.lnYAxisHeight, m.loBrush, m.loPen, 2) * IF THIS.ShowScale * This._DrawScale(m.loPen, 2) * ENDIF ENDIF WITH _SCREEN.SYSTEM.Drawing m.lnHeight = THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight - THIS._TopOffSet - m.ln3D THIS._ChartY0 = THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight - m.ln3D THIS._ChartY1 = THIS._ChartY0 - m.lnHeight * Рисуем ось X m.lnMargin = THIS._yAxisWidth + THIS._LeftOffset LOCAL x0, x1, y0 x0 = m.lnMargin x1 = THIS.ChartCanvas.WIDTH - THIS._Rightoffset y0 = ROUND(THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight + 1,0) IF THIS.ShowAxis IF m.ln3D = 0 m.loGfx.DrawLine(m.loPen, x0, y0, x1, y0) ELSE LOCAL laPoints(4) laPoints(1) = .POINT.New(x0, y0) laPoints(2) = .POINT.New(x0 + m.ln3D, y0 - m.ln3D) laPoints(3) = .POINT.New(x1, y0 - m.ln3D) laPoints(4) = .POINT.New(x1 - m.ln3D, y0) TEXT to lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT THIS._updatecoordinates (,'BottomSide', x0, y0, m.ln3D, m.ln3D, '', 0, lcPoints, 0) m.loGfx.FillPolygon(m.loBrush, @laPoints) LOCAL laPointsB(6) laPointsB(1) = laPoints(1) laPointsB(2) = laPoints(4) laPointsB(3) = laPoints(3) laPointsB(4) = .POINT.New(laPoints(3).x, y0 - m.ln3D + 3) laPointsB(5) = .POINT.New(laPoints(4).x, y0 + 3) laPointsB(6) = .POINT.New(laPoints(1).x, y0 + 3) m.loGfx.FillPolygon(m.loBrush, @laPointsB) m.loGfx.DrawLine(m.loPen, x0, y0, x0 + m.ln3D, y0 - m.ln3D) ENDIF ENDIF * Draw the main X Axis caption IF NOT EMPTY(THIS.XAxis.CAPTION) THIS.XAxis.RESET() LOCAL lnW, lnH m.lnX = m.lnMargin m.lnY = y0 + THIS._LegendPixHeight + 4 m.lnW = x1 - x0 m.lnH = THIS.XAxis._Height THIS.XAxis._DrawString(m.lnX, m.lnY, m.lnW, m.lnH) DO CASE CASE THIS.XAxis.ALIGNMENT = 0 lnLeft = INT(lnX) CASE THIS.XAxis.ALIGNMENT = 1 lnLeft = INT(lnX + m.lnW - THIS.XAxis._Width) OTHER lnLeft= INT(lnX + ( m.lnW-THIS.XAxis._Width )/2) ENDCASE lnTop = INT(lnY) lnRight = INT(lnLeft + THIS.XAxis._Width) lnBottom = INT(lnTop + THIS.XAxis._Height) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT THIS._updatecoordinates(,"XaxisCaption", lnLeft, lnTop, THIS.XAxis._Width, THIS.XAxis._Height, 0, THIS.XAxis.CAPTION, lcPoints) ENDIF IF THIS.ShowScale THIS._DrawScale(m.loPen) ENDIF IF THIS.ChartType = 18 && DoubleAxis IF THIS.ShowScale THIS._DrawScale(m.loPen, 2) ENDIF ENDIF ENDWITH ENDPROC PROCEDURE _drawbar LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tnMaxBarHeight, tn3D, tnMaxRowBarHeight, tnBarType * Yudin Alex 27 May 2013 LOCAL lcFront, lcPoints, llFrustum, lnBarType, ln3D, loShape, loTopBrush m.tnHeight = ABS(m.tnHeight) m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) m.lnBarType = EVL(m.tnBarType,THIS.BarType) DO CASE CASE m.lnBarType = 1 && Cylinder THIS._DrawCylinder(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue) RETURN CASE m.lnBarType = 2 && Triangle THIS._DrawTriangleBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue) RETURN CASE INLIST(m.lnBarType , 3, 5) && Cone or Conoid m.llFrustum = NOT EMPTY(m.tnMaxBarHeight) AND IIF(THIS._Orientation = 1,m.tnHeight,m.tnWidth)+1 < INT(m.tnMaxBarHeight) IF m.llFrustum RETURN THIS._DrawConoid(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D, m.tnMaxBarHeight ) ELSE RETURN THIS._DrawCone(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D ) ENDIF CASE INLIST(m.lnBarType , 4, 6) && Pyramid or Frustum m.llFrustum = NOT EMPTY(m.tnMaxBarHeight) AND IIF(THIS._Orientation = 1,m.tnHeight,m.tnWidth)+1 < INT(m.tnMaxBarHeight) IF m.llFrustum RETURN THIS._DrawFrustum(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D, m.tnMaxBarHeight) ELSE RETURN THIS._DrawPyramid(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue, @m.tn3D) ENDIF ENDCASE THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex)) LOCAL loPen AS xfcPen, loGfx AS xfcGraphics, loMainBrush AS xfcBrush, lo3dBrush AS xfcBrush m.loPen = THIS._oBorderPen m.loGfx = THIS.oGfx m.lo3dBrush = THIS._o3DBrush m.loMainBrush = THIS._oMainBrush WITH _SCREEN.SYSTEM.Drawing * Draw the 3D Bar using the 3DBrush IF m.ln3D > 0 && 3D IF NOT THIS.SHADOW * Prepare Array of points to draw the 3D part of the Bar LOCAL laPoints(4) m.tnY = m.tnY m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D) m.laPoints(3) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D) m.laPoints(4) = .PointF.New(m.tnX, m.tnY) LOCAL loPath AS xfcGraphicsPath m.loPath = .Drawing2D.GraphicsPath.New() m.loPath.FillMode = .Drawing2D.FillMode.ALTERNATE m.loPath.StartFigure() m.loPath.ADDLINE(m.tnX + m.tnWidth, m.tnY, m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D) m.loPath.ADDLINE(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D, m.tnX + m.ln3D, m.tnY - m.ln3D) m.loPath.ADDLINE(m.tnX + m.ln3D, m.tnY - m.ln3D, m.tnX, m.tnY) m.loPath.ADDLINE(m.tnX, m.tnY, m.tnX + m.tnWidth, m.tnY) m.loTopBrush = _SCREEN.FoxChartsHelper.PathGradient( , m.loPath, THIS._nColor,-1, m.tnX+m.tnWidth/2+m.ln3D/2, m.tnY+m.ln3D/2) m.loGfx.FillPolygon(m.loTopBrush, @laPoints) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillPolygon(THIS._oDimBrush, @laPoints) ENDIF m.loGfx.DrawPolygon(m.loPen, @laPoints) * Change only Points 3 and 4 m.laPoints(3) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY + m.tnHeight - m.ln3D) m.laPoints(4) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.loGfx.FillPolygon(THIS._oRightbrush , @laPoints) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillPolygon(THIS._oDimBrush , @laPoints) ENDIF m.loGfx.DrawPolygon(m.loPen, @laPoints) ELSE LOCAL loShadowBrush AS xfcSolidBrush m.loShadowBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel,128,128,128)) m.loGfx.FillRectangle(m.loShadowBrush , m.tnX + m.ln3D, m.tnY + m.ln3D, m.tnWidth, m.tnHeight - m.ln3D - m.ln3D) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillRectangle(THIS._oDimBrush , m.tnX + m.ln3D, m.tnY + m.ln3D, m.tnWidth, m.tnHeight - m.ln3D - m.ln3D) ENDIF LOCAL laPoints(4) m.laPoints(1) = .PointF.New(m.tnX , m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth , m.tnY + m.tnHeight) m.laPoints(3) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY + m.tnHeight - m.ln3D) m.laPoints(4) = .PointF.New(m.tnX + m.ln3D, m.tnY + m.tnHeight - m.ln3D) m.loGfx.FillPolygon(m.loShadowBrush , @laPoints) ENDIF ENDIF m.loGfx.FillRectangle(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillRectangle(THIS._oDimBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight) ENDIF m.loGfx.DrawRectangle(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight) TEXT TO m.lcPoints <>,<>,<>,<> <>,<>,<>,<> <>,<>,<>,<> <>,<>,<>,<> <>,<>,<>,<> <>,<>,<>,<> ENDTEXT TEXT TO m.lcFront <>,<> <>,<> <>,<> <>,<> ENDTEXT m.loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,m.lcPoints,,m.lcFront) IF THIS._GeneralType = "Bar" THIS._DrawLegendinBar(m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,m.loShape) ENDIF ENDWITH ENDPROC PROCEDURE _drawbarchart * Yudin Alex 2 June 2013 LOCAL lnBarType, lnBottomValue LOCAL lcAlias, lcLastPoint, ; lnBottomHeight, lnBottomWidth, lnColumn, lnCount, lnHorDelta, lnLine, lnLines, lnMaxBarHeight, lnMaxBarWidth, lnMaxRowHeight, lnMaxRowWidth, lnNativeValue, ; lnNewHorDelta, lnNewVertDelta, lnOldCone3D, lnStack, lnSumBarHeight, lnSumBarWidth, lnTotalMaxBarHeight, lnTotalMaxBarWidth, lnX1, lnY1, lnYDelta LOCAL lnWidth, lnHeight, x1, y1, N, lnValue, lnLeftMargin, ln3D, lnTopMargin LOCAL lnPointHeight AS NUMBER, lnYBase AS NUMBER WITH THIS SELECT(._DataCursor) m.ln3D = ._3D m.lnWidth = .ChartCanvas.WIDTH - ._LeftOffset - ._RightOffset - m.ln3D - ._yAxisWidth m.lnHeight = .ChartCanvas.HEIGHT - ._XAxisHeight - ._TopOffSet - m.ln3D IF (m.lnWidth <= 0) OR (m.lnHeight <= 0) RETURN ENDIF m.lnLeftMargin = ._yAxisWidth + ._LeftOffset m.lnTopMargin = ._TopOffSet + m.ln3D LOCAL lnBarWidth, lnBarHeight, lnBetween, lnMaxValue, lnAdjust, lnChartsCount m.lnBetween = .BarsSpaceBetween m.lnMaxValue = ._ScaleRange m.lnChartsCount = .ChartsCount * Prepare Points IF ._Orientation = 1 && Vertical IF ._DeepChart m.lnWidth = m.lnWidth - (m.ln3D * (m.lnChartsCount - 1)) ENDIF m.lnBetween = MIN(m.lnBetween, ; (m.lnWidth - ._nRecords) / ._nRecords) m.lnBarWidth = (m.lnWidth - (._nRecords - 1) * m.lnBetween) / ._nRecords SCAN m.n = RECNO() m.x1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (m.n - 1)) ._aPoints(m.n,1) = m.x1 + (m.lnBarWidth / 2) ENDSCAN ELSE && Horizontal m.lnBetween = MIN(m.lnBetween, ; (m.lnHeight - ._nRecords) / ._nRecords) m.lnBarHeight = (m.lnHeight - (._nRecords - 1) * m.lnBetween) / ._nRecords SCAN m.n = RECNO() m.y1 = m.lnTopMargin + ((m.lnBarHeight + m.lnBetween) * (m.n - 1)) ._aPoints(m.n,2) = m.y1 + (m.lnBarHeight / 2) ENDSCAN ._DrawYAxisLegend() ENDIF ._DrawVerticalLineBack() m.lnMaxBarHeight=0 DO CASE CASE .ChartType = 7 && Simple Bar SELECT (._DataCursor) LOCAL laStack(RECCOUNT(),7) m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnHeight m.lnZeroY = ._TopOffSet + m.ln3D + (._MaxScale / m.lnMaxValue * m.lnHeight) IF ._MinScale > 0 m.lnZeroY = m.lnZeroY - (._MinScale / m.lnMaxValue * m.lnHeight) ENDIF ._ChartIndex = .ChartRow m.lcLastPoint='' SCAN m.lnLine = RECNO() m.lnValue = ._GetValue(.ChartRow, .T.) IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale LOOP ENDIF IF m.lnValue < 0 m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) m.lnY1 = m.lnZeroY ELSE m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) + ; IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0) m.lnY1 = m.lnZeroY - m.lnBarHeight ENDIF m.lnX1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (RECNO() - 1)) m.lnMaxBarHeight=MAX(m.lnMaxBarHeight,m.lnBarHeight) laStack(m.lnLine,1)=m.lnX1 laStack(m.lnLine,2)=m.lnY1 laStack(m.lnLine,3)=m.lnBarWidth laStack(m.lnLine,4)=m.lnBarHeight laStack(m.lnLine,5)=m.lnValue laStack(m.lnLine,6)= RECNO() laStack(m.lnLine,7) = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) ENDSCAN FOR m.lnLine=1 TO RECCOUNT() GO laStack(m.lnLine,6) ._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarHeight),,,laStack(m.lnLine,7)) NEXT CASE .ChartType = 8 && Multi Bars LOCAL lnChart, lnOneBarWidth, lnZeroY, lnScaleAdjustment, lnTotRow, laValues(m.lnChartsCount), laBottom(m.lnChartsCount) m.lnOneBarWidth = m.lnBarWidth / m.lnChartsCount m.lnZeroY = ._TopOffSet + m.ln3D + (._MaxScale / m.lnMaxValue * m.lnHeight) IF ._MinScale > 0 m.lnZeroY = m.lnZeroY - (._MinScale / m.lnMaxValue * m.lnHeight) ENDIF m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnHeight m.lcAlias=ALIAS() LOCAL laLastPoint(MAX(1,m.lnChartsCount)) m.laLastPoint='' STORE 0 TO m.lnValue,m.lnBottomValue, m.lnCount m.lnLines =RECCOUNT() SCAN m.lnLine = RECNO() m.lnTotRow = 0 * Get the total for the current row FOR m.lnColumn = 1 TO m.lnChartsCount m.lnValue = ._GetValue(m.lnColumn, .T.) laValues(m.lnColumn) = m.lnValue m.lnTotRow = m.lnTotRow + NVL(m.lnValue, 0) NEXT FOR m.lnColumn = 1 TO m.lnChartsCount m.lnValue = laValues(m.lnColumn) IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale LOOP ENDIF ._ChartIndex = m.lnColumn m.lnX1 = m.lnLeftMargin + ; ((m.lnBarWidth + m.lnBetween) * (m.lnLine - 1)) + ; ((m.lnColumn-1 ) * m.lnOneBarWidth) IF m.lnValue < 0 m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) m.lnY1 = m.lnZeroY ELSE m.lnBarHeight = (m.lnValue / m.lnMaxValue * m.lnHeight) + IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0) m.BottomHeight=(m.lnBottomValue / m.lnMaxValue * m.lnHeight) m.lnY1 = m.lnZeroY - m.lnBarHeight - m.BottomHeight ENDIF .ChartSum = m.lnTotRow m.lnMaxBarHeight=MAX(m.lnMaxBarHeight,m.lnBarHeight) m.lnCount = m.lnCount+1 LOCAL laStack(lnCount,8) laStack(m.lnCount,1) = m.lnX1 laStack(m.lnCount,2) = m.lnY1 laStack(m.lnCount,3) = m.lnOneBarWidth laStack(m.lnCount,4) = m.lnBarHeight laStack(m.lnCount,5) = m.lnValue laStack(m.lnCount,6) = m.lnLine laStack(m.lnCount,7) = m.lnColumn laStack(m.lnCount,8) = IIF(.Fields(m.lnColumn).Bartype<0, .Bartype, .Fields(m.lnColumn).Bartype) NEXT ENDSCAN m.lcLastPoint='' FOR m.lnLine=1 TO m.lnCount GO laStack(m.lnLine,6) ._ChartIndex = laStack(m.lnLine,7) lnBartype = laStack(m.lnLine,8) ._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarHeight),,,lnBartype) NEXT ._ChartIndex = 1 CASE .ChartType = 9 && Stacked Bars m.lnZeroY = ._TopOffSet + m.ln3D + (._MaxScale / m.lnMaxValue * m.lnHeight) m.lnYBase = IIF(._HasNegatives, m.lnZeroY, ._TopOffSet + m.ln3D + m.lnHeight) m.lnTotalMaxBarHeight = 0 LOCAL laMaxConeHeight(MAX(1,RECCOUNT())) m.laMaxConeHeight = 0 STORE 0 TO m.lnValue,m.lnBottomValue FOR .ROW = 1 TO RECCOUNT() STORE m.lnYBase TO m.lnY1, m.yMinus1 STORE 0 TO m.lnStack, m.lnSumBarHeight FOR .COLUMN = 1 TO .ChartsCount ._ChartIndex = .COLUMN m.lnBarType = IIF(.Fields(.Column).Bartype<0, .Bartype, .Fields(.Column).Bartype) .GetValue() m.lnNativeValue = .VALUE m.lnValue = ABS(NVL(m.lnNativeValue,0)) m.lnBarHeight = m.lnValue / m.lnMaxValue * m.lnHeight IF m.lnBarType # 7 m.laMaxConeHeight(.ROW) = m.laMaxConeHeight(.ROW) + m.lnBarHeight m.lnSumBarHeight = m.lnSumBarHeight + m.lnBarHeight ENDIF IF m.lnNativeValue >=0 LOOP ENDIF m.lnX1 = m.lnLeftMargin + ; ((m.lnBarWidth + m.lnBetween) * (.ROW - 1)) m.lnMaxBarHeight=MAX(m.lnMaxBarHeight,m.lnBarHeight) m.lnStack = m.lnStack +1 LOCAL laStack(m.lnStack,8) laStack(m.lnStack,1) = m.lnX1 laStack(m.lnStack,2) = m.yMinus1 laStack(m.lnStack,3) = m.lnBarWidth laStack(m.lnStack,4) = m.lnBarHeight laStack(m.lnStack,5) = m.lnNativeValue laStack(m.lnStack,6) = ._ChartIndex laStack(m.lnStack,7) = m.lnSumBarHeight laStack(m.lnStack,8) = m.lnBarType m.yMinus1 = m.yMinus1 + m.lnBarHeight NEXT m.lnTotalMaxBarHeight = MAX(m.lnTotalMaxBarHeight, m.lnSumBarHeight) FOR m.lnLine=m.lnStack TO 1 STEP -1 ._ChartIndex = laStack(m.lnLine,6) ._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5),m.lnMaxBarHeight,,,laStack(m.lnLine,8)) NEXT NEXT LOCAL laLastPoint(MAX(1,m.lnChartsCount)) m.laLastPoint='' FOR .ROW = 1 TO RECCOUNT() m.lnY1 = m.lnYBase m.lnBottomHeight=0 m.lnHorDelta = 0 m.ln3dDelta = 0 m.lnCone3d = ._3D m.lnMaxRowHeight = m.laMaxConeHeight(.ROW) FOR .COLUMN = 1 TO .ChartsCount ._ChartIndex = .COLUMN .GetValue() m.lnNativeValue = .VALUE IF m.lnNativeValue <=0 LOOP ENDIF m.lnBarType = IIF(.Fields(.Column).Bartype<0, .Bartype, .Fields(.Column).Bartype) m.lnValue = ABS(NVL(m.lnNativeValue,0)) m.lnBarHeight = m.lnValue / m.lnMaxValue * m.lnHeight m.lnX1 = m.lnLeftMargin + ((m.lnBarWidth + m.lnBetween) * (.ROW - 1)) m.lnOldCone3D = m.lnCone3d DO CASE CASE INLIST(m.lnBarType,3,4) m.lnY1 = m.lnY1 - m.lnBarHeight m.lnNewHorDelta = ._DrawBar(m.lnX1 + m.lnHorDelta + m.ln3dDelta, m.lnY1 - m.ln3dDelta, ; m.lnBarWidth-m.lnHorDelta-m.lnHorDelta, m.lnBarHeight, ; m.lnValue, m.lnMaxRowHeight-m.lnBottomHeight, @m.lnCone3d,,m.lnBartype) OTHER m.lnY1 = m.lnY1 - m.lnBarHeight m.lnNewHorDelta = ._DrawBar(m.lnX1 + m.lnHorDelta + m.ln3dDelta, m.lnY1 - m.ln3dDelta, ; m.lnBarWidth-m.lnHorDelta-m.lnHorDelta, m.lnBarHeight, ; m.lnValue, m.lnTotalMaxBarHeight-m.lnBottomHeight, @m.lnCone3d, m.laMaxConeHeight(.ROW)-m.lnBottomHeight, m.lnBartype) ENDCASE m.lnHorDelta = m.lnHorDelta + IIF(VARTYPE(m.lnNewHorDelta) ='N',m.lnNewHorDelta,0) m.lnBottomHeight = m.lnBottomHeight + IIF(m.lnBarType = 7, 0, m.lnBarHeight) m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2 NEXT NEXT ._ChartIndex = 1 CASE .ChartType = 11 && 3D Bars * Calculate the maximum width of the chart m.lnHeight = m.lnHeight - (m.ln3D * (m.lnChartsCount - 1)) m.lnStack = 0 FOR ._ChartIndex = 1 TO m.lnChartsCount m.lnAdjust = m.ln3D * (m.lnChartsCount - ._ChartIndex ) SCAN m.lnValue = ._GetValue(._ChartIndex, .T.) m.lnX1 = m.lnLeftMargin + m.lnAdjust + ((m.lnBarWidth + m.lnBetween) * (RECNO() - 1)) IF ._ChartIndex = m.lnChartsCount * Prepare Points ._aPoints(RECNO(),1) = m.lnX1 + (m.lnBarWidth / 2) ENDIF IF ISNULL(m.lnValue) LOOP ENDIF m.lnPointHeight = (m.lnValue-._MinScale) / m.lnMaxValue * m.lnHeight m.lnY1 = ._TopOffSet + (m.lnHeight - m.lnPointHeight) - m.lnAdjust + (m.ln3D * (m.lnChartsCount)) m.lnYBase = .ChartCanvas.HEIGHT - ._XAxisHeight - m.lnAdjust m.lnBarHeight = m.lnYBase - m.lnY1 m.lnMaxBarHeight = MAX(m.lnMaxBarHeight , m.lnBarHeight) m.lnStack = m.lnStack + 1 LOCAL laStack(lnStack,8) laStack(m.lnStack,1) = m.lnX1 laStack(m.lnStack,2) = m.lnY1 laStack(m.lnStack,3) = m.lnBarWidth laStack(m.lnStack,4) = m.lnBarHeight laStack(m.lnStack,5) = m.lnValue laStack(m.lnStack,6) = RECNO() laStack(m.lnStack,7) = ._ChartIndex laStack(m.lnStack,8) = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) ENDSCAN NEXT LOCAL laLastPoint(RECCOUNT()) STORE '' TO m.laLastPoint FOR m.lnLine=1 TO m.lnStack GO laStack(m.lnLine,6) ._ChartIndex = laStack(m.lnLine,7) ._ChartIndex = laStack(m.lnLine,7) ._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarHeight),,,laStack(m.lnLine,8)) NEXT CASE .ChartType = 12 && HORIZONTAL Simple Bar IF m.lnBetween >= m.lnHeight / (._nRecords - 1) m.lnBarHeight = 1 m.lnBetween = (m.lnHeight - ._nRecords) / (._nRecords - 1) ENDIF LOCAL lnZeroX, lnScaleAdjustment, laLastPoint(RECCOUNT()) m.lnZeroX = m.lnLeftMargin + IIF(._ScaleAdjust < 0 , 0, (._ScaleAdjust / m.lnMaxValue * m.lnWidth)) m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnWidth ._ChartIndex = .ChartRow SET ORDER TO REVERT m.lnStack=0 m.lnMaxBarWidth = 0 SCAN m.lnValue = ._GetValue(.ChartRow, .T.) IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale LOOP ENDIF IF m.lnValue < 0 m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth) m.lnX1 = m.lnZeroX - m.lnBarWidth ELSE m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) + ; IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0) m.lnX1 = m.lnZeroX ENDIF m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D m.lnStack = m.lnStack +1 LOCAL laStack(m.lnStack,7) laStack(m.lnStack,1) =m.lnX1 laStack(m.lnStack,2) =m.lnY1 laStack(m.lnStack,3) =m.lnBarWidth laStack(m.lnStack,4) =m.lnBarHeight laStack(m.lnStack,5) = m.lnValue laStack(m.lnStack,6) = RECNO() m.lnMaxBarWidth = MAX(m.lnMaxBarWidth, m.lnBarWidth) laStack(m.lnStack,7) = IIF(.Fields(.ChartRow).Bartype<0, .Bartype, .Fields(.ChartRow).Bartype) ENDSCAN FOR m.lnLine=1 TO m.lnStack GO laStack(m.lnLine,6) lnBartype = laStack(m.lnLine,7) ._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(lnBarType,3,4),0,m.lnMaxBarWidth),,,lnBarType) NEXT SET ORDER TO CASE .ChartType = 13 && HORIZONTAL Multi Bars IF m.lnBetween >= m.lnHeight / (._nRecords - 1) m.lnBarHeight = 1 m.lnBetween = (m.lnHeight - ._nRecords) / (._nRecords - 1) ENDIF m.lnMaxBarWidth = 0 m.lnBarHeight = (m.lnHeight - (._nRecords - 1) * m.lnBetween) / ._nRecords LOCAL i, lnOneBarHeight m.lnOneBarHeight = m.lnBarHeight / m.lnChartsCount LOCAL lnZeroX, lnScaleAdjustment, lnTotRow, laValues(m.lnChartsCount) m.lnZeroX = m.lnLeftMargin + IIF(._ScaleAdjust < 0 , 0, (._ScaleAdjust / m.lnMaxValue * m.lnWidth)) m.lnScaleAdjustment = ._ScaleAdjust / m.lnMaxValue * m.lnWidth LOCAL laLastPoint( RECCOUNT()) m.lnStack = 0 SET ORDER TO REVERT SCAN m.lnTotRow = 0 * Get the total for the current row FOR ._ChartIndex = .ChartsCount TO 1 STEP -1 m.lnValue = ._GetValue(._ChartIndex, .T.) laValues(._ChartIndex) = m.lnValue m.lnTotRow = m.lnTotRow + NVL(m.lnValue, 0) NEXT FOR ._ChartIndex = .ChartsCount TO 1 STEP -1 m.lnValue = laValues(._ChartIndex) IF ISNULL(m.lnValue) OR m.lnValue < ._MinScale LOOP ENDIF IF m.lnValue < 0 m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth) m.lnX1 = m.lnZeroX - m.lnBarWidth ELSE m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) + ; IIF(._ScaleAdjust < 0, m.lnScaleAdjustment, 0) m.lnX1 = m.lnZeroX ENDIF m.lnY1 = ._TopOffSet + m.ln3D + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + ; ((._ChartIndex-1 ) * m.lnOneBarHeight) .ChartSum = m.lnTotRow m.lnStack = m.lnStack +1 LOCAL laStack(m.lnStack,8) laStack(m.lnStack,1) = m.lnX1 laStack(m.lnStack,2) = m.lnY1 + m.lnOneBarHeight/2 laStack(m.lnStack,3) = m.lnBarWidth laStack(m.lnStack,4) = m.lnOneBarHeight laStack(m.lnStack,5) = m.lnValue laStack(m.lnStack,6) = RECNO() laStack(m.lnStack,7) = ._ChartIndex laStack(m.lnStack,8) = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) m.lnMaxBarWidth = MAX(m.lnMaxBarWidth, m.lnBarWidth) NEXT ENDSCAN FOR m.lnLine=1 TO m.lnStack GO laStack(m.lnLine,6) ._ChartIndex = laStack(m.lnLine,7) ._DrawBar(laStack(m.lnLine,1),laStack(m.lnLine,2),laStack(m.lnLine,3),laStack(m.lnLine,4),laStack(m.lnLine,5), IIF(INLIST(.BarType,3,4),0,m.lnMaxBarWidth),,,laStack(m.lnLine,8)) NEXT SET ORDER TO ._ChartIndex = 1 CASE .ChartType = 14 && HORIZONTAL Stacked Bars IF m.lnBetween >= m.lnHeight / (._nRecords - 1) m.lnBarHeight = 1 m.lnBetween = (m.lnHeight - ._nRecordss) / (._nRecords - 1) ENDIF SET ORDER TO REVERT m.lnTotalMaxBarWidth = 0 LOCAL laMaxConeWidth(MAX(1,RECCOUNT())) m.laMaxConeWidth = 0 SCAN m.lnX1 = m.lnLeftMargin m.lnStack=0 m.lnSumBarWidth = 0 FOR ._ChartIndex = 1 TO m.lnChartsCount m.lnValue = ._GetValue(._ChartIndex, .T.) IF ISNULL(m.lnValue) OR EMPTY(m.lnValue) LOOP ENDIF m.lnBarWidth = ROUND( m.lnValue / m.lnMaxValue * m.lnWidth, 0) m.laMaxConeWidth(RECNO()) = m.laMaxConeWidth(RECNO()) + m.lnBarWidth m.lnSumBarWidth = m.lnSumBarWidth + m.lnBarWidth NEXT m.lnTotalMaxBarWidth = MAX(m.lnTotalMaxBarWidth, m.lnSumBarWidth) ENDSCAN LOCAL lnVertDelta, lnCone3d, ln3dDelta, laLastPoint(RECCOUNT()) SCAN m.lnYDelta = 0 m.lnX1 = m.lnLeftMargin STORE 0 TO m.lnVertDelta, m.ln3dDelta, m.lnBottomWidth m.lnCone3d = ._3D m.lnMaxRowWidth = m.laMaxConeWidth(RECNO()) m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D FOR ._ChartIndex = .ChartsCount TO 1 STEP -1 m.lnValue = ._GetValue(._ChartIndex, .T.) IF ISNULL(m.lnValue) OR EMPTY(m.lnValue) LOOP ENDIF m.lnValue = ABS(NVL(m.lnValue,0)) m.lnBarWidth = ROUND(m.lnValue / m.lnMaxValue * m.lnWidth,0) lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) m.lnOldCone3D = m.lnCone3d IF INLIST(.BarType,3,4) m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1 + m.lnVertDelta- m.ln3dDelta, ; m.lnBarWidth, m.lnBarHeight-m.lnVertDelta*2, ; m.lnValue, m.lnMaxRowWidth-m.lnBottomWidth, @m.lnCone3d,,m.lnBarType) m.lnX1 = m.lnX1 + m.lnBarWidth ELSE m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1 + m.lnVertDelta- m.ln3dDelta , ; m.lnBarWidth, m.lnBarHeight-m.lnVertDelta*2, ; m.lnValue, m.lnTotalMaxBarWidth-m.lnBottomWidth, @m.lnCone3d, m.laMaxConeWidth(RECNO()),m.lnBarType) m.lnX1 = m.lnX1 + m.lnBarWidth ENDIF m.lnVertDelta = m.lnVertDelta + IIF(VARTYPE(m.lnNewVertDelta) ='N',m.lnNewVertDelta,0) m.lnBottomWidth=m.lnBottomWidth+m.lnBarWidth m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2 NEXT ENDSCAN SET ORDER TO ._ChartIndex = 1 CASE .ChartType = 15 && HORIZONTAL Full-Stacked Bars IF m.lnBetween >= m.lnHeight / (._nRecords - 1) m.lnBarHeight = 1 m.lnBetween = (m.lnHeight - ._nRecords) / (._nRecords - 1) ENDIF SET ORDER TO REVERT LOCAL lnTotRow, laValues(m.lnChartsCount) STORE 0 TO m.lnTotalMaxBarWidth, m.lnStack SCAN m.lnBottomWidth=0 m.lnVertDelta = 0 m.ln3dDelta = 0 m.lnCone3d = ._3D m.lnTotRow = 0 * Get the total for the current row FOR ._ChartIndex = .ChartsCount TO 1 STEP -1 m.lnValue = ._GetValue(._ChartIndex, .T.) laValues(._ChartIndex) = m.lnValue m.lnTotRow = m.lnTotRow + m.lnValue NEXT m.lnSumBarWidth = 0 m.lnX1 = m.lnLeftMargin m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (RECNO() - 1)) + m.ln3D FOR ._ChartIndex = .ChartsCount TO 1 STEP -1 m.lnValue = laValues(._ChartIndex) IF EMPTY(m.lnValue) LOOP ENDIF m.lnBarWidth = m.lnValue / m.lnTotRow * m.lnWidth m.lnSumBarWidth = m.lnSumBarWidth + m.lnBarWidth .ChartSum = m.lnTotRow m.lnStack = m.lnStack +1 LOCAL laStack(m.lnStack,8) laStack(m.lnStack,1) = m.lnX1 laStack(m.lnStack,2) = m.lnY1 laStack(m.lnStack,3) = m.lnBarWidth laStack(m.lnStack,4) = m.lnBarHeight laStack(m.lnStack,5) = m.lnValue laStack(m.lnStack,6) = ._ChartIndex laStack(m.lnStack,7) = m.lnSumBarWidth m.lnOldCone3D = m.lnCone3d m.lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) laStack(m.lnStack,8) = m.lnBarType IF INLIST(.BarType,3,5) m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1 + m.lnVertDelta - m.ln3dDelta, ; m.lnBarWidth, m.lnBarHeight-m.lnVertDelta*2, ; m.lnValue, m.lnWidth-m.lnBottomWidth, @m.lnCone3d,,m.lnBarType) ELSE m.lnNewVertDelta = ._DrawBar(m.lnX1 + m.ln3dDelta, m.lnY1 + m.lnVertDelta- m.ln3dDelta, ; m.lnBarWidth, m.lnBarHeight-m.lnVertDelta-m.lnVertDelta, ; m.lnValue, m.lnWidth-m.lnBottomWidth, @m.lnCone3d, m.lnWidth-m.lnBottomWidth,m.lnBarType) ENDIF m.lnX1 = m.lnX1 + m.lnBarWidth m.lnBottomWidth = m.lnBottomWidth + m.lnBarWidth m.lnVertDelta = m.lnVertDelta + IIF(VARTYPE(m.lnNewVertDelta) ='N',m.lnNewVertDelta,0) m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2 NEXT ENDSCAN SET ORDER TO ._ChartIndex = 1 CASE .ChartType = 3 && Full-Stacked Bars LOCAL lnTotRow, laValues(m.lnChartsCount) m.lnYBase = ._TopOffSet + m.ln3D + m.lnHeight FOR .ROW = 1 TO RECCOUNT() m.lnY1 = m.lnYBase m.lnTotRow = 0 * Get the total for the current row FOR .COLUMN = 1 TO .ChartsCount ._ChartIndex = .COLUMN .GetValue() ._ChartIndex = .COLUMN laValues(.COLUMN) = .VALUE m.lnTotRow = m.lnTotRow + .VALUE NEXT m.lnStack=0 m.lnSumBarHeight = 0 FOR .COLUMN = 1 TO .ChartsCount ._ChartIndex = .COLUMN m.lnValue = laValues(.COLUMN) IF m.lnValue = 0 LOOP ENDIF m.lnBarHeight = m.lnValue / m.lnTotRow * m.lnHeight m.lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) m.lnX1 = m.lnLeftMargin + ; ((m.lnBarWidth + m.lnBetween) * (.ROW - 1)) m.lnY1 = m.lnY1 - m.lnBarHeight .ChartSum = m.lnTotRow m.lnStack = m.lnStack +1 LOCAL laStack(m.lnStack,6) laStack(m.lnStack,1) = m.lnX1 laStack(m.lnStack,2) = m.lnY1 laStack(m.lnStack,3) = m.lnBarWidth laStack(m.lnStack,3) = m.lnBarHeight laStack(m.lnStack,4) = m.lnValue laStack(m.lnStack,5) = .COLUMN laStack(m.lnStack,6) = m.lnBarType NEXT m.lnBottomHeight=0 m.lnHorDelta = 0 m.ln3dDelta = 0 m.lnCone3d = ._3D FOR m.lnLine=1 TO m.lnStack ._ChartIndex = laStack(m.lnLine,5) .COLUMN = laStack(m.lnLine,5) m.lnX1 = laStack(m.lnLine,1) m.lnY1 = laStack(m.lnLine,2) m.lnBarHeight = laStack(m.lnLine,3) m.lnOldCone3D = m.lnCone3d m.lnNewHorDelta = ._DrawBar(m.lnX1 + m.lnHorDelta + m.ln3dDelta, m.lnY1 - m.ln3dDelta, ; m.lnBarWidth-m.lnHorDelta-m.lnHorDelta, m.lnBarHeight, ; laStack(m.lnLine,4), m.lnHeight-m.lnBottomHeight, @m.lnCone3d , m.lnHeight - m.lnBottomHeight, laStack(m.lnLine,6)) m.lnHorDelta = m.lnHorDelta + IIF(VARTYPE(m.lnNewHorDelta) ='N',m.lnNewHorDelta,0) m.lnBottomHeight=m.lnBottomHeight+m.lnBarHeight m.ln3dDelta = m.ln3dDelta + (m.lnOldCone3D - m.lnCone3d) / 2 NEXT NEXT ._ChartIndex = 1 CASE .ChartType = 17 && PAIRED HORIZONTAL BARS LOCAL lnZeroX, lnScaleAdjustment, lnAlign m.lnZeroX = m.lnLeftMargin + (m.lnWidth / 2) SET ORDER TO REVERT * Draw the left side of the chart m.lnAlign = .ShapeLegend.ALIGNMENT DO CASE CASE m.lnAlign = 0 && Left .ShapeLegend.ALIGNMENT = 1 && Right CASE m.lnAlign = 1 && Right .ShapeLegend.ALIGNMENT = 0 && Left OTHERWISE ENDCASE ._ChartIndex = 1 LOCAL laMax( RECCOUNT()), llCalcMax, lnRecno m.lnBarType = IIF(.Fields(._ChartIndex).Bartype<0, .Bartype, .Fields(._ChartIndex).Bartype) m.llCalcMax = INLIST(lnBarType,5,6) AND m.lnChartsCount > 1 SCAN m.lnRecno = RECNO() IF m.llCalcMax m.lnValue = ._GetValue(2, .T.) laMax(m.lnRecno) = ABS(m.lnValue / m.lnMaxValue * m.lnWidth) ENDIF m.lnValue = ._GetValue(1, .T.) IF ISNULL(m.lnValue) OR (m.lnValue <= 0) LOOP ENDIF m.lnBarWidth = ABS(m.lnValue / m.lnMaxValue * m.lnWidth) laMax(m.lnRecno) = ROUND(IIF(m.llCalcMax, MAX(laMax(m.lnRecno),m.lnBarWidth), 0),0) m.lnX1 = m.lnZeroX - m.lnBarWidth m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (m.lnRecno - 1)) + m.ln3D ._DrawBar(m.lnX1, m.lnY1, m.lnBarWidth, m.lnBarHeight, m.lnValue, laMax(m.lnRecno),,,m.lnBarType) ENDSCAN .ShapeLegend.ALIGNMENT = m.lnAlign && Restore to the original setting IF m.lnChartsCount > 1 * Draw the right side of the chart ._ChartIndex = 2 SCAN m.lnRecno = RECNO() m.lnValue = ._GetValue(2, .T.) IF ISNULL(m.lnValue) OR (m.lnValue < ._MinScale) LOOP ENDIF m.lnBarWidth = (m.lnValue / m.lnMaxValue * m.lnWidth) m.lnX1 = m.lnZeroX m.lnY1 = ._TopOffSet + ((m.lnBarHeight + m.lnBetween) * (m.lnRecno - 1)) + m.ln3D ._DrawBar(m.lnX1, m.lnY1, m.lnBarWidth, m.lnBarHeight, m.lnValue, IIF(m.llCalcMax,laMax(m.lnRecno),.F.),,m.lnBarType) ENDSCAN ENDIF SET ORDER TO OTHERWISE ENDCASE * Draw Legends on X Axis for Vertical charts IF ._Orientation = 1 && Vertical IF .BarType > 0 ._DrawXAxisLegend(m.ln3D/2) ELSE ._DrawXAxisLegend() ENDIF ENDIF ENDWITH ENDPROC PROCEDURE _drawcomments LOCAL lcCaption, lcObjectName, lcPolyGon, ; lnAlignment, lnAlphaChannel, lnBackColor, lnFontSize, lnForeColor, lnGradientLevel, lnLeft, lnLine, lnRotation, lnTextHeight, lnTextWidth, lnTop, ; loBrush, loColor1, loColor2, loShape,lnCenterX, m.lnCenterY FOR lnLine=1 TO THIS.CommentsSet.COUNT * lcObjectName='Shape'+ALLTRIM(STR(THIS.Shapes.OBJECTS.COUNT+1)) * THIS.Shapes.ADDOBJECT(lcObjectName,[Charts.Figure]) * loShape = EVALUATE('this.Shapes.' + lcObjectName) loLegend = THIS.Comments WITH THIS.CommentsSet(lnLine) lnLeft = IIF(BETWEEN(.LEFT,0,1), THIS.ChartCanvas.WIDTH,1) * .LEFT lnTop = IIF(BETWEEN(.TOP,0,1),THIS.ChartCanvas.HEIGHT,1) * .TOP lnLeft = IIF(BETWEEN(.LEFT,0,1), THIS.WIDTH,1) * .LEFT lnTop = IIF(BETWEEN(.TOP,0,1),THIS.HEIGHT,1) * .TOP loLegend.FONTSIZE = EVL(.FONTSIZE,11) loLegend.ALIGNMENT = IIF(BETWEEN(.ALIGNMENT,0,2),.ALIGNMENT,2) loLegend.FORECOLOR = .FORECOLOR loLegend.BACKCOLOR = .BACKCOLOR loLegend.FONTNAME = .FONTNAME loLegend.FONTSIZE = .FONTSIZE loLegend.FONTBOLD = .FONTBOLD loLegend.FONTITALIC = .FONTITALIC loLegend.ForeColorAlpha = .ForeColorAlpha loLegend.BackColorAlpha = IIF(.TYPE>0,255,.BackColorAlpha) lnGradientLevel = .GradientLevel lnRotation = .ROTATION loLegend.ROTATION=0 loLegend._Setup () lcCaption = .CAPTION IF 'CHR(13)' $ lcCaption lcCaption = STRTRAN(lcCaption,[CHR(13)], CHR(13)+CHR(10)) ENDIF loLegend._Value = lcCaption lnTextHeight = CEILING(loLegend._Height) lnTextWidth = CEILING(loLegend._Width) m.lnTextLeft = m.lnLeft m.lnTextTop = m.lnTop lnHeight = lnTextHeight lnWidth = lnTextWidth lnCenterX = m.lnLeft lnCenterY = m.lnTop lcPolyGon = Labels(.TYPE, @lnTextLeft, @lnTextTop, @lnWidth, @lnHeight, @lnCenterX, @lnCenterY, .PointerSide, .PointerSubSide, .PointerWidth ) loBrush = _SCREEN.SYSTEM.Drawing.SolidBrush.New(_SCREEN.SYSTEM.Drawing.COLOR.FromARGB(.BackColorAlpha,.BACKCOLOR)) ENDWITH loShape = THIS._UpdateCoordinates(,"Comments", m.lnLeft, m.lnTop, m.lnWidth, m.lnHeight) WITH loShape lnMargin = 4 .SetDimensions( m.lnLeft, m.lnTop, m.lnTextWidth, m.lnTextHeight) IF THIS.CommentsSet(lnLine).TYPE>0 .PATH = lcPolyGon ENDIF .Contour = _Screen.FoxchartsHelper.SimplifyPath(lcPolyGon) IF NOT EMPTY(lnRotation) .Contour = _Screen.FoxchartsHelper.RotatePath(m.lnCenterX, m.lnCenterY, .Contour, lnRotation) ENDIF .Front = [] .Legend = lcCaption .COLOR = lnForeColor .ChartIndex = lnLine .DRAW(THIS.oGfx, THIS._oblackpen, loBrush, m.lnCenterX, m.lnCenterY, lnRotation) THIS.Comments._DrawString(lnTextLeft, m.lnTextTop,lnTextWidth,lnTextHeight) THIS.oGfx.ResetTransform() ENDWITH NEXT ENDPROC PROCEDURE _drawcone LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D * Yudin Alex LOCAL lcFile, llConoid, ln, lnA, lnA2, lnAngle, lnB, lnB2, lnCount, lnDelta, lnDet, ; lnLine, lnMX, lnMY, lnRight, lnTop3D, lnTopHeight, lnTopWidth, lnX, lnY, lnY0, loTopBrush LOCAL lnBottomY, lnRectY, ln3D, lcPoints, lnAlpha, lnOrigAlpha, lnTopX, lnX0,lnHorDelta, ; loBottomBrush AS xfcBrush, loPen AS xfcPen, loGfx AS xfcGraphics, ; loPath AS xfcGraphicsPath m.loPen = THIS._oBorderPen m.loGfx = THIS.oGfx m.lcPoints='' m.lnY = tnY lnHorDelta=0 This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex)) lnOrigAlpha = THIS.AlphaChannel lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25)) THIS.AlphaChannel = lnAlpha m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) WITH _SCREEN.SYSTEM.Drawing DO CASE CASE THIS.BrushType = 1 && SolidColors loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) CASE THIS.BrushType = 2 && Gradient loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 50))) loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80))) CASE THIS.BrushType = 4 && TextureBrush lcFile = THIS.getTexture() IF EMPTY(lcFile) loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) ELSE loTopBrush = THIS._o3dBrush loBottomBrush = loTopBrush ENDIF OTHERWISE THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) loTopBrush = THIS._oMainBrush loBottomBrush = loTopBrush ENDCASE THIS.AlphaChannel = lnOrigAlpha IF THIS._Orientation = 1 && Vertical ***************************** * * * C o n e - Vertical * * * ***************************** m.lnRectY = tnY - m.ln3D / 2 m.lnBottomY = tnY + tnHeight - m.ln3D m.lnX0 = tnX + m.ln3D / 2 * Draw ellipse m.loGfx.FillEllipse(loBottomBrush, m.lnX0, m.lnBottomY, tnWidth, m.ln3D) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, m.lnX0, m.lnBottomY, tnWidth, m.ln3D) ENDIF * Draw the front shape using a GraphicsPath object * Prepare the Main Path lnTopX = m.lnX0 + tnWidth/2 loPath = .Drawing2D.GraphicsPath.New() loPath.StartFigure() * Bottom arc lnB2 = m.ln3D*m.ln3D/4 lnA2 = tnWidth * tnWidth/4 lnMY = lnB2 / tnHeight lnDet = (1-lnMY*lnMY/lnB2) * lnA2 IF lnDet>0 lnMX = SQRT(lnDet) lnAngle = RTOD(ATAN(lnMY/lnMX)) ELSE lnAngle=90 lnMX = tnWidth/2 lnMY = 0 ENDIF loPath.ADDLINE(lnTopX, m.lnRectY, lnTopX, m.lnRectY) loPath.AddArc(m.lnX0, m.lnBottomY, tnWidth, m.ln3D, -lnAngle, 180+lnAngle+lnAngle) loPath.ADDLINE(lnTopX, m.lnRectY, lnTopX, m.lnRectY) loPath.Reverse() loPath.ADDLINE(lnTopX, m.lnRectY, lnTopX, m.lnRectY) * Draw the path THIS.FillPathDim(THIS._oMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) IF lnMY = 0 m.loGfx.Drawline(m.loPen,m.lnX0 + tnWidth/2, m.lnRectY, m.lnX0+tnWidth/2-lnMX , m.lnBottomY - m.lnMY + m.ln3D / 2) ENDIF TEXT TO lcPoints && Iпdеделяем точки контуdа для dаспознавания конуса <>,<>,<>,<>,0 <>,<>,<>,<>,<<-lnAngle>>,<<180+lnAngle+lnAngle>> <>,<>,<>,<>,0 ENDTEXT ELSE &&_Orientation = 2 llLeftRight = THIS.Charttype # 17 AND THIS._ChartIndex>1 m.lnTopX = m.tnX + m.tnWidth &&- m.ln3D/2 * IIF(llLeftRight,0,1) IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.lnStore=m.lnTopX m.lnTopX = m.tnX m.tnX=m.lnStore ENDIF m.lnX0 = tnX m.lnY = tnY - m.ln3D / 2 * Draw the front shape using a GraphicsPath object * Prepare the Main Path loPath = .Drawing2D.GraphicsPath.New() * Ellipse m.loGfx.FillEllipse(THIS._oMainBrush, tnX, lnY, m.ln3D, tnHeight) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight) ENDIF loPath.StartFigure() * Bottom Arc lnB2 = m.ln3D*m.ln3D/4 lnA2 = tnHeight * tnHeight/4 lnMY = lnB2 / tnWidth lnDet = (1-lnMY*lnMY/lnB2) * lnA2 IF lnDet>0 lnMX = SQRT(lnDet) lnAngle = RTOD(ATAN(lnMY/lnMX)) ELSE lnAngle=90 lnMX = tnHeight/2 lnMY = 0 ENDIF loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90-lnAngle, 180 + lnAngle + lnAngle) loPath.Reverse() THIS.FillPathDim(THIS._oMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) IF lnMY = 0 m.loGfx.Drawline(m.loPen, m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, lnY + tnHeight/2-lnMX ) ENDIF * Lines loPath.ADDLINE(tnX + m.ln3D / 2 + lnMY, ROUND(lnY + tnHeight/2+lnMX,0), m.lnTopX + m.ln3D / 2, lnY + tnHeight/2) loPath.ADDLINE(m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, ROUND(lnY + tnHeight/2-lnMX,0)) * Draw the path THIS.FillPathDim(THIS._oMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) IF lnMY = 0 m.loGfx.Drawline(m.loPen, m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, lnY + tnHeight/2-lnMX ) ENDIF TEXT TO lcPoints && define the contour points for the recognition of the cone <>, <>, <>, <> <>,<>,<>,<>,<<90-lnAngle>>,<<180 +lnAngle+lnAngle>> <>,<>,<>,<> ENDTEXT IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.lnX0=m.lnTopX ENDIF ENDIF loShape = THIS._UpdateCoordinates(,"Rect", m.lnX0 + THIS._3d / 2, m.lnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints) THIS._DrawLegendinBar(m.lnX0, lnY, tnWidth, tnHeight, tnValue) ENDWITH RETURN lnHorDelta ENDPROC PROCEDURE _drawconoid LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D, tnMaxBarHeight * Yudin Alex 16 Apr 2013 LOCAL lcFile, lcTopEllipse,lcTopEllipse1, llConoid, ln, lnA, lnA2, lnAngle, lnB, lnB2, lnCount, lnDelta, lnDet, ; lnLine, lnMX, lnMY, lnRight, lnTop3D, lnTopHeight, lnTopWidth, lnX, lnY, lnY0, loTopBrush, ; lnBottomY, lnRectY, ln3D, lcPoints, lnAlpha, lnOrigAlpha, lnTopX, lnX0,lnHorDelta, ; loBottomBrush AS xfcBrush, loPen AS xfcPen, loGfx AS xfcGraphics, ; loPath AS xfcGraphicsPath m.loGfx = THIS.oGfx STORE '' TO m.lcPoints, lcFront THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex)) m.loPen = THIS._oBorderPen lnHorDelta=0 lnOrigAlpha = THIS.AlphaChannel lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25)) THIS.AlphaChannel = lnAlpha m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) WITH _SCREEN.SYSTEM.Drawing DO CASE CASE THIS.BrushType = 1 && SolidColors loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) CASE THIS.BrushType = 2 && Gradient loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 50))) loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80))) CASE THIS.BrushType = 4 && TextureBrush lcFile = THIS.getTexture() IF EMPTY(lcFile) loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBottomBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) ELSE loTopBrush = THIS._o3dBrush loBottomBrush = loTopBrush ENDIF OTHERWISE THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) loTopBrush = THIS._oMainBrush loBottomBrush = loTopBrush ENDCASE THIS.AlphaChannel = lnOrigAlpha IF THIS._Orientation = 1 && Vertical ************************ * Vertical conoid * ************************ LOCAL lnRectY, lnX0, yBotCyl, loPath AS xfcGraphicsPath lnY = ROUND(tnY,0) lnB=0 lnTopWidth = (tnMaxBarHeight-tnHeight) / tnMaxBarHeight * tnWidth lnTop3D = lnTopWidth * m.ln3D/tnWidth m.lnRectY = tnY - m.ln3D / 2 yBotCyl = tnY + tnHeight - m.ln3D tnX= ROUND(tnx,0) lnX0 = ROUND(tnX + m.ln3D / 2,0) * Bottom ellipse m.loGfx.FillEllipse(loBottomBrush, lnX0, yBotCyl, tnWidth, m.ln3D) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, lnX0, yBotCyl, tnWidth, m.ln3D) ENDIF loPath = .Drawing2D.GraphicsPath.New() loPath.StartFigure() * Bottom arc lnB2 = m.ln3D*m.ln3D/4 lnA2 = tnWidth * tnWidth/4 lnMY = lnB2 / tnMaxBarHeight lnDet = (1-lnMY*lnMY/lnB2) * lnA2 IF lnDet>0 lnMX = SQRT(lnDet) lnAngle = RTOD(ATAN(lnMY/lnMX)) ELSE lnAngle=90 lnMX = tnWidth/2 lnMY = 0 ENDIF lnCenterX = lnX0 + tnWidth/2 IF m.ln3D<3 loPath.ADDLINE(m.lnX0+tnWidth, tnY + tnHeight-ln3D/2,m.lnX0, tnY + tnHeight-ln3D/2) ELSE loPath.AddArc(m.lnX0, yBotCyl, tnWidth, m.ln3D, 360-lnAngle, 180+lnAngle+lnAngle) loPath.Reverse() ENDIF loPath.AddArc(ROUND(lnX0 + tnWidth/2 - lnTopWidth/2,0), ROUND(m.lnRectY - m.lnTop3D/2,0), ROUND(lnTopWidth,0), ROUND(m.lnTop3D,0), MOD(360-lnAngle,360), MOD(180+lnAngle*2,360)) loPath.Reverse() TEXT TO lcPoints <>,<>,<>,<>,<<360-lnAngle>>,<<180+lnAngle*2>> ENDTEXT loPath.AddArc(m.lnX0, yBotCyl, tnWidth, m.ln3D, 180+lnAngle,0.01) && A начальну_ точку THIS.FillPathDim(THIS._oMainBrush, loPath) * Top ellipse IF m.lnTop3D<3 loPath.ADDLINE(m.lnX0, tnY + tnHeight-ln3D/2,m.lnCenterX-lnTopWidth/2, tnY-ln3D/2) loPath.ADDLINE(m.lnCenterX+lnTopWidth/2, tnY-ln3D/2,m.lnCenterX-lnTopWidth/2, tnY-ln3D/2) loPath.ADDLINE(m.lnCenterX+lnTopWidth/2, tnY-ln3D/2,m.lnX0+tnWidth, tnY + tnHeight-ln3D/2) THIS.FillPathDim(THIS._oMainBrush, loPath) TEXT TO lcTopEllipse <>,<>,<>,<> ENDTEXT lcTopEllipse1=lcTopEllipse ENDIF * Draw the path m.loGfx.DrawPath(m.loPen, loPath) IF NOT m.lnTop3D<3 m.loGfx.FillEllipse(loTopBrush, lnX0+tnWidth/2-lnTopWidth/2, m.lnRectY - m.lnTop3D/2, lnTopWidth, m.lnTop3D) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, lnX0+tnWidth/2-lnTopWidth/2, m.lnRectY - m.lnTop3D/2, lnTopWidth, m.lnTop3D) ENDIF m.loGfx.DrawEllipse(m.loPen , lnX0+tnWidth/2-lnTopWidth/2, m.lnRectY - m.lnTop3D/2, lnTopWidth, m.lnTop3D) TEXT TO lcTopEllipse <>,<>,<>,<>,180,180,1 ENDTEXT TEXT TO lcTopEllipse1 <>,<>,<>,<>,180,-180,1 ENDTEXT ENDIF lnHorDelta = (tnWidth - lnTopWidth) / 2 TEXT TO lcFront <> <>,<>,<>,<>,0 <> <>,<>,<>,<>,0 ENDTEXT TEXT TO lcPoints ADDITIVE <>,<>,<>,<>,0 <> <>,<>,<>,<>,0 ENDTEXT ELSE &&_Orientation = 2 ***************************************** * * * C o n o i d * * Horizontal * * * ***************************************** m.lnY = tnY - m.ln3D / 2 m.lnTopX = tnX + tnWidth && - m.ln3D / 2 m.lnX0 = tnX IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.lnStore=m.lnTopX m.lnTopX = m.tnX m.tnX=m.lnStore ENDIF lnTopHeight = (tnMaxBarHeight-tnWidth) / tnMaxBarHeight * tnHeight lnTop3D = lnTopHeight * m.ln3D/tnHeight m.lnRectY = lnY &&- m.ln3D / 2 yBotCyl = lnY + tnHeight && - m.ln3D lnX0 = tnX + m.ln3D / 2 loPath = .Drawing2D.GraphicsPath.New() m.loGfx.DrawEllipse(m.loPen , tnX, lnY, m.ln3D, tnHeight) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight) ENDIF lnHorDelta = (tnHeight - lnTopHeight) /2 IF VARTYPE(tn3D)='N' tn3D = m.lnTop3D ENDIF loPath.StartFigure() * * Left arc of the ellipse * lnB2 = m.ln3D * m.ln3D / 4 lnA2 = tnHeight * tnHeight / 4 lnMY = lnB2 / tnMaxBarHeight lnDet = (1-lnMY*lnMY/lnB2) * lnA2 IF lnDet>=0 lnMX = SQRT(lnDet) lnAngle = RTOD(ATAN(lnMY/lnMX)) ELSE lnAngle=90 lnMX = tnHeight/2 lnMY = 0 ENDIF loPath.StartFigure() loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90-lnAngle, 180 + lnAngle + lnAngle) * loPath.Reverse() * Left arc of the ellipse IF m.ln3D<3 TEXT TO lcLeftEllipsePoint <>,<>,<>,<> ENDTEXT ELSE TEXT TO lcLeftEllipsePoint <>,<>,<>,<>,<<90-lnAngle>>,<<180 +lnAngle+lnAngle>> ENDTEXT ENDIF IF m.lnTop3D<3 lnX = m.lnTopX+ m.ln3D / 2 - lnTop3D/2 loPath.ADDLINE(lnX, lnY + tnHeight/2 - lnTopHeight/2, ; lnX, lnY + tnHeight/2 + lnTopHeight/2) STORE 0 TO lnMx2, lnMy2 TEXT TO lcPoints && Define the contour points for the recognition of the cone <>,<>,<>,<> <>,<>,<>,<>,0 <> <>,<>,<>,<> ENDTEXT lcFront = lcPoints ENDIF * Draw the path m.loGfx.DrawPath(m.loPen, loPath) IF NOT m.lnTop3D<3 && Not small lnB2 = m.lnTop3D * m.lnTop3D /4 lnA2 = lnTopHeight * lnTopHeight / 4 lnMy2 = lnB2 / (tnMaxBarHeight-tnWidth) lnDet = (1-lnMy2*lnMy2/lnB2) * lnA2 IF lnDet>=0 lnMx2 = SQRT(lnDet) ELSE lnMx2 = tnHeight/2 lnMy2 = 0 ENDIF loPath.AddArc(m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight, 270+lnAngle,180 - lnAngle * 2) loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90 - lnAngle,0.001) TEXT TO lcPoints && Define the contour points for the recognition of the cone <>,<>,<>,<>,<<270+lnAngle>>,<<180-lnAngle*2>>,1 <>,<>,<>,<>,0 <> <>,<>,<>,<> ENDTEXT TEXT TO lcFront && points of the front surface <>,<>,<>,<>,<<270+lnAngle>>,<<-180+lnAngle*2>>,0 <>,<>,<>,<>,0 <> <>,<>,<>,<> ENDTEXT ENDIF THIS.FillPathDim(THIS._oMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) IF lnMY = 0 * m.loGfx.Drawline(m.loPen, m.lnTopX + m.ln3D / 2, lnY + tnHeight/2, tnX + m.ln3D / 2 + lnMY, lnY + tnHeight/2-lnMX ) ENDIF * Right ellipse * m.loGfx.FillEllipse(THIS._o3dBrush, m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight) m.loGfx.DrawEllipse(m.loPen , m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, m.lnTopX+ m.ln3D / 2 - lnTop3D/2 , lnY + tnHeight/2 - lnTopHeight/2 , lnTop3D, lnTopHeight) ENDIF IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.lnX0 = m.lnTopX ENDIF ENDIF IF VARTYPE(tn3D)='N' tn3D = m.lnTop3D ENDIF loShape = THIS._UpdateCoordinates(,"Rect", m.lnX0 + THIS._3d / 2, m.lnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints,,lcFront) THIS._DrawLegendinBar(m.lnX0, lnY, tnWidth, tnHeight, tnValue) ENDWITH RETURN lnHorDelta ENDPROC PROCEDURE _drawcylinder LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D LOCAL lcFile, ln, lnY, lcPoints, lnA, lnA2, lnB, lnB2, lnCount, lnDelta, lnLine, lnX ; ,lnAlpha, lnOrigAlpha, loTopBrush AS xfcBrush, loBotBrush AS xfcBrush ; ,loPen AS xfcPen, loGfx AS xfcGraphics This._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(This.SingleData, RECNO(),This._ChartIndex)) m.loPen = THIS._oBorderPen m.loGfx = THIS.oGfx lnOrigAlpha = THIS.AlphaChannel lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25)) THIS.AlphaChannel = lnAlpha m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) lnY = tnY WITH _SCREEN.SYSTEM.Drawing DO CASE CASE THIS.BrushType = 1 && SolidColors loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) CASE THIS.BrushType = 2 && Gradient loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 50))) loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80))) CASE THIS.BrushType = 4 && TextureBrush lcFile = THIS.getTexture() IF EMPTY(lcFile) loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) ELSE loTopBrush = THIS._o3dBrush loBotBrush = loTopBrush ENDIF OTHERWISE THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) loTopBrush = THIS._oMainBrush loBotBrush = loTopBrush ENDCASE THIS.AlphaChannel = lnOrigAlpha IF THIS._Orientation = 1 && Vertical LOCAL lnRectY, lnX0, yTopCyl, yBotCyl lnRectY = tnY - (m.ln3D / 2) yTopCyl = tnY - m.ln3D yBotCyl = tnY + tnHeight - m.ln3D lnX0 = tnX + m.ln3D / 2 * Нижний эллипс m.loGfx.FillEllipse(loBotBrush, lnX0, yBotCyl, tnWidth, m.ln3D) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, lnX0, yBotCyl, tnWidth, m.ln3D) ENDIF * Draw the front shape using a GraphicsPath object * Prepare the Main Path LOCAL loPath AS xfcGraphicsPath loPath = .Drawing2D.GraphicsPath.New() loPath.FillMode = .Drawing2D.FillMode.ALTERNATE loPath.StartFigure() * Нижняя дуга loPath.AddArc(lnX0, yBotCyl, tnWidth, m.ln3D, 180, -180) * loPath.Reverse() * Правая боковая линия loPath.ADDLINE(lnX0 + tnWidth, lnRectY + tnHeight, lnX0 + tnWidth, lnRectY) * Верхняя дуга loPath.AddArc(lnX0, yTopCyl, tnWidth, m.ln3D, 0, 180) * Рисуем дорожку THIS.FillPathDim(THIS._oMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) loPath = .Drawing2D.GraphicsPath.New() * Верхний эллипс loPath.StartFigure() loPath.AddEllipse(lnX0, yTopCyl, tnWidth, m.ln3D) loTopBrush=_Screen.FoxChartsHelper.PathGradient( , m.loPath, THIS._nColor,-1, lnX0+tnWidth/2, yTopCyl+m.ln3D/2) m.loGfx.FillEllipse(loTopBrush, lnX0, yTopCyl, tnWidth, m.ln3D) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, lnX0, yTopCyl, tnWidth, m.ln3D) ENDIF m.loGfx.DrawEllipse(m.loPen , lnX0, yTopCyl, tnWidth, m.ln3D) * * Координаты контура * TEXT TO lcPoints <>,<>,<>,<>,0, 180 <>,<>,<>,<> <>,<>,<>,<>,-180,180,1 <>,<>,<>,<> ENDTEXT ELSE &&_Orientation = 2 - Horizontal *************************************** * * * Горизонтальный цилиндр * * * *************************************** LOCAL xRect xRect = tnX - m.ln3D / 2 xTopCyl = tnX + tnWidth &&- m.ln3D / 2 xBotCyl = tnX - m.ln3D lnY = tnY - m.ln3D / 2 * Draw the left-most ellipse m.loGfx.FillEllipse(loBotBrush , tnX, lnY, m.ln3D, tnHeight) m.loGfx.FillEllipse(THIS._oMainBrush, tnX, lnY, m.ln3D, tnHeight) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight) m.loGfx.FillEllipse(THIS._oDimBrush, tnX, lnY, m.ln3D, tnHeight) ENDIF * Draw the front shape using a GraphicsPath object * Prepare the Main Path LOCAL loPath AS xfcGraphicsPath loPath = .Drawing2D.GraphicsPath.New() loPath.StartFigure() * Нижняя дуга loPath.AddArc(tnX, lnY, m.ln3D, tnHeight, 90, 180) loPath.Reverse() * Нижняя линия loPath.ADDLINE(tnX + m.ln3D / 2, lnY + tnHeight, xTopCyl + m.ln3D / 2, lnY + tnHeight) * Top Arc loPath.AddArc(xTopCyl, lnY, m.ln3D, tnHeight, 90, 180) * Top Line loPath.ADDLINE(xTopCyl + m.ln3D / 2, lnY, tnX + m.ln3D / 2, lnY) * Draw the path THIS.FillPathDim(THIS._oMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) * Draw the upper ellipse m.loGfx.FillEllipse(loTopBrush, xTopCyl, lnY, m.ln3D, tnHeight) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillEllipse(THIS._oDimBrush, xTopCyl, lnY, m.ln3D, tnHeight) ENDIF m.loGfx.DrawEllipse(m.loPen, xTopCyl, lnY, m.ln3D, tnHeight) * * Координаты контура * TEXT TO lcPoints <>,<>,<>,<> <>,<>,<>,<>, 90, 180 <>,<>,<>,<> <>,<>,<>,<>, 270,180,1 ENDTEXT ENDIF loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + THIS._3d / 2, m.lnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints) THIS._DrawLegendinBar(tnX, lnY, tnWidth, tnHeight, tnValue,,loShape) ENDWITH ENDPROC PROCEDURE _drawdoughnutslice LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnValue, toShape IF tnWidth <=0 OR tnHeight <=0 RETURN ENDIF WITH THIS ._AdjustStartSweep(@tnStart, @tnSweep, tnWidth, tnHeight) toShape = THIS._UpdateCoordinates(toShape,"Pie", tnX, tnY, tnWidth, tnHeight, tnValue, tnStart, tnSweep) LOCAL lnXBrush, lnYBrush IF THIS.PieEnhancedDrawing lnXBrush = tnX lnYBrush = tnY ELSE lnXBrush = 0 lnYBrush = 0 ENDIF THIS._PrepareBrushes(lnXBrush, lnYBrush, m.tnWidth, m.tnHeight, .F., RECNO()) LOCAL loPen AS xfcPen, loGfx AS xfcGraphics, loMainBrush AS xfcBrush, lo3dBrush AS xfcBrush, ln3d, lnFinalAngle m.loPen = THIS._oBorderPen m.loGfx = THIS.oGfx m.loMainBrush = THIS._oMainBrush lo3dBrush = THIS._o3DBrush m.ln3d = THIS._3D lnFinalAngle = tnStart + tnSweep IF lnFinalAngle > 360 lnFinalAngle = lnFinalAngle - 360 ENDIF ENDWITH IF THIS.PieEnhancedDrawing && New behavior for Doughnuts && Drawing all edges using the GraphicsPath class WITH _SCREEN.SYSTEM.Drawing * Create a GraphicsPath object. LOCAL loMainPath AS xfcGraphicsPath loMainPath = .Drawing2D.GraphicsPath.New() LOCAL loRect AS xfcRectangle, loRect2 AS xfcRectangle, lnRatio lnRatio = THIS.DonutRatio loRect = .Rectangle.New(tnX, tnY, tnWidth, tnHeight) loRect2 = .Rectangle.New(; tnX + (tnWidth * (1 - lnRatio) / 2), ; tnY + (tnHeight * (1 - lnRatio) / 2), ; tnWidth * lnRatio, ; tnHeight * lnRatio) LOCAL lnXInt, lnYInt, lnHInt, lnWInt lnXInt = loRect2.X lnYInt = loRect2.Y lnWInt = loRect2.WIDTH lnHInt = loRect2.HEIGHT LOCAL loPoint0 AS xfcPointF, loPoint1 AS xfcPointF, loPoint2 AS xfcPointF, loPoint3 AS xfcPointF, loPath AS xfcGraphicsPath * Obtaining the needed points loMainPath.AddArc(loRect, tnStart, 0.0001) loPoint0 = loMainPath.GetLastPoint() loMainPath.AddArc(loRect2, tnStart, 0.0001) loPoint3 = loMainPath.GetLastPoint() loMainPath.AddArc(loRect, tnStart, tnSweep) loPoint1 = loMainPath.GetLastPoint() loMainPath.AddArc(loRect2, tnStart, tnSweep) loPoint2 = loMainPath.GetLastPoint() loPoint4 = .POINT.New(loPoint3.X, loPoint3.Y + m.ln3d) loPoint5 = .POINT.New(loPoint0.X, loPoint0.Y + m.ln3d) loPoint6 = .POINT.New(loPoint1.X, loPoint1.Y + m.ln3d) * Prepare the Main Path loPath = .Drawing2D.GraphicsPath.New() loPath.StartFigure() loPath.AddArc(loRect2, tnStart, tnSweep) loPath.Reverse() loPath.ADDLINE(loPoint3.X, loPoint3.Y, loPoint0.X, loPoint0.Y) loPath.AddArc(loRect, tnStart, tnSweep) loPath.ADDLINE(loPoint1.X, loPoint1.Y, loPoint2.X, loPoint2.Y) IF ln3d = 0 OR THIS.SHADOW * Draw shadow IF THIS.SHADOW * Prepare the Shadow Path LOCAL loPath2 AS xfcGraphicsPath loPath2 = .Drawing2D.GraphicsPath.New() loPath2.StartFigure() loPath2.AddArc(loRect2.X, loRect2.Y + ln3d, loRect2.WIDTH, loRect2.HEIGHT, tnStart, tnSweep) loPath2.Reverse() loPath2.ADDLINE(loPoint3.X, loPoint3.Y + ln3d, loPoint0.X, loPoint0.Y + ln3d) loPath2.AddArc(loRect.X, loRect.Y + ln3d, loRect.WIDTH, loRect.HEIGHT, tnStart, tnSweep) loPath2.ADDLINE(loPoint1.X, loPoint1.Y + ln3d, loPoint2.X, loPoint2.Y + ln3d) * Prepare the shadow brush LOCAL loShadowBrush AS xfcSolidBrush m.loShadowBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel,128,128,128)) * Draw the shadow THIS.FillPathDim(loShadowBrush, loPath2) ENDIF * Draw the Main doughnut slice (path) THIS.FillPathDim(m.loMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) RETURN ENDIF * Continue Drawing, for 3D chart * Prepare the polygon points for the final part of the slice DIMENSION laEndPoints(4) laEndPoints(1) = loPoint1 laEndPoints(2) = loPoint2 laEndPoints(3) = .POINT.New(loPoint2.X, loPoint2.Y + m.ln3d) laEndPoints(4) = loPoint6 * Prepare the polygon points for the beginning part of the slice DIMENSION laStartPoints(4) laStartPoints(1) = loPoint0 laStartPoints(2) = loPoint5 laStartPoints(3) = loPoint4 laStartPoints(4) = loPoint3 * If the slice ends in the left side, draw the Ending polygon before the top face of the slice IF BETWEEN(lnFinalAngle, 90.001, 269.999) m.loGfx.DrawPolygon(m.loPen, @laEndPoints) m.loGfx.FillPolygon(lo3dBrush, @laEndPoints) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillPolygon(THIS._oDimBrush, @laEndPoints) ENDIF ENDIF IF NOT (tnStart >= 90 AND tnStart <= 270) m.loGfx.DrawPolygon(m.loPen, @laStartPoints) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillPolygon(THIS._oDimBrush, @laStartPoints) ENDIF ENDIF * Draw the external and internal paths LOCAL lnFinalAngle lnFinalAngle = tnStart + tnSweep IF lnFinalAngle > 360 lnFinalAngle = lnFinalAngle - 360 ENDIF LOCAL lnAdjStart, lnAdjSweep lnAdjStart = tnStart lnAdjSweep = tnSweep LOCAL loAdjPoint0 AS xfcPoint, loAdjPoint1 AS xfcPoint loAdjPoint0 = loPoint0 loAdjPoint1 = loPoint1 LOCAL loAdjPoint2 AS xfcPoint, loAdjPoint3 AS xfcPoint loAdjPoint2 = loPoint3 loAdjPoint3 = loPoint2 IF tnStart >= 270 AND ; tnStart < 360 AND ; BETWEEN(lnFinalAngle, 0, 270) LOCAL loTempPoint AS xfcPoint loTempPoint = .POINT.New(tnX + tnWidth, tnY + tnHeight / 2) LOCAL loTempPoint2 AS xfcPoint loTempPoint2 = .POINT.New(lnXInt + lnWInt, lnYInt + lnHInt / 2) * External part THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, tnStart, 360 - tnStart, loPoint0, loTempPoint) * Internal part THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, tnStart, 360 - tnStart, loPoint3, loTempPoint2) lnAdjStart = 0 lnAdjSweep = tnSweep - (360 - tnStart) loAdjPoint0 = loTempPoint loAdjPoint1 = loPoint1 * Internal loAdjPoint2 = loTempPoint2 loAdjPoint3 = loPoint2 ENDIF LOCAL llDrawExtAtEnd llDrawExtAtEnd = .F. IF (tnStart < 180 AND lnFinalAngle > 180) OR ; (tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 270.01) IF tnStart >= 270 lnAdjStart = 0 lnAdjSweep = 180 ELSE lnAdjStart = tnStart lnAdjSweep = 180 - tnStart ENDIF loAdjPoint1 = .POINT.New(tnX, tnY + tnHeight / 2) loAdjPoint3 = .POINT.New(lnXInt, lnYInt + lnHInt / 2) * External part llDrawExtAtEnd = .T. LOCAL lnStartB, lnSweepB, loPoint0B, loPoint1B lnStartB = lnAdjStart lnSweepB = lnAdjSweep loPoint0B = loAdjPoint0 loPoint1B = loAdjPoint1 * Internal part THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, lnAdjStart, lnAdjSweep, loAdjPoint2, loAdjPoint3) loAdjPoint0 = loAdjPoint1 loAdjPoint2 = loAdjPoint3 lnAdjStart = 180 lnAdjSweep = lnFinalAngle - 180 ENDIF IF BETWEEN(lnFinalAngle, 0,180) * Internal part THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, lnAdjStart, lnAdjSweep, loAdjPoint2, loPoint2) * External part THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, lnAdjStart, lnAdjSweep, loAdjPoint0, loPoint1) ELSE * External part THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, lnAdjStart, lnAdjSweep, loAdjPoint0, loPoint1) * Internal part THIS._DrawSliceExternal(lnXInt, lnYInt, lnWInt, lnHInt, lnAdjStart, lnAdjSweep, loAdjPoint2, loPoint2) ENDIF IF llDrawExtAtEnd THIS._DrawSliceExternal(tnX, tnY, tnWidth, tnHeight, lnStartB, lnSweepB, loPoint0B, loPoint1B) ENDIF * Draw polygon at the beginning of the doughnut IF tnStart > 90 AND tnStart < 270 m.loGfx.DrawPolygon(m.loPen, @laStartPoints) m.loGfx.FillPolygon(lo3dBrush, @laStartPoints) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillPolygon(THIS._oDimBrush, @laStartPoints) ENDIF ENDIF IF NOT BETWEEN(lnFinalAngle, 90, 270) m.loGfx.DrawPolygon(m.loPen, @laEndPoints) m.loGfx.FillPolygon(lo3dBrush, @laEndPoints) IF VARTYPE(THIS._oDimBrush)='O' m.loGfx.FillPolygon(THIS._oDimBrush, @laEndPoints) ENDIF ENDIF * Draw the main path THIS.FillPathDim(m.loMainBrush, loPath) m.loGfx.DrawPath(m.loPen, loPath) ENDWITH ELSE && This.PieEnhancedDrawing .F. - This is the old Behavior WITH _SCREEN.SYSTEM.Drawing LOCAL loBmp AS xfcBitmap loBmp = poTempBmp LOCAL loTempGfx AS xfcGraphics loTempGfx = .Graphics.FromImage(loBmp) loTempGfx.CLEAR(.COLOR.Transparent) loTempGfx.SmoothingMode = .Drawing2D.SmoothingMode.AntiAlias * Create a GraphicsPath object. LOCAL loTempPath AS xfcGraphicsPath loTempPath = .Drawing2D.GraphicsPath.New() LOCAL loRect AS xfcRectangle, loRect2 AS xfcRectangle, lnRatio lnRatio = THIS.DonutRatio loRect = .Rectangle.New(0, 0, tnWidth, tnHeight) loRect2 = .Rectangle.New(; (tnWidth * (1 - lnRatio) / 2), ; (tnHeight * (1 - lnRatio) / 2), ; tnWidth * lnRatio, ; tnHeight * lnRatio) LOCAL loPoint0 AS xfcPointF, loPoint1 AS xfcPointF, loPoint2 AS xfcPointF, loPoint3 AS xfcPointF * Obtaining the needed points loTempPath.AddArc(loRect, tnStart, 0.0001) loPoint0 = loTempPath.GetLastPoint() loTempPath.AddArc(loRect2, tnStart, 0.0001) loPoint3 = loTempPath.GetLastPoint() loTempPath.AddArc(loRect, tnStart, tnSweep) loPoint1 = loTempPath.GetLastPoint() loTempPath.AddArc(loRect2, tnStart, tnSweep) loPoint2 = loTempPath.GetLastPoint() loPoint4 = .POINT.New(loPoint3.X, loPoint3.Y + m.ln3d) loPoint5 = .POINT.New(loPoint0.X, loPoint0.Y + m.ln3d) loPoint6 = .POINT.New(loPoint1.X, loPoint1.Y + m.ln3d) * Prepare the Main Path LOCAL loPath AS xfcGraphicsPath loPath = .Drawing2D.GraphicsPath.New() loPath.StartFigure() loPath.ADDLINE(loPoint0.X, loPoint0.Y, loPoint3.X, loPoint3.Y) loPath.AddArc(loRect2, tnStart, tnSweep) loPath.StartFigure() loPath.AddArc(loRect, tnStart, tnSweep) loPath.ADDLINE(loPoint1.X, loPoint1.Y, loPoint2.X, loPoint2.Y) IF m.ln3d > 0 * Create a new Path for the 3D LOCAL lo3DPath AS xfcPath, loMatrix AS xfcMatrix lo3DPath = loPath.CLONE() loMatrix = .Drawing2D.Matrix.New() loMatrix.Translate(0,+1) * Prepare the polygon points for the final part of the slice DIMENSION laPointsB(4) laPointsB(1) = loPoint1 laPointsB(2) = loPoint2 laPointsB(3) = .POINT.New(loPoint2.X, loPoint2.Y + m.ln3d) laPointsB(4) = loPoint6 * If the slice ends in the left side, draw the polygon before the top face of the slice IF BETWEEN(lnFinalAngle, 90, 270) loTempGfx.DrawPolygon(m.loPen, @laPointsB) ENDIF LOCAL N FOR N = 1 TO m.ln3d - 1 lo3DPath.TRANSFORM(loMatrix) loTempGfx.FillPathDim(lo3dBrush, lo3DPath) NEXT * Draw the side Polygons * Draw polygon at the beginning of the donut IF tnStart > 90 AND tnStart < 270 DIMENSION laPoints(4) laPoints(1) = loPoint0 laPoints(2) = loPoint5 laPoints(3) = loPoint4 laPoints(4) = loPoint3 loTempGfx.DrawPolygon(m.loPen, @laPoints) ENDIF * Draw polygon at the end of the donut IF lnFinalAngle < 90 OR lnFinalAngle > 270 loTempGfx.DrawPolygon(m.loPen, @laPointsB) ENDIF ENDIF * Draw the path loTempGfx.FillPathDim(m.loMainBrush, loPath) loTempGfx.DrawPath(THIS._oBorderPen, loPath) loBmp.ApplyColorMatrix(poClrMatrix) m.loGfx.DrawImage(loBmp, tnX, tnY) ENDWITH ENDIF ENDPROC PROCEDURE _drawfrustum LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D, tnMaxBarHeight * Yudin Alex 21 May 2013 LOCAL lcFront, lcPoints, ; ln3D, lnAlpha, lnHorDelta, lnOrigAlpha, lnStore, lnTop3D, lnTopHeight, lnTopWidth, lnTopX, lnTopY, ; loBotBrush, loGfx, loPen m.lnHorDelta=0 m.tnHeight = ABS(m.tnHeight) m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) m.loGfx = THIS.oGfx m.lnOrigAlpha = THIS.AlphaChannel m.lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25)) THIS.AlphaChannel = lnAlpha m.lcFront='' THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) m.loPen = THIS._oBorderPen WITH _SCREEN.SYSTEM.Drawing DO CASE CASE THIS.BrushType = 1 && SolidColors loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) CASE THIS.BrushType = 2 && Gradient loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80))) OTHERWISE * THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) loBotBrush = THIS._oMainBrush ENDCASE THIS.AlphaChannel = lnOrigAlpha lcPoints='' LOCAL laPoints(4) * Draw the 3D Bar using the 3DBrush IF THIS._Orientation = 1 && Vertical lnTopWidth = (tnMaxBarHeight-tnHeight) / tnMaxBarHeight * tnWidth lnTop3D = lnTopWidth * m.ln3D/tnWidth lnHorDelta = (tnWidth - lnTopWidth) /2 lnTopX = m.tnX + (m.tnWidth - lnTopWidth)/2 + (ln3D - lnTop3D)/2 lnTopY = m.tnY - (ln3D - lnTop3D)/2 * Prepare points to draw the 3D part of the Pyramid * Bottom m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(3) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.loGfx.FillPolygon(m.loBotBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Left wall LOCAL laPoints(4) m.laPoints(1) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, lnTopY - m.lnTop3D) m.laPoints(4) = .PointF.New(m.lnTopX, lnTopY) m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Top m.laPoints(1) = .PointF.New(m.lnTopX + lnTopWidth, lnTopY) m.laPoints(2) = .PointF.New(m.lnTopX + lnTopWidth + m.lnTop3D, lnTopY - m.lnTop3D) m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, lnTopY - m.lnTop3D) * m.laPoints(4) = .PointF.New(m.lnTopX, m.tnY) m.loGfx.FillPolygon(m.loBotBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Front m.laPoints(1) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.laPoints(3) = .PointF.New(m.lnTopX + lnTopWidth, m.lnTopY) m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Right wall m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(3) = .PointF.New(m.lnTopX + lnTopWidth+ m.lnTop3D, lnTopY - m.lnTop3D) m.laPoints(4) = .PointF.New(m.lnTopX + lnTopWidth,lnTopY) m.loGfx.FillPolygon(THIS._oRightbrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT TEXT TO lcFront <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT IF VARTYPE(tn3D)='N' tn3D= m.lnTop3D ENDIF ELSE **************** * * * Horizontal * * * **************** lnTopHeight = (tnMaxBarHeight-tnWidth) / tnMaxBarHeight * tnHeight lnTop3D = lnTopHeight * m.ln3D/tnHeight lnHorDelta = (tnHeight - lnTopHeight) /2 lnTopX = m.tnX + m.tnWidth + (ln3D - lnTop3D)/2 lnTopY = m.tnY + (m.tnHeight - lnTopHeight)/2 + (ln3D - lnTop3D)/2 -(ln3D - lnTop3D) IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.lnStore=m.lnTopX m.lnTopX = m.tnX m.tnX=m.lnStore ENDIF * Left bottom m.laPoints(1) = .PointF.New(m.tnX, m.tnY) m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D) m.laPoints(3) = .PointF.New(m.tnX+ m.ln3D, m.tnY + m.tnHeight - m.ln3D) m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.loGfx.FillPolygon(m.loBotBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Right bottom m.laPoints(1) = .PointF.New(m.lnTopX, m.lnTopY) m.laPoints(2) = .PointF.New(m.lnTopX + m.lnTop3D, m.lnTopY - m.lnTop3D) m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, m.lnTopY + m.lnTopHeight - m.lnTop3D) m.laPoints(4) = .PointF.New(m.lnTopX, m.lnTopY + m.lnTopHeight) m.loGfx.FillPolygon(m.loBotBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Walls * 1.Top m.laPoints(1) = .PointF.New(m.tnX, m.tnY) m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D) m.laPoints(3) = .PointF.New(m.lnTopX + m.lnTop3D, m.lnTopY - m.lnTop3D) m.laPoints(4) = .PointF.New(m.lnTopX, m.lnTopY) m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * 2. Front m.laPoints(1) = .PointF.New(m.tnX, m.tnY) m.laPoints(2) = .PointF.New(m.lnTopX, m.lnTopY) m.laPoints(3) = .PointF.New(m.lnTopX, m.lnTopY + m.lnTopHeight) m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT TEXT TO lcFront <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT IF VARTYPE(tn3D)='N' tn3D= m.lnTop3D ENDIF IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.tnX=m.lnTopX ENDIF ENDIF loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints,,lcFront) THIS._DrawLegendinBar(tnX, tnY, tnWidth, tnHeight, tnValue) ENDWITH RETURN lnHorDelta ENDPROC PROCEDURE _drawlegendinbar LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tnIndex, loShapeObject * Zero values in Stacked charts will not have space for drawing legends * so we'll ignore this case LOCAL lcCaption, lcLegend, lcValue, lnDecimals, loObject IF VARTYPE(tnHeight) # 'N' tnHeight = 8 ENDIF WITH THIS IF ._Stacked AND tnValue = 0 RETURN ENDIF .CurrIndex = ._nIndex LOCAL lnLeftMargin lnLeftMargin = ._yAxisWidth + ._LeftOffset *!* Other available properties *!* .CurrValue *!* .CurrLegend *!* .CurrObjType *!* .CurrRecno *!* .CurrColumn IF TYPE('.Fields(._ChartIndex)') # 'U' AND NOT .FIELDS(._ChartIndex).ShowValuesOnShape RETURN ENDIF m.lcLegend = '' LOCAL lcExpr, lnAlign, lnDirection lcExpr = .ShapeLegendExpression IF (VARTYPE(lcExpr) = "C") AND (NOT EMPTY(lcExpr)) .ShapeLegend._Value = EVALUATE(lcExpr) ELSE IF ._SumRow AND .ShowPercentages * Show percentages as values DO CASE CASE EMPTY(.ShapeLegend.FORMAT) AND EMPTY(.ShapeLegendExpression) .ShapeLegend._ForceFormat = ; ._GetFieldType(.SourceAlias, EVALUATE(".Fields(.ChartRow).FieldValue"), .T.) + "%" CASE NOT "%" $ .ShapeLegend.FORMAT .ShapeLegend._ForceFormat = .ShapeLegend.FORMAT + "%" ENDCASE LOCAL lnValue lnValue = ROUND(m.tnValue / .ChartSum * 100,0) .ShapeLegend._Value = lnValue ELSE .ShapeLegend._Value = tnValue ENDIF ENDIF lnDecimals = SET("Decimals") SET DECIMALS TO .ShowDecimals lcValue = IIF(VARTYPE(.ShapeLegend._Value)='N', ; TRANSFORM(.ShapeLegend._Value,[999 999 999 999]+IIF(.ShowDecimals>0,[.]+REPLICATE([9],.ShowDecimals),'')), ; .ShapeLegend._Value) .ShapeLegend._Value = IIF(EMPTY(m.lcLegend),'', m.lcLegend + CHR(13)+CHR(10)) + IIF(.ShowValue,ALLTRIM(lcValue),'') IF VARTYPE(loShapeObject)='O' loShapeObject.CAPTION=.ShapeLegend._Value ENDIF SET DECIMALS TO lnDecimals IF NOT .ShowValuesOnShapes OR EMPTY(.ShapeLegend._Value) RETURN ENDIF lnAlign = .ShapeLegend.ALIGNMENT *!* IF ._InvertShapeLegendAlignment = .T. *!* DO CASE *!* CASE lnAlign = 0 && Left *!* lnAlign = 1 && Right *!* CASE lnAlign = 1 && Right *!* lnAlign = 0 && Left *!* OTHERWISE *!* ENDCASE *!* ENDIF lnDirection = IIF(EMPTY(.ShapeLegend.ROTATION),.BarLegendDirection,0) IF lnDirection = 0 && Horizontal * Draw the Values inside the shapes IF ._Orientation = 1 && Vertical *!* IF (tnHeight < .ShapeLegend._Height) AND (NOT ._Stacked) *!* LOCAL y0 *!* y0 = .ChartCanvas.HEIGHT - ._XAxisHeight + 1 *!* tnY = y0 - .ShapeLegend._Height *!* ENDIF DO CASE CASE .ShapeLegendVertAlignment=2 tnY=tnY+tnHeight/2 - .ShapeLegend._Height/2 CASE .ShapeLegendVertAlignment=1 tnY=tnY+tnHeight - .ShapeLegend._Height ENDCASE DO CASE CASE .ShapeLegend.ROTATION # 0 AND .BarLegendType = 1 tnY = tnY - .ShapeLegend._Height - 2 loShape = .ShapeLegend._DrawString(tnX + tnWidth / 2, tnY) CASE lnAlign = 0 && Left loShape = .ShapeLegend._DrawString(tnX, tnY) CASE lnAlign = 1 && Right loShape = .ShapeLegend._DrawString(tnX + tnWidth, tnY) CASE lnAlign = 2 && Center x1=tnX + tnWidth / 2 loShape = .ShapeLegend._DrawString(x1, tnY) OTHERWISE ENDCASE ELSE && ._Orientation = 2 && Horizontal DO CASE CASE lnAlign = 2 && Center IF .ShapeLegend._Width > tnWidth && force left .ShapeLegend.ALIGNMENT = 0 loShape = .ShapeLegend._DrawString(tnX, tnY) .ShapeLegend.ALIGNMENT = 2 ELSE loShape = .ShapeLegend._DrawString(tnX + tnWidth / 2, tnY) ENDIF CASE lnAlign = 0 AND tnValue >= 0 && Left loShape = .ShapeLegend._DrawString(tnX, tnY) CASE lnAlign = 1 AND tnValue >= 0 && Right IF .ShapeLegend._Width > tnWidth && force left .ShapeLegend.ALIGNMENT = 0 loShape = .ShapeLegend._DrawString(tnX, tnY) .ShapeLegend.ALIGNMENT = 1 ELSE loShape = .ShapeLegend._DrawString(tnX + tnWidth, tnY) ENDIF CASE lnAlign = 1 AND tnValue < 0 && Force Left .ShapeLegend.ALIGNMENT = 0 loShape = .ShapeLegend._DrawString(tnX, tnY) .ShapeLegend.ALIGNMENT = 1 CASE lnAlign = 0 AND tnValue < 0 && Force Right .ShapeLegend.ALIGNMENT = 1 loShape = .ShapeLegend._DrawString(tnX + tnWidth, tnY) .ShapeLegend.ALIGNMENT = 0 OTHERWISE ENDCASE ENDIF ELSE && BarLegendDirection = 1 && Vertical IF lnDirection = 2 && Invert Direction LOCAL lnRotCenter lnRotCenter = .ShapeLegend.RotationCenter .ShapeLegend.RotationCenter = lnRotCenter + 180 ENDIF IF tnValue >= 0 OR lnAlign = 2 loShape = .ShapeLegend._DrawString(tnX, tnY, tnWidth, tnHeight, .T.) ELSE IF lnAlign = 0 .ShapeLegend.ALIGNMENT = 1 ELSE .ShapeLegend.ALIGNMENT = 0 ENDIF loShape = .ShapeLegend._DrawString(tnX, tnY, tnWidth, tnHeight, .T.) .ShapeLegend.ALIGNMENT = lnAlign ENDIF IF lnDirection = 2 && Invert Direction .ShapeLegend.RotationCenter = lnRotCenter ENDIF ENDIF loShape.CAPTION=.ShapeLegend._Value ENDWITH ENDPROC PROCEDURE _drawlinechart LOCAL laPoints[1], ; laPointsI[1], ; lcType as String, ; lnAdjust as Number, ; lnBarHeight as Number, ; lnBarWidth as Number SELECT(This._DataCursor) LOCAL lnLeftMargin, lnWidth, lnHeight, lnValue LOCAL lnBetween, lnBetween2, n, i, j, lnMaxValue, lnPointHeight, x1, y1, ln3D, lnChartsCount LOCAL llIsNull, lnYBase LOCAL lnTipPixels, lnType2, lnAlignment, lnRecs LOCAL lnMaxValue2 m.lnAlignment = This.ShapeLegend.Alignment m.lnRecs = This._nRecords m.lnTipPixels = This._TipPixels m.lnLeftMargin = This._YAxisWidth + This._LeftOffset m.ln3D = This._3D m.lnChartsCount = This.ChartsCount * Calculate the maximum width of the chart m.lnWidth = This.ChartCanvas.Width - This._YAxisWidth - This._LeftOffset - (m.ln3D * m.lnChartsCount) - This._RightOffset - THIS._yAxisWidth2 m.lnHeight = This.ChartCanvas.Height - This._XAxisHeight - This._TopOffSet - (m.ln3D * m.lnChartsCount) IF m.lnWidth < 10 OR m.lnHeight < 10 OR m.lnRecs < 1 RETURN ENDIF LOCAL loGfx as xfcGraphics m.loGfx = This.oGfx * Get the maximum value of the chart m.lnMaxValue = This._ScaleRange m.lnMaxValue2 = This._ScaleRange2 LOCAL loBrush as xfcBrush IF This.BrushType = 1 m.loBrush = "This._o3dbrush" ELSE m.loBrush = "This._oMainBrush" ENDIF * Prepare array of points * 1st column is the current point object * 2nd column is the global index number for the coordinates array LOCAL lnArrayLength IF INLIST(This.ChartType, 5, 18) && Line m.lnArrayLength = m.lnRecs ELSE && Area m.lnArrayLength = m.lnRecs + 3 ENDIF DIMENSION m.laPoints(m.lnArrayLength) DIMENSION m.laPointsI(m.lnArrayLength) WITH _Screen.System.Drawing FOR m.i = 1 TO m.lnChartsCount This._ChartIndex = m.i m.lnType2 = EVALUATE("This.Fields(i).ChartType") m.lnAdjust = (m.ln3D * (m.lnChartsCount - m.i )) m.lnYBase = This._TopOffSet + m.lnHeight - m.lnAdjust + (m.ln3D * m.lnChartsCount) * If MultiChart mode, the chart needs to start half a position further IF This.Multichart AND This.MultiChartMargin m.lnBetween = m.lnWidth / (m.lnRecs) ELSE m.lnBetween = m.lnWidth / (m.lnRecs - IIF(m.lnRecs = 1, 0, 1)) ENDIF m.lnBetween2 = m.lnBetween + m.lnAdjust && the X distance between the points to be used when drawing the legends in the X axis SCAN m.n = RECNO() m.x1 = m.lnLeftMargin + (m.lnBetween * (m.n - 1)) + ; m.lnAdjust + IIF(This.Multichart AND This.MultiChartMargin, ; (m.lnBetween / 2), 0) m.lnValue = This._GetValue(m.i, .T.) m.llIsNull = ISNULL(m.lnValue) IF m.llIsNull m.lnValue = 0 ENDIF IF This.Fields(m.i).AxisIndex = 2 AND This.ChartType = 18 m.lnValue = m.lnValue + This._ScaleAdjust2 m.lnPointHeight = m.lnValue / m.lnMaxValue2 * m.lnHeight m.y1 = m.lnYBase - m.lnPointHeight This._aPoints(m.n, 1) = m.x1 + m.ln3D This._aPoints(m.n, 2) = m.y1 This._aPoints(m.n, 3) = m.lnValue - This._ScaleAdjust2 && Restore the original value ELSE && This.Fields(i).AxisIndex = 1 IF m.llIsNull AND (m.n > 1) AND (This.LineIgnoreNULLs) && Special situation to Tamar Granor This._aPoints(m.n, 1) = This._aPoints(m.n - 1, 1) This._aPoints(m.n, 2) = This._aPoints(m.n - 1, 2) This._aPoints(m.n, 3) = This._aPoints(m.n - 1, 3) * Extra checking to avoid drawing a line if the starting values are NULLs IF VARTYPE(m.laPoints(m.n - 1)) = "L" m.laPoints(RECNO()) = .F. ELSE m.laPoints(RECNO()) = .Point.New(This._aPoints(m.n, 1) - m.ln3D, This._aPoints(m.n, 2)) ENDIF LOOP ENDIF m.lnValue = m.lnValue + This._ScaleAdjust m.lnPointHeight = m.lnValue / m.lnMaxValue * m.lnHeight m.y1 = m.lnYBase - m.lnPointHeight This._aPoints(m.n, 1) = m.x1 + m.ln3D This._aPoints(m.n, 2) = m.y1 This._aPoints(m.n, 3) = m.lnValue - This._ScaleAdjust && Restore the original value ENDIF m.laPoints(RECNO()) = IIF(m.llIsNull, .F., .Point.New(m.x1, m.y1)) ENDSCAN GO TOP * Draw the vertical line only for the first line IF m.i = 1 This._DrawVerticalLineBack() ENDIF DO CASE *-- 2010-11-26 *-- Fix by Paulo Henrique de Almeida (Casion) CASE m.lnType2 = 3 && Single Bar m.lnBarWidth = (m.lnWidth - (m.lnRecs - 1) * This.BarsSpaceBetween) / m.lnRecs FOR m.n = 1 TO m.lnRecs IF VARTYPE(m.laPoints(m.n)) <> "O" LOOP ENDIF * changed by paulo henrique m.x1 = This._aPoints(m.n, 1) - m.lnBarWidth / 2 - m.ln3D m.y1 = This.Height - ((0 - This._MinScale) / m.lnMaxValue * m.lnHeight) - This._XAxisHeight m.lnValue = This._aPoints(m.n, 3) m.lnBarHeight = m.y1 - This._aPoints(m.n, 2) m.y1 = min(m.y1, This._aPoints(m.n, 2)) * end - changed by paulo henrique This._CurrentRow = m.n This._DrawBar(m.x1, m.y1, m.lnBarWidth, m.lnBarHeight, m.lnValue) m.laPointsI(m.n) = This._nIndex ENDFOR *-- CASE This.ChartType = 4 OR m.lnType2 = 4 && Point / Secondary Point FOR m.n = 1 TO m.lnRecs IF VARTYPE(m.laPoints(m.n)) <> "O" LOOP ENDIF This._DrawShape(m.laPoints(m.n).X, m.laPoints(m.n).Y, This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex This._CurrentRow = m.n ENDFOR OTHERWISE && ChartType <> 4 - Line or Area IF This.ChartType = 6 && Area This._PrepareBrushes(0, 0, This.ChartCanvas.Width, This.ChartCanvas.Height, .F., m.i) ENDIF LOCAL laPolygon(4) LOCAL laPolygonB(4) IF m.ln3D = 0 * Create pen. LOCAL loLinePen as xfcPen LOCAL lnColor IF This.BrushType = 3 && Monochrome m.lnColor = 0 m.loLinePen = .Pen.New(This._oClrBlack, 3) m.loLinePen.DashStyle = m.i - 1 && _Screen.System.Drawing.Drawing2D.DashStyle.Dash ELSE m.lnColor = This.aColors(m.i) m.loLinePen = .Pen.New(.Color.FromRGB(m.lnColor), 2) ENDIF FOR m.n = 1 TO m.lnRecs - 1 This._CurrentRow = m.n m.lcType = VARTYPE(m.laPoints(m.n)) + VARTYPE(m.laPoints(m.n + 1)) DO CASE CASE m.lcType = "LO" OR m.lcType = "LL" LOOP CASE m.lcType = "OL" m.loGfx.Drawline(m.loLinePen, m.laPoints(m.n).X, m.laPoints(m.n).Y, m.laPoints(m.n).X + 1, m.laPoints(m.n).Y + 1) This._UpdateCoordinates(,"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ; This._aPoints(m.n, 3), m.n) m.laPointsI(m.n) = This._nIndex LOOP OTHERWISE m.loGfx.Drawline(m.loLinePen, m.laPoints(m.n), m.laPoints(m.n + 1)) ENDCASE IF This.ChartType = 6 && Area * Draw the area m.laPolygonB(1) = m.laPoints(m.n) m.laPolygonB(2) = m.laPoints(m.n + 1) m.laPolygonB(3) = .Point.New(m.laPolygonB(2).X, m.lnYBase) m.laPolygonB(4) = .Point.New(m.laPolygonB(1).X, m.lnYBase) m.loGfx.FillPolygon(This._oMainBrush, @m.laPolygonB) IF This.AreaDrawBorders m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygonB) ENDIF ENDIF This._UpdateCoordinates(,"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ; This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex ENDFOR IF VARTYPE(m.laPoints(m.n)) = "O" This._CurrentRow = m.n This._UpdateCoordinates(, ; "Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, ; m.lnTipPixels, m.lnTipPixels, This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex ENDIF * Draw the shapes after (over) the lines IF This.LineCaps = .T. AND INLIST(This.ChartType, 5, 18) && Line FOR m.j = 1 TO m.lnRecs IF VARTYPE(m.laPoints(m.j)) <> "O" OR ; VARTYPE(m.laPoints(m.j).X) + VARTYPE(m.laPoints(m.j).Y) <> "NN" LOOP ENDIF This._DrawShape(m.laPoints(m.j).X, m.laPoints(m.j).Y, This._aPoints(m.j, 3)) m.laPointsI(m.n) = This._nIndex This._CurrentRow = m.j ENDFOR ENDIF ELSE && m.ln3D <> 0 * Store a big area brush that will be used for the main area part of the shapes LOCAL loAreaBrush, llDrawPointLine m.loAreaBrush = This._oMainBrush FOR m.n = 1 TO m.lnRecs - 1 This._CurrentRow = m.n m.lcType = VARTYPE(m.laPoints(m.n)) + VARTYPE(m.laPoints(m.n + 1)) DO CASE CASE m.lcType = "LO" OR m.lcType = "LL" LOOP CASE m.lcType = "OL" m.llDrawPointLine = .T. OTHERWISE m.llDrawPointLine = .F. ENDCASE IF This.ChartType = 6 ; && Area AND "L" $ m.lcType IF m.lcType = "OL" This._UpdateCoordinates(,"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ; This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex ENDIF LOOP ENDIF IF INLIST(This.ChartType, 5, 18) OR (This.ChartType = 6 AND This.Area3dTop) m.laPolygon(1) = m.laPoints(m.n) m.laPolygon(2) = .Point.New(m.laPoints(m.n).X + m.ln3D, m.laPoints(m.n).Y - m.ln3D) IF m.llDrawPointLine LOCAL lnColor, loLinePen as xfcPen m.lnColor = This.aColors(m.i) m.loLinePen = .Pen.New(.Color.FromRGB(m.lnColor), 2) m.loGfx.Drawline(m.loLinePen, m.laPolygon(1), m.laPolygon(2)) This._UpdateCoordinates(,"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ; This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex LOOP ENDIF m.laPolygon(3) = .Point.New(m.laPoints(m.n + 1).X + m.ln3D, m.laPoints(m.n + 1).Y - m.ln3D) m.laPolygon(4) = m.laPoints(m.n + 1) This._PrepareBrushes(m.laPoints(m.n).X, m.laPoints(m.n).Y - m.ln3D, ; m.laPoints(m.n + 1).X + m.ln3D - m.laPoints(m.n).X, ; MAX(2, ABS(m.laPoints(m.n).Y - m.laPoints(m.n + 1).Y)), .F., m.i) m.loGfx.FillPolygon(This._oMainBrush, @m.laPolygon) m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygon) ENDIF IF This.ChartType = 6 && Area * Draw the area m.laPolygonB(1) = m.laPoints(m.n) m.laPolygonB(2) = m.laPoints(m.n + 1) m.laPolygonB(3) = .Point.New(m.laPolygonB(2).X, m.lnYBase) m.laPolygonB(4) = .Point.New(m.laPolygonB(1).X, m.lnYBase) m.loGfx.FillPolygon(m.loAreaBrush, @m.laPolygonB) IF This.AreaDrawBorders m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygonB) ENDIF * Draw the right 3d edge of the Area IF This.Area3dTop m.laPolygonB(1) = .Point.New(m.laPolygonB(2).X + m.ln3D, m.laPolygonB(2).Y - m.ln3D) m.laPolygonB(4) = .Point.New(m.laPolygonB(3).X + m.ln3D, m.laPolygonB(3).Y - m.ln3D) m.loGfx.FillPolygon(This._o3dbrush, @m.laPolygonB) m.loGfx.DrawPolygon(This._oBorderPen, @m.laPolygonB) ENDIF ENDIF && ChartType = 6 - Area This._UpdateCoordinates(,"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ; This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex ENDFOR This._CurrentRow = m.n IF VARTYPE(m.laPoints(m.n)) = "O" This._UpdateCoordinates(,"Rect", m.laPoints(m.n).X - m.lnTipPixels / 2, m.laPoints(m.n).Y - m.lnTipPixels / 2, m.lnTipPixels, m.lnTipPixels, ; This._aPoints(m.n, 3)) m.laPointsI(m.n) = This._nIndex ENDIF ENDIF && m.ln3D = 0 ENDCASE * Reset Row counter This._CurrentRow = 0 * Adjust _aPoints Array to show the information in the correct position FOR m.n = 1 TO m.lnRecs This._aPoints(m.n, 1) = This._aPoints(m.n, 1) - m.ln3D ENDFOR IF This.ShowValuesOnShapes AND This.Fields(m.i).ShowValuesOnShape LOCAL lnIndex * Draw Legends above the points FOR m.n = 1 TO m.lnRecs * Adjust _aPoints Array to show the information in the correct position This._aPoints(m.n, 1) = This._aPoints(m.n, 1) - m.ln3D IF VARTYPE(m.laPoints(m.n)) = "L" LOOP ENDIF m.x1 = This._aPoints(m.n, 1) m.y1 = This._aPoints(m.n, 2) m.lnIndex = m.laPointsI(m.n) This._DrawShapeLegend(m.x1, m.y1, m.lnIndex) ENDFOR ENDIF ENDFOR This._DrawXAxisLegend(.F., m.lnBetween2) ENDWITH This.ShapeLegend.Alignment = m.lnAlignment RETURN ENDPROC PROCEDURE _drawpiechart LPARAMETERS toShape LOCAL lcCursor, ln3D, lnDetachAngle, lnDetachPixels, lnHeight, lnMaxHeight, lnMaxWidth, lnNativeValue, ; lnStart, lnSweep, lnTempStart, lnTempSweep, lnTotal, lnValue, lnWidth, lnX, lnX1, lnY, lnY1, lnRow, loShape lnRow = IIF(TYPE('toShape.CurrentRow')='N', toShape.CurrentRow, 0) WITH THIS SELECT ( ._DataCursor ) lnLines = RECCOUNT() m.lnDetachPixels = .PieDetachPixels m.lnMaxWidth = .ChartCanvas.WIDTH - ._LeftOffset - ._RightOffset - (lnDetachPixels * 2) m.lnMaxHeight = .ChartCanvas.HEIGHT - (.MARGIN * 2) - .MarginBottom - ; .MarginTop - ._TitleHeight - ._3d - ; (lnDetachPixels * 2) - ; ._LegendHeight m.lnMaxHeight = .ChartCanvas.HEIGHT-(.MARGIN * 2)-.MarginBottom-.MarginTop-._TitleHeight-._3d- ; (lnDetachPixels*2)-._LegendHeight m.lnWidth = MIN(lnMaxWidth, lnMaxHeight) m.lnHeight = m.lnWidth IF NOT .PieForceCircle * Adjust the maximum width in order to ensure that the chart will retain LOCAL lnFactor m.lnFactor = 0.80 IF m.lnMaxWidth <= m.lnWidth / m.lnFactor m.lnWidth = lnMaxWidth ELSE m.lnWidth = m.lnWidth / m.lnFactor ENDIF ENDIF m.ln3D = ._3d IF .PieCompensateAngles m.lnWidth = m.lnMaxWidth ENDIF IF m.lnWidth <= 10 OR ; lnHeight <= 10 OR ; lnHeight <= ln3D RETURN ENDIF * Calculate the chart basic positions lnX = lnDetachPixels + .MARGIN + ._LeftOffset + ((lnMaxWidth - m.lnWidth) / 2) lnY = .MARGIN + ._TopOffSet + ((lnMaxHeight - m.lnHeight) / 2) + lnDetachPixels lnTotal = .ChartSum IF NOT .PieEnhancedDrawing && Draws without taking care of slices edges * Prepare the Gdi+ objects WITH _SCREEN.SYSTEM.Drawing PRIVATE poTempBmp AS xfcBitmap, poClrMatrix AS xfcColorMatrix poTempBmp = .BITMAP.New(m.lnWidth + m.ln3D + 2, m.lnHeight + m.ln3D + 2) poClrMatrix = .Imaging.ColorMatrix.New() poClrMatrix.Matrix33 = .AlphaChannel / 255 ENDWITH ENDIF LOCAL laLegends(lnLines + 1, 3), lnRec, llHidden, llDrawLegend, lnPixelsOut llDrawLegend = .ShowValuesonShapes lnRec = 1 ._ChartIndex = .ChartRow ._Pie1stDetached = .F. IF .PieDirection = 1 && Anticlockwise SET ORDER TO REVERT ENDIF * Draw the pie * Draw the RIGHT side of the pie lnStart = 270 .COLUMN = IIF(BETWEEN(._ChartIndex, 1, .ChartsCount), ._ChartIndex,1) FOR .ROW = 1 TO RECCOUNT() IF lnStart >=450 EXIT ENDIF .GetValue() *SCAN FOR lnStart < 450 lnX1 = lnX lnY1 = lnY * Calculate Start point and Sweep lnNativeValue = .VALUE lnValue = ABS(lnNativeValue) IF lnValue <= 0 LOOP ENDIF lnSweep = lnValue / lnTotal * 360 IF lnSweep > 359.99 lnSweep = 359.99 ENDIF llHidden = lSliceHidden OR (NOT EMPTY(lnRow) AND lnRow#.ROW) IF lDetach IF lnRec = 1 ._Pie1stDetached = .T. ._PieX0 = lnX1 ._PieY0 = lnY1 ENDIF IF VARTYPE(._PieAnimatedRec) ='N' AND .ROW = ._PieAnimatedRec lnPixelsOut = ._PieAnimationPix ELSE lnPixelsOut = lnDetachPixels ENDIF lnTempStart = lnStart lnTempSweep = lnSweep ._AdjustStartSweep(@lnTempStart, @lnTempSweep, m.lnWidth, m.lnHeight) lnDetachAngle = 360 - (lnTempStart + (lnTempSweep / 2)) lnX1 = lnX + (COS(DTOR(lnDetachAngle)) * lnPixelsOut) lnY1 = lnY - (SIN(DTOR(lnDetachAngle)) * lnPixelsOut) ELSE lnX1 = lnX lnY1 = lnY ENDIF IF lnStart + lnSweep > 450 EXIT ENDIF loShape = IIF(lnRow>0,toShape, ._UpdateCoordinates(,"Pie",0,0,0,0,0,,,,,lnRec)) IF NOT llHidden IF .ChartType = 1 && Pie ._DrawSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape) ELSE && 2 - Doughnut ._DrawDoughnutSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape) ENDIF IF llDrawLegend ._PrepareLegendinSlice(@lnX1, @lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue) laLegends(lnRec,1) = lnX1 laLegends(lnRec,2) = lnY1 laLegends(lnRec,3) = lnNativeValue lnRec = lnRec + 1 ENDIF ENDIF lnStart = lnStart + lnSweep NEXT * Draw the LEFT side of the pie .ROW = RECCOUNT() lnStart = 270 DO WHILE lnStart >= 90 IF lnStart < 90 EXIT ENDIF .GetValue() * Calculate Start point and Sweep IF .VALUE = 0 IF .ROW = 1 EXIT ENDIF .ROW = .ROW -1 LOOP ENDIF lnX1 = lnX lnY1 = lnY lnNativeValue = .VALUE lnValue = ABS(lnNativeValue) lnSweep = lnValue / lnTotal * 360 IF lnSweep > 359.99 lnSweep = 359.99 ENDIF lnStart = lnStart - lnSweep llHidden = lSliceHidden OR (NOT EMPTY(lnRow) AND lnRow # .ROW) IF lDetach lnTempStart = lnStart lnTempSweep = lnSweep IF lnStart + lnSweep >= 269.9 ._Pie1stDetached = .T. ._PieX0 = lnX1 ._PieY0 = lnY1 ENDIF IF VARTYPE(._PieAnimatedRec) ='N' AND .ROW = ._PieAnimatedRec lnPixelsOut = ._PieAnimationPix ELSE lnPixelsOut = lnDetachPixels ENDIF ._AdjustStartSweep(@lnTempStart, @lnTempSweep, m.lnWidth, m.lnHeight) lnDetachAngle = 360 - (lnTempStart + (lnTempSweep / 2)) lnX1 = lnX + (COS(DTOR(lnDetachAngle)) * lnPixelsOut) lnY1 = lnY - (SIN(DTOR(lnDetachAngle)) * lnPixelsOut) ENDIF loShape = IIF(lnRow>0,toShape, ._UpdateCoordinates(,"Pie",0,0,0,0,0,,,,,lnRec)) IF NOT llHidden IF .ChartType = 1 && Pie ._DrawSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape) ELSE && 2 - Doughnut ._DrawDoughnutSlice(lnX1, lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue,loShape) ENDIF IF llDrawLegend ._PrepareLegendinSlice(@lnX1, @lnY1, m.lnWidth, m.lnHeight, lnStart, lnSweep, lnNativeValue) laLegends(lnRec,1) = lnX1 laLegends(lnRec,2) = lnY1 laLegends(lnRec,3) = lnNativeValue lnRec = lnRec + 1 ENDIF ENDIF IF .ROW=1 EXIT ENDIF .ROW = .ROW - 1 ENDDO * Draw the legends at the end of the process in order to avoid * a slice hiding a legend IF TYPE('.FIELDS(._ChartIndex).ShowValuesOnShape') # 'L' OR .FIELDS(._ChartIndex).ShowValuesOnShape IF llDrawLegend LOCAL lnOrigAlign, N lnOrigAlign = .ShapeLegend.ALIGNMENT .ShapeLegend.ALIGNMENT = 2 && Force Center lc='' FOR N = 1 TO lnRec - 1 LOCAL lcExpr lcExpr = .ShapeLegendExpression IF VARTYPE(lcExpr) = "C" AND NOT EMPTY(lcExpr) *!* Other available properties *!* .CurrValue *!* .CurrLegend *!* .CurrObjType *!* .CurrRecno *!* .CurrColumn .CurrIndex = N lnValue = EVALUATE(lcExpr) ELSE IF .PieShowPercent DO CASE CASE EMPTY(.ShapeLegend.FORMAT) AND EMPTY(lcExpr) .ShapeLegend._ForceFormat = ; ._GetFieldType(._DataCursor, 'nValue'+ALLTRIM(STR(.ChartRow)), .T.) + "%" CASE NOT "%" $ .ShapeLegend.FORMAT .ShapeLegend._ForceFormat = .ShapeLegend.FORMAT + "%" ENDCASE lnValue = (laLegends(N,3) / lnTotal) * 100 ELSE lnValue = laLegends(N,3) ENDIF ENDIF .ShapeLegend._Value = lnValue TEXT TO lc addi <<.CurrLegend>> (<<.CurrIndex>>) : <>, <>, <> <> endtext lnX1 = laLegends(N,1) IF VARTYPE(lnX1) <> "N" EXIT ENDIF lnY1 = laLegends(N,2) * Draw the Text .ShapeLegend._DrawString( lnX1, lnY1,,,,,loShape) NEXT .ShapeLegend._ForceFormat = "" .ShapeLegend.ALIGNMENT = lnOrigAlign ENDIF ENDIF IF .PieDirection = 1 && Anticlockwise SET ORDER TO ENDIF ENDWITH ENDPROC PROCEDURE _drawpyramid LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D * Yudin Alex 21 May 2013 LOCAL lcFront, lcPoints, ; llLeftRight, ln3D, lnAlpha, lnOrigAlpha, lnStore, lnTopX, lnTopY, ; loBotBrush, loGfx, loPen m.tnHeight = ABS(m.tnHeight) m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) m.loGfx = THIS.oGfx lnOrigAlpha = THIS.AlphaChannel lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25)) THIS.AlphaChannel = lnAlpha THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex)) WITH _SCREEN.SYSTEM.Drawing DO CASE CASE THIS.BrushType = 1 && SolidColors loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) CASE THIS.BrushType = 2 && Gradient loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, + 80))) OTHERWISE THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) loBotBrush = THIS._oMainBrush ENDCASE m.loPen = THIS._oBorderPen THIS.AlphaChannel = lnOrigAlpha STORE '' TO lcPoints, lcFront LOCAL laPoints(4) * Draw the 3D Bar using the 3DBrush IF THIS._Orientation = 1 && Vertical * Points for 3D pyramid parts * Bottom m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(3) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.loGfx.FillPolygon(m.loBotBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Left wall LOCAL laPoints(3) m.laPoints(1) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.laPoints(3) = .PointF.New(m.tnX + m.tnWidth/2 + m.ln3D/2, m.tnY - m.ln3D/2) m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Front wall m.laPoints(1) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) m.laPoints(1) = .PointF.New(m.tnX + m.tnWidth, m.tnY + m.tnHeight) m.laPoints(2) = .PointF.New(m.tnX + m.tnWidth + m.ln3D, m.tnY - m.ln3D + m.tnHeight) m.loGfx.FillPolygon(THIS._oRightbrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT TEXT TO lcFront <>,<> <>,<> <>,<> <>,<> ENDTEXT ELSE *Horizont llLeftRight = THIS.Charttype # 17 AND THIS._ChartIndex>1 lnTopX = m.tnX + m.tnWidth + m.ln3D/2 * IIF(llLeftRight,1,0) lnTopY = m.tnY + m.tnHeight/2 - m.ln3D/2 IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.lnStore=m.lnTopX m.lnTopX = m.tnX m.tnX=m.lnStore ENDIF * Bottom m.laPoints(1) = .PointF.New(m.tnX, m.tnY) m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D) m.laPoints(3) = .PointF.New(m.tnX+ m.ln3D, m.tnY + m.tnHeight - m.ln3D) m.laPoints(4) = .PointF.New(m.tnX, m.tnY + m.tnHeight) m.loGfx.FillPolygon(m.loBotBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) * Walls LOCAL laPoints(3) m.laPoints(1) = .PointF.New(m.tnX, m.tnY) m.laPoints(2) = .PointF.New(m.tnX + m.ln3D, m.tnY - m.ln3D) m.laPoints(3) = .PointF.New(lnTopX, lnTopY) m.loGfx.FillPolygon(THIS._o3DBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) m.laPoints(1) = .PointF.New(m.tnX, m.tnY) m.laPoints(2) = .PointF.New(m.tnX , m.tnY + m.tnHeight) m.laPoints(3) = .PointF.New(lnTopX, lnTopY) m.loGfx.FillPolygon(THIS._oMainBrush, @laPoints) m.loGfx.DrawPolygon(m.loPen, @laPoints) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT TEXT TO lcFront <>,<> <>,<> <>,<> <>,<> ENDTEXT IF THIS.Charttype = 17 AND THIS._ChartIndex=1 m.tnX=m.lnTopX ENDIF ENDIF loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints,,lcFront) THIS._DrawLegendinBar(tnX, tnY, tnWidth, tnHeight, tnValue) ENDWITH ENDPROC PROCEDURE _drawscale LPARAMETERS toPen, tnAxisIndex LOCAL lnScaleNumber as Number, ; lnScaleWidth as Number, ; lnThisScale as Number, ; lnValue as Number, ; lnWidth as Number, x m.tnAxisIndex = EVL(m.tnAxisIndex, 1) * Draw the scale in the Y Axis Local ln3D, lnHeight, lnMargin, lnScaleValue, llShowLineZero IF This.ChartType = 17 && Paired m.llShowLineZero = .F. ELSE m.llShowLineZero = This.ShowLineZero ENDIF IF This._DeepChart && Point, Line or Area m.ln3D = This._3D * This.ChartsCount ELSE m.ln3D = This._3D ENDIF LOCAL lnMaxValue, lnScale, lnScaleAdjust, lnMinScale, lnMaxScale m.lnMaxValue = IIF(m.tnAxisIndex = 1, This._ScaleRange, This._ScaleRange2) m.lnScale = IIF(m.tnAxisIndex = 1, This._Scale, This._Scale2) m.lnScaleAdjust = IIF(m.tnAxisIndex = 1, This._ScaleAdjust, This._ScaleAdjust2) m.lnMinScale = IIF(m.tnAxisIndex = 1, This._MinScale, This._MinScale2) m.lnMaxScale = IIF(m.tnAxisIndex = 1, This._MaxScale, This._MaxScale2) LOCAL loGfx AS xfcGraphics m.loGfx = This.oGfx LOCAL loBackBrush AS xfcSolidBrush LOCAL loBackPen AS xfcPen LOCAL loBlackPen AS xfcPen LOCAL llDrawBack, lnOneScale, lnxWidth m.loBlackPen = This._oBlackPen m.llDrawBack = .T. This.ScaleLegend._Setup() If This._Orientation = 1 && Vertical Local lnRectColor, lnLineColor If This.BrushType = 3 && Monochrome m.lnRectColor = Rgb(255, 255, 255) && White m.lnLineColor = 0 && Black Else m.lnRectColor = This.ScaleBackColor m.lnLineColor = This.ScaleLineColor Endif With _Screen.System.Drawing m.loBackBrush = .SolidBrush.New(.Color.FromARGB(This.ScaleBackAlpha, m.lnRectColor)) This._oBlackPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, m.lnLineColor), This.ScaleBackLinesWidth - 1) Endwith Local lnDashValue m.lnDashValue = This.ScaleBackLinesDash If m.lnDashValue > 0 This._oBlackPen.DashStyle = m.lnDashValue && _Screen.System.Drawing.Drawing2D.DashStyle.Dash Endif m.lnHeight = This.Height - This._XAxisHeight - This._TopOffSet - m.ln3D m.lnOneScale = m.lnScale / m.lnMaxValue * m.lnHeight m.lnxWidth = This.Width - This._LeftOffset - This._RightOffset - This._yAxisWidth - m.ln3D Local x0, x1, y0, y1, lnScaleHeight, N, Y m.y0 = This.Height - This._XAxisHeight m.x0 = IIF(m.tnAxisIndex = 1, ; This._yAxisWidth + This._LeftOffset, ; This.ChartCanvas.Width - This._RightOffset - m.ln3D + 2 + 2) **************************************************************** * Jim Nelson 10/10/08 * * Loop now calls method GetScaleValue (and its cousin GetScaleLegend) to get the * scale values and associated legends. lnScaleNumber = 0 returns highest scale * Save original Alignment settings LOCAL lnOrigAlignment, lcOrigScaleFormat m.lnOrigAlignment = This.ScaleLegend.Alignment m.lcOrigScaleFormat = This.ScaleLegend._ForceFormat * CCHALOM 2013-02-21 * Fix in getting a nice Scale legend format for both axes * New properties inserted: _ScaleLegAxis1ForceFormat , _ScaleLegAxis2ForceFormat This.ScaleLegend._ForceFormat = IIF(m.tnAxisIndex = 1, This._ScaleLegAxis1ForceFormat, This._ScaleLegAxis2ForceFormat) For m.lnScaleNumber = 0 To 1000 m.lnValue = This.GetScaleValue (m.lnScaleNumber, m.tnAxisIndex) If "N" # Vartype(m.lnValue) Exit Endif * Yudin: Escape zero divide m.lnScaleHeight = IIF(m.lnMaxValue=0,0,(m.lnValue - m.lnMinScale) / m.lnMaxValue * m.lnHeight) m.Y = This.Height - m.lnScaleHeight - This._XAxisHeight m.x1 = IIF(m.tnAxisIndex = 1, ; This._yAxisWidth + This._LeftOffset - 7, ; This.ChartCanvas.Width - This._RightOffset - m.ln3D + 6) m.y1 = m.Y - (This._ScaleH/2) m.lnScaleValue = m.lnValue - m.lnScaleAdjust * 2nd Y Axis IF m.tnAxisIndex = 1 This.ScaleLegend.Alignment = 1 && Force Right alignment ELSE This.ScaleLegend.Alignment = 0 && Force Left alignment ENDIF This.ScaleLegend._Value = This.GetScaleLegend(m.lnScaleNumber, (m.lnValue / This.ScaleDivider)) This.ScaleLegend._DrawString(m.x1, m.y1) * Draw the horizontal scale (tick) line in the Y Axis m.loGfx.DrawLine(m.toPen, m.x0, m.Y, m.x0 + m.ln3D, m.Y - m.ln3D) m.loGfx.DrawLine(m.loBlackPen, m.x0 - 0, m.Y, m.x0 - This.TicLength, m.Y) * Chack if finished drawing IF "N" # VARTYPE(This.GetScaleValue (m.lnScaleNumber + 1)) EXIT ENDIF * Draw the scale background Local x1Scale, y1Scale m.x1Scale = m.x0 + m.ln3D m.y1Scale = m.Y - m.ln3D If m.llDrawBack AND m.tnAxisIndex = 1 **************************************************************** * Jim Nelson 10/11/08 * * Calculate height to next scale m.lnThisScale = (This.GetScaleValue (m.lnScaleNumber) - This.GetScaleValue (m.lnScaleNumber+1)) / m.lnMaxValue * m.lnHeight IF INLIST(This.ScaleBackBarsType, 1, 3) && Horizontal, Both **************************************************************** * Jim Nelson 10/11/08 * * Calculate the height of this horizontal bar (allowing for case where not all bars are same height) * loGfx.FillRectangle(loBackBrush, x1Scale, y1Scale, lnxWidth, lnOneScale) m.loGfx.FillRectangle(m.loBackBrush, m.x1Scale, m.y1Scale, m.lnxWidth, m.lnThisScale) ENDIF IF INLIST(This.ScaleBackLinesType, 1, 3) && Horizontal, Both **************************************************************** * Jim Nelson 10/10/08 * * Do NOT draw the line if its the zero line (see below) IF NOT ( ; m.llShowLineZero ; AND ABS(m.lnValue) < m.lnScale / 100 ; AND m.lnMaxScale > 0 ; AND m.lnMinScale < 0 ; AND m.ln3D = 0 ; ) m.loGfx.DrawLine(This._oBlackPen, m.x1Scale, m.y1Scale, m.x1Scale + m.lnxWidth, m.y1Scale) m.loGfx.DrawLine(This._oBlackPen, m.x1Scale, m.y1Scale + m.lnThisScale, m.x1Scale + m.lnxWidth, m.y1Scale + m.lnThisScale) ENDIF ENDIF ENDIF m.llDrawBack = Not m.llDrawBack IF m.llShowLineZero AND m.tnAxisIndex = 1 * Draw the ZERO line IF ABS(m.lnValue) < m.lnScale / 100 And m.lnMaxScale > 0 And m.lnMinScale < 0 WITH _Screen.System.Drawing LOCAL loZeroPen As xfcPen m.loZeroPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, This.ScaleLineZeroColor), 1) If m.ln3D = 0 m.loGfx.DrawLine(m.loZeroPen, ; m.x1Scale, m.y1Scale, m.x1Scale + m.lnxWidth, m.y1Scale) Else * Following line moved; does not apply to case m.ln3D = 0 m.y1Scale = m.y1Scale + 1 Local laPolygon(4) m.laPolygon(1) = .Point.New(m.x1Scale, m.y1Scale) m.laPolygon(2) = .Point.New(m.x1Scale + m.lnxWidth, m.y1Scale) m.laPolygon(3) = .Point.New(m.x1Scale + m.lnxWidth - m.ln3D, m.y1Scale + m.ln3D) m.laPolygon(4) = .Point.New(m.x1Scale - m.ln3D, m.y1Scale + m.ln3D) Local loZeroBrush As xfcSolidBrush m.loZeroBrush = .SolidBrush.New(.Color.FromARGB(64, This.ScaleLineZeroColor)) m.loGfx.FillPolygon(m.loZeroBrush, @m.laPolygon) m.loGfx.DrawPolygon(m.loZeroPen, @m.laPolygon) Endif Endwith Endif Endif Endfor This._ChartY0 = This.Height - This._XAxisHeight - m.ln3D This._ChartY1 = This._ChartY0 - m.lnHeight * Restore original Alignment settings This.ScaleLegend.Alignment = m.lnOrigAlignment This.ScaleLegend._ForceFormat = m.lcOrigScaleFormat Else && _Orientation = 2 HORIZONTAL Local x0, x1, y0, y1 m.lnMargin = This._yAxisWidth + This._LeftOffset m.y0 = This._TopOffSet m.y1 = This.Height - This._XAxisHeight + 6 m.x0 = m.lnMargin m.x1 = This.Width - This._RightOffset && This._LegendWidth m.lnWidth = This.Width - This._LeftOffset - This._RightOffset - This._yAxisWidth - m.ln3D Local llDrawBack, lnOneScale m.llDrawBack = .T. Local lnRectColor, lnLineColor If This.BrushType = 3 && Monochrome m.lnRectColor = Rgb(255, 255, 255) && White m.lnLineColor = 0 && Black Else m.lnRectColor = This.ScaleBackColor m.lnLineColor = This.ScaleLineColor Endif With _Screen.System.Drawing m.loBackBrush = .SolidBrush.New(.Color.FromARGB(This.ScaleBackAlpha, m.lnRectColor)) This._oBlackPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, m.lnLineColor), This.ScaleBackLinesWidth - 1) Endwith Local lnDashValue m.lnDashValue = This.ScaleBackLinesDash If m.lnDashValue > 0 This._oBlackPen.DashStyle = m.lnDashValue && _Screen.System.Drawing.Drawing2D.DashStyle.Dash Endif m.lnOneScale = m.lnScale / m.lnMaxValue * m.lnWidth **************************************************************** * Jim Nelson 10/10/08 * * Loop now calls method GetScaleValue (and its cousin GetScaleLegend) to get the * scale values and associated legends. lnScaleNumber = 0 returns highest scale For m.lnScaleNumber = 0 To 1000 m.lnValue = This.GetScaleValue (m.lnScaleNumber) If "N" # Vartype( m.lnValue) Exit Endif m.lnScaleWidth = (m.lnValue - m.lnMinScale) / m.lnMaxValue * m.lnWidth m.x = m.x0 + m.lnScaleWidth m.lnScaleValue = This.GetScaleLegend (m.lnScaleNumber, m.lnValue) IF VARTYPE(m.lnScaleValue) = "C" This.ScaleLegend._Value = m.lnScaleValue ELSE This.ScaleLegend._Value = IIF(This._AbsoluteScaleValues, ABS(m.lnScaleValue), m.lnScaleValue) ENDIF If This.ScaleLegend.Rotation = 0 This.ScaleLegend._DrawString(m.x, m.y1, .T.) && Force Center Else This.ScaleLegend._DrawString(m.x, m.y1) Endif * Draw the horizontal scale line in the Y Axis m.loGfx.DrawLine(m.toPen, m.x, m.y1 - 5, m.x + m.ln3D, m.y1 - 5 - m.ln3D) m.loGfx.DrawLine(m.loBlackPen, m.x, m.y1, m.x, m.y1 - This.TicLength) * Draw the scale background Local x1Scale, y1Scale m.x1Scale = m.x + m.ln3D m.y1Scale = m.y1 - m.ln3D - 3 If m.llDrawBack and "N" = Vartype (This.GetScaleValue (m.lnScaleNumber+1)) **************************************************************** * Jim Nelson 10/11/08 * * Calculate width to next scale m.lnThisScale = (This.GetScaleValue (m.lnScaleNumber) - This.GetScaleValue (m.lnScaleNumber+1)) / m.lnMaxValue * m.lnWidth If Inlist(This.ScaleBackBarsType, 2, 3) && Vertical, Both **************************************************************** * Jim Nelson 10/11/08 * * Calculate the widtht of this horizontal bar (allowing for case where not all bars are same height) m.loGfx.FillRectangle(m.loBackBrush, m.x1Scale - m.lnThisScale, m.y0, m.lnThisScale, m.y1Scale - m.y0) Endif If Inlist(This.ScaleBackLinesType, 2, 3) && Vertical, Both **************************************************************** * Jim Nelson 10/10/08 * * Do NOT draw the line if its the zero line (see below) If Not ( ; m.llShowLineZero ; and Abs(m.lnValue) < m.lnScale / 100 ; And m.lnMaxScale > 0 ; And m.lnMinScale < 0 ; and m.ln3D = 0 ; ) m.loGfx.DrawLine(This._oBlackPen, m.x1Scale, m.y0, m.x1Scale, m.y1Scale) m.loGfx.DrawLine(This._oBlackPen, m.x1Scale - m.lnThisScale, m.y0, m.x1Scale - m.lnThisScale, m.y1Scale) Endif Endif Endif m.llDrawBack = Not m.llDrawBack If m.llShowLineZero * Draw the ZERO line If Abs(m.lnValue) < m.lnScale / 100 And m.lnMaxScale > 0 And m.lnMinScale < 0 With _Screen.System.Drawing Local loZeroPen As xfcPen m.loZeroPen = .Pen.New(.Color.FromARGB(This.AxisAlpha, This.ScaleLineZeroColor), 1) If m.ln3D = 0 m.loGfx.DrawLine(m.loZeroPen, m.x1Scale, m.y0, m.x1Scale, m.y1Scale) Else * Following line moved; does not apply to case m.ln3D = 0 m.y1Scale = m.y1Scale + 1 Local laPolygon(4) m.laPolygon(1) = .Point.New(m.x1Scale, m.y0) m.laPolygon(2) = .Point.New(m.x1Scale, m.y1Scale) m.laPolygon(3) = .Point.New(m.x1Scale - m.ln3D, m.y1Scale + m.ln3D) m.laPolygon(4) = .Point.New(m.x1Scale - m.ln3D, m.y0 + m.ln3D) Local loZeroBrush As xfcSolidBrush m.loZeroBrush = .SolidBrush.New(.Color.FromARGB(64, This.ScaleLineZeroColor)) m.loGfx.FillPolygon(m.loZeroBrush, @m.laPolygon) m.loGfx.DrawPolygon(m.loZeroPen, @m.laPolygon) Endif Endwith Endif Endif Endfor Endif Return ENDPROC PROCEDURE _drawshape LPARAMETERS tnX, tnY, tnValue, tcObjType, luShape, tnBartype LOCAL lnX1, lnY1, loRect, luShape, lcType, lnIndex, lnTipPixels, lnColor, loGfx AS xfcGraphics, loObject AS OBJECT lnTipPixels = THIS._TipPixels lnIndex = THIS._ChartIndex tnBartype = EVL(tnBartype,0) IF EMPTY(tcObjType) tcObjType = "Rect" ENDIF IF THIS.BrushType = 3 && Monochrome lnColor = 0 ELSE lnColor = EVL(THIS.aColors(lnIndex),0) ENDIF DO CASE CASE VARTYPE(luShape)='O' CASE NOT EMPTY(THIS.LineCapsShape) luShape = THIS.LineCapsShape OTHER luShape = THIS.FIELDS(lnIndex).SHAPE ENDCASE lcType = VARTYPE(luShape) m.loGfx = THIS.oGfx DO CASE CASE lcType = "N" OR lcType = "O" && Graphics path using predefined Shape LOCAL loPath AS xfcGraphicsPath, lnWidth, lnHeight, loBrush AS xfcSolidBrush, loAdjPath AS xfcGraphicsPath, loMatrix AS xfcMatrix IF VARTYPE(THIS._aShapes(lnIndex, 1)) = "O" m.loPath = THIS._aShapes(lnIndex, 1) ELSE IF lcType = "O" loPath = luShape.CLONE() THIS._CenterPath(loPath, .T.) ELSE loPath = THIS._GetShapePath(luShape) THIS._CenterPath(loPath, .T.) ENDIF ENDIF loRect = loPath.GetBounds() lnWidth = loRect.WIDTH lnHeight = loRect.HEIGHT loBrush = .SolidBrush.New(.COLOR.FromRGB(lnColor)) loAdjPath = loPath.CLONE() loMatrix = _SCREEN.SYSTEM.Drawing.Drawing2D.Matrix.New() loMatrix.Translate(tnX, tnY) loAdjPath.TRANSFORM(loMatrix) THIS.FillPathDim(loBrush, loAdjPath) lnX1 = tnX - (m.lnWidth / 2) lnY1 = tnY - (lnHeight / 2) loObject = loPath CASE lcType = "C" && Image File LOCAL loBmp AS xfcBitmap, lnWidth, lnHeight IF VARTYPE(THIS._aShapes(lnIndex, 1)) = "O" loBmp = THIS._aShapes(lnIndex, 1) lnWidth = THIS._aShapes(lnIndex, 2) lnHeight = THIS._aShapes(lnIndex, 3) ELSE loBmp = _SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(FILETOSTR(luShape)) lnWidth = loBmp.WIDTH lnHeight = loBmp.HEIGHT ENDIF lnX1 = tnX - (m.lnWidth /2) lnY1 = tnY - (lnHeight /2) m.loGfx.DrawImage(loBmp, lnX1, lnY1) loObject = loBmp OTHERWISE ENDCASE * Fix by Anal Roy Chowdhurry IF NOT (THIS.LineCaps AND INLIST(This.ChartType, 5, 18)) AND tnBartype#7 THIS._UpdateCoordinates(,tcObjType, lnX1, lnY1, m.lnWidth, lnHeight, tnValue) ENDIF * End of Revision new checking THIS._aShapes(lnIndex, 1) = loObject THIS._aShapes(lnIndex, 2) = lnWidth THIS._aShapes(lnIndex, 3) = lnHeight ENDPROC PROCEDURE _drawsidelegends **!* Property LegendPosition *!* Numeric, *!* Determines the position where the side legend wiil be drawn in the canvas. *1* 0 - No Legend *!* 1 - Vertical Top Left *!* 2 - Vertical Bottom Left *!* 3 - Vertical Top Right *!* 4 - Vertical Bottom Right *!* 5 - Horiz Top Left *!* 6 - Horiz Top Center *!* 7 - Horiz Top Right *!* 8 - Horiz Bottom Left *!* 9 - Horiz Bottom Center *!* 10 - Horiz Bottom Right *!* 11 - Vertical Center Left *!* 12 - Vertical Center Right LOCAL lcCaption, llHorizontal, lnWidth, lnHeight, lnX1, lnY1, ; lnAvailableHeight, lnChart, lnCount, lnExternalMargin, lnLegendHeight, lnLength, lnMargin, lnNeededHeight, lnOrigAlignment, lnOrigIndex, lnPosition, lnStart, lnTopMargin, lnVertHeight m.lnPosition = THIS.LegendPosition IF NOT THIS.ShowSideLegend OR m.lnPosition = 0 RETURN ENDIF * Force left alignment for the side legend - this value will be restored at the end of this method m.lnOrigAlignment = THIS.SideLegend.ALIGNMENT THIS.SideLegend.ALIGNMENT = 0 && Left THIS._InLegend = .T. m.llHorizontal = INLIST(m.lnPosition, 5, 6, 7, 8, 9, 10) && Horizontal Top or Bottom m.lnLegendHeight = THIS.SideLegend._Height m.lnExternalMargin = THIS._LegendExternalMargin m.lnCount = ALEN(THIS._aSideLegends, 1) IF this.ChartType=17 m.lnCount = MIN(2,m.lnCount) ENDIF m.lnTopMargin = THIS.MarginTop + THIS.MARGIN + THIS._TitleHeight WITH _SCREEN.SYSTEM.Drawing * Check if we have enough space for legends m.lnAvailableHeight = THIS.ChartCanvas.HEIGHT - m.lnTopMargin - THIS.MARGIN m.lnNeededHeight = (m.lnCount * m.lnLegendHeight) + (THIS.MARGIN * m.lnCount - 1) IF m.lnNeededHeight > m.lnAvailableHeight * Recalculate the Margin m.lnMargin = (m.lnAvailableHeight - (m.lnCount * m.lnLegendHeight)) / m.lnCount ELSE m.lnMargin = 3 ENDIF STORE m.lnLegendHeight TO m.lnWidth, m.lnHeight m.lnLegendHeight = m.lnLegendHeight + MIN(m.lnMargin, m.lnLegendHeight / 2) m.lnVertHeight = m.lnCount * m.lnLegendHeight DO CASE CASE m.lnPosition = 1 && Vertical Top Left Side m.lnX1 = THIS.MARGIN + THIS.MarginLeft + m.lnExternalMargin m.lnY1 = m.lnTopMargin CASE m.lnPosition = 2 && Vertical Bottom Left Side m.lnX1 = THIS.MARGIN + THIS.MarginLeft + m.lnExternalMargin m.lnY1 = THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - THIS.MARGIN - m.lnVertHeight CASE m.lnPosition = 11 && Vertical Center Left Side m.lnX1 = THIS.MARGIN + THIS.MarginLeft + m.lnExternalMargin m.lnY1 = (THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin CASE m.lnPosition = 3 && Vertical Top Right Side (Default) m.lnX1 = THIS.ChartCanvas.WIDTH - THIS._RightOffset + m.lnExternalMargin + THIS._Axis2ScaleWidth m.lnY1 = m.lnTopMargin CASE m.lnPosition = 4 && Vertical Bottom Right Side (Default) m.lnX1 = THIS.ChartCanvas.WIDTH - THIS._RightOffset + m.lnExternalMargin + THIS._Axis2ScaleWidth m.lnY1 = THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - THIS.MARGIN - m.lnVertHeight CASE m.lnPosition = 12 && Vertical Center Right Side m.lnX1 = THIS.ChartCanvas.WIDTH - THIS._RightOffset + m.lnExternalMargin + THIS._Axis2ScaleWidth m.lnY1 = (THIS.ChartCanvas.HEIGHT - THIS.MarginBottom - m.lnTopMargin - m.lnVertHeight) / 2 + m.lnTopMargin CASE m.llHorizontal && Horizontal Top or Bottom * Calculate the whole legends width in order to obtain the starting point STORE 0 TO m.lnLength, m.lnStart * Obtain the needed width for the whole horizontal legend FOR m.lnChart = 1 TO m.lnCount THIS.SideLegend.CAPTION = THIS._aSideLegends(m.lnChart,1) m.lnLength = m.lnLength + m.lnWidth + 10 + THIS.SideLegend._Width NEXT DO CASE CASE INLIST(m.lnPosition, 5, 8) && Left aligned && do nothing CASE INLIST(m.lnPosition, 6, 9) && Center m.lnStart = THIS._LeftOffset + (THIS.ChartCanvas.WIDTH - THIS._LeftOffset - THIS._RightOffset - m.lnLength) / 2 CASE INLIST(m.lnPosition, 7, 10) && Right m.lnStart = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.lnLength ENDCASE m.lnX1 = THIS._LeftOffset + m.lnStart IF INLIST(m.lnPosition , 5, 6, 7) && Horizontal Top m.lnY1 = m.lnTopMargin + m.lnExternalMargin ELSE && Horizontal Bottom m.lnY1 = THIS.ChartCanvas.HEIGHT - THIS._LegendHeight - THIS.MARGIN - THIS.MarginBottom + THIS._LegendExternalMargin ENDIF ENDCASE LOCAL loLinePen AS xfcPen * Save the current _CharIndex m.lnOrigIndex = THIS._ChartIndex FOR m.lnChart = 1 TO m.lnCount IF m.lnY1 <= 0 EXIT ENDIF THIS._ChartIndex = m.lnChart m.lcCaption = THIS._aSideLegends(m.lnChart,1) IF EMPTY(m.lcCaption) LOOP ENDIF THIS.SideLegend.CAPTION = m.lcCaption THIS.SideLegend._DrawString(m.lnX1 + m.lnWidth + 3, m.lnY1) THIS._UpdateCoordinates(,"Legend", m.lnX1, m.lnY1, m.lnWidth + THIS.SideLegend._Width + 5, m.lnLegendHeight, m.lnChart, m.lcCaption) DO CASE CASE INLIST(THIS.ChartType, 5, 18) ; AND THIS._3D = 0 ; AND THIS.BrushType = 3 ; && Line, Plain, Monochrome AND NOT THIS.Multichart m.loLinePen = .PEN.New(THIS._oClrBlack, 3) m.loLinePen.DashStyle = m.lnChart - 1 && _Screen.System.Drawing.Drawing2D.DashStyle.Dash THIS.oGfx.DrawLine(m.loLinePen, m.lnX1, m.lnY1 + m.lnHeight / 2, m.lnX1 + m.lnWidth, m.lnY1 + m.lnHeight / 2) CASE (THIS.ChartType = 4 ; && Point OR (INLIST(THIS.ChartType, 5, 18) AND THIS._3D = 0 AND THIS.LineCaps)) ; && Plain line AND NOT THIS.Multichart LOCAL loPath AS xfcGraphicsPath m.loPath = THIS._aShapes(m.lnChart,1) IF VARTYPE(m.loPath) <> "O" RETURN ENDIF IF INLIST(LOWER(m.loPath.CLASS),"xfcbitmap", "xfcimage") THIS.oGfx.DrawImage(m.loPath, m.lnX1, m.lnY1, m.lnWidth, m.lnHeight) ELSE THIS._DrawShape(m.lnX1 + m.lnWidth / 2, m.lnY1 + m.lnHeight / 2, 0, "Legend") IF THIS._aShapes(m.lnChart,3) > m.lnLegendHeight m.lnLegendHeight = THIS._aShapes(m.lnChart,3) + 1 * m.lnY1 = m.lnY1 + This._aShapes(m.lnChart,3) + 3 ENDIF ENDIF OTHERWISE THIS._PrepareBrushes(m.lnX1, m.lnY1, m.lnWidth, m.lnHeight, .T., m.lnChart, .T.) && 7-th parameter. Avoid GradientShapeDirection>2. Yudin THIS.oGfx.FillRectangle(THIS._oMainBrush, m.lnX1, m.lnY1, m.lnWidth, m.lnHeight) THIS.oGfx.DrawRectangle(THIS._oBorderPen, m.lnX1, m.lnY1, m.lnWidth, m.lnHeight) ENDCASE IF m.llHorizontal && Horizontal side legends m.lnX1 = m.lnX1 + m.lnWidth + 10 + THIS.SideLegend._Width ELSE m.lnY1 = m.lnY1 + m.lnLegendHeight ENDIF NEXT * Restore the current _CharIndex THIS._ChartIndex = m.lnOrigIndex ENDWITH WITH THIS.SideLegend .TOP = m.lnTopMargin .LEFT = m.lnX1 .WIDTH = THIS._LegendWidth .HEIGHT = MAX(0, m.lnY1 - m.lnTopMargin) * Restore the alignment value to the original .ALIGNMENT = m.lnOrigAlignment ENDWITH THIS._InLegend = .F. ENDPROC PROCEDURE _drawslice LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnStart, tnSweep, tnNativeValue, toShape LOCAL llAdjLeft, llAdjRight, ln3D, lnFinalAngle, lnXBrush, lnYBrush IF m.tnWidth <=0 OR m.tnHeight <=0 RETURN ENDIF WITH THIS LOCAL loPen AS xfcPen, loGfx AS xfcGraphics, loMainBrush AS xfcBrush, lo3dBrush AS xfcBrush ._AdjustStartSweep(@tnStart, @tnSweep, m.tnWidth, m.tnHeight) toShape = ._UpdateCoordinates(toShape, "Pie", m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnNativeValue, m.tnStart, m.tnSweep) lcShapeName = TRANSFORM(toShape.CoordNum) IF .PieEnhancedDrawing lnXBrush = m.tnX lnYBrush = m.tnY ELSE lnXBrush = 0 lnYBrush = 0 ENDIF ._PrepareBrushes(lnXBrush, lnYBrush, m.tnWidth, m.tnHeight, .F., RECNO()) m.loPen = ._oBorderPen m.loGfx = .oGfx m.loMainBrush = ._oMainBrush lo3dBrush = ._o3DBrush lnFinalAngle = m.tnStart + m.tnSweep IF lnFinalAngle > 360 lnFinalAngle = lnFinalAngle - 360 ENDIF m.ln3D = ._3D ENDWITH WITH _SCREEN.SYSTEM.Drawing IF THIS.PieEnhancedDrawing * Draw the 3D Slice using the GraphicsPath class IF ln3D > 0 AND NOT THIS.SHADOW x = m.tnX Y = m.tnY w = m.tnWidth h = m.tnHeight * Draw the bottom slice m.loGfx.FillPie(m.loMainBrush, x, Y + m.ln3D, w, h, m.tnStart, m.tnSweep) m.loGfx.DrawPie(m.loPen, x, Y, w, h, m.tnStart, m.tnSweep) * Get the start point LOCAL loPath AS xfcGraphicsPath, loPoint1 AS xfcPoint, loPoint2 AS xfcPoint loPath = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New() loPath.AddPie(x,Y,w,h, m.tnStart, 0.0001) loPoint1 = loPath.GetLastpoint() loPath.AddPie(x,Y,w,h, m.tnStart, m.tnSweep) loPoint2 = loPath.GetLastpoint() * Draw side Polygon 1 LOCAL laPointsA(4), laPointsB(4), lnCenterX, lnCenterY lnCenterX = x + (w/2) lnCenterY = Y + (h/2) laPointsA(1) = .POINT.New(lnCenterX, lnCenterY) laPointsA(2) = .POINT.New(lnCenterX, lnCenterY + m.ln3D) laPointsA(3) = .POINT.New(loPoint1.x, loPoint1.Y + m.ln3D) laPointsA(4) = loPoint1 * Draw side Polygon 2 laPointsB(1) = laPointsA(1) laPointsB(2) = laPointsA(2) laPointsB(3) = .POINT.New(loPoint2.x, loPoint2.Y + m.ln3D) laPointsB(4) = loPoint2 IF m.tnStart <= 90 OR m.tnStart > 270 m.loGfx.DrawPolygon(m.loPen, @laPointsA) m.loGfx.FillPolygon(lo3dBrush, @laPointsA) ENDIF IF lnFinalAngle < 270 AND lnFinalAngle > 90 m.loGfx.FillPolygon(lo3dBrush, @laPointsB) m.loGfx.DrawPolygon(m.loPen, @laPointsB) ENDIF * Draw the external 3d Face LOCAL loPath2 AS xfcGraphicsPath loPath2 = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New() loPath2.FillMode = _SCREEN.SYSTEM.Drawing.Drawing2D.FillMode.winding loPath2.StartFigure() LOCAL lnAdjStart, lnAdjSweep lnAdjStart = m.tnStart lnAdjSweep = m.tnSweep IF m.tnStart >= 270 AND ; m.tnStart < 360 AND ; BETWEEN(lnFinalAngle, 0, 270) llAdjRight = .T. * Create a new partial path for the 1st part LOCAL loPath3 AS xfcGraphicsPath loPath3 = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New() loPath3.StartFigure() loPath3.AddArc(x,Y,w,h, m.tnStart, 360 - m.tnStart) loPath3.Reverse() loPath3.ADDLINE(loPoint1.x, loPoint1.Y, loPoint1.x, loPoint1.Y + m.ln3D) loPath3.AddArc(x,Y + m.ln3D, w, h, m.tnStart, 360 - m.tnStart) loPath3.ADDLINE(m.tnX + m.tnWidth, lnCenterY + m.ln3D, m.tnX + m.tnWidth, lnCenterY) THIS.FillPathDim(lo3dBrush, loPath3) m.loGfx.DrawPath(m.loPen, loPath3) loPoint1 = .POINT.New(m.tnX + m.tnWidth, lnCenterY) lnAdjStart = 0 lnAdjSweep = m.tnSweep - (360 - m.tnStart) ENDIF IF (m.tnStart < 180 AND lnFinalAngle > 180) OR ; (m.tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 270.01) * IF (m.tnStart < 180 AND lnFinalAngle > 180) OR ; (m.tnStart >= 270 AND lnFinalAngle > 180 AND lnFinalAngle < 269.9999) llAdjLeft = .T. * Create a new partial path for the 1st part LOCAL loPath4 AS xfcGraphicsPath loPath4 = _SCREEN.SYSTEM.Drawing.Drawing2D.GraPHICSPATH.New() loPath4.StartFigure() IF m.tnStart >= 270 lnAdjStart = 0 lnAdjSweep = 180 ELSE lnAdjStart = m.tnStart lnAdjSweep = 180 - m.tnStart ENDIF loPath4.AddArc(x,Y,w,h, lnAdjStart, lnAdjSweep) loPath4.Reverse() loPath4.ADDLINE(loPoint1.x, loPoint1.Y, loPoint1.x, loPoint1.Y + m.ln3D) loPath4.AddArc(x,Y + m.ln3D, w, h, lnAdjStart, lnAdjSweep) loPath4.ADDLINE(m.tnX, lnCenterY + m.ln3D, m.tnX, lnCenterY) THIS.FillPathDim(lo3dBrush, loPath4) m.loGfx.DrawPath(m.loPen, loPath4) loPoint1 = .POINT.New(m.tnX, lnCenterY) lnAdjStart = 180 lnAdjSweep = lnFinalAngle - 180 ENDIF loPath2.AddArc(x,Y,w,h, lnAdjStart, lnAdjSweep) loPath2.Reverse() loPath2.ADDLINE(loPoint1.x, loPoint1.Y, loPoint1.x, loPoint1.Y + m.ln3D) loPath2.AddArc(x,Y + m.ln3D, w, h, lnAdjStart, lnAdjSweep) loPath2.ADDLINE(loPoint2.x, loPoint2.Y + m.ln3D, loPoint2.x, loPoint2.Y) THIS.FillPathDim(lo3dBrush, loPath2) m.loGfx.DrawPath(m.loPen, loPath2) IF m.tnStart > 90 AND m.tnStart < 270 m.loGfx.DrawPolygon(m.loPen, @laPointsA) m.loGfx.FillPolygon(lo3dBrush, @laPointsA) ENDIF IF lnFinalAngle > 270 OR lnFinalAngle <= 90 m.loGfx.FillPolygon(lo3dBrush, @laPointsB) m.loGfx.DrawPolygon(m.loPen, @laPointsB) ENDIF * Draw the top slice m.loGfx.FillPie(m.loMainBrush, x, Y, w, h, m.tnStart, m.tnSweep) m.loGfx.DrawPie(m.loPen, x, Y, w, h, m.tnStart, m.tnSweep) ELSE * Draw shadow IF THIS.SHADOW LOCAL loShadowBrush AS xfcSolidBrush m.loShadowBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel,128,128,128)) m.loGfx.FillPie(loShadowBrush, m.tnX, m.tnY + ln3D, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) ENDIF * Draw the main slice m.loGfx.FillPie(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) m.loGfx.DrawPie(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) ENDIF ELSE *** This is the old behavior for Pie slices LOCAL loBmp AS xfcBitmap loBmp = poTempBmp LOCAL loTempGfx AS xfcGraphics loTempGfx = .Graphics.FromImage(loBmp) loTempGfx.CLEAR(.COLOR.Transparent) loTempGfx.SmoothingMode = .Drawing2D.SmoothingMode.AntiAlias * Draw the 3D Slice using the Hatch Brush IF ln3D > 0 LOCAL lnY1, N lnY1 = m.ln3D * Draw the contour of the 3D Slice loTempGfx.FillPie(m.loMainBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) loTempGfx.DrawPie(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) FOR N = 1 TO m.ln3D lnY1 = lnY1 - 1 * Draw the Normal Slice using the Solid Brush loTempGfx.FillPie(lo3dBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) && draw the slice IF m.tnStart > 90 loTempGfx.DrawArc(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, 0.25) ENDIF loTempGfx.DrawArc(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart + m.tnSweep - .25, 0.35) NEXT loTempGfx.FillPie(m.loMainBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) && draw the slice * Draw border line from center of pie LOCAL lnX, lnY lnX = (m.tnWidth / 2) lnY = (m.tnHeight / 2) + lnY1 IF m.tnStart > 90 loTempGfx.DrawLine(m.loPen, lnX, lnY, lnX, lnY + m.ln3D) ENDIF loTempGfx.DrawPie(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) loTempGfx.FillPie(m.loMainBrush, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) loTempGfx.DrawPie(m.loPen, 0, lnY1, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) * Draw the Image loBmp.ApplyColorMatrix(poClrMatrix) m.loGfx.DrawImage(loBmp, m.tnX, m.tnY) ELSE m.loGfx.FillPie(m.loMainBrush, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) m.loGfx.DrawPie(m.loPen, m.tnX, m.tnY, m.tnWidth, m.tnHeight, m.tnStart, m.tnSweep) ENDIF ENDIF ENDWITH ENDPROC PROCEDURE _drawstackedareachart * Generates Stacked and Full-Stacked area Charts (ChartTypes and 16) WITH THIS SELECT (._DataCursor ) LOCAL lnIndex, lnMargin, lnWidth, lnHeight, lnValue, lnRecs, lnBetween, lnRec, lnChartsCount,; lnLine, lnMaxValue, lnPointHeight, ln3D, lnYBase, lnTipPixels, lnX1, lnY1, lnTipPixels, llMultiChart llMultiChart = .F. lnTipPixels = ._TipPixels lnMargin = .MARGIN m.ln3D = ._3D lnRecs = RECCOUNT() lnChartsCount = .ChartsCount * Calculate the maximum width of the chart lnHeight = .ChartCanvas.HEIGHT - ._XAxisHeight - ._TopOffSet - ._3D m.lnWidth = .ChartCanvas.WIDTH - ._YAxisWidth - ._LeftOffset - ln3D - ._RightOffset IF m.lnWidth < 10 OR m.lnHeight < 10 OR lnRecs < 2 RETURN ENDIF LOCAL loGfx AS xfcGraphics m.loGfx = .oGfx * Get the maximum value of the chart lnMaxValue = ._ScaleRange * Get the lower Y point lnYBase = .ChartCanvas.HEIGHT - ._XAxisHeight * If MultiChart mode, the chart needs to start half a position further IF llMultiChart lnBetween = m.lnWidth / (lnRecs) ELSE lnBetween = m.lnWidth / (lnRecs - 1) ENDIF * Prepare array of points * All the main points will be defined here LOCAL laPointsX(lnRecs), laPointsY(lnRecs, lnChartsCount), laPointsYAV(lnRecs, lnChartsCount) ; , lnPrevPoint, lnTotRow, laValues(lnChartsCount) ; , laPointsI(lnRecs, lnChartsCount) && Points Index FOR .ROW = 1 TO RECCOUNT() lnRec = .Row lnPrevPoint = 0 lnX1 = ._YAxisWidth + (lnBetween * (lnRec - 1)) + IIF(llMultiChart, (lnBetween / 2), 0) + ._LeftOffset && lnMargin laPointsX(lnRec) = lnX1 ._aPoints(lnRec,1) = lnX1 + ln3D m.lnTotRow = 0 * Get the total for the current row FOR .COLUMN = 1 TO .ChartsCount .GetValue() laValues(.Column) =.Value m.lnTotRow = m.lnTotRow + .Value NEXT FOR .COLUMN = 1 TO .ChartsCount m.lnValue = laValues(THIS.COLUMN) ._ChartIndex = .Column IF .ChartType = 16 && Full-stacked Area lnPointHeight = IIF( EMPTY( m.lnTotRow ), 0, lnValue / m.lnTotRow * lnHeight) ELSE lnPointHeight = lnValue / lnMaxValue * lnHeight ENDIF lnY1 = lnYBase - (lnPointHeight + lnPrevPoint) laPointsY(lnRec, .Column) = lnY1 laPointsYAV(lnRec, .Column)= lnYBase - (lnPointHeight / 2 + lnPrevPoint) lnPrevPoint = lnPointHeight + lnPrevPoint IF lnValue = 0 ._UpdateCoordinates(,"Rect", 0, 0, 0, 0, lnValue, lnTotRow) ELSE ._UpdateCoordinates(,"Rect", lnX1 - lnTipPixels/2, lnY1, lnTipPixels, lnPointHeight, lnValue, lnTotRow) ENDIF laPointsI(lnRec,.Column) = ._nIndex NEXT NEXT * Draw the vertical line only for the first line ._DrawVerticalLineBack() LOCAL laMainPolygon(lnRecs * 2), laLinePolygon(4), laSidePolygon(4), lnCompl, loBrush AS xfcBrush m.loBrush = IIF( .BrushType = 1,"This._o3dbrush", "This._oMainBrush") ENDWITH WITH _SCREEN.SYSTEM.Drawing FOR THIS.COLUMN = 1 TO THIS.ChartsCount * Fill the main polygon FOR lnRec = 1 TO lnRecs lnCompl = (lnRecs * 2) - lnRec + 1 laMainPolygon(lnRec) = .POINT.New(laPointsX(lnRec), laPointsY(lnRec, THIS.Column)) IF THIS.Column = 1 laMainPolygon(lnCompl) = .POINT.New(laPointsX(lnRec), lnYBase) ELSE laMainPolygon(lnCompl) = .POINT.New(laPointsX(lnRec), laPointsY(lnRec, THIS.Column-1)) ENDIF NEXT THIS._PrepareBrushes(0,0,THIS.ChartCanvas.WIDTH, THIS.ChartCanvas.HEIGHT, .F., THIS.Column) m.loGfx.FillPolygon(THIS._oMainBrush, @laMainPolygon) m.loGfx.DrawPolygon(THIS._oBorderPen, @laMainPolygon) IF m.ln3D > 0 * Draw the 3D line above the main polygon FOR lnRec = 1 TO lnRecs - 1 laLinePolygon(1) = laMainPolygon(lnRec) laLinePolygon(2) = .POINT.New(laMainPolygon(lnRec).X + m.ln3D, laMainPolygon(lnRec).Y - m.ln3D) laLinePolygon(3) = .POINT.New(laMainPolygon(lnRec+1).X + m.ln3D, laMainPolygon(lnRec+1).Y - m.ln3D) laLinePolygon(4) = laMainPolygon(lnRec+1) THIS._PrepareBrushes(laMainPolygon(lnRec).X, laMainPolygon(lnRec).Y - m.ln3D, ; laMainPolygon(lnRec+1).X + m.ln3D - laMainPolygon(lnRec).X, ; MAX(2,ABS(laMainPolygon(lnRec).Y - laMainPolygon(lnRec+1).Y)), .F., THIS.Column) m.loGfx.FillPolygon(EVALUATE(m.loBrush), @laLinePolygon) m.loGfx.DrawPolygon(THIS._oBorderPen, @laLinePolygon) NEXT * Fill the right-most external side of the area * Draw the last 3D polygon, to fill the Area laSidePolygon(1) = laLinePolygon(3) laSidePolygon(2) = laLinePolygon(4) laSidePolygon(3) = laMainPolygon(lnRecs + 1) laSidePolygon(4) = .POINT.New(laSidePolygon(3).X + m.ln3D, laSidePolygon(3).Y - m.ln3D) THIS._PrepareBrushes(laSidePolygon(2).X, laSidePolygon(1).Y, ; m.ln3D, 2, .F., THIS.Column) m.loGfx.FillPolygon(EVALUATE(m.loBrush), @laSidePolygon) m.loGfx.DrawPolygon(THIS._oBorderPen, @laSidePolygon) ENDIF NEXT * Adjust _aPoints Array to show the information in the correct position FOR lnRec = 1 TO lnRecs THIS._aPoints(lnRec,1) = THIS._aPoints(lnRec,1) - ln3D NEXT IF THIS.ShowValuesOnShapes FOR lnLine = 1 TO lnChartsCount IF TYPE('THIS.FIELDS(lnLine).ShowValuesOnShape') = 'U' OR THIS.FIELDS(lnLine).ShowValuesOnShape *** Draw Legends above the points FOR lnRec = 1 TO lnRecs lnX1 = laPointsX(lnRec) lnY1 = laPointsYAV(lnRec, lnLine) lnIndex = laPointsI(lnRec,lnLine) THIS._DrawShapeLegend(lnX1, lnY1, lnIndex) NEXT ENDIF NEXT ENDIF THIS._DrawXAxisLegend() ENDWITH ENDPROC PROCEDURE _drawtrianglebar LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnValue, tn3D LOCAL loGfx AS xfcGraphics, loTopBrush AS xfcBrush, loBotBrush AS xfcBrush ; ,lnColor, ln3D, loPen AS xfcPen, lnAlpha, lnOrigAlpha, loShape m.loGfx = THIS.oGfx lnOrigAlpha = THIS.AlphaChannel lnAlpha = MIN(255, (THIS.AlphaChannel * 1.25)) THIS.AlphaChannel = lnAlpha THIS._PrepareBrushes(m.tnX, m.tnY, m.tnWidth, m.tnHeight, .F., IIF(THIS.SingleData, RECNO(),THIS._ChartIndex)) WITH _SCREEN.SYSTEM.Drawing m.lnColor = THIS.ChangeColor(THIS._nColor, + 60) m.loPen = .PEN.New(.COLOR.FromRGB(lnColor)) m.ln3D = MAX(IIF(VARTYPE(tn3D)='N',tn3D,THIS._3d), 1) DO CASE CASE THIS.BrushType = 1 && SolidColors loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loBotBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) loLeftBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(THIS._nColor, - 20))) loRightBrush = THIS._oMainBrush CASE THIS.BrushType = 2 && Gradient loTopBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS._nColor)) loBotBrush = loTopBrush loLeftBrush = loTopBrush loRightBrush = THIS._oMainBrush CASE THIS.BrushType = 4 && Треугольный столбик loTopBrush = THIS._o3DBrush loBotBrush = loTopBrush loLeftBrush = loTopBrush loRightBrush = THIS._oMainBrush OTHERWISE THIS._PrepareBrushes(tnX, tnY, tnWidth, tnHeight, .F., IIF(THIS.SingleData OR THIS.ChartsCount = 1, RECNO(),THIS._ChartIndex)) loTopBrush = THIS._oMainBrush loBotBrush = loTopBrush loLeftBrush = loTopBrush loRightBrush = THIS._oMainBrush ENDCASE THIS.AlphaChannel = lnOrigAlpha IF THIS._Orientation = 1 && Vertical LOCAL lnCenterX, x0, x1 x0 = tnX + m.ln3D / 2 x1 = x0 + tnWidth lnCenterX = x0 + (tnWidth / 2) * Prepare the bottom triangle LOCAL yBott yBott = tnY + tnHeight LOCAL laBotPoints(3), laLeftPoints(4) laBotPoints(1) = .POINT.New(lnCenterX, yBott) laBotPoints(2) = .POINT.New(x0, yBott - m.ln3D) laBotPoints(3) = .POINT.New(x1, yBott - m.ln3D) m.loGfx.FillPolygon(loBotBrush, @laBotPoints) m.loGfx.DrawPolygon(m.loPen, @laBotPoints) * Prepare the top triangle LOCAL laTopPoints(3) laTopPoints(1) = .POINT.New(lnCenterX, tnY) laTopPoints(2) = .POINT.New(x0, tnY - m.ln3D) laTopPoints(3) = .POINT.New(x1, tnY - m.ln3D) LOCAL loPath AS xfcGraphicsPath loPath = .Drawing2D.GraphicsPath.New() loPath.FillMode = .Drawing2D.FillMode.ALTERNATE loPath.StartFigure() loPath.ADDLINE(lnCenterX, tnY, x0, tnY - m.ln3D) loPath.ADDLINE(x0, tnY - m.ln3D, x1, tnY - m.ln3D) loPath.ADDLINE(x1, tnY - m.ln3D, lnCenterX, tnY) loTopBrush=_Screen.FoxChartsHelper.PathGradient( , m.loPath, THIS._nColor,-1, m.lnCenterX, tnY - m.ln3D/2,,,THIS.AlphaChannel) m.loGfx.FillPolygon(loTopBrush, @laTopPoints) m.loGfx.DrawPolygon(m.loPen, @laTopPoints) * Prepare the LEFT face of the 3d triangle (polygon) laLeftPoints(1) = laTopPoints(1) laLeftPoints(2) = laTopPoints(2) laLeftPoints(3) = laBotPoints(2) laLeftPoints(4) = laBotPoints(1) m.loGfx.DrawPolygon(m.loPen, @laLeftPoints) m.loGfx.FillPolygon(loLeftBrush, @laLeftPoints) * Prepare the RIGHT face of the 3d triangle (polygon) LOCAL laRightPoints(4) laRightPoints(1) = laTopPoints(1) laRightPoints(2) = laTopPoints(3) laRightPoints(3) = laBotPoints(3) laRightPoints(4) = laBotPoints(1) m.loGfx.DrawPolygon(m.loPen, @laRightPoints) m.loGfx.FillPolygon(loRightBrush, @laRightPoints) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints) ELSE && Horizontal LOCAL lnCenterY, y0, ln3D m.ln3D = MAX(THIS._3d, 1) x0 = tnX x1 = x0 + tnWidth lnCenterY = tnY + tnHeight / 2 TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT loShape = THIS._UpdateCoordinates(,"Rect", m.tnX + m.ln3D / 2, m.tnY, m.tnWidth, m.tnHeight, m.tnValue,,lcPoints) * Prepare the right (top) triangle LOCAL laRightPoints(3) laRightPoints(1) = .POINT.New(x1, lnCenterY) laRightPoints(2) = .POINT.New(x1 + ln3D, tnY) laRightPoints(3) = .POINT.New(x1 + ln3D, tnY + tnHeight) m.loGfx.DrawPolygon(m.loPen, @laRightPoints) m.loGfx.FillPolygon(loTopBrush, @laRightPoints) * Prepare the Left triangle LOCAL laLeftPoints(3) laLeftPoints(1) = .POINT.New(x0, lnCenterY) laLeftPoints(2) = .POINT.New(x0 + ln3D, tnY) laLeftPoints(3) = .POINT.New(x0 + ln3D, tnY + tnHeight) m.loGfx.DrawPolygon(m.loPen, @laLeftPoints) m.loGfx.FillPolygon(loBotBrush, @laLeftPoints) * Prepare the Top face of the 3d triangle (polygon) LOCAL laTopPoints(4) laTopPoints(1) = laLeftPoints(1) laTopPoints(2) = laLeftPoints(2) laTopPoints(3) = laRightPoints(2) laTopPoints(4) = laRightPoints(1) m.loGfx.DrawPolygon(m.loPen, @laTopPoints) m.loGfx.FillPolygon(loLeftBrush, @laTopPoints) * Prepare the BOTTOM face of the 3d triangle (polygon) LOCAL laBotPoints(4) laBotPoints(1) = laLeftPoints(1) laBotPoints(2) = laLeftPoints(3) laBotPoints(3) = laRightPoints(3) laBotPoints(4) = laRightPoints(1) m.loGfx.DrawPolygon(m.loPen, @laBotPoints) m.loGfx.FillPolygon(loRightBrush, @laBotPoints) ENDIF * Draw the Values inside the shapes THIS._DrawLegendinBar(x0, tnY, tnWidth, tnHeight, tnValue) ENDWITH ENDPROC PROCEDURE _drawyaxis LPARAMETERS tn3D, tnMinLeft, tnYAxisHeight, toBrush, toPen, tnIndex LOCAL lcPoints, ; ln3d, lnBottom, lnHeight, lnLeft, lnMaxValue, lnMinLeft, lnRight, lnScaleHeight, lnTop, lnX, lnX0, lnX1, lnXWidth, lnY, lnY0, lnY1, lnYAxisHeight, lnYaxisWidth, lnYaxisWidth2, ; loBrush, loGfx, loPen m.loBrush = m.toBrush m.loPen = m.toPen m.loGfx = THIS.oGfx m.lnMinLeft = m.tnMinLeft m.ln3d = m.tn3D m.lnYAxisHeight = m.tnYAxisHeight * DRAWING THE Y Axis m.lnY0 = ROUND(THIS.ChartCanvas.HEIGHT - THIS._XAxisHeight,0) m.lnY1 = ROUND(THIS._TopOffSet,0) IF m.lnY0 - m.lnY1 < m.ln3d RETURN ENDIF IF THIS.ShowAxis = .T. * Draw the main Y Axis caption IF tnIndex = 1 IF EMPTY(THIS.YAxis.CAPTION) THIS._yAxisWidth = 0 ELSE m.lnYaxisWidth = m.lnY0 - m.lnY1 IF m.lnYaxisWidth < 5 OR m.lnYAxisHeight < 5 RETURN ENDIF THIS._yAxisWidth = MAX(m.lnMinLeft, THIS.YAxis._Height + 3 + THIS._ScaleW) THIS.YAxis.ROTATION = 270 THIS.YAxis._DrawString(THIS._LeftOffset, m.lnY1 + m.lnYaxisWidth, m.lnYaxisWidth, m.lnYAxisHeight) lnLeft= INT(THIS._LeftOffset) DO CASE CASE THIS.YAxis.ALIGNMENT = 0 lnTop = INT(lnY1 + m.lnYaxisWidth - THIS.YAxis._Width) CASE THIS.YAxis.ALIGNMENT = 1 lnTop = INT(lnY1) OTHER lnTop = INT(lnY1 + (m.lnYaxisWidth - THIS.YAxis._Width)/2) ENDCASE lnRight = INT(lnLeft + THIS.YAxis._Height) lnBottom = INT(lnTop + THIS.YAxis._Width) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT THIS._UpdateCoordinates(,"YaxisCaption", lnLeft, lnTop, m.lnYAxisHeight, THIS.YAxis._Width, 0, THIS.YAxis.CAPTION, lcPoints) ENDIF ENDIF && tnIndex = 1 IF tnIndex = 2 IF EMPTY(THIS.YAxis2.CAPTION) THIS._yAxisWidth2 = 0 ELSE m.lnYaxisWidth2 = m.lnY0 - m.lnY1 IF m.lnYaxisWidth2 < 5 OR m.lnYAxisHeight < 5 RETURN ENDIF THIS.YAxis2.RESET() THIS._yAxisWidth2 = THIS.YAxis2._Height && + THIS._ScaleW THIS.YAxis2.ROTATION = 270 * Draw the main Y Axis2 caption LOCAL lcYText2 m.lcYText2 = THIS.YAxis2.CAPTION m.lnYAxisHeight = CEILING(THIS.YAxis2._Height) m.lnX0 = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.ln3d - m.lnYAxisHeight + THIS._ScaleW2 + 6 THIS.YAxis2._DrawString( m.lnX0, m.lnY1 + m.lnYaxisWidth2, m.lnYaxisWidth2, m.lnYAxisHeight) lnLeft= INT(lnX0) DO CASE CASE THIS.YAxis2.ALIGNMENT = 0 lnTop = INT(lnY1 + m.lnYaxisWidth2 - THIS.YAxis2._Width) CASE THIS.YAxis.ALIGNMENT = 1 lnTop = INT(lnY1) OTHER lnTop = INT(lnY1 + (m.lnYaxisWidth2 - THIS.YAxis2._Width)/2) ENDCASE lnRight = INT(lnLeft + THIS.YAxis2._Height) lnBottom = INT(lnTop + THIS.YAxis2._Width) TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT THIS._UpdateCoordinates(,"Yaxis2Caption", lnLeft, lnTop, m.lnYAxisHeight, THIS.YAxis._Width, 0, THIS.YAxis.CAPTION, lcPoints) ENDIF ENDIF && tnIndex = 2 m.lnMaxValue = THIS._ScaleRange WITH _SCREEN.SYSTEM.Drawing * Draw the Y Axis IF m.tnIndex = 2 m.lnX0 = THIS.ChartCanvas.WIDTH - THIS._RightOffset - m.ln3d + 2 - THIS._yAxisWidth2 ELSE m.lnX0 = THIS._yAxisWidth + THIS._LeftOffset ENDIF m.lnX1 = m.lnX0 + m.ln3d + THIS._ScaleW IF m.ln3d = 0 m.loGfx.DrawLine(m.loPen, m.lnX0 - 1, m.lnY0, m.lnX0 - 1, m.lnY1) ELSE LOCAL laPoints(4) m.laPoints(1) = .POINT.New(m.lnX0, m.lnY0) m.laPoints(2) = .POINT.New(m.lnX0, THIS._TopOffSet + m.ln3d) m.laPoints(3) = .POINT.New(m.lnX0 + m.ln3d, THIS._TopOffSet) m.laPoints(4) = .POINT.New(m.lnX0 + m.ln3d, m.lnY0 - m.ln3d) m.loGfx.FillPolygon(m.loBrush, @m.laPoints) m.loGfx.DrawPolygon(m.loPen, @m.laPoints) LOCAL laPointsB(6) m.laPointsB(1) = .POINT.New(m.lnX0, m.lnY0 + 4) m.laPointsB(2) = .POINT.New(m.lnX0 - 4, m.lnY0 + 4) m.laPointsB(3) = .POINT.New(m.lnX0 - 4, THIS._TopOffSet + m.ln3d) m.laPointsB(4) = .POINT.New(m.lnX0 - 4 + m.ln3d, THIS._TopOffSet) m.laPointsB(5) = .POINT.New(m.lnX0 + m.ln3d, THIS._TopOffSet) m.laPointsB(6) = .POINT.New(m.lnX0, THIS._TopOffSet + m.ln3d) m.loGfx.FillPolygon(m.loBrush, @m.laPointsB) m.loGfx.DrawPolygon(m.loPen, @m.laPointsB) TEXT to lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT THIS._UpdateCoordinates (, IIF(m.tnIndex=2,'RightSide','LeftSide'), lnx0, lny0, This._TopOffSet + m.ln3D, m.ln3D, '', 0, lcPoints, 0) ENDIF IF NOT EMPTY(THIS.BackImage) AND FILE(THIS.BackImage) m.lnHeight = THIS.HEIGHT - THIS._XAxisHeight - THIS._TopOffSet - m.ln3d lnXWidth = THIS.WIDTH - THIS._LeftOffset - THIS._RightOffset - THIS._yAxisWidth - m.ln3d lnScaleHeight = (THIS.GetScaleValue (0)- THIS._MinScale) / m.lnMaxValue * lnHeight lnY = THIS.HEIGHT - lnScaleHeight - THIS._XAxisHeight - m.ln3d lnX = THIS._yAxisWidth + THIS._LeftOffset + m.ln3d THIS.oGfx.DrawImage(_SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(FILETOSTR(FULLPATH(THIS.BackImage))), lnX, lnY, lnXWidth, m.lnHeight) ENDIF ENDWITH ENDIF ENDPROC PROCEDURE _getchartprop LPARAMETERS toPropertiesList, tcProperty, tnType, toSavedProps, lcDescription, tlShowDescriptions LOCAL lcCRLF lcCRLF = CHR(13) LOCAL lbChanged, lcNewType, lcOldType, lnBlue, lnDope, lnGreen, lnPos, lnRed DO CASE CASE tnType = 1 lbChanged = .T. CASE tnType = 2 IF "." $ tcProperty lnPos = RAT (".", tcProperty) lbChanged = PEMSTATUS ( EVALUATE ("This." + LEFT(tcProperty, lnPos - 1)), SUBSTR(tcProperty, lnPos + 1), 0) ELSE lbChanged = PEMSTATUS(THIS, tcProperty, 5) AND PEMSTATUS(THIS, tcProperty, 0) * lbChanged = Pemstatus (This, tcProperty, 0) ENDIF CASE tnType = 3 lcNewType = TYPE("toPropertiesList." + tcProperty) lcOldType = TYPE("toSavedProps." + tcProperty) lbChanged = (lcNewType # lcOldType) OR NOT ; EVALUATE("toPropertiesList." + tcProperty) == EVALUATE("toSavedProps." + tcProperty) ENDCASE IF NOT lbChanged RETURN '' ENDIF m.lcName = TRIM(tcProperty) m.lxValue = EVALUATE ("toPropertiesList." + tcProperty) m.lcType = VARTYPE (lxValue) DO CASE CASE m.lcType = 'C' m.lxValue = TRIM(lxValue) DO CASE CASE NOT ['] $ m.lxValue m.lcValue = ['] + m.lxValue + ['] CASE NOT ["] $ lxValue m.lcValue = ["] + m.lxValue + ["] OTHERWISE m.lcValue = '[' + m.lxValue + ']' ENDCASE IF CHR(13)+CHR(10) $ lcValue lcapostrophe1 = LEFT(lcValue,1) lcapostrophe2 = RIGHT(lcValue,1) m.lcValue = STRTRAN(m.lcValue, CHR(13)+CHR(10),[<>]+ lcapostrophe2+'+ ;'+CHR(13)+CHR(10)+lcapostrophe1) ENDIF CASE m.lcType = "O" m.lcValue = " " + CHR(38) + CHR(38) + "Custom object - " + m.lxValue.NAME RETURN "* ." + m.lcName + " = " + m.lcValue + lcCRLF CASE m.lcType = "N" LOCAL lcUpName lcUpName = UPPER(lcName) lnDope = AT('***', lcDescription) IF INLIST(ALLTRIM(RIGHT('.' + lcUpName,10)), ; '.FORECOLOR', '.BACKCOLOR') OR ; ('BACKCOLOR2' $ lcUpName) OR ; (').COLOR' $ lcUpName) OR ; (lnDope > 0 AND "COLOR" == UPPER(ALLTRIM(SUBSTR(lcDescription, lnDope + 3)))) lnRed = BITAND(lxValue, 255) lnGreen = BITRSHIFT(BITAND(lxValue, 256 * 255), 8) lnBlue = BITRSHIFT(BITAND(lxValue, 256 * 256 * 255), 16) m.lcValue = 'RGB(' + TRANSFORM(lnRed) + ',' + TRANSFORM(lnGreen) + ',' + TRANSFORM(lnBlue) + ')' ELSE m.lcValue = TRANSFORM(m.lxValue) ENDIF OTHERWISE m.lcValue = TRANSFORM(m.lxValue) ENDCASE RETURN IIF (EMPTY (lcDescription) OR NOT tlShowDescriptions, '', '* ' + lcDescription + lcCRLF) + "." + m.lcName + " = " + m.lcValue + lcCRLF ENDPROC PROCEDURE _getchartproperties **************************************************************** * Jim Nelson 10/20/2008 * * Returns an object with current settings of all FoxCharts properties Local loProperties Local laProperties(1), laSubProperties(1), lcProperty Local lcProperties, lcName, lcType, loObject, lnI, lnJ, laFieldMembers(1), lcFieldMem, loData Local luPropValue, lcPropType Local loFields as "Collection" m.loProperties = Createobject("Empty") m.lcProperties = "Format, FontName, FontSize, FontBold, FontItalic, FontUnderline, FontCharSet, ForeColor, ForeColorAlpha, BackColor, BackColorAlpha, Alignment, Rotation, RotationCenter" Alines (laSubProperties, m.lcProperties, 5, ',') With This Local laProperties(1), lcProperty Amembers(m.laProperties, This, 3) AddProperty (m.loProperties, "_Descriptions(1)", m.laProperties) Acopy(m.laProperties, m.loProperties._Descriptions) For m.lnI = 1 To Alen (m.laProperties,1) m.lcName = Proper(m.laProperties(m.lnI,1)) m.lcType = Proper(m.laProperties(m.lnI,2)) IF EMPTY(.ReadOnlyProps) TEXT to .ReadOnlyProps ,ACOLORS,ALTERED,APALETTECOLORS,CHARTSUM,CHARTTYPE1,COLOR1,COLUMN,CURRCOLUMN,CURRRECNO,CURRINDEX,CURRVALUE,CURRLEGEND,CURROBJTYPE,FIELDVALUE1,FIELDXAXIS,CONTOURGRAPHICS,CONTOURPEN,INVISIBLESHAPES,LCPALETTES,LEGEND1,MINVALUE,OBMP,OGFX,OLDMOUSEINDEX,PICTURETOSAVE,READONLYPROPS,ROW,ROWCOLPROPS,SINGLEDATA,SHAPE1,VALUE,VERSION,WIDTH,HEIGHT,SLEEP ENDTEXT ENDIF Do Case CASE lcType = 'Property' ; && ReadOnly properties AND NOT ','+UPPER (m.lcName)+',' $ .ReadOnlyProps ; AND "_" # LEFT(m.lcName, 1) AND "On_" # LEFT(m.lcName, 3) ; AND (PEMSTATUS(THIS, m.lcName, 4) OR ; INLIST( UPPER(lcName), 'BACKCOLOR', 'FORECOLOR', 'MARGIN', 'SHOWTIPS', 'WIDTH', 'HEIGHT')) ADDPROPERTY (loProperties, lcName, EVALUATE ("This." + lcName)) Case m.lcName = 'Fields' m.loFields = Createobject("Collection") For m.lnJ = 1 To This.Fields.Count m.loData = Createobject("Empty") Amembers(laFieldMembers, This.Fields(m.lnJ)) For Each m.lcFieldMem In m.laFieldMembers m.luPropValue = Evaluate("This.Fields(lnJ)." + m.lcFieldMem) m.lcPropType = VARTYPE(m.luPropValue) IF (m.lcFieldMem = "CHARTTYPE" AND m.lcPropType = "N" AND m.luPropValue = 0) OR ; (m.lcFieldMem = "SHOWVALUESONSHAPE" AND m.lcPropType = "L" AND m.luPropValue = .T.) OR ; (m.lcFieldMem = "SHAPE" AND m.lcPropType = "N" AND m.luPropValue = 0) LOOP ENDIF AddProperty(m.loData, m.lcFieldMem, m.luPropValue) Endfor m.loFields.Add(m.loData) Next m.lnJ AddProperty (m.loProperties, m.lcName, m.loFields) CASE lcType = 'Object' ; AND INLIST (lcName, "Title", "Subtitle", "Xaxis", "Axislegend2", "Yaxis", "Shapelegend", "Scalelegend", "Sidelegend", "Deltalegend", "Yaxis2", "CommentsSet") * create an object AddProperty (m.loProperties, m.lcName, Createobject("Empty")) m.loObject = Evaluate ("loProperties." + m.lcName) * conditionally add caption If Not Inlist (m.lcName, "Axislegend2", "Shapelegend", "Scalelegend", "Sidelegend") AddProperty (m.loObject, "Caption", Evaluate ("This." + m.lcName + ".Caption")) Endif * and add other properties of that object IF INLIST (lcName,"CommentsSet") MESSAGEBOX(loObject.Name) endi For Each m.lcProperty In m.laSubProperties AddProperty (m.loObject, m.lcProperty, Evaluate ("This." + m.lcName + "." + m.lcProperty)) Endfor Endcase Endfor Endwith Return m.loProperties ENDPROC PROCEDURE _newfield LOCAL loData m.loData = CREATEOBJECT("Empty") ADDPROPERTY(m.loData,"ChartType",0) ADDPROPERTY(m.loData,"FieldValue","") ADDPROPERTY(m.loData,"Legend","") ADDPROPERTY(m.loData,"Color",0) ADDPROPERTY(m.loData,"Shape",0) ADDPROPERTY(m.loData,"ShowValuesOnShape",.T.) ADDPROPERTY(m.loData,"AxisIndex",1) ADDPROPERTY(m.loData,"BarType",-1) RETURN m.loData ENDPROC PROCEDURE _preparebrushes LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlRect, tnCount, llFromLegend LOCAL lnShape AS NUMBER EXTERNAL ARRAY XFCGDIPROTATETEXTURETRANSFORM, xfcGdipSetPathGradientSurroundColorsWithCount IF VARTYPE(m.tnCount) = "L" m.tnCount = 1 ENDIF IF PCOUNT() = 0 m.tnX = 0 m.tnY = 0 m.tnWidth = THIS.ChartCanvas.WIDTH m.tnHeight = THIS.ChartCanvas.HEIGHT ENDIF m.tnWidth = MAX(1,m.tnWidth) m.tnHeight = MAX(1,m.tnHeight) LOCAL lnBrushType, lnMainColor, lnGradientPosition m.lnBrushType = THIS.BrushType m.lnMainColor = THIS.aColors(m.tnCount) IF VARTYPE(m.lnMainColor) <> "N" m.lnMainColor = THIS._GetRandomColor() ENDIF THIS._nColor = m.lnMainColor lnGradientPosition=MAX(0.05,MIN(0.95,THIS.GradientPosition)) WITH _SCREEN.SYSTEM.Drawing IF THIS.BrushType = 3 && Monochrome THIS._oBorderPen = .PEN.New(THIS._oClrBlack) ELSE LOCAL lnColor m.lnColor = THIS.ChangeColor(m.lnMainColor, +30) THIS._oBorderPen = .PEN.New(.COLOR.FromRGB(m.lnColor)) * Check if we are drawing on the selected shape IF NOT THIS._InLegend AND THIS.ChangeColoronMouse AND ; THIS._GeneralType <> "Point" LOCAL m.lnShape m.lnShape = THIS._nMouseOnShape IF m.lnShape > 0 AND THIS._nMouseOnShape = THIS._nIndex m.lnMainColor = THIS.SelectedShapeColor ENDIF ENDIF ENDIF DO CASE CASE m.lnBrushType = 1 && Solid Brush THIS._oMainBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, m.lnMainColor)) THIS._o3DBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, - 20))) THIS._oRightbrush=THIS._o3DBrush CASE m.lnBrushType = 2 && Gradient Path Brush LOCAL loColor1 AS xfcColor m.loColor1 = .COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, - 10)) LOCAL loColor2 AS xfcColor m.loColor2 = .COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, THIS.GradientLevel * 10)) IF THIS.GradientInvertColors LOCAL loTmpColor AS xfcColor m.loTmpColor = m.loColor2 m.loColor2 = m.loColor1 m.loColor1 = m.loTmpColor ENDIF DO CASE CASE THIS._GeneralType = "Pie" AND NOT m.tlRect && Pie or Donut Chart and still not at legend LOCAL loPath AS xfcGraphicsPath m.loPath = .Drawing2D.GraphicsPath.New() m.loPath.AddEllipse(m.tnX, m.tnY, m.tnWidth, m.tnHeight) LOCAL loPathGradBrush AS xfcPathGradientBrush m.loPathGradBrush = .Drawing2D.PathGradientBrush.New(m.loPath) m.loPathGradBrush.CenterColor = m.loColor2 IF THIS.PieGradCenterDistance > 0 LOCAL loCenterPt AS xfcPointF m.loCenterPt = THIS._GetCenterPoint(m.tnX, m.tnY, m.tnWidth, m.tnHeight) * Set the center using direct API call because the original funciorn has bugs * When fixed, the line below should work instead: * m.loPathGradBrush.CenterPoint = m.loCenterPt =xfcGdipSetPathGradientCenterPoint(m.loPathGradBrush.Handle, m.loCenterPt.ToVarBinary()) ENDIF * Not working on version 1.20 official * loPathGradBrush.SurroundColors[1] = loColor1 * loPathGradBrush.SurroundColors = loColor1 * Workaround using direct API call to assign the surround colors LOCAL lqColors m.lqColors = BINTOC(m.loColor1.ARGB,"4rs") =xfcGdipSetPathGradientSurroundColorsWithCount(m.loPathGradBrush.Handle, @m.lqColors, 1) IF THIS.GradientType = 0 && SigmaBell m.loPathGradBrush.SetSigmaBellShape(lnGradientPosition, 1.0) ELSE && BlendTriangularShape m.loPathGradBrush.SetBlendTriangularShape(lnGradientPosition, 1.0) ENDIF THIS._oMainBrush = m.loPathGradBrush CASE THIS._GeneralType = "Bar" OR tlRect && Bar Chart lnGradientShapeDirection = EVL(THIS.GradientShapeDirection, 0) lnGradientHorcount = THIS.GradientHorcount && 2 lnGradientVertcount = THIS.GradientVertcount && 3 IF llFromLegend lnGradientShapeDirection = MIN(1,MAX(0,lnGradientShapeDirection)) ELSE m.lnGradientShapeDirection = MIN(3,MAX(0,m.lnGradientShapeDirection)) ENDIF m.tnWidth = MAX(1, m.tnWidth/lnGradientVertcount) m.tnHeight = MAX(1, m.tnHeight/lnGradientHorcount) LOCAL loLinGradBrush AS xfcLinearGradientBrush loLinGradBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(m.tnX, m.tnY, m.tnWidth, m.tnHeight), ; loColor1, loColor2, lnGradientShapeDirection) IF THIS.GradientType = 0 && SigmaBell loLinGradBrush.SetSigmaBellShape(lnGradientPosition, 1) ELSE && BlendTriangularShape loLinGradBrush.SetBlendTriangularShape(lnGradientPosition, 1.0) ENDIF THIS._oMainBrush = loLinGradBrush CASE THIS._GeneralType = "Point" && Line, Point or Area Chart m.loColor2 = .COLOR.FromRGB(THIS.ChangeColor(m.lnMainColor, THIS.GradientLevel * 8)) LOCAL loLinGradBrush AS xfcLinearGradientBrush m.loLinGradBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(m.tnX, m.tnY, m.tnWidth, m.tnHeight), ; m.loColor1, m.loColor2, THIS.GradientShapeDirection) IF THIS.GradientType = 0 && SigmaBell m.loLinGradBrush.SetSigmaBellShape(lnGradientPosition, 1) ELSE && BlendTriangularShape m.loLinGradBrush.SetBlendTriangularShape(lnGradientPosition, 1.0) ENDIF THIS._oMainBrush = m.loLinGradBrush ENDCASE THIS._o3DBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, - 15))) THIS._oRightbrush=THIS._o3DBrush CASE INLIST( m.lnBrushType, 3, 5) && HatchBrush: 3-monochrome, 5 - color LOCAL lnHatchBrushValue IF THIS.ChartsCount > 1 AND NOT THIS.SingleData && Pie, Bar or Donut m.lnHatchBrushValue = 4 + m.tnCount * 2 ELSE m.lnHatchBrushValue = IIF(m.lnBrushType=3,lnMainColor * 2, 6) ENDIF THIS._oMainBrush = .Drawing2D.HatchBrush.New( m.lnHatchBrushValue, ; && HatchStyle THIS._oClrBlack, ; && ForeColor IIF(m.lnBrushType=3,THIS._oClrWhite,.COLOR.FromARGB(THIS.AlphaChannel, m.lnMainColor)) ) && BackColor THIS._o3DBrush = .Drawing2D.HatchBrush.New( m.lnHatchBrushValue , ; && HatchStyle IIF(m.lnBrushType=3,.COLOR.Gray, .COLOR.FromRGB(m.lnMainColor )), ; && ForeColor .COLOR.LightGray) && BackColor THIS._oRightbrush=THIS._oMainBrush CASE m.lnBrushType = 4 && TextureBrush m.lcTextureTheme = THIS.Texturetheme LOCAL lcFile lcFile = THIS.GetTexture (m.lcTextureTheme,m.tnCount) IF EMPTY(lcFile) THIS._oMainBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, m.lnMainColor)) THIS._o3DBrush = .SolidBrush.New(.COLOR.FromARGB(THIS.AlphaChannel, THIS.ChangeColor(m.lnMainColor, - 20))) THIS._oRightbrush = THIS._o3DBrush ELSE THIS._oDimBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(m.tnX, m.tnY, m.tnWidth+THIS._3d, m.tnHeight), ; .COLOR.FromARGB(THIS.AlphaChannel/2,.COLOR.White), ; .COLOR.FromARGB(THIS.AlphaChannel/2,.COLOR.Black), ; 0) THIS._oDimBrush.SetSigmaBellShape(lnGradientPosition, 1) loBmp = .BITMAP.FromVarbinary(FILETOSTR(lcFile)) THIS._oMainBrush = .TextureBrush.New(loBmp) THIS._o3DBrush = .TextureBrush.New(loBmp) THIS._o3DBrush.WrapMode = .Drawing2D.WrapMode.TileFlipX XFCGDIPROTATETEXTURETRANSFORM(THIS._o3DBrush.Handle, -45, _SCREEN.SYSTEM.Drawing.Drawing2D.MatrixOrder.APPEND) THIS._oRightbrush = .TextureBrush.New(loBmp) =xfcGdipRotateTextureTransform(THIS._oRightbrush.Handle, 45, _SCREEN.SYSTEM.Drawing.Drawing2D.MatrixOrder.APPEND) ENDIF ENDCASE ENDWITH ENDPROC PROCEDURE _preparecolors * * Grigory Meriam (Aviv Advanced Solutions Ltd.) * Here I put code sent by Grigory Meriam. * Gradient colors depend on values. * You can see it for m.lnColorType = 3 and ChartType=7 * SELECT(THIS._DataCursor) LOCAL lnColorType, N , m.nIndex m.lnColorType = THIS.ColorType IF NOT THIS.SingleData LOCAL lnColor, lcIndex DIMENSION THIS.aColors(THIS.ChartsCount) FOR m.N = 1 TO THIS.ChartsCount m.lcIndex = THIS._Str(m.N) DO CASE CASE THIS.BrushType = 3 && Monochrome m.lnColor = 0 CASE m.lnColorType = 0 && Basic Colors m.lnColor = THIS._GetBasicColor(m.N) CASE m.lnColorType = 1 && Custom m.lnColor = THIS.FIELDS(m.N).COLOR IF VARTYPE(m.lnColor) <> "N" m.lnColor = THIS._GetRandomColor() ENDIF * CASE m.lnColorType = 2 AND This._UpdateRandomColors && Random CASE m.lnColorType = 2 AND ; (THIS._UpdateRandomColors OR VARTYPE(THIS.aColors(m.N)) = "L") && Random or not initialized m.lnColor = THIS._GetRandomColor() CASE m.lnColorType = 2 AND NOT THIS._UpdateRandomColors && Random RETURN && Keep the current color CASE m.lnColorType = 3 && Gradient m.lnColor = THIS._GetGradientColor(m.N) CASE m.lnColorType >= 4 m.lnColor = THIS._GetPaletteColor(lnColorType - 4, m.N) ENDCASE THIS.aColors(m.N) = m.lnColor ENDFOR ELSE IF THIS.charttype = 7 IF m.lnColorType = 3 AND THIS.BrushType != 3 && Gradient SELECT RECNO() AS nn ; FROM (THIS._DataCursor) ; ORDER BY Nvalue1 DESC ; INTO CURSOR curPrepareColors SELECT curPrepareColors ENDIF ENDIF DIMENSION THIS.aColors(THIS._nRecords) SCAN IF USED('curPrepareColors') m.nIndex = INT(curPrepareColors.nn) ELSE m.nIndex = RECNO() ENDIF m.N = RECNO() DO CASE CASE THIS.BrushType = 3 && Monochrome m.lnColor = m.N CASE m.lnColorType = 0 && Basic Colors m.lnColor = THIS._GetBasicColor(m.N) * CASE m.lnColorType = 2 AND This._UpdateRandomColors && Random CASE m.lnColorType = 2 AND ; (THIS._UpdateRandomColors OR VARTYPE(THIS.aColors(m.N)) = "L") && Random or not initialized m.lnColor = THIS._GetRandomColor() CASE m.lnColorType = 2 AND NOT THIS._UpdateRandomColors && Random RETURN CASE m.lnColorType = 3 && Gradient m.lnColor = THIS._GetGradientColor(m.N) CASE m.lnColorType = 1 AND NOT EMPTY(THIS.FieldColor) && Custom m.lnColor = nColor && Retrieve color from Field CASE m.lnColorType = 1 AND EMPTY(THIS.FieldColor) && Custom IF THIS._UpdateRandomColors m.lnColor = THIS._GetRandomColor() ELSE && no need to update, keep using the same prev color RETURN ENDIF CASE m.lnColorType >= 4 m.lnColor = THIS._GetPaletteColor(lnColorType - 4, m.N) OTHERWISE && Custom color and not Line or Area chart ENDCASE THIS.aColors(m.nIndex) = m.lnColor ENDSCAN IF USED('curPrepareColors') USE IN SELECT ('curPrepareColors') SELECT(THIS._DataCursor) ENDIF ENDIF THIS._UpdateRandomColors = .F. ENDPROC PROCEDURE _preparedata WITH THIS * Comments IF TYPE('.CommentsSet')='U' .ADDOBJECT('CommentsSet','FoxChartsBeta.fields') TEXT TO lcFieldsDesc Left,N Top,N Caption,C FontName,C,ARIAL FontSize,I,<<.Comments.FontSize>> FontBold,L,<<.Comments.FontBold>> FontUnderLine,L FontItalic,L ForeColor,I,<<.Comments.ForeColor>> BackColor,I,<<.Comments.BackColor>> ForeColorAlpha,I,255 BackColorAlpha,I,128 Rotation,I,0 GradientLevel,I,5 Alignment,I,0 Type,I,1 PointerSide,I,0 PointerSubSide,I,1 PointerWidth,N,10 ENDTEXT .CommentsSet.DESC = lcFieldsDesc ENDIF lnLines = IIF(EMPTY(.CommentsSetPack),0,ALINES(la,.CommentsSetPack)) .CommentsSet.SetCount(lnLines) .CommentsSet.UNPACK(.CommentsSetPack) ENDWITH DODEFAULT() ENDPROC PROCEDURE _preparetitle WITH _SCREEN.SYSTEM.Drawing LOCAL lcPoint, lnTitleHeight, lnSubtitleHeight, lnTitleColor, lnLeft STORE 0 TO lnTitleHeight, lnSubtitleHeight * Check if Title was assigned IF NOT EMPTY(This.Title.Caption) This.Title.Reset() lnTop = This.Margin + This.MarginTop This.Title._DrawString(0, This.Margin + This.MarginTop, This.ChartCanvas.Width, This.ChartCanvas.Height) lnTitleHeight = This.Title._height lnLeft = ICASE(This.Title.Alignment = 0,0,This.Title.Alignment =1,This.ChartCanvas.Width -This.Title._Width,(This.ChartCanvas.Width - This.Title._Width)/2) TEXT TO lcPoint <>,<> <>,<> <>,<> <>,<> ENDTEXT This._UpdateCoordinates(,"Title", lnLeft, This.Title.Top, This.Title._Width, lnTitleHeight, 0, This.Title.Caption, lcPoint) ENDIF * Check if Subtitle was assigned IF NOT EMPTY(This.Subtitle.Caption) This.Subtitle.Reset() lnTop = This.Margin + This.MarginTop + lnTitleHeight This.Subtitle._DrawString(0, lnTop, This.ChartCanvas.Width, This.ChartCanvas.Height) lnSubtitleHeight = This.Subtitle._Height lnLeft = ICASE(This.SubTitle.Alignment = 0,0,This.SubTitle.Alignment =1,This.ChartCanvas.Width -This.SubTitle._Width,(This.ChartCanvas.Width - This.SubTitle._Width)/2) TEXT TO lcPoint <>,<> <>,<> <>,<> <>,<> ENDTEXT This._UpdateCoordinates(,"Subtitle", lnLeft, lnTop, This.Subtitle._Width, lnSubtitleHeight, 0, This.Subtitle.Caption, lcPoint) ENDIF This._TitleHeight = lnTitleHeight + lnSubtitleHeight ENDWITH ENDPROC PROCEDURE _updatecoordinates LPARAMETERS loShape, tcObjType, tnX, tnY, tnWidth, tnHeight, tnValue, tnStart, tnSweep, lnColor, tcFront, tnIndex LOCAL lcFourthDimensionLegend, lcLegend, lcObjectName, ; lnFourthIndex, lnLine, lnRow, ; loObject WITH THIS * During DrawReport(), there's no need to update the coordinates SELECT (._DataCursor) m.lcLegend=.F. ._nIndex = ._nIndex + 1 DO CASE CASE tcObjType = "Legend" lcLegend = IIF(VARTYPE(m.tnStart) = "C", m.tnStart, "") CASE tcObjType $ 'Title,Subtitle,YaxisCaption,LeftSide,BottomSide' OTHERWISE IF .SingleData OR .ChartsCount = 1 m.lcLegend = cLegend ELSE IF BETWEEN(._ChartIndex,1,.ChartsCount) m.lcLegend = .FIELDS(._ChartIndex).Legend ELSE m.lcLegend = '' ENDIF ENDIF ENDCASE IF VARTYPE(loShape) # 'O' lnIndex = IIF(EMPTY(tnIndex),.Shapes.OBJECTS.COUNT+1,tnIndex) lcObjectName='Shape'+ALLTRIM(STR(lnIndex)) IF TYPE('.Shapes.'+lcObjectName) = 'U' .Shapes.ADDOBJECT(lcObjectName,[FoxChartsBeta.Figure]) ENDIF loShape = EVALUATE('THIS.Shapes.' + lcObjectName) ENDIF ENDWITH WITH loShape .TYPE = m.tcObjType .LEFT = ROUND(m.tnX,0) .TOP = ROUND(m.tnY,0) .WIDTH = ROUND(m.tnWidth,0) .HEIGHT = ROUND(m.tnHeight,0) .VALUE = EVL(m.tnValue,0) .START = m.tnStart .Sweep = m.tnSweep .Contour = m.tnSweep .Front = tcFront .ChartIndex = THIS._ChartIndex && ChartRow .Currentrow = EVL(THIS._Currentrow, IIF(tcObjType = "Legend", tnValue, RECNO((This._DataCursor)))) && on "Legend" mode, tnValue passes the index .Legend = m.lcLegend .COLOR = EVL(lnColor,THIS._nColor) .CoordNum = VAL(SUBSTR(.NAME,6)) .RowSum = IIF(m.tcObjType = "Rect", EVL(tnStart,0), 0) && Sum of the current row ENDWITH RETURN loShape ENDPROC PROCEDURE AxisLegend2._drawstring LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor LOCAL x1, y1, lnAlign, lnMode, xBack lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates lnAlign = THIS.ALIGNMENT * 0 = Left 1 = Right 2 = Center LOCAL loGfx AS xfcGraphics loGfx = THIS.PARENT.oGfx lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR) WITH _SCREEN.SYSTEM.Drawing DO CASE CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN" lnMode = 1 * Create a STRINGFORMAT object in order to draw the string centered in the image LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign IF tlVertical loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical loStringFmt.LineAlignment = .StringAlignment.CENTER ENDIF LOCAL loSize AS xfcSize, loRect AS xfcRectangle IF tlVertical loSize = .SIZE.New(THIS.PARENT.WIDTH, THIS.PARENT.HEIGHT) ELSE loSize = .SIZE.New(tnWidth, tnHeight) ENDIF loSize = loGfx.MeasureString(; THIS._TransfCaption, THIS._oFont, loSize, loStringFmt) THIS._Height = CEILING(loSize.HEIGHT) THIS._Width = CEILING(loSize.WIDTH) loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height) x1 = tnX y1 = tnY IF tlVertical xBack = tnX + (tnWidth - THIS._Width) / 2 DO CASE CASE lnAlign = 0 && Left y1 = tnY CASE lnAlign = 1 && Right y1 = tnY + tnHeight - THIS._Height CASE lnAlign = 2 && Center y1 = tnY + (tnHeight - THIS._Height) / 2 ENDCASE ELSE DO CASE CASE lnAlign = 0 && Left xBack = tnX CASE lnAlign = 1 && Right xBack = tnX + tnWidth - THIS._Width CASE lnAlign = 2 && Center xBack = tnX + (tnWidth - THIS._Width) / 2 ENDCASE ENDIF CASE lnAlign = 0 && Left STORE tnX TO x1, xBack y1 = tnY CASE lnAlign = 1 && Right x1 = tnX - THIS._Width xBack = x1 y1 = tnY CASE lnAlign = 2 && Center x1 = tnX - (THIS._Width / 2) xBack = x1 y1 = tnY ENDCASE LOCAL lnRotation lnRotation = THIS.ROTATION IF lnRotation <> 0 WITH _SCREEN.SYSTEM.Drawing LOCAL loPointF AS xfcPointF, loMatrix AS xfcMatrix loMatrix = .Drawing2D.Matrix.New() IF lnMode = 1 loPointF = .PointF.New(tnX, tnY) && this is the point of rotation ELSE DO CASE CASE lnAlign = 0 && Left loPointF = .PointF.New(x1 + 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 1 && Right loPointF = .PointF.New(x1 + THIS._Width - 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 2 && Center loPointF = .PointF.New(x1 + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation ENDCASE ENDIF loMatrix.RotateAt(lnRotation, loPointF) loGfx.MultiplyTransform(loMatrix) ENDWITH ENDIF WITH _SCREEN.SYSTEM.Drawing lnRotationCenter = THIS.RotationCenter * Center Rotation IF lnRotationCenter <> 0 LOCAL loMatrixC AS xfcMatrix, loPointFC AS xfcPointF loMatrixC = .Drawing2D.Matrix.New() loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation loMatrixC.RotateAt(lnRotationCenter, loPointFC) loGfx.MultiplyTransform(loMatrixC) ENDIF * IF THIS.BackColorAlpha > 0 * Draw the BackGround Rectangle IF lnMode = 0 && default lnX=x1 lnY=y1 lnWidth = THIS._Width-2 lnHeight=THIS._Height-4 ELSE lnX=xBack+2 lnY=y1+2 lnWidth = THIS._Width-4 lnHeight=THIS._Height-4 ENDIF loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ; lnX, lnY, lnWidth, lnHeight) IF lnMode = 0 loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight) ENDIF * ENDIF lnX1=lnX lnY1=lnY lnX2=lnX+lnWidth lnY2=lnY lnX3=lnX2 lnY3=lnY+lnHeight lnX4=lnX lnY4=lnY3 IF lnRotation # 0 lnX0 = loPointF.X lnY0 = loPointF.Y THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotation) ENDIF IF lnRotationCenter # 0 lnX0 = loPointFC.X lnY0 = loPointFC.Y THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotationCenter) ENDIF TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> ENDTEXT LOCAL laPoints(4) laPoints(1) = .POINT.New(lnX1, lnY1) laPoints(2) = .POINT.New(lnX2, lnY2) laPoints(3) = .POINT.New(lnX3, lnY3) laPoints(4) = .POINT.New(lnX4, lnY4) ENDWITH * Draw the Text IF lnMode = 0 LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign loRect = .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2) loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ELSE IF tlVertical loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height) ENDIF loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ENDIF THIS.PARENT._updatecoordinates (,'AxisLegend2', lnx1, lnY1, lnWidth, lnHeight, THIS._TransfCaption, lnRotationCenter, lcPoints, 0) IF lnRotation # 0 OR lnRotationCenter # 0 loGfx.ResetTransform() ENDIF ENDWITH ENDPROC PROCEDURE ChartCanvas.Click LOCAL lnCoordIndex, lnX, lnY, lnValue, loObject lnCoordIndex = 0 lnX = MCOL(0,3) lnY = MROW(0,3) WITH THIS.PARENT ._CheckMousePosition(0, 0, lnX, lnY, @lnValue, @lnCoordIndex, @loObject) .CurrValue = lnValue .CurrIndex = lnCoordIndex .CurrObjType = IIF(TYPE('loObject.Type')='C',loObject.Type,'') .CLICK() ENDWITH ENDPROC PROCEDURE ChartCanvas.DblClick LOCAL lnCoordIndex, lnX, lnY, lnValue, loObject lnCoordIndex = 0 lnX = MCOL(0,3) lnY = MROW(0,3) WITH THIS.PARENT ._CheckMousePosition(0, 0, lnX, lnY, @lnValue, @lnCoordIndex, @loObject) .CurrValue = lnValue .CurrIndex = lnCoordIndex .CurrObjType = IIF(TYPE('loObject.Type')='C',loObject.Type,'') .DBLCLICK() ENDWITH ENDPROC PROCEDURE ChartCanvas.draw LPARAMETERS tnWidth, tnHeight, toGfx IF THIS.PARENT.Sleep RETURN ENDIF DODEFAULT(tnWidth, tnHeight, toGfx) ENDPROC PROCEDURE ChartCanvas.Init WITH THIS .WIDTH = .PARENT.WIDTH .HEIGHT = .PARENT.HEIGHT IF VARTYPE(.nButton) = 'U' .ADDPROPERTY ('nButton',-1) .ADDPROPERTY ('nShift',-1) .ADDPROPERTY ('nXCoord',-1) .ADDPROPERTY ('nYCoord',-1) ENDIF ENDWITH DODEFAULT() ENDPROC PROCEDURE ChartCanvas.MouseDown LPARAMETERS nButton, nShift, nXCoord, nYCoord LOCAL loObject, lnCoordIndex lnCoordIndex = 0 THIS.PARENT._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, , @lnCoordIndex, @loObject) * Update the index property, that will allow all the other "curr"properties to be up to date THIS.PARENT.CurrIndex = lnCoordIndex THIS.PARENT.MOUSEDOWN( nButton, nShift, nXCoord, nYCoord, loObject) ENDPROC PROCEDURE ChartCanvas.MouseMove LPARAMETERS nButton, nShift, nXCoord, nYCoord LOCAL lnCoordIndex, loObject IF nXCoord=THIS.nXCoord AND nYCoord=THIS.nYCoord AND nButton=THIS.nButton AND nShift = THIS.nShift RETURN ENDIF THIS.nXCoord = nXCoord THIS.nYCoord = nYCoord THIS.nButton = nButton THIS.nShift = nShift m.lnCoordIndex = 0 loObject = .F. WITH THIS.PARENT ._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, , @lnCoordIndex, @loObject) * Update the index property, that will allow all the other "curr"properties to be up to date THIS.PARENT.Currindex = lnCoordIndex .MOUSEMOVE(nButton, nShift, nXCoord, nYCoord, loObject) ENDWITH ENDPROC PROCEDURE ChartCanvas.MouseUp LPARAMETERS nButton, nShift, nXCoord, nYCoord LOCAL lcObjectType, lnCoordIndex, loShape lnCoordIndex = 0 WITH THIS.PARENT ._CheckMousePosition(nButton, nShift, nXCoord, nYCoord, , @lnCoordIndex, @loShape) * Update the index property, that will allow all the other "curr"properties to be up to date .Currindex = lnCoordIndex lcObjectType = IIF(TYPE('loShape.Type')='C', loShape.TYPE, '' ) .MOUSEUP(nButton, nShift, nXCoord, nYCoord, loShape) IF TYPE('loShape') = 'O' AND ._GeneralType = "Pie" AND nButton=1 .Column = loShape.CurrentRow .Row = loShape.ChartIndex IF lcObjectType = "Pie" AND .PieDetachSliceonClick ._DetachClickedSlice(lnCoordIndex) ENDIF IF lcObjectType = "Legend" AND .PieDetachSliceonLegendClick ._DetachClickedSlice(lnCoordIndex) ENDIF ENDIF ENDWITH ENDPROC PROCEDURE Comments.caption_assign lparameters tcText This.Caption = tcText ENDPROC PROCEDURE Comments._drawstring LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor, tnAlignMent LOCAL lnAlign, lnHeight, lnMode, lnRotationCenter, lnWidth, lnX, lnY, ; loGfx as xfcGraphics, loSize as xfcSize, loStringFmt as xfcStringFormat lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates lnAlign = IIF(VARTYPE(tnAlignMent)='N',tnAlignMent,This.Alignment) * 0 = Left 1 = Right 2 = Center loGfx = This.Parent.oGfx lnBackColor=EVL(lnBackColor,this.BackColor) WITH _Screen.System.Drawing DO CASE CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN" lnMode = 1 * Create a STRINGFORMAT object in order to draw the string centered in the image loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.Center CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.Near ENDCASE loStringFmt.Alignment = lnGdipAlign IF tlVertical loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical loStringFmt.LineAlignment = .StringAlignment.Center ENDIF IF tlVertical loSize = .Size.New(This.Parent.Width, This.Parent.Height) ELSE loSize = .Size.New(tnWidth, tnHeight) ENDIF loSize = loGfx.MeasureString( This._TransfCaption, This._oFont, loSize, loStringFmt) This._Height = CEILING(loSize.Height) This._Width = CEILING(loSize.Width) LOCAL loRect as xfcRectangle loRect = .Rectangle.New(tnX, tnY, tnWidth, This._Height) x1 = tnX y1 = tnY IF tlVertical xBack = tnX + (tnWidth - This._Width) / 2 DO CASE CASE lnAlign = 0 && Left y1 = tnY CASE lnAlign = 1 && Right y1 = tnY + tnHeight - This._Height CASE lnAlign = 2 && Center y1 = tnY + (tnHeight - This._Height) / 2 ENDCASE ELSE DO CASE CASE lnAlign = 0 && Left xBack = tnX CASE lnAlign = 1 && Right xBack = tnX + tnWidth - This._Width CASE lnAlign = 2 && Center xBack = tnX + (tnWidth - This._Width) / 2 ENDCASE ENDIF CASE lnAlign = 0 && Left STORE tnX TO x1, xBack y1 = tnY CASE lnAlign = 1 && Right x1 = tnX - This._Width xBack = x1 y1 = tnY CASE lnAlign = 2 && Center x1 = tnX - (This._Width / 2) xBack = x1 y1 = tnY ENDCASE LOCAL lnRotation lnRotation = This.Rotation IF lnRotation <> 0 WITH _SCREEN.System.Drawing LOCAL loPointF as xfcPointF LOCAL loMatrix as xfcMatrix loMatrix = .Drawing2D.Matrix.New() IF lnMode = 1 loPointF = .PointF.New(tnX, tnY) && this is the point of rotation ELSE DO CASE CASE lnAlign = 0 && Left loPointF = .PointF.New(x1 + 5, y1 + This._Height / 2) && this is the point of rotation CASE lnAlign = 1 && Right loPointF = .PointF.New(x1 + This._Width - 5, y1 + This._Height / 2) && this is the point of rotation CASE lnAlign = 2 && Center loPointF = .PointF.New(x1 + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation ENDCASE ENDIF loMatrix.RotateAt(lnRotation, loPointF) loGfx.MultiplyTransform(loMatrix) ENDWITH ENDIF lnRotationCenter = This.RotationCenter * Center Rotation IF lnRotationCenter # 0 WITH _SCREEN.System.Drawing LOCAL loPointFC as xfcPointF, loMatrixC as xfcMatrix loMatrixC = .Drawing2D.Matrix.New() loPointFC = .PointF.New(xBack + This._Width / 2, y1 + This._Height / 2) && this is the point of rotation loMatrixC.RotateAt(lnRotationCenter, loPointFC) loGfx.MultiplyTransform(loMatrixC) ENDWITH ENDIF * Draw the BackGround Rectangle IF lnMode = 0 && default lnX=x1 lnY=y1 lnWidth = THIS._Width-2 lnHeight=THIS._Height-4 ELSE lnX=xBack+2 lnY=y1+2 lnWidth = THIS._Width-4 lnHeight=THIS._Height-4 ENDIF if THIS.BackColorAlpha<255 loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ; lnX, lnY, lnWidth, lnHeight) ENDIF IF lnMode = 0 loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight) ENDIF * Draw the Text IF lnMode = 0 LOCAL loStringFmt as xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.Center CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.Near ENDCASE loStringFmt.Alignment = lnGdipAlign loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, ; .Rectangle.New(x1, y1, CEILING(This._Width), This._Height + 2), ; loStringFmt) ELSE IF tlVertical loRect = .Rectangle.New(xBack, y1, This._Width, This._Height) loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, loRect, loStringFmt) ELSE loGfx.DrawString(This._TransfCaption, This._oFont, This._oBrush, loRect, loStringFmt) ENDIF ENDIF IF lnRotation <> 0 OR lnRotationCenter <> 0 loGfx.ResetTransform() ENDIF ENDWITH ENDPROC PROCEDURE DeltaLegend.caption_assign lparameters tcText This.Caption = tcText ENDPROC PROCEDURE DeltaLegend._drawstring LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor, tnAlignMent LOCAL lnAlign, lnHeight, lnMode, lnRotationCenter, lnWidth, lnX, lnY, ; loGfx AS xfcGraphics, loSize AS xfcSize, loStringFmt AS xfcStringFormat lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates lnAlign = IIF(VARTYPE(tnAlignMent)='N',tnAlignMent,THIS.ALIGNMENT) * 0 = Left 1 = Right 2 = Center loGfx = THIS.PARENT.oGfx lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR) this._Setup WITH _SCREEN.SYSTEM.Drawing DO CASE CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN" lnMode = 1 * Create a STRINGFORMAT object in order to draw the string centered in the image loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign IF tlVertical loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical loStringFmt.LineAlignment = .StringAlignment.CENTER ENDIF IF tlVertical loSize = .SIZE.New(THIS.PARENT.WIDTH, THIS.PARENT.HEIGHT) ELSE loSize = .SIZE.New(tnWidth, tnHeight) ENDIF loSize = loGfx.MeasureString( THIS._TransfCaption, THIS._oFont, loSize, loStringFmt) THIS._Height = CEILING(loSize.HEIGHT) THIS._Width = CEILING(loSize.WIDTH) LOCAL loRect AS xfcRectangle loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height) x1 = tnX y1 = tnY IF tlVertical xBack = tnX + (tnWidth - THIS._Width) / 2 DO CASE CASE lnAlign = 0 && Left y1 = tnY CASE lnAlign = 1 && Right y1 = tnY + tnHeight - THIS._Height CASE lnAlign = 2 && Center y1 = tnY + (tnHeight - THIS._Height) / 2 ENDCASE ELSE DO CASE CASE lnAlign = 0 && Left xBack = tnX CASE lnAlign = 1 && Right xBack = tnX + tnWidth - THIS._Width CASE lnAlign = 2 && Center xBack = tnX + (tnWidth - THIS._Width) / 2 ENDCASE ENDIF CASE lnAlign = 0 && Left STORE tnX TO x1, xBack y1 = tnY CASE lnAlign = 1 && Right x1 = tnX - THIS._Width xBack = x1 y1 = tnY CASE lnAlign = 2 && Center x1 = tnX - (THIS._Width / 2) xBack = x1 y1 = tnY ENDCASE LOCAL lnRotation lnRotation = THIS.ROTATION IF lnRotation <> 0 WITH _SCREEN.SYSTEM.Drawing LOCAL loPointF AS xfcPointF LOCAL loMatrix AS xfcMatrix loMatrix = .Drawing2D.Matrix.New() IF lnMode = 1 loPointF = .PointF.New(tnX, tnY) && this is the point of rotation ELSE DO CASE CASE lnAlign = 0 && Left loPointF = .PointF.New(x1 + 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 1 && Right loPointF = .PointF.New(x1 + THIS._Width - 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 2 && Center loPointF = .PointF.New(x1 + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation ENDCASE ENDIF loMatrix.RotateAt(lnRotation, loPointF) loGfx.MultiplyTransform(loMatrix) ENDWITH ENDIF lnRotationCenter = THIS.RotationCenter * Center Rotation IF lnRotationCenter # 0 WITH _SCREEN.SYSTEM.Drawing LOCAL loPointFC AS xfcPointF, loMatrixC AS xfcMatrix loMatrixC = .Drawing2D.Matrix.New() loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation loMatrixC.RotateAt(lnRotationCenter, loPointFC) loGfx.MultiplyTransform(loMatrixC) ENDWITH ENDIF * Draw the BackGround Rectangle IF lnMode = 0 && default lnX=x1 lnY=y1 lnWidth = THIS._Width-2 lnHeight=THIS._Height-4 ELSE lnX=xBack+2 lnY=y1+2 lnWidth = THIS._Width-4 lnHeight=THIS._Height-4 ENDIF IF THIS.BackColorAlpha<255 loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ; lnX, lnY, lnWidth, lnHeight) ENDIF IF lnMode = 0 loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight) ENDIF * Draw the Text IF lnMode = 0 LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, ; .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2), ; loStringFmt) ELSE IF tlVertical loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height) loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ELSE loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ENDIF ENDIF IF lnRotation <> 0 OR lnRotationCenter <> 0 loGfx.ResetTransform() ENDIF ENDWITH ENDPROC PROCEDURE ScaleLegend._drawstring LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor LOCAL x1, y1, lnAlign, lnMode, xBack lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates lnAlign = THIS.ALIGNMENT * 0 = Left 1 = Right 2 = Center LOCAL loGfx AS xfcGraphics loGfx = THIS.PARENT.oGfx lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR) WITH _SCREEN.SYSTEM.Drawing DO CASE CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN" lnMode = 1 * Create a STRINGFORMAT object in order to draw the string centered in the image LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign IF tlVertical loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical loStringFmt.LineAlignment = .StringAlignment.CENTER ENDIF LOCAL loSize AS xfcSize, loRect AS xfcRectangle IF tlVertical loSize = .SIZE.New(THIS.PARENT.WIDTH, THIS.PARENT.HEIGHT) ELSE loSize = .SIZE.New(tnWidth, tnHeight) ENDIF loSize = loGfx.MeasureString(; THIS._TransfCaption, THIS._oFont, loSize, loStringFmt) THIS._Height = CEILING(loSize.HEIGHT) THIS._Width = CEILING(loSize.WIDTH) loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height) x1 = tnX y1 = tnY IF tlVertical xBack = tnX + (tnWidth - THIS._Width) / 2 DO CASE CASE lnAlign = 0 && Left y1 = tnY CASE lnAlign = 1 && Right y1 = tnY + tnHeight - THIS._Height CASE lnAlign = 2 && Center y1 = tnY + (tnHeight - THIS._Height) / 2 ENDCASE ELSE DO CASE CASE lnAlign = 0 && Left xBack = tnX CASE lnAlign = 1 && Right xBack = tnX + tnWidth - THIS._Width CASE lnAlign = 2 && Center xBack = tnX + (tnWidth - THIS._Width) / 2 ENDCASE ENDIF CASE lnAlign = 0 && Left STORE tnX TO x1, xBack y1 = tnY CASE lnAlign = 1 && Right x1 = tnX - THIS._Width xBack = x1 y1 = tnY CASE lnAlign = 2 && Center x1 = tnX - (THIS._Width / 2) xBack = x1 y1 = tnY ENDCASE LOCAL lnRotation lnRotation = THIS.ROTATION IF lnRotation <> 0 WITH _SCREEN.SYSTEM.Drawing LOCAL loPointF AS xfcPointF, loMatrix AS xfcMatrix loMatrix = .Drawing2D.Matrix.New() IF lnMode = 1 loPointF = .PointF.New(tnX, tnY) && this is the point of rotation ELSE DO CASE CASE lnAlign = 0 && Left loPointF = .PointF.New(x1 + 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 1 && Right loPointF = .PointF.New(x1 + THIS._Width - 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 2 && Center loPointF = .PointF.New(x1 + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation ENDCASE ENDIF loMatrix.RotateAt(lnRotation, loPointF) loGfx.MultiplyTransform(loMatrix) ENDWITH ENDIF WITH _SCREEN.SYSTEM.Drawing lnRotationCenter = THIS.RotationCenter * Center Rotation IF lnRotationCenter <> 0 LOCAL loMatrixC AS xfcMatrix, loPointFC AS xfcPointF loMatrixC = .Drawing2D.Matrix.New() loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation loMatrixC.RotateAt(lnRotationCenter, loPointFC) loGfx.MultiplyTransform(loMatrixC) ENDIF * IF THIS.BackColorAlpha > 0 * Draw the BackGround Rectangle IF lnMode = 0 && default lnX=x1 lnY=y1 lnWidth = THIS._Width-2 lnHeight=THIS._Height-4 ELSE lnX=xBack+2 lnY=y1+2 lnWidth = THIS._Width-4 lnHeight=THIS._Height-4 ENDIF loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ; lnX, lnY, lnWidth, lnHeight) IF lnMode = 0 loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight) ENDIF * ENDIF lnX1=lnX lnY1=lnY lnX2=lnX+lnWidth lnY2=lnY lnX3=lnX2 lnY3=lnY+lnHeight lnX4=lnX lnY4=lnY3 IF lnRotation # 0 lnX0 = loPointF.X lnY0 = loPointF.Y THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotation) ENDIF IF lnRotationCenter # 0 lnX0 = loPointFC.X lnY0 = loPointFC.Y THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotationCenter) ENDIF TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> ENDTEXT LOCAL laPoints(4) laPoints(1) = .POINT.New(lnX1, lnY1) laPoints(2) = .POINT.New(lnX2, lnY2) laPoints(3) = .POINT.New(lnX3, lnY3) laPoints(4) = .POINT.New(lnX4, lnY4) ENDWITH * Draw the Text IF lnMode = 0 LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign loRect = .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2) loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ELSE IF tlVertical loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height) ENDIF loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ENDIF THIS.PARENT._updatecoordinates (,'ScaleLegend', lnX1, lnY1, lnWidth, lnHeight, THIS._TransfCaption, lnRotationCenter, lcPoints, 0) IF lnRotation # 0 OR lnRotationCenter # 0 loGfx.ResetTransform() ENDIF ENDWITH ENDPROC PROCEDURE ShapeLegend._drawstring LPARAMETERS tnX, tnY, tnWidth, tnHeight, tlVertical, lnBackColor, toParentShape LOCAL lcPoints, ; lnHeight, lnMargin, lnRotationCenter, lnWidth, lnX, lnX0, lnX1, lnX2, lnX3, lnX4, lnY, lnY0, lnY1, lnY2, lnY3, lnY4, ; loGfx, loShape , loThisShape LOCAL x1, y1, lnAlign, lnMode, xBack, lnNum IF THIS.PARENT.Bartype = 1 tnX = tnX +THIS.PARENT._3D/2 ENDIF *!* if this.Rotation#0 and tlVertical *!* this.Rotation=MOD(this.Rotation+90,360) *!* ENDIF lnMode = 0 && 0 = x,y Coordinates ; 1 = xfcRectangle coordinates lnAlign = THIS.ALIGNMENT * 0 = Left 1 = Right 2 = Center loGfx = THIS.PARENT.oGfx lnBackColor=EVL(lnBackColor,THIS.BACKCOLOR) WITH _SCREEN.SYSTEM.Drawing DO CASE CASE VARTYPE(tnWidth) + VARTYPE(tnHeight) = "NN" lnMode = 1 * Create a STRINGFORMAT object in order to draw the string centered in the image LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign IF tlVertical loStringFmt.FormatFlags = .StringFormatFlags.DirectionVertical loStringFmt.LineAlignment = .StringAlignment.CENTER ENDIF LOCAL loSize AS xfcSize, loRect AS xfcRectangle IF tlVertical loSize = .SIZE.New(THIS.PARENT.WIDTH, THIS.PARENT.HEIGHT) ELSE loSize = .SIZE.New(tnWidth, tnHeight) ENDIF loSize = loGfx.MeasureString(; THIS._TransfCaption, THIS._oFont, loSize, loStringFmt) THIS._Height = CEILING(loSize.HEIGHT) THIS._Width = CEILING(loSize.WIDTH) loRect = .Rectangle.New(tnX, tnY, tnWidth, THIS._Height) x1 = tnX y1 = tnY IF tlVertical xBack = tnX + (tnWidth - THIS._Width) / 2 DO CASE CASE lnAlign = 0 && Left y1 = tnY CASE lnAlign = 1 && Right y1 = tnY + tnHeight - THIS._Height CASE lnAlign = 2 && Center y1 = tnY + (tnHeight - THIS._Height) / 2 ENDCASE ELSE DO CASE CASE lnAlign = 0 && Left xBack = tnX CASE lnAlign = 1 && Right xBack = tnX + tnWidth - THIS._Width CASE lnAlign = 2 && Center xBack = tnX + (tnWidth - THIS._Width) / 2 ENDCASE ENDIF CASE lnAlign = 0 && Left STORE tnX TO x1, xBack y1 = tnY CASE lnAlign = 1 && Right x1 = tnX - THIS._Width xBack = x1 y1 = tnY CASE lnAlign = 2 && Center x1 = tnX - (THIS._Width / 2) xBack = x1 y1 = tnY ENDCASE LOCAL lnRotation lnRotation = THIS.ROTATION IF lnRotation <> 0 LOCAL loPointF AS xfcPointF, loMatrix AS xfcMatrix loMatrix = .Drawing2D.Matrix.New() IF lnMode = 1 loPointF = .PointF.New(tnX, tnY) && this is the point of rotation ELSE DO CASE CASE lnAlign = 0 && Left loPointF = .PointF.New(x1 + 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 1 && Right loPointF = .PointF.New(x1 + THIS._Width - 5, y1 + THIS._Height / 2) && this is the point of rotation CASE lnAlign = 2 && Center loPointF = .PointF.New(x1 + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation ENDCASE ENDIF loMatrix.RotateAt(lnRotation, loPointF) loGfx.MultiplyTransform(loMatrix) ENDIF lnRotationCenter = THIS.RotationCenter * Center Rotation IF lnRotationCenter # 0 LOCAL loMatrixC AS xfcMatrix, loPointFC AS xfcPointF loMatrixC = .Drawing2D.Matrix.New() loPointFC = .PointF.New(xBack + THIS._Width / 2, y1 + THIS._Height / 2) && this is the point of rotation loMatrixC.RotateAt(lnRotationCenter, loPointFC) loGfx.MultiplyTransform(loMatrixC) ENDIF * IF THIS.BackColorAlpha > 0 * Draw the BackGround Shape IF lnMode = 0 && default lnX=x1 lnY=y1 lnWidth = THIS._Width-2 lnHeight=THIS._Height-4 ELSE lnX=xBack+2 lnY=y1+2 lnWidth = THIS._Width-4 lnHeight=THIS._Height-4 ENDIF IF THIS.PARENT.ShapeLegendType = 1 loGfx.FillRectangle( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ; lnX, lnY, lnWidth, lnHeight) =IIF( lnMode = 0,loGfx.DrawRectangle( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX, lnY, lnWidth, lnHeight),0) ELSE lnMargin=4 loGfx.FillEllipse( .SolidBrush.New(.COLOR.FromRGB(RGB(192,192,192)), 1), ; lnX-lnMargin, lnY, lnWidth+lnMargin*2, lnHeight+lnMargin*2) loGfx.FillEllipse( .SolidBrush.New(.COLOR.FromARGB(THIS.BackColorAlpha,lnBackColor)), ; lnX-lnMargin, lnY-lnMargin, lnWidth+lnMargin*2, lnHeight+lnMargin*2) =IIF( lnMode = 0, loGfx.DrawEllipse( .PEN.New(.COLOR.FromRGB(RGB(192,192,192)), 1),lnX-lnMargin, lnY-lnMargin, lnWidth+lnMargin*2, lnHeight+lnMargin*2),0) lnY = lnY + lnMargin ENDIF lnX1=lnX lnY1=lnY lnX2=lnX+lnWidth lnY2=lnY lnX3=lnX2 lnY3=lnY+lnHeight lnX4=lnX lnY4=lnY3 IF lnRotation # 0 lnX0 = loPointF.X lnY0 = loPointF.Y THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotation) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotation) ENDIF IF lnRotationCenter # 0 lnX0 = loPointFC.X lnY0 = loPointFC.Y THIS.PARENT.ROTATE(lnX0,lnY0,@lnX1, @lnY1, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX2, @lnY2, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX3, @lnY3, lnRotationCenter) THIS.PARENT.ROTATE(lnX0,lnY0,@lnX4, @lnY4, lnRotationCenter) ENDIF TEXT TO lcPoints <>,<> <>,<> <>,<> <>,<> <>,<> ENDTEXT LOCAL laPoints(4) laPoints(1) = .POINT.New(lnX1, lnY1) laPoints(2) = .POINT.New(lnX2, lnY2) laPoints(3) = .POINT.New(lnX3, lnY3) laPoints(4) = .POINT.New(lnX4, lnY4) * Draw the Text IF lnMode = 0 LOCAL loStringFmt AS xfcStringFormat, lnGdipAlign loStringFmt = .StringFormat.New() DO CASE CASE lnAlign = 2 && Center lnGdipAlign = .StringAlignment.CENTER CASE lnAlign = 1 lnGdipAlign = .StringAlignment.Far OTHERWISE lnGdipAlign = .StringAlignment.NEAR ENDCASE loStringFmt.ALIGNMENT = lnGdipAlign loRect = .Rectangle.New(x1, y1, CEILING(THIS._Width), THIS._Height + 2) loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ELSE IF tlVertical loRect = .Rectangle.New(xBack, y1, THIS._Width, THIS._Height) ENDIF loGfx.DrawString(THIS._TransfCaption, THIS._oFont, THIS._oBrush, loRect, loStringFmt) ENDIF loThisShape=.F. lnNum=0 IF VARTYPE(toParentShape)='O' lnNum = toParentShape.CoordNum FOR EACH loShape IN THIS.PARENT.Shapes.OBJECTS IF loShape.ParentCoord = lnNum loThisShape = loShape ENDIF NEXT ENDIF loThisShape = THIS.PARENT._updatecoordinates (loThisShape,'ShapeLegend', lnX1, lny1, lnWidth, lnHeight, THIS._TransfCaption, lnRotationCenter, lcPoints, 0) loThisShape.ParentCoord = lnNum IF lnRotation # 0 OR lnRotationCenter # 0 loGfx.ResetTransform() ENDIF RETURN loThisShape ENDWITH ENDPROC ENDDEFINE DEFINE CLASS foxchartshelper AS custom *< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: arcandpoint *m: arrows *m: drawcontour *m: drawpath *m: insidepath *m: lineandpoint *m: newarrowrow *m: newrow *m: objform *m: pathgradient *m: rotate *m: rotatepath *m: shell *m: simplifypath *m: sl *m: unaxonometric *m: unrgb * * Name = "foxchartshelper" * PROCEDURE arcandpoint LPARAMETERS tnX, tnY, tnWidth, tnHeight, tnAngle1, tnSwap, tlInverse, tnMouseX, tnMouseY * Coordinates LOCAL llBetween, llInverse, llYes, ; ln, lnA, lnAngle, lnAngle1, lnAngle2, lnB, lnCenterX, lnCenterY, lnMouseX, lnMouseY, lnX, lnY1, lnY2 lnCenterX = tnX + tnWidth/2 lnCenterY = tnY+ tnHeight/2 lnMouseX = tnMouseX - lnCenterX lnMouseY = lnCenterY - tnMouseY lnA = tnWidth / 2 lnB = tnHeight / 2 lnY2 = ( 1 - lnMouseX^2/ lnA^2) * lnB^2 IF lnY2<0 RETURN .F. ENDIF llInverse = tlInverse lnAngle1 = IIF(tnAngle1<0,360+tnAngle1,tnAngle1) lnAngle2 = lnAngle1+tnSwap IF lnAngle2<0 lnAngle2 =360+lnAngle2 llInverse = NOT llInverse ENDIF lnAngle2 = IIF(lnAngle2>360,lnAngle2-360,lnAngle2) IF lnAngle1 > lnAngle2 ln=lnAngle1 lnAngle1 = lnAngle2 lnAngle2 = ln llInverse = NOT llInverse ENDIF llYes = .F. * * First point * lnY1 = SQRT(lnY2) m.lnAngle = IIF(lnMouseX=0, IIF(lnY1 < 0, 270, 90), RTOD(ATAN(m.lnY1/m.lnMouseX)) ) DO CASE CASE lnMouseX < 0 m.lnAngle = 180 + m.lnAngle CASE lnY1 < 0 m.lnAngle = 360 + m.lnAngle ENDCASE m.lnAngle = 360 - m.lnAngle llBetween=BETWEEN(lnAngle, lnAngle1, lnAngle2) && AND MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2)))>m.lnMouseX IF llInverse llBetween = NOT llBetween ENDIF IF llBetween lnX = MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2))) && + lnCenterX IF ABS(lnX) < 1 llBetween=.F. ENDIF ENDIF IF llBetween AND lnMouseY < lnY1 llYes = NOT llYes ENDIF * * Second Point * lnY1 = -lnY1 m.lnAngle = IIF(lnMouseX=0, IIF(lnY1<0, 270, 90), RTOD(ATAN(m.lnY1/m.lnMouseX)) ) DO CASE CASE lnMouseX < 0 m.lnAngle = 180 + m.lnAngle CASE lnY1 < 0 m.lnAngle = 360 + m.lnAngle ENDCASE m.lnAngle = 360 - m.lnAngle llBetween=BETWEEN(lnAngle, lnAngle1, lnAngle2) && AND MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2)))>m.lnMouseX IF llBetween lnX = MAX(lnY1/TAN(DTOR(lnAngle1)), lnY1/TAN(DTOR(lnAngle2))) && + lnCenterX IF ABS(lnX) < 1 llBetween=.F. ENDIF ENDIF IF llInverse llBetween = NOT llBetween ENDIF IF llBetween AND lnMouseY < lnY1 llYes = NOT llYes ENDIF RETURN llYes ENDPROC PROCEDURE arrows LPARAMETERS lnType, lnX0, lnY0, lnArrowHeight, lnArrowWidth, lnEndWidth, lnValue LOCAL lcPolygon, lnHalf m.lnHalf = lnArrowHeight/2 lnRad=5 lcPolygon='' DO CASE CASE lnType = 1 This.NewArrowRow( @lcPolygon, lnX0, lnY0+lnHalf-lnRad, lnX0, lnY0-lnHalf+lnRad) This.NewArrowRow( @lcPolygon,lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90) This.NewArrowRow( @lcPolygon,lnX0+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth -lnEndWidth-lnRad,lnY0 - m.lnHalf) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 - m.lnHalf-lnRad*2,lnRad*2,lnRad*2,90,-90) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m. lnArrowHeight+lnRad, lnX0 + m.lnArrowWidth - lnEndWidth ,lnY0- m. lnArrowHeight ) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m. lnArrowHeight, lnX0 + m.lnArrowWidth ,lnY0 ) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight ) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m.lnHalf + lnRad) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 + m.lnHalf,lnRad*2,lnRad*2,0,-90) This.NewArrowRow( @lcPolygon,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0 + m.lnHalf,lnX0+lnRad ,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon,lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,90,90) CASE lnType = 2 This.NewArrowRow( @lcPolygon, lnX0, lnY0-lnHalf,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0 - m.lnHalf ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 - m.lnHalf-lnRad*2,lnRad*2,lnRad*2,90,-90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m.lnHalf-lnRad,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m.lnHalf-lnRad) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 - m. lnArrowHeight,lnX0 + m.lnArrowWidth,lnY0 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m. lnArrowHeight,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0 + m.lnHalf + lnRad) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0 + m.lnHalf,lnRad*2,lnRad*2,0,-90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0 + m.lnHalf,lnX0 ,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 ,lnY0 + m.lnHalf,lnX0+lnHalf ,lnY0) This.NewArrowRow( @lcPolygon, lnX0+lnHalf ,lnY0,lnX0,lnY0-lnHalf) lnX0 = lnX0 + lnHalf CASE lnType = 3 && Двойная *********************************************** This.NewArrowRow( @lcPolygon, lnX0,lnY0,lnX0+lnEndWidth,lnY0-lnArrowHeight) This.NewArrowRow( @lcPolygon, lnX0+lnEndWidth,lnY0-lnArrowHeight,lnX0+lnEndWidth,lnY0 - lnHalf - lnRad) This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0-lnHalf-lnRad*2,lnRad*2,lnRad*2,180,-90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0-lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0-lnHalf-lnRad*2,lnRad*2,lnRad*2,90,-90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0-lnHalf-lnRad,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0-lnHalf*2) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0-lnHalf*2,lnX0 + m.lnArrowWidth,lnY0) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0+lnHalf*2) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth,lnY0+lnHalf*2,lnX0 + m.lnArrowWidth - lnEndWidth,lnY0+lnHalf+lnRad) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad*2,lnY0+lnHalf,lnRad*2,lnRad*2,0,-90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnEndWidth-lnRad,lnY0+lnHalf,lnX0 + lnEndWidth+lnRad,lnY0+lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0+lnHalf,lnRad*2,lnRad*2,270,-90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0+lnHalf+lnRad,lnX0 + m.lnEndWidth,lnY0+lnHalf*2) This.NewArrowRow( @lcPolygon, lnX0 + m.lnEndWidth,lnY0+lnHalf*2,lnX0,lnY0) CASE lnType = 4 This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad) This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90) This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf,lnX0 + m.lnArrowWidth,lnY0 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf,lnX0+lnRad,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,90,90) CASE lnType = 5 This.NewArrowRow( @lcPolygon, lnX0+lnHalf,lnY0) This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0,lnY0 + m.lnHalf) lnX0 = lnX0 + lnHalf CASE lnType = 6 This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad) This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90) This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0-lnHalf,lnX0+lnArrowWidth-lnHalf-lnRad,lnY0-lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf-lnRad*2,lnY0-lnHalf,lnRad*2,lnRad*2,270,90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0-lnHalf+lnRad,lnX0 + m.lnArrowWidth - lnHalf,lnY0-lnHalf/3) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 - m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/3 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 - m.lnHalf/1.5,lnX0 + m.lnArrowWidth,lnY0 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 ,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/1.5,lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/3 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf + 5,lnY0 + m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf+lnRad,lnY0 + m.lnHalf/3 ) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf,lnY0 + m.lnHalf/3 ,lnX0 + m.lnArrowWidth - lnHalf,lnY0 + lnHalf-lnRad) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf-lnRad*2,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,0,90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - lnHalf-lnRad,lnY0+lnHalf,lnX0 + lnRad,lnY0+lnHalf) This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf - lnRad*2,lnRad*2,lnRad*2,90,90) CASE lnType = 7 lnArrowWidth=lnArrowWidth-8 DO CASE CASE lnValue<0 This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad) This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2,180,90) This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0-lnHalf,lnX0 + m.lnArrowWidth -lnRad,lnY0 - m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth-lnRad*2 ,lnY0-lnHalf,lnRad*2,lnRad*2, 270,90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 - m.lnHalf +lnRad, lnX0 + m.lnArrowWidth,lnY0 + m.lnHalf*1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 + m.lnHalf*1.5,lnX0 + m.lnArrowWidth + 8,lnY0 + m.lnHalf*1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth + 8,lnY0 + m.lnHalf*1.5,lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 + m.lnHalf*2.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 + m.lnHalf*2.5,lnX0 + m.lnArrowWidth - m.lnHalf*2 - 8,lnY0 + m.lnHalf*1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf*2 - 8,lnY0 + m.lnHalf*1.5,lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 + m.lnHalf * 1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 + m.lnHalf * 1.5,lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 + m.lnHalf,lnX0+lnRad,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2,90,90) CASE lnValue>0 This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2, 180, -90) This.NewArrowRow( @lcPolygon, lnX0+lnRad,lnY0 + m.lnHalf,lnX0 + m.lnArrowWidth-lnRad,lnY0 + m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth-lnRad*2,lnY0+lnHalf-lnRad*2,lnRad*2,lnRad*2, 90, -90) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 + m.lnHalf - lnRad, lnX0 + m.lnArrowWidth,lnY0 - m.lnHalf*1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth,lnY0 - m.lnHalf*1.5,lnX0 + m.lnArrowWidth + 8,lnY0 - m.lnHalf*1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth + 8,lnY0 - m.lnHalf*1.5,lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 - m.lnHalf*2.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf,lnY0 - m.lnHalf*2.5,lnX0 + m.lnArrowWidth - m.lnHalf*2 - 8,lnY0 - m.lnHalf*1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf*2 - 8,lnY0 - m.lnHalf*1.5,lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 - m.lnHalf * 1.5) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 - m.lnHalf * 1.5,lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 - m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0 + m.lnArrowWidth - m.lnHalf*2,lnY0 - m.lnHalf,lnX0+lnRad,lnY0 - m.lnHalf) This.NewArrowRow( @lcPolygon, lnX0,lnY0-lnHalf,lnRad*2,lnRad*2, 270, -90) This.NewArrowRow( @lcPolygon, lnX0,lnY0+lnHalf-lnRad,lnX0,lnY0-lnHalf+lnRad) OTHERWISE RETURN this.Arrows(1, lnX0, lnY0, lnArrowHeight, lnArrowWidth, lnEndWidth, lnValue) ENDCASE ENDCASE RETURN lcPolygon *!* LPARAMETERS lcText,tcParam1,tcParam2,tcParam3,tcParam4,tcParam5,tcParam6,tcParam7 *!* lnCount = PCOUNT() *!* if lnCount>3 and VARTYPE(tcParam3)#'N' *!* tcParam3=tcParam1 *!* endif *!* FOR lnLine=1 TO lnCOUNT-1 *!* lcStr = IIF(lnLine=1, '', lcStr+',') + Transform(ROUND(EVALUATE('tcParam'+allt(STR(lnLine))),0)) *!* NEXT *!* TEXT TO lcText addi *!* <> *!* ENDTEXT ENDPROC PROCEDURE drawcontour LPARAMETERS loChart, lcLines, tnIndex LOCAL lnGradientPosition, loBrush, loObject WITH loChart IF TYPE('.ContourGraphics.Name') = 'C' .ContourGraphics.dispose() .ContourGraphics=.F. ENDIF loForm = this.ObjForm(loChart) loForm.CLS() lnGradientPosition=MAX(0.05,MIN(0.95,.GradientPosition)) .Tips.VISIBLE = .F. .ContourGraphics = _SCREEN.SYSTEM.Drawing.Graphics.FromHWnd(loForm.HWND) && Create a Graphics object .ContourGraphics.SmoothingMode = 4 .ContourPen = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.White , 2) .ContourPen.DASHSTYLE = 3 IF VARTYPE(lcLines)='O' WITH _SCREEN.SYSTEM.Drawing loBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(lcLines.LEFT, lcLines.TOP, lcLines.WIDTH , lcLines.HEIGHT), ; .COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.Black,.COLOR.White)), ; .COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.White,.COLOR.Black)), ; IIF(loChart._Orientation = 1,0,1)) ENDWITH loBrush.SetSigmaBellShape(lnGradientPosition, 1) lcLines.DrawContour(.ContourGraphics, .ContourPen, loBrush, OBJ2CLIENT(loChart,2), OBJ2CLIENT(loChart,1) ) RETURN ENDIF loObject = EVALUATE([loChart.shapes.shape] + ALLTRIM(STR(tnIndex))) IF loObject.TYPE = 'Rect' AND .SHOWTIPS AND NOT .ShowValuesonshapes WITH loChart.Tips .ZORDER(0) .BACKSTYLE = 1 .BACKCOLOR = loChart.ShapeLegend.BACKCOLOR .VALUE = .F. &&loObject.Caption .CAPTION = loObject.CAPTION * .EvalCaption() .TOP = loObject.TOP .LEFT = loObject.LEFT .WIDTH=200 .AUTOSIZE = .T. .VISIBLE=.T. ENDWITH ENDIF WITH _SCREEN.SYSTEM.Drawing loBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(loObject.LEFT, loObject.TOP, EVL(loObject.WIDTH,1) , EVL(loObject.HEIGHT,1)), ; .COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.Black,.COLOR.White)), ; .COLOR.FromARGB(64,IIF(loChart.GradientInvertColors,.COLOR.White,.COLOR.Black)), ; IIF(loChart._Orientation = 1,0,1)) ENDWITH loBrush.SetSigmaBellShape(lnGradientPosition, 1) this.DrawPath(.ContourGraphics, .ContourPen, loBrush, lcLines, OBJ2CLIENT(loChart,2), OBJ2CLIENT(loChart,1)) ENDWITH ENDPROC PROCEDURE drawpath LPARAMETERS toGraphics, toPen, toPathBrush, tcLines, tnLeft, tnTop LOCAL llAfterArc, llWrapMode, lnCount, lnCount2, lnLeft, lnLine, lnLines, lnParams, lnTop, lnX1, lnX2, lnY1, lnY2, ; loColor, loPath, la(1) PRIVATE gnColor1, gnColor2, gnCenterPointX, gnCenterPointY, gnFocusScales gnFocusScales=.3 EXTERNAL array xfcGdipGetPathGradientSurroundColorCount, xfcGdipSetPathGradientSurroundColorsWithCount, xfcGdipGetPathGradientSurroundColorsWithCount WITH _SCREEN.SYSTEM.Drawing lnLeft = EVL(tnLeft,0) lnTop = EVL(tnTop,0) loPath = .Drawing2D.GraphicsPath.New() loPath.FillMode = .Drawing2D.FillMode.ALTERNATE loPath.StartFigure() tcLines=EVL(tcLines,'') lnLines = ALINES(la, tcLines) lnY1 = VAL(la2(ALINES(la2,la(1),',')))+lnTop lnX1 = VAL(la2(1)) + lnLeft llAfterArc = .F. FOR lnLine=1 TO lnLines lnParams = ALINES(la2,la(lnLine),',') IF lnParams<2 LOOP ENDIF IF lnParams = 4 loPath.ADDLINE( VAL(la2(1)) + lnLeft, VAL(la2(2))+lnTop, VAL(la2(3)) + lnLeft, VAL(la2(4)) + lnTop ) llAfterArc = .T. LOOP ENDIF IF lnParams = 5 loPath.ADDLINE( VAL(la2(1)) + lnLeft, VAL(la2(2))+lnTop, VAL(la2(1)) + lnLeft, VAL(la2(2)) + lnTop ) llAfterArc = .T. LOOP ENDIF IF lnParams > 5 loPath.AddArc(VAL(la2(1))+ lnLeft, VAL(la2(2))+lnTop, VAL(la2(3)), VAL(la2(4)), VAL(la2(5)), VAL(la2(6)) ) IF lnParams >6 AND NOT EMPTY( VAL(la2(7)) ) loPath.Reverse() ENDIF llAfterArc = .T. LOOP ENDIF IF llAfterArc llAfterArc = .F. LOOP ENDIF lnY2 = VAL(la2(2))+lnTop lnX2= VAL(la2(1)) + lnLeft IF llAfterArc llAfterArc = .F. LOOP ELSE loPath.ADDLINE(lnX1,lnY1, lnX2,lnY2) ENDIF lnX1=lnX2 lnY1=lnY2 NEXT IF VARTYPE(toPathBrush) = 'C' gnColor1 = RGB(212,212,212) gnColor2 = RGB(250,250,250) gnCenterPointX = -1 gnCenterPointY = 0 llWrapMode=.T. =EXECSCRIPT(toPathBrush) toPathBrush = .Drawing2D.PathGradientBrush.New(loPath) lnCount=0 =xfcGdipGetPathGradientSurroundColorCount(toPathBrush.Handle, @lnCount) m.lqColors = REPLICATE(0h00000000,lnCount) m.lnCount2 = 0 =xfcGdipGetPathGradientSurroundColorsWithCount(toPathBrush.Handle, @lqColors, @lnCount2) loColor = .COLOR.FromRGB(gnColor1) m.lqColors = REPLICATE(BINTOC(loColor.ARGB,"4rs"),m.lnCount) =xfcGdipSetPathGradientSurroundColorsWithCount(toPathBrush.Handle, @lqColors, @lnCount) toPathBrush.CenterColor = .COLOR.FromRGB(gnColor2) toPathBrush.SetBlendTriangularShape(.5,1) toPathBrush.FocusScales = gnFocusScales IF gnCenterPointX>=0 toPathBrush.CenterPoint = .POINT.New(gnCenterPointX,gnCenterPointY) ENDIF toPathBrush.WrapMode = llWrapMode ENDIF IIF(VARTYPE(toPathBrush) ='O', toGraphics.FillPath(toPathBrush, loPath),.F.) IIF(VARTYPE(toPen) ='O', toGraphics.DrawPath(toPen, loPath),.F.) ENDWITH ENDPROC PROCEDURE insidepath LPARAMETERS lcPoints, lnMouseX, lnMouseY LOCAL llInverse, llMouseInsideShape, ; lnParams, lnPoint, lnPoints, lnX1, lnX2, lnY1, lnY2, la(1), la1(1) llMouseInsideShape = .F. STORE .F. TO lnX2, lnY2 FOR lnPoint=1 TO ALINES(la,RTRIM(lcPoints,CHR(13)+CHR(10))) lnParams=ALINES(la1,la(lnPoint),',') DO CASE CASE INLIST(lnParams,4,5) && Line lnX1 = VAL(la1(1)) lnY1 = VAL(la1(2)) lnX2 = VAL(la1(3)) lnY2 = VAL(la1(4)) IF VARTYPE(lnX2)='N' AND This.LineAndPoint (lnX1, lnY1, lnX2, lnY2, lnMouseX, lnMouseY) && and not lnX1=lnX2 llMouseInsideShape = NOT llMouseInsideShape ENDIF lnX2 = lnX1 lnY2 = lnY1 CASE lnParams>5 && Arc STORE .F. TO lnX2, lnY2 llInverse = IIF(lnParams=6,.F., la1(7)='1') IF This.ArcAndPoint( VAL(la1(1)), VAL(la1(2)), VAL(la1(3)), VAL(la1(4)), VAL(la1(5)), VAL(la1(6)), llInverse, lnMouseX, lnMouseY ) llMouseInsideShape = NOT llMouseInsideShape ENDIF CASE lnParams>1 && Point lnX1 = VAL(la1(1)) lnY1 = VAL(la1(2)) IF VARTYPE(lnX2)='N' AND This.LineAndPoint (lnX1, lnY1, lnX2, lnY2, lnMouseX, lnMouseY) llMouseInsideShape = NOT llMouseInsideShape ENDIF lnX2 = lnX1 lnY2 = lnY1 ENDCASE NEXT RETURN llMouseInsideShape ENDPROC PROCEDURE lineandpoint LPARAMETERS lnX1, lnY1, lnX2, lnY2, lnMouseX, lnMouseY LOCAL lnA1, lnB1, lnY_of_Meeting IF MIN(m.lnY1,m.lnY2)>m.lnMouseY OR NOT BETWEEN(m.lnMouseX, MIN(m.lnX1,m.lnX2), MAX(m.lnX1,m.lnX2)-0.1) RETURN .F. ENDIF m.lnA1 = (m.lnY2-m.lnY1) / (m.lnX2-m.lnX1) m.lnB1 = m.lnY1 - m.lnX1*m.lnA1 m.lnY_of_Meeting = m.lnA1*m.lnMouseX +m.lnB1 RETURN m.lnY_of_Meeting <= m.lnMouseY && and lnX2#lnMouseX ENDPROC PROCEDURE newarrowrow LPARAMETERS lcText,tcParam1,tcParam2,tcParam3,tcParam4,tcParam5,tcParam6,tcParam7 lnCount = PCOUNT() IF lnCount>3 AND VARTYPE(tcParam3)#'N' tcParam3=tcParam1 ENDIF FOR lnLine=1 TO lnCount-1 lcStr = IIF(lnLine=1, '', lcStr+',') + TRANSFORM(ROUND(EVALUATE('tcParam'+ALLT(STR(lnLine))),0)) NEXT TEXT TO lcText addi <> ENDTEXT ENDPROC PROCEDURE newrow LPARAMETERS lcText,tcParam1,tcParam2,tcParam3,tcParam4,tcParam5,tcParam6,tcParam7 LOCAL lcStr, lnCount, lnLine lnCount = PCOUNT() lcStr = '' IF lnCount>3 AND VARTYPE(tcParam3)#'N' tcParam3=tcParam1 ENDIF FOR lnLine=1 TO lnCount-1 lcStr = IIF(EMPTY(lcStr), '', lcStr+',') + TRANSF(ROUND(EVALUATE('tcParam'+ALLT(STR(lnLine))),0)) NEXT TEXT TO lcText addi <> ENDTEXT ENDPROC PROCEDURE objform LPARAMETERS loObj LOCAL lnLine IF TYPE('loObj')#'O' OR UPPER(loObj.BASECLASS)='FORM' RETURN loObj ENDIF FOR lnLine=1 TO 20 loObj=loObj.PARENT IF UPPER(loObj.BASECLASS)='FORM' EXIT ENDIF NEXT RETURN loObj ENDPROC PROCEDURE pathgradient LPARAMETERS toGraphics, toPath, lnColor1, lnColor2, lnCenterPointX, lnCenterPointY, lnXkoef, lnYkoef, lnAlphaChannel EXTERNAL array xfcGdipGetPathGradientSurroundColorCount, xfcGdipSetPathGradientSurroundColorsWithCount LOCAL llWrapMode, lnB, lnCount, lnCount2, lnFocusScales, lnG, lnGray, lnR, loColor, loPathBrush IF lnColor2<0 STORE 0 TO lnR, lnG, lnB, lnGray THIS.UnRGB(lnColor1, @lnR, @lnG, @lnB, @lnGray) lnColor2= IIF( lnGray > 127, RGB(114,43,0),RGB(255,249,183)) ENDIF lnAlphaChannel = IIF(VARTYPE( lnAlphaChannel)='N', lnAlphaChannel,255) lnFocusScales= 0 llWrapMode = .F. lnXkoef = IIF(VARTYPE(lnXkoef)='N',lnXkoef,1) lnYkoef = IIF(VARTYPE(lnYkoef)='N',lnYkoef,0.7) WITH _SCREEN.SYSTEM.Drawing loPathBrush = .Drawing2D.PathGradientBrush.New(toPath) lnCount=0 =xfcGdipGetPathGradientSurroundColorCount(loPathBrush.Handle, @lnCount) m.lqColors = REPLICATE(0h00000000,lnCount) m.lnCount2 = 0 =xfcGdipGetPathGradientSurroundColorsWithCount(loPathBrush.Handle, @lqColors, @lnCount2) loColor = .COLOR.FromRGB(lnColor1) m.lqColors = REPLICATE(BINTOC(loColor.ARGB,"4rs"),m.lnCount) =xfcGdipSetPathGradientSurroundColorsWithCount(loPathBrush.Handle, @lqColors, @lnCount) loPathBrush.CenterColor = .COLOR.FromARGB( lnAlphaChannel,lnColor2) loPathBrush.SetBlendTriangularShape(lnXkoef, lnYkoef) loPathBrush.FocusScales = lnFocusScales IF lnCenterPointX>=0 loPathBrush.CenterPoint = .POINT.New(lnCenterPointX,lnCenterPointY) ENDIF loPathBrush.WrapMode = llWrapMode ENDWITH IF VARTYPE(toGraphics)='O' toGraphics.FillPath(loPathBrush, toPath) ENDIF RETURN loPathBrush ENDPROC PROCEDURE rotate LPARAMETERS lnX0,lnY0, lnX, lnY, lnNewAngle LOCAL lnX1, lnY1 lnX1=lnX-lnX0 lnY1=lnY-lnY0 lnX = lnX1*COS(lnNewAngle)-lnY1*SIN(lnNewAngle) +lnX0 lnY = lnX1*SIN(lnNewAngle)+lnY1*COS(lnNewAngle) +lnY0 ENDPROC PROCEDURE rotatepath LPARAMETERS lnX0, lnY0, lcPath, lnAngle LOCAL lcNewPath, lcNewStr, lnCount, lnLine, lnX1, lnX2, lnY1, lnY2, la(1), la1(1) lnAngle = DTOR(lnAngle) lcNewPath = '' FOR lnLine=1 TO IIF(EMPTY(lcPath),0,ALINE(la1,lcPath)) lnCount = ALINE(la, la1(lnLine), ',') lnX1=VAL(la(1)) lnY1=VAL(la(2)) THIS.ROTATE(lnX0, lnY0, @lnX1, @lnY1, lnAngle) la(1)=Transform(ROUND(lnX1,0)) la(2)=Transform(ROUND(lnY1,0)) IF lnCount=4 lnX1=VAL(la(3)) lnY1=VAL(la(4)) THIS.ROTATE(lnX0, lnY0, @lnX1, @lnY1, lnAngle) la(3)=Transform(ROUND(lnX1,0)) la(4)=Transform(ROUND(lnY1,0)) ENDIF FOR lnCol=1 TO lnCount lcNewStr = IIF(lnCol=1,'',lcNewStr + ',')+la(lnCol) NEXT TEXT to lcNewPath addi <> ENDTEXT NEXT RETURN lcNewPath ENDPROC PROCEDURE shell LPARAMETERS lcFileName,tcWorkDir,tcOperation,lcparams, llInVisible LOCAL lcWorkDir,lcOperation IF EMPTY(lcFileName) RETURN -1 ENDIF lcFileName=ALLTRIM(lcFileName) lcWorkDir=IIF(TYPE("tcWorkDir")="C",ALLTRIM(tcWorkDir),"") lcOperation=IIF(TYPE("tcOperation")="C" AND ! EMPTY(tcOperation),ALLTRIM(tcOperation),"Open") IF PCOUNT()<4 lcparams='' ENDIF DECLARE INTEGER ShellExecute ; IN SHELL32.DLL ; INTEGER nWinHandle,; STRING cOperation, STRING cFileName, STRING cParameters,; STRING cDirectory, INTEGER nShowWindow RETURN ShellExecute(0,lcOperation,lcFileName,lcparams,lcWorkDir,IIF(EMPTY(llInVisible),1,0)) ENDPROC PROCEDURE simplifypath LPARAMETERS lcPath LOCAL lnLine IF EMPTY(lcPath) RETURN '' ENDIF LOCAL lcLeft, lcNew, lcNext, lcTop, lnCount, lnLines lcNew='' lnLines = ALINE(la1,lcPath) IF lnLines = 1 RETU lcPath ENDIF lnCount= ALINE(la,la1(lnLines), [,]) IF lnCount>4 lnCount= ALINE(la,la1(lnLines-1), [,]) ENDIF lcLeft=la(1) lcTop=la(2) FOR lnLine=1 TO lnLines lnCount = ALINE(la, la1(lnLine), [,]) IF lnCount>4 lcNext = la1(IIF(lnLine=lnLines,1,lnLine+1)) ALINE(la2, lcNext,',') TEXT to lcNew addi <>,<>,<>,<> ENDTEXT LOOP ENDIF TEXT to lcNew addi <> ENDTEXT lcLeft = la(lnCount-1) lcTop= la(lnCount) NEXT RETU lcNew ENDPROC PROCEDURE sl LPARAMETERS lc,lcName,llLeave, lcType LOCAL lcReturn lcName=EVL(lcName,SET("Default")+CURDIR()+'\_Help.txt') STRTOFILE(IIF(VARTYPE(lc)='C',lc,TRANSFORM(lc)),lcName,0) IF EMPTY(lcType) OR VARTYPE(lcType)#'C' MODIFY COMMAND &lcName && RANGE 1,1 lcReturn = FILETOSTR(lcName) IF EMPTY(llLeave) TRY ERASE &lcName CATCH ENDTRY ENDIF ELSE this.SHELL(lcType,'',,FULLPATH(lcName) ) lcReturn = FILETOSTR(lcName) ENDIF RETURN lcReturn ENDPROC PROCEDURE unaxonometric LPARAMETERS tnAngle, tnWidth, tnHeight LOCAL lnNewAngle IF m.tnAngle > 360 m.tnAngle = m.tnAngle - 360 ENDIF IF m.tnAngle < 0 m.tnAngle = m.tnAngle + 360 ENDIF m.tnAngle = ROUND(m.tnAngle, 4) lnNewAngle=DTOR(m.tnAngle - IIF(m.tnAngle>90 AND m.tnAngle<= 270,180,0)) lnNewAngle=RTOD(ATAN(TAN(lnNewAngle)*tnWidth/tnHeight)) + ICASE( BETWEEN(m.tnAngle , 0, 90),0, BETWEEN(m.tnAngle ,90,270),180, .T., 360) IF m.lnNewAngle < 0 m.lnNewAngle = m.lnNewAngle + 360 ENDIF IF m.lnNewAngle - m.tnAngle > 170 m.lnNewAngle = m.lnNewAngle - 180 ENDIF RETURN m.lnNewAngle ENDPROC PROCEDURE unrgb LPARAMETERS lnColor, lnRed, lnBlue, lnGreen, lnGrayColor lnRed=MOD(lnColor,256) lnGreen=ROUND(MOD((lnColor-lnRed)/256,256),0) lnBlue=ROUND(MOD((lnColor-lnRed-lnGreen*256)/256/256,256),0) lnGrayColor = ROUND(0.229*lnRed + 0.587*lnGreen + 0.114*lnBlue,0) Return TEXTMERGE([RGB(<>,<>,<>)]) ENDPROC ENDDEFINE DEFINE CLASS pattern AS imgcanvas OF "gdiplusx.vcx" *< CLASSDATA: Baseclass="image" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: myrenderosb *p: brush *p: pen *p: todraw * * brush = .F. Name = "pattern" pen = .F. todraw = .F. * PROCEDURE beforedraw WITH THIS .CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.Transparent) .RenderMode = 4 && Memory PNG .BACKSTYLE = 0 && Transparent IF NOT EMPTY(.ToDraw) RETURN EXECSCRIPT(.ToDraw) ENDIF ENDWITH ENDPROC PROCEDURE draw LPARAMETERS tnWidth, tnHeight, toGfx WITH THIS .CLEAR(_SCREEN.SYSTEM.Drawing.COLOR.white) .RenderMode = 0 && Memory PNG .BACKSTYLE = 0 && Transparent IF NOT EMPTY(.ToDraw ) =EXECSCRIPT(.ToDraw) ENDIF ENDWITH DODEFAULT( tnWidth, tnHeight, toGfx ) ENDPROC PROCEDURE MouseMove LPARAMETERS nButton, nShift, nXCoord, nYCoord IF TYPE('this.Parent.ChartCanvas.Name')='C' THIS.PARENT.ChartCanvas.MOUSEMOVE(nButton, nShift, nXCoord, nYCoord) ENDIF ENDPROC PROCEDURE myrenderosb ************************************************************** * FUNCTION MyRenderOSB * ************************************************************** LOCAL llLockScreen IF This._InForm m.llLockScreen = ThisForm.LockScreen ThisForm.LockScreen = .T. ENDIF DO CASE CASE This.RenderMode = 0 && Memory BITMAP This.PictureVal = This.oBmp.GetPictureValfromHBitmap() CASE This.RenderMode = 1 && File BITMAP IF EMPTY(This._tempfile) This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".bmp" ELSE This.Picture = "" CLEAR RESOURCES (This._tempfile) DELETE FILE (This._tempfile) This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".bmp" ENDIF This.oBmp.Save(This._tempfile, _Screen.System.Drawing.Imaging.ImageFormat.Bmp) This.Picture = (This._tempfile) CASE This.RenderMode = 4 && Memory PNG ** PNG PictureVal is only supported in SP2 and later IF VERSION(4) >= "09.00.0000.5411" && "09.00.0000.5815" && VFP 9.0 SP2 This.PictureVal = This.oBmp.GetPictureVal(_Screen.System.Drawing.Imaging.ImageFormat.Png) ELSE ** Default to BMP if SP1 or earlier This.PictureVal = This.oBmp.GetPictureValfromHBitmap() ENDIF CASE This.RenderMode = 5 && File PNG IF EMPTY(This._tempfile) This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".png" ELSE This.Picture = "" CLEAR RESOURCES (This._tempfile) DELETE FILE (This._tempfile) This._tempfile = ADDBS(SYS(2023))+SYS(2015)+".png" ENDIF This.oBmp.Save(This._tempfile, _Screen.System.Drawing.Imaging.ImageFormat.Png) This.Picture = (This._tempfile) CASE This.RenderMode = 8 && File EMF This.oGfx = NULL LOCAL llLocked IF This._InForm m.llLocked = ThisForm.LockScreen ThisForm.LockScreen = .T. ENDIF This.Picture = (This._tempFile) IF This._InForm AND NOT ThisForm.LockScreen = m.llLocked ThisForm.LockScreen = m.llLocked ENDIF ENDCASE IF This._InForm ThisForm.LockScreen = m.llLockScreen ENDIF RETURN ENDPROC ENDDEFINE DEFINE CLASS radialgauge AS imgcanvas OF "gdiplusx.vcx" *< CLASSDATA: Baseclass="image" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: addshape *m: editproperies *m: interactivechange && Occurs when the user changes the value of a control using the keyboard or the mouse. *m: readproperties *m: saveproperties *m: _checkmouseposition *p: adjustbrush *p: arrowcolor *p: arrowdownwidth *p: arrowendwidth *p: arrowtopwidth *p: bigsteps *p: centerradius *p: centerx *p: centery *p: color1 *p: color2 *p: contourgraphics *p: contourpen *p: cornerrad *p: currindex *p: downarcheight *p: focusscales *p: fontbold && Specifies if the text is bold. *p: fontname && Specifies the name of the font used to display text. *p: fontsize && Specifies the font size for text displayed with an object. *p: fontunderline && Specifies if the text is underlined. *p: forecolor && Specifies the foreground color used to display text and graphics in an object. *p: gradientshapedirection *p: id *p: leftmargin *p: legend *p: maxvalue *p: minvalue *p: mode *p: nbutton *p: newprops *p: nshift *p: nxcoord *p: nycoord *p: pen *p: props *p: savedpicture *p: savedpictureval *p: scalecolor *p: scalemargin *p: scalewidth *p: shapes && An array for accessing the objects in a container object. *p: showcontour *p: showscale *p: smallsteps *p: topmargin *p: type *p: value && Specifies the current state of a control. * * adjustbrush = arrowcolor = (RGB(128,128,255)) arrowdownwidth = 10 arrowendwidth = 4 arrowtopwidth = 6 bigsteps = 5 centerradius = 5 centerx = 0 centery = 0 color1 = (RGB(245,245,245)) color2 = (RGB(255,255,255)) contourgraphics = .F. contourpen = .F. cornerrad = 14 currindex = 0 downarcheight = 4 focusscales = 0 fontbold = .F. fontname = Arial fontsize = 8 fontunderline = .F. forecolor = 0 gradientshapedirection = 0 Height = 100 id = leftmargin = 4 legend = .F. maxvalue = 100 minvalue = 0 mode = Name = "radialgauge" nbutton = 0 newprops = .F. nshift = 0 nxcoord = 0 nycoord = 0 pen = .F. props = .F. savedpicture = .F. savedpictureval = scalecolor = (RGB(165,170,194)) scalemargin = 0.15 scalewidth = 0.05 shapes = .F. showcontour = .T. showscale = .T. smallsteps = 5 topmargin = 5 type = 1 value = 0 Width = 110 * PROCEDURE addshape LPARAMETERS tcObjectName, tcType, tcPolyGon, tnX0, tnY0, tnWidth, tnHeight, tcCaption IF TYPE('this.Shapes.'+tcObjectName) = 'U' THIS.Shapes.ADDOBJECT(tcObjectName , "FoxChartsBeta.Figure") ENDIF WITH EVALUATE('This.Shapes.'+tcObjectName) .TYPE=tcType .SetDimensions( 0, 0, this.Width, this.Height) .CAPTION = EVL(tcCaption,tcType) .PATH = tcPolyGon .Contour = tcPolyGon .CoordNum = this.Shapes.ControlCount ENDWITH ENDPROC PROCEDURE beforedraw LPARAMETERS llRedraw LOCAL lcContour, llImageReady, ; lnAngle, lnAngle1, lnAngle2, lnAngleDegree, lnArrowAngle, lnBackColor, lnBackColorAlpha, lnBigRadius, lnBigRadius1, lnBigRadius2, lnBottomY, lnDelta, lnDelta1, lnDeltaX, lnDownAngle, lnDownBeta, lnDownLeft, lnDownRad, lnDownTop, lnEndLeft, lnEndTop, lnHeight, lnLine, lnMainRad, lnOuterMargin, lnSmallRadius, lnSmallRadius1, lnSmallRadius2, lnSmallValue, lnStep, lnStep1, lnTopBeta, lnUpLeft, lnUpTop, lnValue, lnValue1, lnWidth, lnX, lnX1, lnX2, lnX3, lnY, lnY1, lnY2, lnY3, ; loArrowBrush, loBlackPen, loCenterBrush, loColor1, loColor2, loCommonBrush, loDarkPen, loGrayPen, loScaleBrush, loWhiteBrush, loWhitePen WITH THIS lnWidth = FLOOR((.WIDTH - .LeftMargin*2)/2)*2 lnHeight = .HEIGHT - .TopMargin * 2 lnMainRad = ROUND( (MIN(lnWidth/2, lnHeight-.DownArcHeight- .CornerRad)),0) .CenterX= .LeftMargin + lnMainRad .CenterY = ROUND(.HEIGHT - .DownArcHeight- .CornerRad - .TopMargin, 0) lnSmallRadius = ROUND(lnMainRad * (1-.ScaleMargin - .ScaleWidth),0) lnArrowAngle= (.VALUE-.MinValue) / (.MaxValue - .MinValue) * 180 + 180 lnOuterMargin = 4 WITH .Legend .FONTSIZE = THIS.FONTSIZE .FONTNAME = THIS.FONTNAME .FONTBOLD= THIS.FONTBOLD .FORECOLOR = THIS.FORECOLOR .oGfx = THIS.oGfx ._Setup() ENDWITH * Кисти и ручки llImageReady = VARTYPE(THIS.SavedPicture ) = 'O' AND NOT llRedraw WITH _SCREEN.SYSTEM.Drawing loArrowBrush = .SolidBrush.New(.COLOR.FromARGB(180,IIF(VARTYPE(THIS.ArrowColor)='C', EVAL(THIS.ArrowColor),THIS.ArrowColor))) loDarkPen = .PEN.New(.COLOR.FromRGB(RGB(212,212,212)),1) loBlackPen = .PEN.New(.COLOR.FromRGB(0),1) lnBigRadius = ROUND(lnMainRad * (1-THIS.ScaleMargin),0) lnBigRadius1 = lnBigRadius + lnOuterMargin lnSmallRadius1= lnSmallRadius - lnOuterMargin IF NOT llImageReady loGrayPen = .PEN.New(.COLOR.FromRGB(RGB(222,222,222)),4) lnBackColor = THIS.ScaleColor lnBackColorAlpha = 255 loScalePen = .PEN.New(.COLOR.FromRGB(RGB(212,212,212)),1) loScaleBrush = .SolidBrush.New(.COLOR.FromARGB(lnBackColorAlpha,lnBackColor)) loWhiteBrush = .SolidBrush.New(.COLOR.FromRGB(RGB(128,255,255))) loWhitePen = .PEN.New(.COLOR.FromRGB(RGB(255,255,255))) loColor1 = .COLOR.FromRGB( RGB(245,245,245)) loColor2 = .COLOR.FromRGB( RGB(192,192,192)) *!* loCommonBrush = .Drawing2D.LinearGradientBrush.New(; *!* .Rectangle.New(THIS.LeftMargin, THIS.TopMargin, lnWidth, lnHeight), ; *!* loColor1, loColor2, THIS.GradientShapeDirection) *!* loCommonBrush.SetSigmaBellShape(1, 1) loCenterBrush = .Drawing2D.LinearGradientBrush.New(; .Rectangle.New(THIS.CenterX-THIS.CenterRadius, THIS.CenterY-THIS.CenterRadius, THIS.CenterRadius*2, THIS.CenterRadius*2), ; loColor1, loColor2, 0) loCenterBrush.SetSigmaBellShape(1, 1) ENDIF ENDWITH lnDownRad = .DownArcHeight + .CornerRad lnDownAngle = RTOD(ASIN(.CornerRad / lnDownRad)) IF llImageReady THIS.oGfx.DrawImage(THIS.SavedPicture, 0, 0, THIS.WIDTH, THIS.HEIGHT) ELSE TEXT TO this.AdjustBrush gnColor1 = <<.Color1>> gnColor2 = <<.Color2>> gnCenterPointX = <<.LeftMargin + lnMainRad>> gnCenterPointY = <> gnFocusScales=<<.FocusScales>> ENDTEXT * * Внешний контур * lcContour='' _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnDownRad,.CenterY - lnDownRad, lnDownRad*2, lnDownRad*2, lnDownAngle, 180 - lnDownAngle*2) && 1 lnDeltaX = lnDownRad * COS(DTOR(lnDownAngle)) lnX = .CenterX - lnDeltaX lnBottomY = .CenterY + .CornerRad _Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnBottomY, .CenterX - lnMainRad + .CornerRad, lnBottomY) && 2. Прямая * Левый угол скруглить lnX = .CenterX - lnMainRad lnBottomY = .CenterY - .CornerRad _Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnBottomY , .CornerRad*2, .CornerRad*2, 90, 90) && 3 * Большая дуга lnY = .CenterY -lnMainRad lnX = .CenterX - lnMainRad _Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnY, lnMainRad*2, lnMainRad*2, 180, 180) && 4 - большая дуга * Правый угол скруглить lnX = .CenterX + lnMainRad - .CornerRad*2 _Screen.FoxChartsHelper.NewRow( @lcContour, lnX, lnBottomY, .CornerRad*2, .CornerRad*2, 0, 90) && 5 lnX = .CenterX + lnMainRad - .CornerRad * Прямая к начальной точке _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnMainRad - .CornerRad, .CenterY + .CornerRad , .CenterX + lnDeltaX , .CenterY + .CornerRad) _Screen.FoxChartsHelper.DrawPath(.oGfx, loGrayPen, loCommonBrush , lcContour, 2, 2) _Screen.FoxChartsHelper.DrawPath(.oGfx, .PEN, .AdjustBrush , lcContour, 0, 0) * * Контур шкалы * IF .ShowScale lcContour='' _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnBigRadius, .CenterY - lnBigRadius, lnBigRadius*2, lnBigRadius*2, 180, 180) && 3 - большая дуга _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnBigRadius, .CenterY, .CenterX + lnSmallRadius, .CenterY) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius, .CenterY - lnSmallRadius, lnSmallRadius*2, lnSmallRadius*2, 0, -180) && 3 - малая дуга _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius, .CenterY, .CenterX - lnBigRadius, .CenterY) _Screen.FoxChartsHelper.DrawPath(.oGfx, .PEN, loScaleBrush , lcContour, 0, 0) ENDIF * Крупные засечки lnStep = (THIS.MaxValue-THIS.MinValue)/THIS.BigSteps lnDelta = 180/(THIS.MaxValue-THIS.MinValue) lnStep1 = lnStep / THIS.SmallSteps lnDelta1 = lnDelta / THIS.SmallSteps lnBigRadius2 = lnBigRadius - 1 lnSmallRadius2= lnSmallRadius + 1 lnSmallValue = 1.1 FOR lnValue = THIS.MinValue TO THIS.MaxValue STEP lnStep lcContour='' lnAngleDegree = (lnValue - THIS.MinValue)*lnDelta + 180 lnAngle = DTOR(lnAngleDegree) lnAngle1 = DTOR((lnValue - lnSmallValue - THIS.MinValue)*lnDelta + 180) lnAngle2 = DTOR((lnValue + lnSmallValue - THIS.MinValue)*lnDelta + 180) lnX1 = lnBigRadius1 * COS(lnAngle1) + .CenterX lnY1 = lnBigRadius1 *SIN(lnAngle1) + .CenterY lnX2 = lnBigRadius1 * COS(lnAngle2) + .CenterX lnY2 = lnBigRadius1 *SIN(lnAngle2) + .CenterY lnX3 = lnSmallRadius1 * COS(lnAngle) + .CenterX lnY3 = lnSmallRadius1 *SIN(lnAngle) + .CenterY _Screen.FoxChartsHelper.NewRow(@lcContour,lnX1, lnY1, lnX2, lnY2) _Screen.FoxChartsHelper.NewRow(@lcContour,lnX2, lnY2, lnX3, lnY3) _Screen.FoxChartsHelper.NewRow(@lcContour,lnX3, lnY3, lnX1, lnY1) _Screen.FoxChartsHelper.DrawPath(.oGfx, loDarkPen, loWhiteBrush , lcContour, 0, 0) .Legend.CAPTION = TRANSFORM(lnValue) .Legend._UpdateMeasures() IF BETWEEN(lnAngleDegree-180,45,135) lnX = lnX3-.Legend._Width/2 lnY = lnY3 .Legend.ALIGNMENT=2 ELSE lnX = lnX3 - IIF(lnAngleDegree-180>134,.Legend._Width-4,0) lnY = lnY3-.Legend._Height/2 .Legend.ALIGNMENT=1 ENDIF .Legend._DrawString(lnX, lnY, .Legend._Width,.Legend._Height,.F.,.oGfx) IF lnValue = THIS.MaxValue EXIT ENDIF * Мелкие засечки FOR lnLine = 1 TO THIS.SmallSteps-1 lcContour='' lnValue1 = lnValue + lnStep1 * lnLine lnAngle = DTOR((lnValue1 - THIS.MinValue)*lnDelta + 180) lnX1 = ROUND(lnBigRadius2 * COS(lnAngle) + .CenterX,0) lnY1 = ROUND(lnBigRadius2 * SIN(lnAngle) + .CenterY,0) lnX2 = ROUND(lnSmallRadius2 * COS(lnAngle) + .CenterX,0) lnY2 = ROUND(lnSmallRadius2 * SIN(lnAngle) + .CenterY,0) _Screen.FoxChartsHelper.NewRow(@lcContour,lnX1, lnY1, lnX2, lnY2) _Screen.FoxChartsHelper.DrawPath(.oGfx, loScalePen, , lcContour, 0, 0) NEXT NEXT * Центр lcContour='' _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - .CenterRadius, .CenterY - .CenterRadius, .CenterRadius*2, .CenterRadius*2, 0, 360) && Круг в центре _Screen.FoxChartsHelper.DrawPath(.oGfx, loDarkPen, loCenterBrush , lcContour, 0, 0) .renderosb () .SavedPicture = _SCREEN.SYSTEM.Drawing.BITMAP.FromVarbinary(THIS.PICTUREVAL) IF NOT EMPTY(.ID) .SavedPictureVal = .PictureVal ENDIF ENDIF * * Объект для распознавания шкалы * IF TYPE('.Scale') = 'U' lcContour='' _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnBigRadius1, .CenterY - lnBigRadius1, lnBigRadius1*2, lnBigRadius1*2, 180, 180) && 3 - большая дуга _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnBigRadius1, .CenterY, .CenterX + lnBigRadius1, .CenterY+4) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnBigRadius1, .CenterY+4, .CenterX + lnSmallRadius1, .CenterY+4) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX + lnSmallRadius1,.CenterY+4, .CenterX + lnSmallRadius1, .CenterY) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY - lnSmallRadius1, lnSmallRadius1*2, lnSmallRadius1*2, 0, -180) && 3 - малая дуга _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY, .CenterX - lnBigRadius1, .CenterY) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY, .CenterX - lnSmallRadius1, .CenterY+4) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnSmallRadius1, .CenterY+4, .CenterX - lnBigRadius1, .CenterY+4) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - lnBigRadius1, .CenterY+4, .CenterX - lnBigRadius1, .CenterY) .AddShape('Scale', 'Scale', lcContour, ; .CenterX - lnBigRadius, .CenterY - lnBigRadius, lnBigRadius*2, lnBigRadius) ENDIF * * Стрелка * lcContour='' lnArrowEndwidth = MIN(.ArrowEndwidth, lnBigRadius/4) lnSmallRadius2 = lnSmallRadius - lnArrowEndwidth .ArrowTopWidth = MIN(.ArrowTopWidth, .CenterRadius) .ArrowDownWidth = MIN(.ArrowDownWidth, .CenterRadius*2) lnTopBeta = ROUND(90 - RTOD(ACOS(.ArrowTopWidth/2/lnSmallRadius2)),0) lnDownBeta = ROUND(90 - RTOD(ACOS(.ArrowDownWidth/2/.CenterRadius)),0) _Screen.FoxChartsHelper.NewRow( @lcContour, .CenterX - .CenterRadius, .CenterY - .CenterRadius, ; .CenterRadius*2, .CenterRadius*2, lnArrowAngle-lnDownBeta, lnDownBeta*2) && Нижняя дуга lnDownLeft = ROUND(.CenterRadius * COS(DTOR(lnArrowAngle+lnDownBeta)) + .CenterX,0) lnDownTop = ROUND(.CenterRadius * SIN(DTOR(lnArrowAngle+lnDownBeta)) + .CenterY,0) lnUpLeft = ROUND(lnSmallRadius2 * COS(DTOR(lnArrowAngle+lnTopBeta)) + .CenterX,0) lnUpTop = ROUND(lnSmallRadius2 * SIN(DTOR(lnArrowAngle+lnTopBeta)) + .CenterY,0) _Screen.FoxChartsHelper.NewRow(@lcContour,lnDownLeft , lnDownTop, lnUpLeft, lnUpTop) lnEndLeft = ROUND(lnSmallRadius * COS(DTOR(lnArrowAngle)) + .CenterX,0) lnEndTop = ROUND(lnSmallRadius * SIN(DTOR(lnArrowAngle)) + .CenterY,0) _Screen.FoxChartsHelper.NewRow(@lcContour,lnUpLeft , lnUpTop, lnEndLeft, lnEndTop) lnDownLeft = ROUND(.CenterRadius * COS(DTOR(lnArrowAngle-lnDownBeta)) + .CenterX,0) lnDownTop = ROUND(.CenterRadius * SIN(DTOR(lnArrowAngle-lnDownBeta)) + .CenterY,0) lnUpLeft = ROUND(lnSmallRadius2 * COS(DTOR(lnArrowAngle-lnTopBeta)) + .CenterX,0) lnUpTop = ROUND(lnSmallRadius2 * SIN(DTOR(lnArrowAngle-lnTopBeta)) + .CenterY,0) _Screen.FoxChartsHelper.NewRow(@lcContour,lnEndLeft, lnEndTop,lnUpLeft , lnUpTop) _Screen.FoxChartsHelper.NewRow(@lcContour, lnUpLeft, lnUpTop,lnDownLeft , lnDownTop) _Screen.FoxChartsHelper.DrawPath(.oGfx, loDarkPen, loArrowBrush , lcContour, 0, 0) ENDWITH ENDPROC PROCEDURE createosb LPARAMETERS tnWidth, tnHeight This.DeleteOSB() LOCAL loRect IF EMPTY(m.tnWidth) m.tnWidth = This.Width m.tnHeight = This.Height ENDIF This._BMPWidth = m.tnWidth This._BMPHeight = m.tnHeight m.tnWidth = MAX(m.tnWidth,1) m.tnHeight = MAX(m.tnHeight,1) WITH _Screen.System.Drawing This.oBmp = .Bitmap.New(m.tnWidth, m.tnHeight) This.oGfx = .Graphics.FromImage(This.oBmp) This.oGfx.SmoothingMode = This.SmoothingMode This.oGfx.TextRenderingHint = This.TextRenderingHint This.oGfx.InterpolationMode = This.InterpolationMode ENDWITH ENDPROC PROCEDURE Destroy this.SaveProperties() DODEFAULT() ENDPROC PROCEDURE draw LPARAMETERS tnWidth, tnHeight, toGfx, llHide n000=SECONDS() LOCAL llRedraw THISFORM.LOCKSCREEN = .T. m.llRedraw = .F. IF EMPTY(m.tnWidth) THIS._WidthOverride = -1 THIS._HeightOverride = -1 m.tnWidth =THIS.WIDTH m.tnHeight = THIS.HEIGHT ELSE IF VARTYPE(tnWidth)='L' m.llRedraw = .T. m.tnWidth = THIS.WIDTH m.tnHeight = EVL(m.tnHeight, THIS.HEIGHT) ENDIF THIS._WidthOverride = m.tnWidth THIS._HeightOverride = m.tnHeight ENDIF THIS._cSize = BINTOC(EVL(m.tnWidth,THIS.WIDTH),"4rs") + BINTOC(EVL(m.tnHeight,THIS.HEIGHT),"4rs") IF THIS._BMPWidth <> m.tnWidth OR THIS._BMPHeight <> m.tnHeight OR THIS.RenderMode = 7 THIS.CreateOSB(m.tnWidth, m.tnHeight) ENDIF nn1=SECONDS()-n000 n000=SECONDS() THIS.BeforeDraw(llRedraw) nn2=SECONDS()-n000 n000=SECONDS() THIS.RenderOSB() nn3=SECONDS()-n000 n000=SECONDS() THIS.AfterDraw() nn4=SECONDS()-n000 n000=SECONDS() THISFORM.LOCKSCREEN = .F. TEXT TO lc <>, <>, <>, <> endtext *sl(lc) ENDPROC PROCEDURE editproperies LOCAL lcMode lcMode = THIS.Mode lcMode = _Screen.FoxChartsHelper.sl(THIS.Mode) IF NOT THIS.Mode == lcMode THIS.NewProps = .T. THIS.ReadProperties (lcMode) this.Draw(.t.) ENDIF ENDPROC PROCEDURE Init SET CLASSLIB TO foxchartsBeta.vcx ADDI IF TYPE('_Screen.FoxChartsHelper') = 'U' _Screen.ADDOBJECT('FoxChartsHelper', 'FoxChartsBeta.FoxChartsHelper') ENDIF WITH THIS TEXT TO .Props Arrowcolor Arrowdownwidth ArrowEndWidth ArrowTopWidth Bigsteps Centerradius Color1 Color2 Cornerrad DownArcHeight FocusScales Fontbold Fontname Fontsize Fontunderline Forecolor Gradientshapedirection Height Interpolationmode Left Leftmargin Maxvalue Minvalue Scalecolor Scalemargin Scalewidth Showcontour Showscale Smallsteps Topmargin Type Width ENDTEXT .RenderMode = 4 && Memory PNG .oGfx.SmoothingMode = _SCREEN.SYSTEM.Drawing.Drawing2D.SmoothingMode.AntiAlias .PEN = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.FromRGB(RGB(150,150,155)) , 3) .Legend = CREATEOBJECT("_Legend") .Legend.oGfx = .oGfx .Shapes = CREATEOBJECT('Container') .ReadProperties() .DRAW ENDWITH ENDPROC PROCEDURE interactivechange && Occurs when the user changes the value of a control using the keyboard or the mouse. ENDPROC PROCEDURE MouseMove LPARAMETERS nButton, nShift, nXCoord, nYCoord LOCAL lnCoordIndex, loObject WITH THIS IF nXCoord=THIS.nXCoord AND nYCoord=.nYCoord AND nButton=.nButton AND nShift = .nShift RETURN ENDIF .nButton = nButton .nShift = nShift .nXCoord = nXCoord .nYCoord = nYCoord m.lnCoordIndex = 0 lnX = nXCoord - obj2Client(THIS, 2) lnY = nYCoord - obj2Client(THIS, 1) loObject = .F. loShape = .Shapes.SCALE IF .ShowContour AND loShape.CheckMousePosition(lnX, lnY) IF VARTYPE(.ContourGraphics) # 'O' .ContourGraphics = _SCREEN.SYSTEM.Drawing.Graphics.FromHWnd(THISFORM.HWND) && Create a Graphics object .ContourGraphics.SmoothingMode = 4 .ContourPen = _SCREEN.SYSTEM.Drawing.PEN.New(_SCREEN.SYSTEM.Drawing.COLOR.FromARGB(212, RGB(255,255,255)) , 2) .ContourPen.DASHSTYLE = 0 ENDIF IF loShape.CoordNum # .Currindex THISFORM.CLS() loShape.DrawContour(.ContourGraphics, .ContourPen,, obj2Client(THIS, 2), obj2Client(THIS, 1)) ENDIF lnCoordIndex = loShape.CoordNum ENDIF IF .Currindex # lnCoordIndex AND lnCoordIndex=0 THISFORM.CLS() ENDIF .Currindex = lnCoordIndex ENDWITH ENDPROC PROCEDURE MouseUp LPARAMETERS nButton, nShift, tnMouseX, tnMouseY IF nButton=2 AND nShift=3 THIS.EditProperies() RETURN ENDIF LOCAL lnA, lnAngle, lnB, lnMouseX, lnMouseY, lnOldValue, lnStart, loShape tnMouseX = tnMouseX -Obj2Client(THIS,2) tnMouseY = tnMouseY - Obj2Client(THIS,1) WITH THIS FOR EACH loShape IN THIS.Shapes.OBJECTS IF loShape.TYPE = 'Scale' AND loShape.CheckMousePosition(tnMouseX, tnMouseY) lnMouseX = tnMouseX - .CenterX lnMouseY = tnMouseY - .CenterY lnA = 1 lnB = 1 lnAngle = MOD(RTOD(ATAN( lnMouseY / lnMouseX * lnA/lnB ))- 90, 360) IF lnMouseX < 0 m.lnAngle = 180 + m.lnAngle ENDIF lnAngle=MOD(360+lnAngle,360) lnStart = 90 lnOldValue = .VALUE IF NOT BETWEEN(lnAngle, lnStart, 360-lnStart) .VALUE = IIF(lnAngle>=<> ENDTEXT NEXT IF llStoreMode .Mode = lcSave RETURN ENDIF SELECT Gauges IF NOT ID == .ID LOCATE FOR ALLTRIM(ID) == .ID ENDIF REPLACE Mode WITH lcSave, PICTUREVAL WITH .SavedPictureVal ENDWITH ENDPROC PROCEDURE _checkmouseposition ENDPROC ENDDEFINE DEFINE CLASS shapes AS container *< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: clear && Clears the contents of a ComboBox or ListBox control. * * Height = 43 Name = "shapes" Visible = .F. Width = 113 * PROCEDURE clear && Clears the contents of a ComboBox or ListBox control. LOCAL lnLine FOR lnLine=THIS.OBJECTS.COUNT TO 1 STEP -1 THIS.REMOVEOBJECT (THIS.OBJECTS(lnLine).NAME) NEXT ENDPROC ENDDEFINE DEFINE CLASS tips AS label *< CLASSDATA: Baseclass="label" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: evalcaption *p: caption1 *p: caption2 *p: stringformat *p: value && Specifies the current state of a control. * * AutoSize = .T. BackColor = 255,255,228 Caption = "" caption1 = .F. caption2 = .F. Height = 17 Name = "tips" stringformat = 999 999 999 999.99 value = .F. Width = 0 WordWrap = .T. * PROCEDURE evalcaption WITH THIS DO CASE CASE VARTYPE(.VALUE) = 'N' .CAPTION = IIF(EMPTY(.StringFormat), TRANSFORM(.VALUE), CHRTRAN(ALLTRIM(TRANSFORM( .VALUE, .StringFormat)),[ ],[_])) CASE VARTYPE(.VALUE) $ 'CM' .CAPTION = .VALUE OTHERWISE .CAPTION='' ENDCASE IF NOT EMPTY(.Caption1) .CAPTION = IIF(EMPTY(.CAPTION),'' , .CAPTION + CHR(13)+CHR(10)) + TRANSFORM(.Caption1) ENDI IF NOT EMPTY(.Caption2) .CAPTION = IIF(EMPTY(.CAPTION),'' , .CAPTION + CHR(13)+CHR(10)) + TRANSFORM(.Caption2) ENDIF .WordWrap = CHR(13) $ .Caption .Width = 2000 .AutoSize=.T. * .CAPTION = CHRTRAN(.CAPTION,'_',' ') ENDWITH ENDPROC ENDDEFINE