Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Touch screen and treeview

Status
Not open for further replies.

AlastairP

Technical User
Feb 8, 2011
286
AU
So I am building this application for touch screen - this is for data entry by technicians.
I am trying to make it simple and quick
To make navigating easier, I include some large command buttons on screen for navigating up/down in the data lists
However, one form has a treeview and I would like to reproduce the key presses from the arrow keys on the keyboard
eg have 4 x large command buttons up/down/left/right
That way the user can navigate the treeview including expanding and collapsing nodes

I am trying to avoid using as much as possible any keyboards that can be called up by the tablet for reasons of speed and simplicity for the user

 
As simple as

Keyboard '{LEFTARROW}'
Keyboard '{RIGHTARROW}'
Keyboard '{DNARROW}'
Keyboard '{UPARROW}'

Bye, Olaf
 
As simple as...
Except the buttons will have focus, so the KEYBOARD command would act on that.
You may be able to set focus first to the treeview then issue the KEYBOARD command.
But on the other hand it may be more complex such as looping through each node, determining which node is the currently selected node, then acting on that node.
Here's a quick example of how to expand a selected node, if it is expandable:
Code:
FOR EACH oNode IN ThisForm.oletreeView.Nodes
   IF oNode.selected
      oNode.expanded = .T.
   ENDIF
ENDFOR

RETURN



-Dave Summers-
[cheers]
Even more Fox stuff at:
 
Well,

"buttons will have focus"
Not, if you do that i a toolbar with toolbar buttons. They won't influence form/control focus.
And a simple SetFocus would also be sufficient to move the focus, where it's needed.

For example you could simply create buttons captioned A-Z and Keyboard this.caption would already emulate a keyboard.

Bye, Olaf.
 
Thanks Olaf,
That is exactly what I need
I was aware I would have to keep focus on the treeview
Thanks also Dave, that little snippet will come in handy I bet

Alastair
 
OK, just a follow up:

keyboard{} command works with native VFP controls no problem
however can't get it to work with the treeview object

Code:
[u][b][b]Not Working[/b][/b][/u]

thisform.oletree.SetFocus
Keyboard '{DNARROW}'

[u][b]Working[/b][/u]

thisform.grid1.setfocus
Keyboard '{DNARROW}'

If I issue a setfocus to the treeview, the first node is highlighted
after the keyboard command fires, focus leaves the treeview and goes to another control
I guess the real answer is to use a tool bar as focus will stay on the treeview



 
My understanding is that the KEYBOARD command only works with native VFP controls. It is not supported by ActiveX controls such as the Treeview.

I think you'll have to fall back on Dave's suggestion and do the whole thing in code.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Well, if the KEYBOARD command really doesn't work, SendMessage of WM_KEYDOWN and WM_KEYUP windows messages to the treeview.hwnd surely will work. But before you go that route, it's even simpler to drill down nodes and expand them. Dave has give the code for selected nodes, you can also drill down child nodes from there. I don't really know what the arrow keys would cause, but it surely can be emulated as needed. If you need a reference for the treeview, and have Visual Studio 6 (the version including VFP6) it has the MSDN library containing the reference CHM help on Version 5&6 MS OCX controls.

Bye, Olaf.
 
Olaf said:
I don't really know what the arrow keys would cause, but it surely can be emulated as needed.

Just a quick guide:

Up Arrow and Down Arrow : Highlights the next / previous visible node (at any level)

Right Arrow : If the current node has child nodes and these are not currently visible, expands the node by one level. If a child node is visible, highlights that node. If the current does not have child nodes, does nothing.

Left Arrow : If the current node has child nodes, and these are currently visible, collapses the current node. If the child nodes are not visible, highlights the current node's parent. If the current node has no visible child nodes and no parent, does nothing.

PgUp and PgDn : Moves the highlight up or down one screenful; highlights the appropriate visible node, regardless of level.

Home and End : Moves the highlight to the first or last visible node respectively, regardless of level.

Any of the above with Ctrl : Scrolls the tree one line or one screenful at a time, but does not move the highlight.

Any of the above with Shift : Same as without shift.

Note that the above are based on my own observations, not from any official documentation.

I suggest you need to support the four arrow keys, and possibly PgUp / PgDn, but not bother with the others.

Mike







__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
But, on reflection, you don't really need to similulate the actual keys. Your aim is to provide a touch-based navigation, not to provide touch equivalents for every possible keystrokes.

So, I suggest you just have four buttons: two to move the highlight up or down between the visible nodes; and two to move it left or right, expanding and collapsing as you go. With luck, that should give your users everything they need.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Thanks, I am working on it now.
Will post the results for reference when done

Alastair
 
Ok here it is:

Left Arrow Command Button

Code:
thisform.oletree.SetFocus
oNode=thisform.oletree.selectedItem

IF thisform.oletree.Nodes.Count = 0 && Total nodes
	RETURN 
ENDIF 	
IF oNode.expanded = .t.
	oNode.expanded = .f.
ENDIF

Right Arrow Command Button


Code:
thisform.oletree.SetFocus
oNodeSel=thisform.oletree.selectedItem

