NOTE TO OUR READERS
This web resource is written for our own use. But we feel strongly that the PL/B language should be shared with the software community. So feel free to use this at will!
BUT PLEASE...
if you find errors or omissions or have a better way to do something. TELL US! Dialog helps us all. Send e-mail to:
support@mmcctech.com
web forum includes many discussions of ListViews. You can search that site for everything. Some items, however, are worth repeating here just as a reminder and quick review.
Credit for these discussions go to Sunbelt for sponsoring the discussion forum on their web site and to the many great PL/B programmers who contribute to the body of knowledge shared by the PL/B community.
Determining which ListView subitem was clicked on?
PL/B Language section: Thread #9798 - 04/30/04 09:16 AM
Jim Kovalsky
I remember previous posts about editting in-place in a Listview, but I can't seem to find them, so I'm going ask the question again....
I see that there are SubItemHitTest and GetItemRect methods for the listview.. Subitemhittest will report what row and column I would get at a certain position, and GetitemRect will give me the coordinates of the corresponding cell....
Am I correct that I should set a Mregion on top of the Listview, and then use the click on the mouse region, create an editnumber or edittext at those coordinates, and work with that?
All that being said, is there an EASIER method?
David Gabler
It is actually easier than that. The getitemrect will give you the top, bottom, left and right of your edittext. Not necessarily in that order. Look at the docs for the order, but after that create, you can edit, or combo to your delight!
I have found it very useful to disable the scrollbar during the edit, because you will find that the listview is blissfully unaware that it is being edited, and will scroll your row completely out of view if the user tries.
Stuart Elliott - Clay County Judicial I/S
And, of course, when the user scrolls the listview, the edittext stays put right where the 'cell' WAS originally! It'd be great to have a scroll event on a listview so we would be able to handle this problem. Also, they could scroll left and right as well as up and down.
Jim Kovalsky
That seems OK if I know what subitem I want to edit, but until they click, I don't know what subitem they want.
How can I determine which *subitem* in the row they actually clicked on?
Gerhard Weiss
You use the $ITEMACTIVATE events results.
For me, I use the ENSUREVISIBLE method in case they click on a partial row. I'd also like to see an ENSUREVISIBLE method for the COLUMN, in case they try to edit a column that is partially visible. Having those two, it works ok to disable the scrollbars during the actual edit, and then turn it back on after.
Gerhard
Another solution is turning off the EDITTEXT if the user clicks
outside of the EDITTEXT. One possible (I say possible because I have
not tested this) way of doing this is to also use a MREGION along
with your EDTTEXT and have both of their ZORDERs above the other
objects on the window. The MREGION would have to cover the whole
client area of the Window (You might be able to use big
numbers: Top=1, Bottom=1000, Left=1, Right=1000 instead of having
to know the clients size.).
Conceptual code:
LVW LISTVIEW
MRG MREGION
TXT EDITTEXT
.
CREATE LVW,ZORDER=10
CREATE MRG=1:1000:1:1000,ZORDER=20
CREATE TXT,ZORDER=21
.
EVENTREG MRG,$MouseDown,MRG_MouseDown
.
. Code to call routine ActTxtMrg when the user wants to edit a cell.
.
. User invoked the EDITTEXT routine
ActTxtMrg
ACTIVATE TXT
ACTIVATE MRG
RETURN
.
. User Clicked outside of the TXT object
MRG_MouseDown
.. process the TXT object
DEACTIVE TXT
DEACTIVE MRG
RETURN
You will probably want other ways to turn off the TXT object.
(Such as if the user presses the ENTER key or TAB key.) Checking
the TXT objects KEYPRESS event would do that for you.
Maybe checking if the TXT object lost focus would be another.
Micosoft does something similar to this inside of Outlook.
When creating a new appointment they allow you
to invoke a popup calendar. If you click outside of the
calendar on another object, lets say a edittext box,
the calendar closes down but focus does not move
to the edittext box. You have to click a second time
to move focus to the edittext box. I think what is
happening is similar to the logic shown above.
Stuart Elliott - Clay County Judicial I/S
We're using this technique on a listview to accomplish a 'spreadsheet' approach by placing the edittext on the 'cell' in the upper left hand corner then using the KEYPRESS event to detect the enter key, arrow keys, etc. For instance, if they press the right-arrow key in the edittext, we put the current edittext value into the current cell then move the edittext to the next column (same row) and get it's value from the cell under it. This all works pretty well if they keep their hands on the keyboard but as soon as they reach for the mouse to manipulate the scrollbar, we're sunk. (And you're right, ensurevisible for a column would be essential also.)
You said you you turn off the scrollbar until they're finished. How do you know when they're finished? If they hit the enter key? If so, when they hit enter, do you hide the edittext until they click on a cell again?
See, we're trying to simulate a datagrid that allows keys and mouse moves to manipulate the grid and it's data. And, we can't disable the scrollbar 'until they're finished' because they aren't finished. If they hit enter (or use the arrow keys) we move the edittext, we don't hide it.
I guess what we need to do is disable the scrollbar, as you do, and only let them navigate with the arrow keys. We could also add the PgUp, PgDn, Ctrl-Home, Ctrl-End, etc. to the KEYPRESS routine for quicker movement.
Matthew Lake
I use the MouseMove event to track the mouse position. Then when the doubleclick event occurs, I use the mouse position from the last mousemove event for the SubItemHitTest. The the doubleclick #EVENTRESULT contains the row, and the return from SubItemHitTest contains the column used in the GetItemRect method.
Then you need to disable the scroll bars on the listview as other mentioned when you create your edittext/editnumber. I use the lost focus event to destroy the edit control created over the listview.
You have to disable the scroll bars because they cause no events at all. The edit control does not even loose focus so there is no way to detect when a user moves the listview's scroll bars.
ps. An additional thought, if you have column sorting ( i.e. the user can click on the column header to sort the column ) you may want to setprop LV,Enable=false to prevent any listview activity while it's being edited.
James Seale
The listview can be scrolled by command. I've used this technique when the selected cell is not totally visible to scroll the listview before creating the edittext. Excerpted code follows:
OBJHANDL INTEGER 4
LVM_SCROLL INTEGER 2,"4116" // LVM_FIRST + 20
RECT DIM 16
RECT2 DIM 16
IRECTL INTEGER 4 // LEFT
IRECTT INTEGER 4 // TOP
IRECTR INTEGER 4 // RIGHT
IRECTB INTEGER 4 // BOTTOM
LEFT INTEGER 4
TOP INTEGER 4
RIGHT INTEGER 4
BOTTOM INTEGER 4
DX INTEGER 4
DYINTEGER 4
RET INTEGER 4
SENDMSG PROFILE !user32,SendMessageA,INT4,INT4,INT4,INT4,INT4
.. Get the Listview handle
.
GETPROP P_LV,HWND=OBJHANDL
.
.
. Determine whether the subitem is in full view, if not scroll it
.
GETPROP P_LV,WIDTH=W
CALC RESULT = ( RIGHT - W )
IF ( RESULT > 0 ) // NEED TO SCROLL
MOVE ( RESULT + 25 ), DX // ADD 25 FOR VERT SCROLL BAR
CLEAR DY
WINAPI SENDMSG GIVING RET USING OBJHANDL,LVM_SCROLL,DX,DY
SUB DX, LEFT // ADJUST HOR LOC BY AMT SCROLLED
SUB DX,RIGHT
ENDIF
RETURN
.
. Determine whether the sorted column is in the same view position,
. if not scroll it
.
RETURN IF ( LEFT = IRECTL ) // SAME POSITION, RETURN
CLEAR TOP
CALC DX = ( LEFT - IRECTL )
WINAPI SENDMSG GIVING RET USING OBJHANDL,LVM_SCROLL,DX,TOP
RETURN
The first instance of SENDMSG was to scroll the listview, the second to restore it.
David Gabler
Yes, I trap for all those cursor movement keys, and let them navigate that way. I actually have 2 hidden edittexts -- one with a tabid greater than my edittext, and one less, so I can know if they are tabbing or backtabbing as well.
v1.10