View Issue Details

IDProjectCategoryView StatusLast Update
0004905JEDI VCL00 JVCL Componentspublic2009-10-25 12:16
ReportertetarddAssigned ToAHUser 
PrioritynormalSeveritymajorReproducibilityalways
Status resolvedResolutionfixed 
Product Version3.36 
Target VersionFixed in Version3.39 
Summary0004905: TJvTreeView.OnNodeCheckChange not triggered
DescriptionTJvTreeView.OnNodeCheckChange not triggered when clicking the check box in the control. It's only triggered when changing the TJcTreeNode.Checked in code.
Additional InformationSteps to reproduce:
- Add a TJvTreeView in a form, create a few items, configure to have the check boxes visible.

- Set a ShowMessage('xxx') code in the TJvTreeView.OnNodeCheckChange of the tree view.

- Run and change the check mark. No message.
TagsNo tags attached.

Activities

2009-08-28 14:28

 

Bugs TJvTreeView.zip (390,675 bytes)

tetardd

2009-10-22 22:43

reporter   ~0016797

Proposed fix:

Here is a fix that seems to work (see code marked "// DT: Proposed fix:"):

procedure TJvTreeView.WMLButtonDown(var Msg: TWMLButtonDown);
var
  Node: TTreeNode;
  FirstNodeIndex, I: Integer;
begin
  ResetPostOperationFlags;
  with Msg do
    if (htOnItem in GetHitTestInfoAt(XPos, YPos)) then
    begin
      if MultiSelect then
      begin
        Node := GetNodeAt(XPos, YPos);
        if Assigned(Node) and (ssCtrl in KeysToShiftState(Keys)) then
        begin
          SelectItem(Node, IsNodeSelected(Node));
        end
        else
        if Assigned(Node) and (ssShift in KeysToShiftState(Keys)) then
        begin
          FirstNodeIndex := 0;

          {$IFDEF COMPILER6_UP}
          if SelectionCount > 0 then
            FirstNodeIndex := Selections[0].Index;
          {ELSE}
          if Assigned(Selected) then
            FirstNodeIndex := Selected.Index;
          {$ENDIF COMPILER6_UP}

          ClearSelection;
          if FirstNodeIndex < Node.Index then
          begin
            for I := FirstNodeIndex to Node.Index do
              SelectItem(Items[I]);
          end
          else
          begin
            for I := FirstNodeIndex downto Node.Index do
              SelectItem(Items[I]);
          end;
        end
        else
        begin
          ClearSelection;
          SelectItem(Node);
        end;
      end;
    End;

    // DT: Proposed fix:
    If htOnStateIcon in GetHitTestInfoAt(Msg.XPos, Msg.YPos) then
         If Checkboxes Then
              DoNodeCheckedChange(TJvTreeNode(Selected));
    // End of proposed fix.

  inherited;
end;

tetardd

2009-10-23 13:27

reporter   ~0016798

Note: here, it's a quick and very dirty fix to test that it work. Of course, the code of the whole procedure could be rewritten to optimise it, in particular, have only 1 call to GetHitTestInfoAt.

tetardd

2009-10-24 08:04

reporter   ~0016804

Sorry, this is not a suitable fix (see below issues it has) so ignore it:
1- The OnNodeCheckedChange is triggered passing the wrong node.
2- The Checked state of the node is not correctly set in the event either.

tetardd

2009-10-25 08:50

reporter   ~0016806

OK. Looking at it in details, I think the following should be implemented:

However, I could not make it work.
Now, I found a hack that's not brilliant but it work for now.

Define:
DoNodeCheckChange = wm_User + 1;

procedure TJvTreeView.WMLButtonDown(var Msg: TWMLButtonDown);
var
  Node: TTreeNode;
  FirstNodeIndex, I: Integer;
begin
  ResetPostOperationFlags;
  with Msg do
    if (htOnItem in GetHitTestInfoAt(XPos, YPos)) then
    begin
      if MultiSelect then
      begin
        Node := GetNodeAt(XPos, YPos);
        if Assigned(Node) and (ssCtrl in KeysToShiftState(Keys)) then
        begin
          SelectItem(Node, IsNodeSelected(Node));
        end
        else
        if Assigned(Node) and (ssShift in KeysToShiftState(Keys)) then
        begin
          FirstNodeIndex := 0;

          {$IFDEF COMPILER6_UP}
          if SelectionCount > 0 then
            FirstNodeIndex := Selections[0].Index;
          {ELSE}
          if Assigned(Selected) then
            FirstNodeIndex := Selected.Index;
          {$ENDIF COMPILER6_UP}

          ClearSelection;
          if FirstNodeIndex < Node.Index then
          begin
            for I := FirstNodeIndex to Node.Index do
              SelectItem(Items[I]);
          end
          else
          begin
            for I := FirstNodeIndex downto Node.Index do
              SelectItem(Items[I]);
          end;
        end
        else
        begin
          ClearSelection;
          SelectItem(Node);
        end;
      end;
    End;

  // David Tetard:
  // Cannot call DoNodeCheckedChange now as the Selection and Checked state are
  // not yet properly set.
  // Defer call by posting a message:
  If htOnStateIcon In GetHitTestInfoAt(Msg.XPos, Msg.YPos) Then
       If FCheckBoxes Then
            PostMessage(Handle, wm_DoNodeCheckChange, 0, 0);

  inherited;
end;


// David Tetard:
Procedure TJvTreeView.WMDoNodeCheckChange(var Msg: TMessage);
Begin
     // Now, Selected is the one ticked and its Check state is the one shown
     // in the control:
     DoNodeCheckedChange(TJvTreeNode(Selected));
End;

AHUser

2009-10-25 12:16

developer   ~0016808

Fixed in SVN.

Issue History

Date Modified Username Field Change
2009-08-28 14:14 tetardd New Issue
2009-08-28 14:28 tetardd File Added: Bugs TJvTreeView.zip
2009-09-09 19:34 obones Status new => acknowledged
2009-10-22 22:43 tetardd Note Added: 0016797
2009-10-23 13:27 tetardd Note Added: 0016798
2009-10-24 08:04 tetardd Note Added: 0016804
2009-10-25 08:50 tetardd Note Added: 0016806
2009-10-25 12:16 AHUser Note Added: 0016808
2009-10-25 12:16 AHUser Status acknowledged => resolved
2009-10-25 12:16 AHUser Fixed in Version => Daily / SVN
2009-10-25 12:16 AHUser Resolution open => fixed
2009-10-25 12:16 AHUser Assigned To => AHUser