IF thisform.oletree.Nodes.Count = 0 && Total nodes
	RETURN 
ENDIF 	

IF oNodeSel.children > 0 && only change the property if we actually have childs
	IF oNodeSel.expanded = .f.
		oNodeSel.expanded = .t.
	ENDIF 
ENDIF

Down Arrow Command Button

Code:
thisform.oletree.SetFocus

lnCnt=thisform.oletree.Nodes.Count && Total nodes
IF lnCnt = 0
	RETURN 
ENDIF 	


&& check if we are on the last node
oNodeSel=thisform.oletree.selectedItem && Currently Selected node
lnCurrent=oNodeSel.index && current index number

IF lnCurrent = lncnt && we are on last node, do nothing
	RETURN 
ENDIF 		
&& Else - OK to move to next node

&& Check to see if we are on the last node of a current expanded or set of nodes
lnLast=oNodeSel.LastSibling.Index

IF  lnCurrent < lnLast && we have not got to the last node yet
	&& Check for childs
	IF oNodeSel.children = 0
		&& Change property to be sure
		oNodeSel.expanded = .f.
		lnNext=oNodeSel.Next.Index && Next Node index
		thisform.oletree.Nodes(lnNext).Selected = .t. && We have moved to next node in the same level
	ELSE && we have kids	
		IF oNodeSel.expanded = .t. && we are expanded
			lnChild=oNodeSel.Child.Index && Index number of the first child node
			thisform.oletree.Nodes(lnChild).Selected = .t.			
		ELSE && Not expanded
			lnNext=oNodeSel.Next.Index && Next Node index
			thisform.oletree.Nodes(lnNext).Selected = .t. && We have moved to next node in the same level		
		ENDIF 
	ENDIF 
ELSE && we are already at lastsibling, so move into next level, either parent or child

	IF oNodeSel.children = 0
		&& Change property to be sure
		oNodeSel.expanded = .f.	
		&& Try and move into a parent node
		TRY 
			lnNext=oNodeSel.parent.next.index
			thisform.oletree.Nodes(lnNext).Selected = .t.			
		CATCH
			Lastnode=.t. && do nothing, there are no more parents
		ENDTRY  	
	ELSE && we have kids	
		IF oNodeSel.expanded = .t.
			&& Move into childs
			lnChild=oNodeSel.Child.Index && Index number of the first child node
			thisform.oletree.Nodes(lnChild).Selected = .t.
		ELSE 
			&& do nothing	
		ENDIF 
	ENDIF 
ENDIF


Up Arrow Command Button

Code:
thisform.oletree.SetFocus

lnCnt=thisform.oletree.Nodes.Count && Total nodes
IF lnCnt = 0
	RETURN 
ENDIF 	

oNodeSel=thisform.oletree.selectedItem && Currently Selected node

&& check if we are on the first node
IF oNodeSel.index = 1 && we are on first node, do nothing
	RETURN 
ENDIF 		

&& OK to move to previous node

lnFirst=thisform.oletree.selectedItem.FirstSibling.Index
lnCurrent=oNodeSel.index

IF lnCurrent > lnFirst
	&& Have not got to first node in this level
	oPrev=oNodeSel.Previous && previous Node same level
	&& Check to see if the previous node on the same level is expanded, and if so go to last child node
	IF oPrev.children = 0 && We have no kids
		&& Change property to be sure
		oPrev.expanded = .f.
		thisform.oletree.Nodes(oPrev.index).Selected = .t.	
	ELSE && We have kids
		IF oPrev.expanded = .t.
			oFirstChild=oPrev.child && First Child
			lnLast=oFirstChild.lastsibling.index && Index of last node in childs
			thisform.oletree.Nodes(lnLast).Selected = .t.
		ELSE 
			thisform.oletree.Nodes(oPrev.index).Selected = .t.
		ENDIF 
	ENDIF 	
ELSE && We are already on first sibling of this level, move into previous  node 

	IF oNodeSel.children = 0
		&& Change property to be sure
		oNodeSel.expanded = .f.	
		&& Try and move into a parent node
		TRY 
			lnPrev=oNodeSel.parent.index
			thisform.oletree.Nodes(lnPrev).Selected = .t.			
		CATCH
			Lastnode=.t. && do nothing, there are no more parents
		ENDTRY  	
	ELSE && we have kids	
		IF oNodeSel.expanded = .t.
			oFirstChild=oNodeSel.child && First Child
			lnLast=oFirstChild.lastsibling.index && Index of last node in childs
			thisform.oletree.Nodes(lnLast).Selected = .t.
		ELSE 
			&& Try and move into a parent node
			TRY 
				lnPrev=oNodeSel.parent.index
				thisform.oletree.Nodes(lnPrev).Selected = .t.			
			CATCH
				Lastnode=.t. && do nothing, there are no more parents
			ENDTRY 
		ENDIF 
	ENDIF 
	

ENDIF



 
Looks good. I wonder if the up/down arrow code needs to be so longwinded, if you'd add more short methods and make use of recursion. But if it works, it works.

Bye, Olaf.
 
