How do I detect clicking and double-clicking a node in a TreeView? - delphi

How do I track the event of clicking a node or double-clicking a node item (meaning, that textual thing next to the plus sign) in a tree view, but not the treeview itself?

Detect a click or double-click on the control in general with the OnClick and OnDblClick events. To find out which specific node was clicked, use the control's GetNodeAt method with the mouse's current coordinates.
You can get the coordinates as they were at the time of the click with GetMessagePos; reading Mouse.CursorPos will give you the coordinates at the time you read the property, which might be very different from the time of the click if there is any sort of load on the system, and that can lead to detecting clicks at places that aren't even within the bounds of your control.

Use usual OnClick and OnDblClick events and look which is the current node item.
http://docwiki.embarcadero.com/Libraries/XE3/en/Vcl.ComCtrls.TCustomTreeView.Selected
See also linked examples.
But better use VirtualTreeView.
http://www.lischke-online.de/VirtualTreeview/VTGallery.php
http://code.google.com/p/virtual-treeview/

Related

At design time, can you prevent components from moving on the first selection click?

All of our forms tend to have things get a few pixels out of place because when we click a component to modify the properties, there is a tendency to have the component move if the mouse is still moving the tiniest bit when we select a component.
Is there a setting that makes it so you can't move a component that isn't already selected? (Requiring a second intentinoal click to actually move things.)
You can enable "Lock controls" from the "Edit" menu, then it won't move when you click it, but it will of course remain locked also at the second click.
However, at least it will save you from the accidental moves just because you need to select the control
I find uncheck (use designer guidline) can prevent the problem,
but you will not see the alignment line.
tools->options->Form Designer

draw a icon on Treeview node on mouseover, when clicked display popup menu

using delphi ex-5
as of now, I can display the popupmenu on right click of a selected node
is it possible to display a icon on a treeview node (right side) on a moveover? When the icon is moused over, display a popupmenu?
thanx
EDIT: Inclusion of two screenshots to better convey my need (Yes, this was taken forom a webpage - it is what I am trying to do)
https://dl.dropboxusercontent.com/u/73677254/Delphi%20Demos/screenshot1.png
https://dl.dropboxusercontent.com/u/73677254/Delphi%20Demos/screenshot2.png
If you want the icon on the left side, you can use the TTreeNode.StateIndex property. But to put an icon on the right side, you have to owner-draw the TTreeView nodes instead.
Either way, use the TTreeView.OnMouseMove event to keep track of which node is currently under the mouse at all times, and when you detect a different node then you can reset the StateIndex of the previous node and update the StateIndex of the new node, or trigger a repaint and draw the icon only on the new node, depending on which approach you take.

Show different popup menu depending on what column the mouse is over in a Delphi TListView control?

I have a Delphi 6 application that has a TJvListView control. I have a popup menu tied to that control via the control's PopupMenu property. What I would like to do is show a different popup menu based on which column the user had the mouse over when they right clicked, with the additional option to not show a popup menu at all if the current column does not need one. How can I do this?
Thanks to this detailed sample by Remy Lebeau on in-place editing in a TListView I know what row and column the mouse is over except for one wrinkle. The mouse down event where I determine the current row and column occurs after the popup menu is exited.
I now need to know two things. First, how can I get some event to fire before the popup menu shows after a right mouse click so I can record the current list view row and column and suppress the popup menu if I want to, and second, how I can show a different popup based on the current column. I am hoping to avoid having to write a bunch of mini-forms instead of using the TListView PopupMenu property and supporting code. Is there a simple solution, perhaps some fancy footwork in a sub-class I should create around TJvListView?
You could perform the detection in mousemove instead of mousedown/Click and change the popupmenu depending.
You also could remove any popupmenu and call the wished via p.pupup in mousedown as you desire.

How do I move multiple nodes at once in a TJvTreeView?

When you select multiple nodes of a JvTreeView, and then try to drag these nodes, the JvTreeView selects the node you clicked to drag, rather than initiating dragging all the selected nodes. You end up dragging only this single node.
Is it possible to drag multiple nodes in a JvTreeView? I am using Delphi 2007.
UPDATE: Oddly enough, if I hold down CTRL+SHIFT when dragging the items, I can successfully drag them all. Any ideas?
Suppose MultiSelectStyle is the default [msControlSelect], then the answer to your question is 'you don't release the control key when you're selecting the last item and beginning dragging'.
The culprit is in TJvTreeView.WMLButtonDown in JvComCtrls.pas. Code there tests if 'Ctrl' is pressed when the TreeView is MultiSelect, and clears all items and selects the clicked item if 'Ctrl' is not pressed. It should instead test if the clicked item is already selected and do nothing if it is.
You can see the broken behavior without dragging. Multi select a few items and then click a selected item with the mouse. The VCL TreeView do not select or de-select anything, while the JVTreeView, instead, de-selects all items and selects the clicked one.
Yes absolutely, I do it all the time.
Of course Multi-Select needs to be True and you may need to have a look at the TTreeView's MultiSelectStyle. That controls what type of nodes can be selected at the same time. For example if msSiblingOnly is set to true, you can only select sibblings.
Are you using dmAutomatic or dmManual. If the latter, it could be that you are doing something in the OnMouse* events that is negating the multi-selection you made earlier.

TStringGrid dirty hack - Restricting the selection to one single row

I have a heavily modified control based on TStringGrid. I want to allow the user to make selections in this grid but restrict the selection one single row (the current row).
Implementation:
When the user presses the left mouse button I am using a dirty hack: On OnMouseDown event I capture the mouse cursor and keep it on the current row. The user can move the mouse device up and down on its pad but the cursor will not go up or down. It will stay on the current row. When the user releases the button (OnMouseUp event), I release the capture.
However, this hack is as I said very dirty. There are several problems. For example, if the user presses the left mouse button (LMB) and then without releasing that button it presses the right button, the associated pop-up menu will pop but the mouse capture will never be released. So, the mouse will be locked in a screen region until the user will has the brilliant idea to click the LMB one more time to unlock the mouse. This may be a bug in D7. There is a separate post about it here: TStringGrid - OnMouseUp is not called!
There is a elegant way to do this?
Edit:
OnSelectCell is not working. OnSelectCell event is called only once when you click the cell. If you keep the button pressed and move the mouse to expand the selection, OnSelectCell will not be called again.
Indeed MoveCurrent appears only in TCustomGrid.MouseDown.
Use the OnSelectCell event and set the CanSelect var parameter depending on whether the ARow parameter is what you want.
A nice solution
Check the options property on TStringGrid
There is an Option called 'goRangeSelect'
Set this to false using the object inspector
Or programatically this can be done by
StringGrid1.Options - [goRangeSelect];
This answer is not elegant at all, but it works.
My solution is NOT to use the PopupMenu property of the StringGrid. Instead I implemented my own PopUpMenu property. Works almost perfect. There is on small problem, the bottom of the pop-up menu appears next to the cursor and not its top.

Resources