Recent

Author Topic: Issues with TVirtualString Tree  (Read 2083 times)

pusuni

  • Jr. Member
  • **
  • Posts: 72
Issues with TVirtualString Tree
« on: October 19, 2018, 02:42:58 pm »
Hi! I have some  problems with VirtualString Tree in lazarus:

The first of them: I don't know how I can detect when I  click  with the mouse in the red circle. The control has one event, Onclick, but it happens when I make click in every place in the control.Any suggestions?

https://image.ibb.co/m7Fsy0/Sin-t-tulo1.jpg



The other problem happens when I use  icons with 24x24  pixels . the icons overlap. I found the "DefaultNodeHeight" property. It fixed the height issue, but no the width.  :'(

https://image.ibb.co/mQAsy0/Sin-t-tulo2.jpg


https://image.ibb.co/nwtvJ0/Sin-t-tulo3.jpg


Thanks in advanced
« Last Edit: October 20, 2018, 10:36:54 am by pusuni »

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: Issues with TshellTreeView
« Reply #1 on: October 19, 2018, 04:18:00 pm »
Part 1 of your question: The OnNodeClick event provides a HitTest parameter from which "everything" can be queried:

Code: Pascal  [Select][+][-]
  1. type
  2.   THitInfo = record
  3.     HitNode: PVirtualNode;
  4.     HitPositions: THitPositions;
  5.     HitColumn: TColumnIndex;
  6.     HitPoint: TPoint;
  7.   end;
  8.  
  9. procedure TForm1.VirtualStringTree1NodeClick(Sender: TBaseVirtualTree;
  10.   const HitInfo: THitInfo);
  11. begin
  12.   Memo1.Lines.Clear;
  13.   Memo1.Lines.Add('Clicked position: ');
  14.   if hiAbove in HitInfo.HitPositions then
  15.     Memo1.Lines.Add('above the client area (if relative) or the absolute tree area');
  16.   if hiBelow in HitInfo.HitPositions then
  17.     Memo1.Lines.Add('below the client area (if relative) or the absolute tree area');
  18.   if hiNowhere in HitInfo.HitPositions then
  19.     Memo1.Lines.Add('no node is involved (possible only if the tree is not as tall as the client area');
  20.   if hiOnItem in HitInfo.HitPositions then
  21.     Memo1.Lines.Add('on the bitmaps/buttons or label associated with an item');
  22.   if hiOnItemButton in HitInfo.HitPositions then
  23.     Memo1.Lines.Add('on the button associated with an item');
  24.   if hiOnItemButtonExact in HitInfo.HitPositions then
  25.     Memo1.Lines.Add('exactly on the button associated with an item');
  26.   if hiOnItemCheckbox in HitInfo.HitPositions then
  27.     Memo1.Lines.Add('on the checkbox if enabled');
  28.   if hiOnItemIndent in HitInfo.Hitpositions then
  29.     Memo1.Lines.Add('in the indentation area in front of a node');
  30.   if hiOnItemLabel in HitInfo.HitPositions then
  31.     Memo1.Lines.Add('on the normal text area associated with an item');
  32.   if hiOnItemLeft in HitInfo.Hitpositions then
  33.     Memo1.Lines.Add('in the area to the left of a node''s text area (e.g. when right aligned or centered)');
  34.   if hiOnItemRight in HitInfo.Hitpositions then
  35.     Memo1.Lines.Add('in the area to the right of a node''s text area (e.g. if left aligned or centered)');
  36.   if hiOnNormalIcon in HitInfo.HitPositions then
  37.     Memo1.Lines.Add('on the "normal" image');
  38.   if hiOnStateIcon in HitInfo.HitPositions then
  39.     memo1.Lines.Add('on the state image');
  40.   if hiToLeft in HitInfo.HitPositions then
  41.     Memo1.Lines.Add('to the left of the client area (if relative) or the absolute tree area');
  42.   if hiToRight in HitInfo.HitPositions then
  43.     Memo1.Lines.Add('to the right of the client area (if relative) or the absolute tree area');
  44.   if hiUpperSplitter in HitInfo.HitPositions then
  45.     Memo1.Lines.Add('in the upper splitter area of a node');
  46.   if hiLowerSplitter in HitInfo.HitPositions then
  47.     Memo1.Lines.Add('in the lower splitter area of a node');
  48. end;

As of part 2 of your question:
It is working fine for me - see attached demo (Win 10). Did you set Width and Height of the ImageList correctly before adding images?

[EDIT]
Ah, now I see a discrepancy between the title (ShellTreeView) and the text (VirtualStringTree) of your post. These are two different things. My answer is for VirtualStringTree.
« Last Edit: October 19, 2018, 04:38:38 pm by wp »

pusuni

  • Jr. Member
  • **
  • Posts: 72
Re: Issues with TshellTreeView
« Reply #2 on: October 20, 2018, 10:36:41 am »
First of all. Thanks a lot wp!!

I didn't know, why I wrote "TshellTreeView" when my question is about  VirtualString Tree. In the post it is right. I changed the title of topic

 2ª question: I'revised my code and yes it's  wrong: I wrote 16x24 dimensions .I don't know why i wrote that : my icons are 24x24 bits  %)

1ª question: thanks for the code I'm going to check if it validate for my purpose.
« Last Edit: October 20, 2018, 11:58:38 am by pusuni »

pusuni

  • Jr. Member
  • **
  • Posts: 72
Re: Issues with TshellTreeView
« Reply #3 on: October 20, 2018, 11:57:51 am »
Part 1 of your question: The OnNodeClick event provides a HitTest parameter from which "everything" can be queried:

Code: Pascal  [Select][+][-]
  1. type
  2.   THitInfo = record
  3.     HitNode: PVirtualNode;
  4.     HitPositions: THitPositions;
  5.     HitColumn: TColumnIndex;
  6.     HitPoint: TPoint;
  7.   end;
  8.  
  9. procedure TForm1.VirtualStringTree1NodeClick(Sender: TBaseVirtualTree;
  10.   const HitInfo: THitInfo);
  11. begin
  12.   Memo1.Lines.Clear;
  13.   Memo1.Lines.Add('Clicked position: ');
  14.   if hiAbove in HitInfo.HitPositions then
  15.     Memo1.Lines.Add('above the client area (if relative) or the absolute tree area');
  16.   if hiBelow in HitInfo.HitPositions then
  17.     Memo1.Lines.Add('below the client area (if relative) or the absolute tree area');
  18.   if hiNowhere in HitInfo.HitPositions then
  19.     Memo1.Lines.Add('no node is involved (possible only if the tree is not as tall as the client area');
  20.   if hiOnItem in HitInfo.HitPositions then
  21.     Memo1.Lines.Add('on the bitmaps/buttons or label associated with an item');
  22.   if hiOnItemButton in HitInfo.HitPositions then
  23.     Memo1.Lines.Add('on the button associated with an item');
  24.   if hiOnItemButtonExact in HitInfo.HitPositions then
  25.     Memo1.Lines.Add('exactly on the button associated with an item');
  26.   if hiOnItemCheckbox in HitInfo.HitPositions then
  27.     Memo1.Lines.Add('on the checkbox if enabled');
  28.   if hiOnItemIndent in HitInfo.Hitpositions then
  29.     Memo1.Lines.Add('in the indentation area in front of a node');
  30.   if hiOnItemLabel in HitInfo.HitPositions then
  31.     Memo1.Lines.Add('on the normal text area associated with an item');
  32.   if hiOnItemLeft in HitInfo.Hitpositions then
  33.     Memo1.Lines.Add('in the area to the left of a node''s text area (e.g. when right aligned or centered)');
  34.   if hiOnItemRight in HitInfo.Hitpositions then
  35.     Memo1.Lines.Add('in the area to the right of a node''s text area (e.g. if left aligned or centered)');
  36.   if hiOnNormalIcon in HitInfo.HitPositions then
  37.     Memo1.Lines.Add('on the "normal" image');
  38.   if hiOnStateIcon in HitInfo.HitPositions then
  39.     memo1.Lines.Add('on the state image');
  40.   if hiToLeft in HitInfo.HitPositions then
  41.     Memo1.Lines.Add('to the left of the client area (if relative) or the absolute tree area');
  42.   if hiToRight in HitInfo.HitPositions then
  43.     Memo1.Lines.Add('to the right of the client area (if relative) or the absolute tree area');
  44.   if hiUpperSplitter in HitInfo.HitPositions then
  45.     Memo1.Lines.Add('in the upper splitter area of a node');
  46.   if hiLowerSplitter in HitInfo.HitPositions then
  47.     Memo1.Lines.Add('in the lower splitter area of a node');
  48. end;


I've test your code and I've  seen that the "virtualstring" tree has undocumented HitPositions states.

At the begining what I wanted to do, it was not working because I select hiOnItemLabel ('= 8'), but sometimes the function returns 24 and 54  for HitPositions . There is not states for those values  ( the last hiLowerSplitter = 16).

Code: Pascal  [Select][+][-]
  1.  if integer(FHitInfo.HitPositions) in [8, 24, 56] then

thats working for me. There is not elegant solution but...it's OK.

Anyway, thanks a lot

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: Issues with TVirtualString Tree
« Reply #4 on: October 20, 2018, 01:14:22 pm »
Why do you use numeric values for the HitPositions? This is not good programming style, you get much better readability if you use the enumerated values. And do you really understand what you are doing?

THitPosition is an enumeration, i.e. named values for the bits of an integer. The first enumerated value (hiAbove in THitPosition) corresponds to the right-most bit and thus has the value 1. The fourth value (hiOnItem) has the numeric value 2^(4-1) = 8. The easiest way to calculate this is by shifting the 1 to the left by as many bits as specified by the ord value of the enumeration element., i.e. 1 shl (ord(hiOnItem). Although being the fourth bit, hiOnItem has the ord value of 3 because counting starts at 0.

But forget about the numerical values, the compiler takes care of it.

THitPositions (plural!) is a set, i.e. an unordered combination of the enumerated value. In the bit representation each included set element corresponds to a bit switched to its ON state. If the first and fourth elements are included (hiAbove and hiOnItem) then the value of the set is 1+8 = 9. This is the reason why you are seeing "undocumented" values. You can get the numerical value of the set by casting the set to an integer: "integer(HitInfo.HitPositions)"

Again, forget about the bits, use the features of the Pascal language instead:

In order to check whether a HitPosition is included in the set you just use the "in" operator: "if hiAbove in HitInfo.HitPositions". In the "bit-world" you must not check for equality because other bits can be set as well, i.e. don't do "if 1 = HitInfo.HitPositions", but use an AND operation to mask out the 1st bit: "if 1 and integer(HitInfo.HitPositions <> 0"

If several values are included in the set, e.g. hiOnItem and hiOnItemLabel as it happens when you click on a node text, the you can check whether the intersection of the sets [hiOnItem, hiOnItemLabel] and HitPositions is not empty; the intersection operation has the symbol '*' in Pascal, i.e. "if [hiOnItem, hiOnItemLabel] * HitInfo.HitPosition <> []".

You hopefully understand now why the Pascal way has better readability, is better to understand and less error-prone.

See the attached demo program which checks the HitPositions after each click into a simple virtualtree. It displays the numeric values as well.

 

TinyPortal © 2005-2018