Edit: This post provides the overall concept but not a working code set. I’ve left this post in place and added a new post that contains working code, see here: Generalizing Form Behavior – Refined

I have a lot of functionality for forms that I want repeated across multiple forms… of course, the general rule here is to write procedures in one place and call those procedures from the forms as required so we don’t duplicate a bunch of code.  But still, that tends to be a lot of code behind the form that’s more or less boilerplate, especially when we want to deal with common event code.

For quite a while, my answer to this was a helper class that would be attached to forms, using WithEvents on the form (and applicable standarized controls) to automatically link up the event procedures.  This was nice as it was a drastic cutback on the amount of boilerplate code-behind, transferring it all into the class module instead.  Here’s a general idea of what I’m talking about…

That’d be the class module, then to use it you’d just do this (and of course include a button called “btnExit”):

So that’s pretty cool, except I get pretty sick of having to include a module with open/close for each and every form, and the inevitable Load/Unload to set the helper object that’s required when we do it this way.  What if we could get that same kind of generic functionality without actually having to include any code in the form at all?  That’d be slick…

The helper class takes a reference to the form, but doesn’t much care where that reference comes from. How about a psuedo-overload of the DoCmd.OpenForm method, which we can try to automatically link these two? Check this out:

Name the module UI, then (via my Module Naming post), replace DoCmd.OpenForm with UI.OpenForm and there we go, all forms opening via UI.OpenForm have an attached helper module without us having to do anything other than change the open method.

Here’s an example of an updated FormHandler class:

Of course, we wouldn’t really want this type of functionality without the option to turn it off here and there, preferably on a per-event basis (remember, when syncing events, there’s no guarantee which order the event procedures will fire: we want to reserve the right to turn off our global behaviors in cases where we need customized handling on the form end of things).

We can do this with some basic testing for a public property presence in the form that’s linked. Let’s for now assume that we have a “DisableGlobalKeyShortcuts” property on the form that’s being linked to from the handler, and add this code to the handler class:

You can see that the handler’s version defaults to false if it doesn’t seem to exist on the form, and we just add a quick conditional check in the Init procedure to optionally link up the event.

Now, for the form end of things, all you need to do in order to disable the global handling is add a public property accordingly:

This is nice because we can now get access to ALL generic events of a form, with the ability to disable so there’s no event procedure method firing order issues that often come with the use of WithEvents.

The only 100% required event by FormHandler is Close(), which only releases the form from the UI collection, and Close can’t be cancelled so there’s no chance of conflict regardless of whether the form’s Close or the FormHandler’s Close event fires first… doesn’t matter.

 

And there you go… generic form handling without having to add a single line of code to any forms (also note that Allen Browne’s Multiple Form Instances article advises to create multiple instances of forms (and release them via hWnd) in a similar way, which can be integrated into this functionality as well).

One caveat: in order for the WithEvents linking to work, each form MUST have its HasModule property set to true. It doesn’t actually need a module to show up in the VBIDE, but that property needs to be set. This is a simple matter of using a dev utility or predeployment utility that loops your forms and does it for you.