We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now


OnKeyPress = "=somefunction()" how function can receive the key pressed?

ramrom asked
Medium Priority
Last Modified: 2008-02-01
The event procedure for OnKeyPress starts:
Private Sub xxx_KeyPress(KeyAscii As Integer).

However when I change it to a function call:
OnKeyPress = "=somefunction()"
there does not seem to be a way to send the KeyAscii value to the function. Is there some way for the function to get the key pressed?

Why do I want this? To avoid having to write lots of keypress event subroutines. I have code that scans a form when it opens for certain comboboxes, and sets them up in certain ways. The only place I'm stuck is handling keypress.
Watch Question

Luke ChungPresident

It sounds like you're trying to do something outside the "natural" behavior of Access' event model.  Subverting the natural behavior of Access keystrokes is dangerous because people who are used to the behavior in other instances of Access may end up fighting your application.  But that could quickly get into a religious argument, so I'll refrain.

Unfortunately, if you want to handle the keystrokes, you're going to need to use the Event Procedure, and pass that to your function. Good luck.

Donald MaloneyConsultant

Is this what umean?

in form  text box?

Private Sub FIELDNAME_KeyPress(KeyAscii As Integer)
testfunction (KeyAscii)

End Sub

in modules

Public Function testfunction(key As Integer)
MsgBox key
End Function



donaldmaloney: no. I want to avoid writing event procedures, and use a function instead.

LukeChung-FMS: I want my combo box to respond to ctrl-e. There is currently no action triggered by ctrl-e in combo boxes so I think I am safe.

Of course if I could intercept right click then I'd have no problem (I'd use that instead). But the only way to do that (again) is with a mouse event procedure, which I choose to avoid.
Database Developer
<Warning - substantial post>
Hi ramrom - how goes it?
(I do like your questions ;-)

When you asked the question my first thought (apart from the point Luke raises - but you're an experienced developer, so I'm sure you'll be doing this for a good reason) was that you'll need to create a class (or two) to catch these keypresses.

First off - I'm assuming you really don't want to be making alterations to your existing functions.
For example sticking in a bunch of new code to whatever function calls might be going in to the Event properties - I'm assuming you want to avoid that.

So - back to the classes.
To successfully hook into a control's event - you'd need to have [Event Procedure] in the event property.
So - that kyboshes that one.
However the Form's keypress remains (hopefully!!) to be set to an [Event Procedure].
Is that a fair enough statement?
And if not - then is there a definite need for both control *and* form to have function calls in the keypress?  Could we live without one?

If the controls could be sacrificed then it's easier.
If not the we can still use the form - and I'll push on with that, as it's the more involved of the two (and you've mentioned controls specifically in your question).

A class which sinks the keypress event of the form.
Checks the current control of that form.
If it's one of the "certain comboboxes" then a class property makes available (through the parameter which it still receives) the ASCII character of the key that's just been pressed.
Of course the value needs to be retrieved by your functions somehow.
That could be simply by the form setting a public property of its own - or perhaps a global variable.

At a simple level - you could pass to the class a string delimited list of the controls which you're wanting to include (I assume they have some obvious identifier - perhaps a flag in the tag property or a common naming convention).
So they could always be enumerated at runtime - either in the code with which you pass the property to the class - or within the class itself once it has a form object to examine the controls of.

I'm sure this all sounds about as clear as mud.
Please feel free to post back why this wouldn't work (i.e. both keypress events are spoken for - which would be a shame) or if it's just not clear what I'm getting at.
And with more details too if you like - of how you identify the special combos for example.

I'll post here what I envisage the start of a class which should be enough to get back usable information.

Private WithEvents mfrmKey As Access.Form
Private mstrCtrlList As String
Private mintLastKey As Integer

Public Event BeenPressed()

Private Sub mfrmKey_KeyPress(KeyAscii As Integer)
    Dim strControl As String
    strControl = mfrmKey.ActiveControl.Name
    Debug.Print "In Class pressed " & KeyAscii & "  " & Chr(KeyAscii)
    'Check the current control is one we care about
    If InStr(1, mstrCtrlList, strControl) > 0 Then
        mintLastKey = KeyAscii
        mintLastKey = 0
    End If
    RaiseEvent BeenPressed
End Sub

Public Property Set CurFormKey(pfrm As Access.Form)
    Set mfrmKey = pfrm
End Property

Public Property Let ControlList(pstrList As String)

    mstrCtrlList = pstrList
End Property

Public Property Get LastKeyCode() As Integer

    LastKeyCode = mintLastKey
End Property

lol of course another possiblity could be to just use the control Keydown before the keypress to tell what would have been aquired.
(Or the form event more directly).
But why simplify matters when there's fun to be had.
I honestly don't think it would take long to set up.
And once done - it's done for use throughout... from then on. :-)

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts


Yep. That's the approach I took. Nice to have it confirmed. Let me expound.

I wrote a Sub OpenForm which amongst other things calls docmd.openform, and a class (FormHelper) which contains code similar to what you posted.

User requests for forms are sent to OpenForm.

OpenForm checks to see if the form has an instance of the FormHelper class, and if not, writes "Dim Helper as New FormHelper" to the declarations of the form's module. It also ensures that the form's OnKeyUp = "[event procedure]" and keypreview = True.

It loops thru the form's controls looking for those of type combobox that have a tag. The tag contains directives used to set the combo box properties.

FormHelper watches for KeyUp events, examines the ActiveControl.tag, and acts as needed.

FWIW OpenForm also checks to see if the form has a Sub reinit(), and if not, writes the code for it to the form's module.
Subsequently it calls this method, passing up to 6 arguments (which are at the end of the argument list for OpenForm).

This totally overcomes the limitations of openargs.

The place I ran into trouble was that subforms did not benefit from this passage thru openform, as they are opened automatically. So I lacked a way to apply the above technology to the subforms. So I was looking to function call instead of eventy procedure to help.

I now work around that by having openform visit the subforms and update them as well.

I sure do miss the ease I had in FoxPro of just subclassing combobox. Sigh.

Leigh PurvisDatabase Developer

So you're using Keyup events in your class - and hence are free to have an "[Event Procedure]" there?
So no need for a form object?
Or do you do so to keep it simple (i.e. watching for the keyup on that form - rather than any of the controls.)

Another option would be to have a couple of classes (parent and child) where the child holds a combo object and watches for the events of your very particular controls - and the parent maintains a collection of those classes.

If you were adding controls then I suppose whether a form was a main or subform - then if it added the controls to the class itself it wouldn't matter.

But it's just semantics now - you're up and running :-)

Not that I've ever used Foxpro (or are ever likely to now) - but how does it subclass combos in a widespread way?
i.e. All combos?  You could subclass the entire combo type class? (Rather than an individual control at a time?)


In FoxPro one may:

DEFINE CLASS xxx AS combobox
  borderstyle = 1
  backcolor = 999
  PROCEDURE KeyPress(nKeyCode, nShiftAltCtrl)
    * code to act on KeyPress

Then add any number of controls to forms based on this class.

One may then define other classes based on combobox, or on xxx (subclassing).

  caption = "Foo"
  backcolor = 9989
  PROCEDURE LostFocus()
    * code to act on LostFocus

yyy "inherits" backstyle and KeyPress from xxx, creates some new things, and "overrides backcolor.

These definitions can also be made using a Visual Class Designer. Just like laying out a form! One may then drag-drop the visual class onto a form to create an instance of the class (control or whatever).
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.