![]() | Steema Issues DatabaseNote: This database is for bugs and wishes only. For technical support help, if you are a customer please visit our online forums;otherwise you can use StackOverflow. Before using this bug-tracker we recommend a look at this document, Steema Bug Fixing Policy. |
| Summary: | Inner TColorLineTool component of TColorBandTool has no name, thus causing corrupt DFM file | ||
|---|---|---|---|
| Product: | VCL TeeChart | Reporter: | Jarl Balgruuf the Greater <mertelmeyer> |
| Component: | Tools | Assignee: | Steema Issue Manager <issuemanager> |
| Status: | RESOLVED FIXED | ||
| Severity: | critical | CC: | david, mertelmeyer, yeray |
| Priority: | --- | ||
| Version: | 140512 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows | ||
| Chart Series: | --- | Delphi / C++ Builder RAD IDE Version: | RAD XE5, RAD XE6 |
| Attachments: | List index out of bounds error adding a TFrame with a TChart and a TColorBandTool at designtime | ||
(1) Modifying the source in order to give those components names in the DFM somehow gave them names, but the application still crashes at runtime when a TColorBandTool is present (2) It works flawlessly on TeeChart Pro VCL 130920. The resulting TColorBandTool looks completely different (and valid) in the DFM: object ChartTool1: TColorBandTool EndLinePen.EndStyle = esFlat EndValue = 8.000000000000000000 StartLinePen.EndStyle = esFlat StartValue = 2.000000000000000000 AxisID = 0 end I hope I'm not stealing too much of your time and/or making a fool out of myself, but this is probably related to TColorBandTool.ReadState(..), starting at line 3779 of Build '2014.11.140425' in Sources\VCL\VCLTee.TeeTools.pas. I can only take a wild guess because I honestly cannot understand those methods. Created attachment 199 [details]
List index out of bounds error adding a TFrame with a TChart and a TColorBandTool at designtime
Reproduced with XE6 at design time with the attached project.
If you try to add the TFrame2 to the TForm1 at designtime, it gives you a
"List index out of bounds (0)" exception (complete error message below).
However, if you add it at runtime (as done in the project at TForm1.FormCreate), it works without problems.
[5017640D]{rtl200.bpl } System.Classes.TComponent.GetComponent (Line 16136, "System.Classes.pas" + 1) + $F
[01214C1F]{designide200.bpl} Update.TUpdateObject.AddChild (Line 753, "Update.pas" + 10) + $B
[193465D0]{TeePro920.bpl} Vcltee.Teetools.TColorBandTool.GetChildren + $1C
[01214B3B]{designide200.bpl} Update.TUpdateObject.Create (Line 722, "Update.pas" + 31) + $1E
[01214C42]{designide200.bpl} Update.TUpdateObject.AddChild (Line 755, "Update.pas" + 12) + $1A
[422A772C]{Tee920.bpl } Vcltee.Chart.TCustomChart.GetChildren + $40
[01214B3B]{designide200.bpl} Update.TUpdateObject.Create (Line 722, "Update.pas" + 31) + $1E
[01214C42]{designide200.bpl} Update.TUpdateObject.AddChild (Line 755, "Update.pas" + 12) + $1A
[504FADE7]{vcl200.bpl } Vcl.Controls.TWinControl.GetChildren (Line 12430, "Vcl.Controls.pas" + 4) + $D
[5063800B]{vcl200.bpl } Vcl.Forms.TCustomFrame.GetChildren (Line 3491, "Vcl.Forms.pas" + 1) + $A
[5005F18E]{rtl200.bpl } System.@CallDynaInst (Line 16236, "System.pas" + 4) + $0
[01214B3B]{designide200.bpl} Update.TUpdateObject.Create (Line 722, "Update.pas" + 31) + $1E
[01215A7A]{designide200.bpl} Update.TUpdateManager.Create (Line 1202, "Update.pas" + 9) + $14
[01232E1B]{designide200.bpl} ComponentDesigner.TComponentRoot.FrameCreateComponent (Line 3195, "ComponentDesigner.pas" + 36) + $2D
[01232FF5]{designide200.bpl} ComponentDesigner.TComponentRoot.ReaderFindComponentClass (Line 3243, "ComponentDesigner.pas" + 13) + $20
[01232F2F]{designide200.bpl} ComponentDesigner.TComponentRoot.ReaderCreateComponent (Line 3223, "ComponentDesigner.pas" + 1) + $7
[50166B0C]{rtl200.bpl } System.Classes.CreateComponent (Line 10147, "System.Classes.pas" + 5) + $14
[50166D90]{rtl200.bpl } System.Classes.TReader.ReadComponent (Line 10202, "System.Classes.pas" + 10) + $6
[5016812A]{rtl200.bpl } System.Classes.TReader.ReadComponents (Line 10741, "System.Classes.pas" + 11) + $1
[0123378E]{designide200.bpl} ComponentDesigner.TComponentRoot.ReadStream (Line 3422, "ComponentDesigner.pas" + 28) + $14
[01233400]{designide200.bpl} ComponentDesigner.TComponentRoot.SelectReadStream (Line 3348, "ComponentDesigner.pas" + 4) + $10
[012328D3]{designide200.bpl} ComponentDesigner.TComponentRoot.PasteSelectionFromStream (Line 3057, "ComponentDesigner.pas" + 3) + $A
[0123CEA7]{designide200.bpl} ComponentDesigner.TComponentDesigner.PasteSelectionFromStream (Line 6670, "ComponentDesigner.pas" + 2) + $9
[21D3E331]{delphicoreide200.bpl} CompPalMgr.TFramePalettePageItemDelegate.CreateComponent (Line 3098, "CompPalMgr.pas" + 44) + $17
[01230F39]{designide200.bpl} ComponentDesigner.TComponentRoot.DoCreateComponent (Line 2440, "ComponentDesigner.pas" + 25) + $17
[01236B5A]{designide200.bpl} ComponentDesigner.TComponentRoot.CreateCurrentComponent (Line 4619, "ComponentDesigner.pas" + 2) + $32
[01252002]{designide200.bpl} Surface.TDesignSurface.CreateItem (Line 196, "Surface.pas" + 1) + $11
[01201D92]{designide200.bpl} Designer.TDesigner.DoDragCreate (Line 795, "Designer.pas" + 1) + $F
[01202640]{designide200.bpl} Designer.TDesigner.DragEnd (Line 975, "Designer.pas" + 19) + $3
[01204C80]{designide200.bpl} Designer.TDesigner.MouseUp (Line 1764, "Designer.pas" + 1) + $2
[51FBEF52]{vcldesigner200.bpl} VCLSurface.MouseEvent (Line 3187, "VCLSurface.pas" + 45) + $11
[5005FA4F]{rtl200.bpl } System.TMonitor.Exit (Line 17352, "System.pas" + 2) + $7
[51FBFB3F]{vcldesigner200.bpl} VCLSurface.TVclDesignSurface.IsDesignMsg (Line 3448, "VCLSurface.pas" + 48) + $6
[5005F042]{rtl200.bpl } System.@IsClass (Line 16068, "System.pas" + 1) + $8
[504F297B]{vcl200.bpl } Vcl.Controls.TControl.WndProc (Line 7145, "Vcl.Controls.pas" + 4) + $21
[50177B88]{rtl200.bpl } System.Classes.StdWndProc (Line 17064, "System.Classes.pas" + 6) + $1
[504F6F6F]{vcl200.bpl } Vcl.Controls.TWinControl.IsControlMouseMsg (Line 9815, "Vcl.Controls.pas" + 1) + $9
[504F7739]{vcl200.bpl } Vcl.Controls.TWinControl.WndProc (Line 10047, "Vcl.Controls.pas" + 153) + $6
[50639B40]{vcl200.bpl } Vcl.Forms.TCustomForm.WndProc (Line 4426, "Vcl.Forms.pas" + 206) + $5
[51FC866F]{vcldesigner200.bpl} VCLFormContainer.TControlSizer.ControlWndProc (Line 313, "VCLFormContainer.pas" + 33) + $C
[504F6D80]{vcl200.bpl } Vcl.Controls.TWinControl.MainWndProc (Line 9759, "Vcl.Controls.pas" + 3) + $6
[50177B88]{rtl200.bpl } System.Classes.StdWndProc (Line 17064, "System.Classes.pas" + 6) + $1
[506A301B]{vcl200.bpl } Vcl.AppEvnts.TMultiCaster.GetAppEvents (Line 654, "Vcl.AppEvnts.pas" + 1) + $5
[50644441]{vcl200.bpl } Vcl.Forms.TApplication.CancelHint (Line 11180, "Vcl.Forms.pas" + 6) + $D
[506430DF]{vcl200.bpl } Vcl.Forms.TApplication.ProcessMessage (Line 10351, "Vcl.Forms.pas" + 23) + $1
[50643122]{vcl200.bpl } Vcl.Forms.TApplication.HandleMessage (Line 10381, "Vcl.Forms.pas" + 1) + $4
[50643455]{vcl200.bpl } Vcl.Forms.TApplication.Run (Line 10519, "Vcl.Forms.pas" + 26) + $3
The suggested workaround (adding the TFrame with the corrupted DFM at runtime) does not work (at least on XE5): Here is the callstack: :00674126 TTeeCustomToolAxis.ReadAxis + $12 :006740b2 TTeeCustomToolAxis.DefineProperties + $2E :004be096 TReader.ReadDataInner + $1A :004be078 TReader.ReadData + $6C :004c8c0e TComponent.ReadState + $6 :004be10a TReader.ReadDataInner + $8E :004be078 TReader.ReadData + $6C :004c8c0e TComponent.ReadState + $6 :004be10a TReader.ReadDataInner + $8E :004be078 TReader.ReadData + $6C :004c8c0e TComponent.ReadState + $6 :00633ddb TCustomTeePanel.ReadState + $27 :004bdeee TReader.ReadComponent + $122 :004be10a TReader.ReadDataInner + $8E :004be049 TReader.ReadData + $3D :004c8c0e TComponent.ReadState + $6 :004bf006 TReader.ReadRootComponent + $1DA :004b8f03 TStream.ReadComponent + $37 :004ae9c0 InternalReadComponentRes + $5C :004b0314 InitComponent + $64 :004b03a2 InitInheritedComponent + $66 :005c4315 TCustomFrame.Create + $69 Unit1.TForm1.FormCreate($8338E0) :005c4afb TCustomForm.DoCreate + $37 :005c471b TCustomForm.AfterConstruction + $17 :005c46cc TCustomForm.Create + $1A0 :005cf611 TApplication.CreateForm + $79 Project1.Project1 Just tried the last attachment with XE6, no errors at all, both at design-time and run-time. (In reply to david berneda from comment #5) > Just tried the last attachment with XE6, no errors at all, both at > design-time and run-time. Placing the frame on the form (design-time) and THEN running the program will still fail: The program crashes then at runtime, failing to create the form. Tested with XE6 Update 1 + TeeChart Pro v2014.11.140512 32bit VCL. Note: The same problem also happens with simple inherited forms (not TFrame). Naming the ColorLine objects is not possible as it'll interfere in the Object TreeView and other places. (Other kind of Streaming load/save errors) Fixed. The fix is not the ideal, but its the only solution I've found so far to solve the problem. To avoid the Delphi ide to raise the design-time exception when loading a form or frame inherited from another form or frame, the solution is to not store the inherited StartLine and EndLine properties of the ColorBand tool. ie: All properties in the ancestor can be modified and will be saved as usually, but any change in the inherited form or frame will not be stored at design-time. Changes can be done at runtime by code: procedure TForm2.FormCreate(Sender: TObject); begin inherited; ChartTool1.StartLine.Value:=123; end; At least, loading the form will not raise any error. Not ideal, but there is no other workaround as this is a limitation of the default TReader.FindAncestorComponent method. btw: The same problem happens when using simple inherited forms, with no Frame involved. |
Disclaimer: I filed it as version '140220' but I am actually using '2014.11.140425 BETA'. But I believe this does not matter [1] As the title says: TeeTools::TColorBandTool.NewColorLine() creates a TColorLineTool that has no name. Therefore, a TColorBandTool gets written to the DFM like this: object Chart1: TChart [...] object ChartTool1: TColorBandTool <-- It has a name. All is well. Color = 8388863 EndValue = 8.000000000000000000 ResizeEnd = True ResizeStart = True StartValue = 6.000000000000000000 Transparency = 12 AxisID = 0 object TColorLineTool <-- THIS IS BAD DragRepaint = True Value = 6.000000000000000000 AxisID = 0 object TAnnotationTool <-- THIS IS BAD Shape.Alignment = taCenter Shape.Shadow.Visible = False Shape.TextAlignment = taCenter TextAlignment = taCenter end end object TColorLineTool <-- THIS IS BAD DragRepaint = True Value = 8.000000000000000000 AxisID = 0 object TAnnotationTool Shape.Alignment = taCenter Shape.Shadow.Visible = False Shape.TextAlignment = taCenter TextAlignment = taCenter end end end end As a side effect, the form designer refuses to place frames that have a chart with a TColorBandTool. However, if a chart is placed directly on a form, you're only going to find with an access violation in VCLTee.TeEngine.pas at runtime! I believe the classless function TeeTools::CreateAnnotation(..) also suffers from this: The annotation also does not have a name. Workaround: Not sure. I'll edit the TeeChart source files (Never done that before) and see how this goes... [1] The only difference between 140220 and 140425 regarding my issue is that " procedure TColorBandTool.InitColorLine(var Value:TColorLineTool); " changed to " procedure TColorBandTool.InitColorLine(const Value:TColorLineTool); ".