LPARAMETERS nColIndex llChangingRow = .f. with this oColumn = .columns(.FindColumn(nColIndex)) if lastkey() = 145 && Adding new rec .nLastValidRec = .nCurrec endif thisform.LockScreen = .lInGrid if mdown() lnBottom = .top+.headerheight+.relativerow * .rowheight lnTop = lnBottom - this.rowheight lnMouseRowPos = mrow(wontop(),3) lnMouseColPos = mcol(wontop(),3) llChangingRow = !(between(lnMouseRowPos,lnTop, lnBottom) ; and between(lnMouseColPos,.left,.left+.width)) else llChangingRow = inlist(lastkey(),24,5,18,3,145,148) endif if llChangingRow if !empty(oColumn.dynamiccurrentcontrol) cCurrentControl = eval(oColumn.dynamiccurrentcontrol) else cCurrentControl = oColumn.currentcontrol endif with evaluate("oColumn."+cCurrentcontrol) * .value = .value && So we can evaluate table ruleexpression endwith oColumn = .null. if !empty(dbgetprop(.recordsource,"Table","RuleExpression")) ; and !evaluate(dbgetprop(.recordsource,"Table","RuleExpression")) thisform.LockScreen = .F. if messagebox(.cRevertMessage,4+16,"") = 6 tablerevert(.f.,.recordsource) .recchange() else nodefault endif endif endif endwithIt has some custom methods and properties. Its purpose was to have an editable, addable grid with blank fileds checking (that's preventing VFP messaging kick in). Here primarily I dealt with "row" change, it could be modified to handle column changes and would be possible to know the column "attempted to move on". Hope helps.