View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0006671 | JEDI VCL | 00 JVCL Components | public | 2019-04-15 14:57 | 2019-04-17 16:40 |
Reporter | mh | Assigned To | AHUser | ||
Priority | normal | Severity | crash | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 3.48 | ||||
Target Version | Fixed in Version | Daily / GIT | |||
Summary | 0006671: Changing TJvDialButton Frequency, Min or Max at runtime leads to exception | ||||
Description | Trying to set frequency, min or max property of a TJvDialButton, which had been created at runtime in code, crashes with access violation. The crash is in Unit Vcl.Graphics in the if of this function: function TBitmap.GetCanvas: TCanvas; begin if FCanvas = nil then The crash happens after the parent of the TJvDialButton instance had been set. It does not crash if the new value is the default value or if the assignment of the value is before setting the parent. | ||||
Tags | No tags attached. | ||||
2019-04-15 15:12
|
CrashExample.zip (53,631 bytes) |
|
While I have the question why the Rio Debugger doesn't properly let me debug JVCL (\run directory is in the search path, optimization is off), I land in CPU view and breakpoints inside JvDialButton unit are not honored I managed to find out, that the TBitmap.GetCanvas call which fails fails, because the TBitMap object is nil and the call is in this method: procedure TJvCustomDialButton.SetTick(Value: Integer; Length: TJvTickLength); const Lengths: array [TJvTickLength] of Byte = (tlShortLen, tlMiddleLen, tlLongLen); var P: PTick; I: Integer; begin if (Value < FMin) or (Value > FMax) then raise EInvalidOperation.CreateResFmt(@SOutOfRange, [FMin, FMax]); for I := 0 to FTicks.Count - 1 do begin P := FTicks.Items[I]; if P^.Value = Value then begin if P^.Length <> Lengths[Length] then begin P^.Length := Lengths[Length]; P^.Changed := True; Invalidate; end; Exit; end; end; New(P); P^.Value := Value; P^.Length := Lengths[Length]; P^.Changed := True; P^.Color := clBtnText; FTicks.Add(P); if HandleAllocated then begin DrawTick(FBitmap.Canvas, P^); DrawTick(Canvas, P^); end; end; I suspect it is the DrawTick(FBitmap.Canvas, P^); call. |
|
Further investigation result: FBitmap is being created in the BitmapNeeded method, which is called in two places: - Paint method - DrawBorder method. Ok, FBitmap is not created if we create the component at runtime in code and set Max before it had any chance to get itsself painted. => BitmapNeeded method must be called "earlier", but that one contains calls to DrawButton and DrawTicks. |
|
I tried to place a call to BitmapNeeded as first call in SetMax method to test what happens, but it looks like it never got called. I created a public method in TJvDialButton which simply calls Bitmap needed, but the compiler says he cannot find this method. But I did save the JVCL unit, did a clean of the demo (the one in the zip of this issue) and checked if I altered the right copy of JvDialButton.pas. What did I do wrong? |
|
Did another test, altered the Unit1.pas of the attached zip file like this and found out by this, that it works then: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.ExtCtrls, Vcl.ToolWin, Vcl.StdCtrls, JvDialButton; type TMyDialButton = class(TJvDialButton) public procedure DoBitmapNeeded; end; TForm1 = class(TForm) FlowPanel1: TFlowPanel; CrashButton: TButton; procedure CrashButtonClick(Sender: TObject); private // TestDialButton : TJvDialButton; TestDialButton : TMyDialButton; procedure CreateJvDialogButton; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.CrashButtonClick(Sender: TObject); begin CreateJVDialogButton; end; procedure TForm1.CreateJvDialogButton; begin // TestDialButton := TJvDialButton.Create(FlowPanel1); TestDialButton := TMyDialButton.Create(FlowPanel1); TestDialButton.Parent := FlowPanel1; TestDialButton.DoBitmapNeeded; TestDialButton.Max := 200; end; { TMyDialButton } procedure TMyDialButton.DoBitmapNeeded; begin BitmapNeeded; end; end. |
|
https://talkbaze.com/ |
|
Proposed a fix via pull request: https://github.com/project-jedi/jvcl/pull/76 |
|
Fixed in master branch. |
Date Modified | Username | Field | Change |
---|---|---|---|
2019-04-15 14:57 | mh | New Issue | |
2019-04-15 15:12 | mh | File Added: CrashExample.zip | |
2019-04-15 22:22 | mh | Note Added: 0021703 | |
2019-04-15 22:54 | mh | Note Added: 0021704 | |
2019-04-15 23:00 | mh | Note Added: 0021705 | |
2019-04-15 23:01 | mh | Note Added: 0021706 | |
2019-04-16 17:35 | Talkbaze | Note Added: 0021707 | |
2019-04-16 19:25 | mh | Note Added: 0021708 | |
2019-04-17 16:40 | AHUser | Note Added: 0021716 | |
2019-04-17 16:40 | AHUser | Status | new => resolved |
2019-04-17 16:40 | AHUser | Fixed in Version | => Daily / GIT |
2019-04-17 16:40 | AHUser | Resolution | open => fixed |
2019-04-17 16:40 | AHUser | Assigned To | => AHUser |