Here is the problem: Access won't tell you anything you didn't tell it first. Access has a Form "Dirty" flag but not a "control" dirty flag. That is because it is really more associated with the RECORD's information, not the form. It is saying the RECORD is potentially dirty. (It is also why there is no DIRTY flag on an unbound form.) If you want to know if an INDIVIDUAL field has changed, then you have to plan ahead for that question. The method I used was in parts:
1. Every field for which I had an interest in "change" was either bound or unbound. This recording was in the "OnCurrent" event. For unbound forms it was trickier since there IS no OnCurrent event for such forms. For the unbound cases, I had variables set aside to record the old values. I usually had a "ResetForm" subroutine that would go through and reset the contents of a form. If it was a form for which I wanted to setup up the "change" event you described, that is where the "old value" resets would occur.
2. For every control where I wanted this information, I used the LostFocus event to compare the current contents of the form vs. the .OldValue (if it had one) or the stored prior value (if not bound). I also had a flag that told me if the user had tab-cycled through all of the fields a second time so that I wouldn't trigger the action a second time on the same control.
3. Because the last control on the form was tab-cycled back to the first (no auto-navigate), I had a separate action control button to do the Save. Since clicking that control DID generate a LostFocus from that last data control, there were no holes in the coverage.
Just one man's take on the problem.