Yes, it looks like it should work. I haven't tried running it, but I can't off-hand see any problems.

But I'll make a suggestion. It looks like each of the four chunks of code is intended to be run directly from the respective touch buttons. Personally, I would make them methods of the treeview class instead. That way, you can remove references to "thisform.oletree", which will make it more generic. It also means that, if you ever want to provide some other means of navigation, other than these particular touch buttons, you won't have to duplicate the code.

Apart from that, it's looking good.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Well, this was my attempt to make it work, so next step is to decide where to class it.
I will either make a cmd button class, or class it in the treeview

I will also try changing the left arrow method so it will collapse the nodes from any child, not just the child with the +/- next to it

Alastair
 
OK, so I classed the treeview and modified the code a bit. Added methods for up/down etc

moveup
Code:
&& UP

this.oletree.SetFocus

lnCnt=this.oletree.Nodes.Count && Total nodes
IF lnCnt = 0
	RETURN 
ENDIF 	

oNodeSel=this.oletree.selectedItem && Currently Selected node

&& check if we are on the first node
IF oNodeSel.index = 1 && we are on first node, do nothing
	RETURN 
ENDIF 		

&& OK to move to previous node

lnFirst=this.oletree.selectedItem.FirstSibling.Index
lnCurrent=oNodeSel.index

IF lnCurrent > lnFirst
	&& Have not got to first node in this level
	oPrev=oNodeSel.Previous && previous Node same level
	&& Check to see if the previous node on the same level is expanded, and if so go to last child node
	IF oPrev.children = 0 && We have no kids
		&& Change property to be sure
		oPrev.expanded = .f.
		this._nodemove(oPrev.index)
		RETURN 
	ELSE && We have kids
		IF oPrev.expanded = .t.
			oFirstChild=oPrev.child && First Child
			this._nodemove(oFirstChild.lastsibling.index)&& Index of last node in childs
			RETURN 
		ELSE 
			this._nodemove(oPrev.index)
			RETURN 			
		ENDIF 
	ENDIF 	
ELSE && We are already on first sibling of this level, move into previous  node 

	IF oNodeSel.children = 0
		&& Change property to be sure
		oNodeSel.expanded = .f.	
		&& Try and move into a parent node
		TRY 
			this._nodemove(oNodeSel.parent.index)
		CATCH
			Lastnode=.t. && do nothing, there are no more parents
		ENDTRY  
		RETURN 	
	ELSE && we have kids	
		IF oNodeSel.expanded = .t.
			oFirstChild=oNodeSel.child && First Child
			this._nodemove(oFirstChild.lastsibling.index)  && Index of last node in childs
			RETURN 			
		ELSE 
			&& Try and move into a parent node
			TRY 
				this._nodemove(oNodeSel.parent.index)
			CATCH
				Lastnode=.t. && do nothing, there are no more parents
			ENDTRY 
			RETURN 					
		ENDIF 
	ENDIF 
ENDIF

movedown

Code:
&& DOWN

this.oletree.SetFocus

lnCnt=this.oletree.Nodes.Count && Total nodes
IF lnCnt = 0
	RETURN 
ENDIF 	


&& check if we are on the last node
oNodeSel=this.oletree.selectedItem && Currently Selected node
lnCurrent=oNodeSel.index && current index number

IF lnCurrent = lncnt && we are on last node, do nothing
	RETURN 
ENDIF 		
&& Else - OK to move to next node
lnMove=.f.

&& Check to see if we are on the last node of a current expanded or set of nodes
lnLast=oNodeSel.LastSibling.Index

IF  lnCurrent < lnLast && we have not got to the last node yet
	&& Check for childs
	IF oNodeSel.children = 0
		&& Change property to be sure
		oNodeSel.expanded = .f.
		this._nodemove(oNodeSel.Next.Index) && We have moved to next node in the same level
		RETURN 
	ELSE && we have kids	
		IF oNodeSel.expanded = .t. && we are expanded
			this._nodemove(oNodeSel.Child.Index)	&& Index number of the first child node
			RETURN 
		ELSE && Not expanded
			this._nodemove(oNodeSel.Next.Index) && We have moved to next node in the same level	
			RETURN 	
		ENDIF 
	ENDIF 
ELSE && we are already at lastsibling, so move into next level, either parent or child

	IF oNodeSel.children = 0
		&& Change property to be sure
		oNodeSel.expanded = .f.	
		&& Try and move into a parent node
		TRY 
			this._nodemove(oNodeSel.parent.next.index)
		CATCH
			Lastnode=.t. && do nothing, there are no more parents
		ENDTRY  
		RETURN 
	ELSE && we have kids	
		IF oNodeSel.expanded = .t.
			&& Move into childs
			this._nodemove(oNodeSel.Child.Index)&& Index number of the first child node
			RETURN 
		ELSE 
			&& do nothing	
		ENDIF 
	ENDIF 
ENDIF

 
Alastair,

So your class is in fact a container rather than the actual treeview? And the container contains the treeview? That makes sense. That way, you could add, say, an Imageview to the same container without upsetting the class structure.

Looks like you're going about it the right way.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top