Subject |
Re: Grid Navigation |
From |
Mervyn Bick <invalid@invalid.invalid> |
Date |
Mon, 12 Feb 2018 11:06:27 +0200 |
Newsgroups |
dbase.getting-started |
Attachment(s) |
test_grid_callback2.wfm |
On 2018-02-10 10:28 PM, Mustansir Ghor wrote:
> Dear All
>
> I have grid with 5 columns. 1st column is combobox, 2nd column is entryfield, 3rd and 4th are reference display from lookuprowset. 5th is a calculated one based on item selection from 1st column and entryfiled of 2nd column. I therefore wish to restrict navigation to only 2 columns 1st and 2nd. Can anybody advise how this can be achieved.
The fact that you have a combobox in your grid suggests that you are
using the grid for data entry and/or editing.
Over the years I've come to the conclusion that using a grid for editing
is not a good idea. It is simply too easy to make mistakes. I prefer
to display data in a grid and use entryfields for adding/editing fields
in conjunction with Edit, Add, Save and Abandon buttons. Still, if you
really want to use a grid for adding/editing rows it can be done.
The only way I could restrict navigation to the first two columns of the
grid was to use the CALLBACK command. This means this will only work
for dBASE Plus 8 and later. (This is where someone, usually Ivar
Jesson, pops up with a Better Way than the Bick Way. :-) )
The attached example installs a keyboard "hook". This intercepts all
keystrokes to the form by forcing Windows to execute a function in the
program in place of it's own function. The program can then monitor all
keystrokes including those that the normal onKey and Key event handlers
miss.
Normally the keystroke is passed straight back to the Windows function
but by returning 1 instead of calling the Windows hook the keystroke is
ignored by Windows. If the keystroke was Tab or Enter in the second
column the function doOnEnter is executed and the Tab or Enter keystroke
is not returned to Windows but is dealt with by doOnEnter..
If the user uses the mouse to click in any of the fields column 1 gets
focus.
Some points to watch
The underlying fields for columns 3 - 5 must have their readonly
property set true.
After the form has been run I've found that the sourcecode editor
crashes after changes have been made to the code. The changes are,
however, saved first. Close dBASE and restart. It's a PITA but nothing
else seems to get hurt. I'll be submitting a bug report later.
Mervyn.
| clear
if file('test_grid_callback.dbf')
drop table test_grid_callback
endif
if not file('test_grid_callback.dbf')
create table test_grid_callback (job_no character(5),customer character(15),address1 character(15),address2 character(15),address3 character(15))
use test_grid_callback
generate 10
go top
for n = 1 to 10
replace job_no with '1'+str(N,3,0,'0')
SKIP
next
go top
replace customer with 'Abel'
SKIP
replace customer with 'Baker'
SKIP
replace customer with 'Charlie'
SKIP
replace customer with 'Delta'
SKIP
replace customer with 'Echo'
SKIP
use
endif
** END HEADER -- do not remove this line
//
// Generated on 2018/02/12
//
parameter bModal
local f
f = new test_rid_callback2Form()
if (bModal)
f.mdi = false // ensure not MDI
f.readModal()
else
f.open()
endif
class test_rid_callback2Form of FORM
with (this)
canClose = class::FORM_CANCLOSE
onOpen = class::FORM_ONOPEN
onClose = class::FORM_ONCLOSE
height = 26.7273
left = 44.2857
top = 3.2273
width = 134.8571
text = ""
scrollBar = 2 // Auto
endwith
this.TEST_GRID_CALLBACK1 = new QUERY(this)
with (this.TEST_GRID_CALLBACK1)
left = 2.0
top = 1.0
width = 14.0
height = 1.0
sql = 'select * from "test_grid_callback.DBF"'
active = true
endwith
with (this.TEST_GRID_CALLBACK1.rowset)
with (fields["address1"])
readOnly = true
endwith
with (fields["address2"])
readOnly = true
endwith
with (fields["address3"])
readOnly = true
endwith
endwith
this.GRID1 = new GRID(this)
with (this.GRID1)
onLeftMouseUp = class::GRID1_ONLEFTMOUSEUP
dataLink = form.test_grid_callback1.rowset
height = 15.5
left = 12.0
top = 6.0
width = 103.0
endwith
this.rowset = this.test_grid_callback1.rowset
function form_onClose()
form.test_grid_callback1.active = false
return
function form_onOpen()
clear
#include winuser.h
if type("dBGetCurrentThreadId") # "FP"
extern CULONG dBGetCurrentThreadId() kernel32 from "GetCurrentThreadId"
endif
if type("dBGetWindowLong") # "FP"
extern CLONG dBGetWindowLong(CHANDLE, CINT) user32 from "GetWindowLongW"
endif
if type("dBSetWindowsHookEx") # "FP"
extern CLONG dBSetWindowsHookEx(CINT, CPTR, CHANDLE, CULONG) user32 from "SetWindowsHookExW"
endif
if type("dBUnhookWindowsHookEx") # "FP"
extern CLOGICAL dBUnhookWindowsHookEx(CHANDLE) user32 from "UnhookWindowsHookEx"
endif
if type("dBCallNextHookEx") # "FP"
extern CLONG dBCallNextHookEx(CHANDLE, CINT, CUINT, CUINT) user32 from "CallNextHookEx"
endif
// if type("GetAsyncKeyState") # "FP"
// extern CSHORT GetAsyncKeyState(CSHORT) user32
// endif
CALLBACK CLONG hookWndProc(CINT, CUINT, CUINT) OBJECT this
this.hookProc = GetCallAddress(class::HOOKWNDPROC)
this.hInst = dBGetWindowLong(this.hwnd, GWL_HINSTANCE)
this.hook = dBSetWindowsHookEx(WH_KEYBOARD, this.hookProc, this.hInst, dBGetCurrentThreadId())
form.grid1.setFocus()
return
function GRID1_onLeftMouseUP(flags, col, row)
keyboard '{tab}'
keyboard '{home}'
return
function form_canClose
//detach the hook.
dBUnhookWindowsHookEx(this.hook)
return true
function doOnEnter
if form.test_grid_callback1.rowset.atlast()
form.test_grid_callback1.rowset.beginAppend()
else
form.test_grid_callback1.rowset.next()
endif
keyboard '{home}'
return
function hookWndproc(hCode, wParam, lParam)
cReturn = dBCallNextHookEx(this.hook, hCode, wParam, lParam)
if (wParam = VK_RETURN or wParam = VK_TAB) and hcode = 0 and not bitset(lparam,31)
if upper(form.activeControl.name) = 'GRID1' and form.grid1.currentcolumn = 2
//tab or return in column 1 is ignored here and passed on to Windows like any other keystroke
if form.test_grid_callback1.rowset.state = 3 and form.grid1.currentcolumn = 2
form.test_grid_callback1.rowset.save()
endif
class::doOnEnter() //Deal with tab or return in coulmn 2
cReturn = 1 // Don't call next hook. This prevents Enter or Tab from moving cursor to next field
endif
endif
return cReturn
endclass
|
|