Project JEDI - Issue Tracker
Mantis Bugtracker

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0006671 [JEDI VCL] 00 JVCL Components crash always 2019-04-15 14:57 2019-04-17 16:40
Reporter mh View Status public  
Assigned To AHUser
Priority normal Resolution fixed  
Status resolved   Product Version 3.48
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.

Additional Information
Tags No tags attached.
Attached Files zip file icon CrashExample.zip [^] (53,631 bytes) 2019-04-15 15:12

- Relationships

-  Notes
(0021703)
mh (reporter)
2019-04-15 22:22

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.
(0021704)
mh (reporter)
2019-04-15 22:54

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.
(0021705)
mh (reporter)
2019-04-15 23:00

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?
(0021706)
mh (reporter)
2019-04-15 23:01

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.
(0021707)
Talkbaze (reporter)
2019-04-16 17:35

https://talkbaze.com/ [^]
(0021708)
mh (reporter)
2019-04-16 19:25

Proposed a fix via pull request:
https://github.com/project-jedi/jvcl/pull/76 [^]
(0021716)
AHUser (developer)
2019-04-17 16:40

Fixed in master branch.

- Issue History
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


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker