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.
Back Up Your Microsoft Windows Server®

Back up all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

I originally created this report in Crystal Reports 2008 where there is an option to underlay sections. I initially came across the problem in Access Reports where I was unable to run my border lines down through the entire page as I was using the P…
Introduction The Visual Basic for Applications (VBA) language is at the heart of every application that you write. It is your key to taking Access beyond the world of wizards into a world where anything is possible. This article introduces you to…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

840 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