Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TTreeView drawing error when deactivating a form

I have found what appears to be a bug related to TTreeView.

  • Take a form containing a TTreeView with HideSelection set to True.
  • Make the tree view multi-select and select multiple items in the tree view.
  • Show another form so that your app has two forms.
  • Give the tree view the focus and then click in the other form.

The result looks like this:

enter image description here

But in fact there should be no items highlighted. Interestingly, the last item is selected and it is no longer highlighted, as indeed should all the other items. It appears that the most recently clicked item is the one that gets the special treatment.

If instead you click in the edit box (or indeed any other control that takes focus) then all items are correctly hidden. So it's fine for the focus to transfer to another control on the form—the problem seems to be limited to deactivating the form.

I have discovered by trial and error that I can fix this by calling Invalidate on the tree view whenever the form is deactivated and activated (need to prevent mirror image of the bug). However, I'm looking for a better understanding of what the bug is and how to fix it in a less invasive manner, i.e. at the tree view level rather than the containing form level.

So, to summarise, my questions are:

  1. What exactly is causing the problem?
  2. How can I fix it without writing code that hooks TForm events?

Submitted the issue as QC#94908.

like image 638
David Heffernan Avatar asked Jun 08 '11 12:06

David Heffernan


1 Answers

The solution seems to be to respond to NM_SETFOCUS and NM_KILLFOCUS notifications by invalidating selected nodes. You can modify TCustomTreeView.CNNotify directly or you can write a new TCustomTreeView descendant. Here is a quick hack only to show the missing code:

type
  TTreeView = class(ComCtrls.TTreeView)
  private
    procedure CNNotify(var Message: TWMNotifyTV); message CN_NOTIFY;
  end;

procedure TTreeView.CNNotify(var Message: TWMNotifyTV);
begin
  case Message.NMHdr^.code of
    NM_KILLFOCUS, NM_SETFOCUS:
      InvalidateSelectionsRects;
  end;
  inherited;
end;

Edit: David's QC report.

like image 64
Ondrej Kelle Avatar answered Oct 13 '22 22:10

Ondrej Kelle