Thursday, May 14, 2015

Overcoming RefEdit Event Shortcomings

Introduction

This post is based on work I am doing on a userform that uses two RefEdit controls.  One problem with the RefEdit controls is the Events are not reliable.  In this case, I wanted to use changes to each control (RefEdits and Checkboxes) to trigger code that checks to see if certain buttons should be enabled.

Problems/Issues

When tabbing from the RefEdits I was able to use the Checkbox Enter events to trigger this button-enabling routine. However, if I moused from one RefEdit to the next nothing happened.  Neither the Exit nor MouseMove events for the RefEdit controls would trigger.

Fix Number 1: Use the UserForm_MouseMove Event

The following overcomes this shortcoming by using the MouseMove event for the userform.  Whenever the mouse is moved across the form but between its controls, UserForm_MouseMove triggers.  The sub for the UserForm_MouseMove event then calls the same Sub as before. 

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    Call EnableDisableButtons
End Sub

NOTE:  The code for EnableDisableButtons is/will be included in the posting building the userform and its functionality.

Using the UserForm_MouseMove event has the disadvantage of constantly triggering EnableDisableButtons, whenever the mouse is moving over the form, as long as it is not over a control. This may cause some performance issues. 

Fix number 2: Limit the MouseMove Event Area

The objective of this improvement is to eliminate much of the form's area from the event and trip the mouse movement only to those areas where it might leave the RefEdit controls.

Form Changes

To limit the area where the MouseMove event is triggered, each RefEdit control is put inside it's own Frame control.  As shown in the figure below, this not only eliminates much of the area that might be crossed going from a RefEdit control to another, it also limits the space in lay when moving between other controls or simply across the open form.
Figure 1 - Frames added to Control MouseMove Area (Design view, Frames Slected)
The steps are
  • Expand the form to allow space to work.
  • Add Frame controls (frRefEditSource and frRefEditTarget)
    NOTE: Two frames were used instead of one to preserve the tab order
  • Move RefEdit controls inside their respective Frames
  • Re-size Frames so that a bare minimum of non-border shows around each RefEdit control. 
  • Move Frames to carry the RefEdit controls to their proper places
  • Format Frames be invisible when the form was shown
  • Modify Tab Order
  • Figure 2 - Modified Tab Order: Frames followed by Associated Checkboxes

    Code for Frames' MouseMove Events

    The calls for EnableDisableButtons are simply put into the two Frames' MouseMove event subs, lessening the problem of excessive triggering of  EnableDisableButtons while providing for triggering it when mouse-moving to-from the RefEdit controls.

    Private Sub frRefEditSource_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
        Call EnableDisableButtons
    End Sub

    Private Sub frRefEditTarget_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
        Call EnableDisableButtons
    End Sub