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

Posted on 2006-10-22
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.
Question by:ramrom
LVL 10

Expert Comment

by:Luke Chung
ID: 17784940
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.

LVL 11

Expert Comment

ID: 17784969
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

LVL 17

Author Comment

ID: 17785607
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.
The Eight Noble Truths of Backup and Recovery

How can IT departments tackle the challenges of a Big Data world? This white paper provides a roadmap to success and helps companies ensure that all their data is safe and secure, no matter if it resides on-premise with physical or virtual machines or in the cloud.

LVL 44

Accepted Solution

Leigh Purvis earned 125 total points
ID: 17785619
<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. :-)
LVL 17

Author Comment

ID: 17786088
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.

LVL 44

Expert Comment

by:Leigh Purvis
ID: 17788870
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?)
LVL 17

Author Comment

ID: 17790867
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).

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Search for text in a .txt file 14 41
Modal form 11 29
Calculation in Access 5 25
SQL multicriteria from ONE textbox 32 41
I see at least one EE question a week that pertains to using temporary tables in MS Access.  But surprisingly, I was unable to find a single article devoted solely to this topic. I don’t intend to describe all of the uses of temporary tables in t…
It’s been over a month into 2017, and there is already a sophisticated Gmail phishing email making it rounds. New techniques and tactics, have given hackers a way to authentically impersonate your contacts.How it Works The attack works by targeti…
Familiarize people with the process of utilizing SQL Server functions from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Ac…
Using Microsoft Access, learn some simple rules for how to construct tables in a relational database. Split up all multi-value fields into single values: Split up fields that belong to other things into separate tables: Make sure that all record…

813 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now