By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,776 Members | 1,302 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,776 IT Pros & Developers. It's quick & easy.

Overcoming CommandButton autorepeat flaw for record navigation

P: n/a
Howdy,

Saw a couple threads from the past few years on this topic, but didn't
really find any solutions.

Here's one I found:
http://groups.google.com/group/comp....cff0186d12566/

That fella wanted to do pretty well the same thing I did (use a command
button to move between records in a form). Moving from record to record
is easy enough, but continuing to scroll through the records while the
left mouse button is being held down is not so easy.

As I said, none of the other threads had a workable solution, so I'm
providing one for future reference.

The AutoRepeat property of the CommandButton is ignored once you move
to a different record. Attempted various Timer functions, but didn't
like any of them. Tried various methods of recalling a MouseDown or
Click event from MouseUp, but those were unsuccessful, as well. MouseUp
is automatically fired whether it has happened or not when the current
record changes to another.

The only reliable method I found was to go to API calls and fire a
function within the form's class module (or any other class module, for
that matter) to continuously run code to move to the next/previous
record until the left button is released. Here's the code snippet:

'**************Declarations section**************
Private mlngVirtualLeft As Long
' Virtual left mouse button. If the user has elected to swap
' their mouse buttons, the physical buttons will not line up
' with the virtual buttons. To preserve expected behavior of
' apiGetAsyncKeyState calls, this value is detected on
' Form_Load or Class_Initialize for use in subsequent API calls.
Private mlngTimerInterval(1) As Long
' apiSleep timer interval in milliseconds
' (0) First pass interval
' (1) Consecutive pass interval

'**************API Constants**************
Private Const VK_LBUTTON As Long = &H1 ' Left mouse button
Private Const VK_RBUTTON As Long = &H2 ' Right mouse button
Private Const SM_SWAPBUTTON As Long = 23
' When used as nIndex in apiGetSystemMetrics this will be
' nonzero if the meanings of the left and right mouse buttons
' are swapped; otherwise, 0 (zero).

'**************API Functions**************
' The GetAsyncKeyState function determines whether a key is
' up or down at the time the function is called, and whether
' the key was pressed after a previous call to GetAsyncKeyState.
Private Declare Function apiGetAsyncKeyState Lib "user32.dll" _
Alias "GetAsyncKeyState" (ByVal vKey As Long) As Integer
' The GetSystemMetrics function retrieves various system
' metrics (widths and heights of display elements) and system
' configuration settings.
Private Declare Function apiGetSystemMetrics Lib "user32.dll" _
Alias "GetSystemMetrics" (ByVal nIndex As Long) As Long
' The Sleep function suspends the execution of the current
' thread for at least the specified interval.
Private Declare Sub apiSleep Lib "kernel32.dll" Alias "Sleep" _
(ByVal dwMilliseconds As Long)

'**************Functional code**************
Private Sub DetectState(bytRecord As AcRecord)
Dim intBtnState As Integer, blnNotFirstPass As Boolean
Do
' Move to record specified
Call RecordNav(bytRecord)
' Pause code for specified interval
Call Sleep(mlngTimerInterval(Abs(blnNotFirstPass)))
blnNotFirstPass = True
' Detect mouse button
intBtnState = GetAsyncKeyState(mlngVirtualLeft)
' Loop until button released
Loop Until (intBtnState = 0) Or (intBtnState = 1)
End Sub

Private Sub RecordNav(bytRecord As AcRecord)
' This function maintained seperately so that it may
' be called from places other than DetectState
' to provide functionality such as RecordNav(acLast)
DoCmd.GoToRecord , , bytRecord
End Sub

Private Sub Form_Load()
' Should be Class_Initialize if you're using it in a custom class
' Check virtual mouse key settings for virtual left
mlngVirtualLeft = apiGetSystemMetrics(SM_SWAPBUTTON)
If mlngVirtualLeft = 0 Then
mlngVirtualLeft = VK_LBUTTON
Else: mlngVirtualLeft = VK_RBUTTON
End If
' Default timer settings
mlngTimerInterval(0) = 500
mlngTimerInterval(1) = 50
End Sub

Private Sub NextButton_Click()
Call DetectState(acNext)
End Sub

Private Sub PreviousButton_Click()
Call DetectState(acPrevious)
End Sub

'**************End code**************

This hasn't been troubleshot completely, yet, and obviously needs some
error handling. Some structural error handling to detect movement to
the First or Last record will be needed to keep from getting error
2105: "You can't go to the specified record." This will happen under
this structure when you navigate all the way to the beginning or end of
the recordset.

If you see any problems or ways to improve the code, please reply.

Nov 13 '06 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Jamey Shuemaker wrote:
Howdy,

Saw a couple threads from the past few years on this topic, but didn't
really find any solutions.

Here's one I found:
http://groups.google.com/group/comp....cff0186d12566/

That fella wanted to do pretty well the same thing I did (use a command
button to move between records in a form). Moving from record to record
is easy enough, but continuing to scroll through the records while the
left mouse button is being held down is not so easy.

As I said, none of the other threads had a workable solution, so I'm
providing one for future reference.

The AutoRepeat property of the CommandButton is ignored once you move
to a different record. Attempted various Timer functions, but didn't
like any of them. Tried various methods of recalling a MouseDown or
Click event from MouseUp, but those were unsuccessful, as well. MouseUp
is automatically fired whether it has happened or not when the current
record changes to another.

The only reliable method I found was to go to API calls and fire a
function within the form's class module (or any other class module, for
that matter) to continuously run code to move to the next/previous
record until the left button is released. Here's the code snippet:

'**************Declarations section**************
Private mlngVirtualLeft As Long
' Virtual left mouse button. If the user has elected to swap
' their mouse buttons, the physical buttons will not line up
' with the virtual buttons. To preserve expected behavior of
' apiGetAsyncKeyState calls, this value is detected on
' Form_Load or Class_Initialize for use in subsequent API calls.
Private mlngTimerInterval(1) As Long
' apiSleep timer interval in milliseconds
' (0) First pass interval
' (1) Consecutive pass interval

'**************API Constants**************
Private Const VK_LBUTTON As Long = &H1 ' Left mouse button
Private Const VK_RBUTTON As Long = &H2 ' Right mouse button
Private Const SM_SWAPBUTTON As Long = 23
' When used as nIndex in apiGetSystemMetrics this will be
' nonzero if the meanings of the left and right mouse buttons
' are swapped; otherwise, 0 (zero).

'**************API Functions**************
' The GetAsyncKeyState function determines whether a key is
' up or down at the time the function is called, and whether
' the key was pressed after a previous call to GetAsyncKeyState.
Private Declare Function apiGetAsyncKeyState Lib "user32.dll" _
Alias "GetAsyncKeyState" (ByVal vKey As Long) As Integer
' The GetSystemMetrics function retrieves various system
' metrics (widths and heights of display elements) and system
' configuration settings.
Private Declare Function apiGetSystemMetrics Lib "user32.dll" _
Alias "GetSystemMetrics" (ByVal nIndex As Long) As Long
' The Sleep function suspends the execution of the current
' thread for at least the specified interval.
Private Declare Sub apiSleep Lib "kernel32.dll" Alias "Sleep" _
(ByVal dwMilliseconds As Long)

'**************Functional code**************
Private Sub DetectState(bytRecord As AcRecord)
Dim intBtnState As Integer, blnNotFirstPass As Boolean
Do
' Move to record specified
Call RecordNav(bytRecord)
' Pause code for specified interval
Call Sleep(mlngTimerInterval(Abs(blnNotFirstPass)))
blnNotFirstPass = True
' Detect mouse button
intBtnState = GetAsyncKeyState(mlngVirtualLeft)
' Loop until button released
Loop Until (intBtnState = 0) Or (intBtnState = 1)
End Sub

Private Sub RecordNav(bytRecord As AcRecord)
' This function maintained seperately so that it may
' be called from places other than DetectState
' to provide functionality such as RecordNav(acLast)
DoCmd.GoToRecord , , bytRecord
End Sub

Private Sub Form_Load()
' Should be Class_Initialize if you're using it in a custom class
' Check virtual mouse key settings for virtual left
mlngVirtualLeft = apiGetSystemMetrics(SM_SWAPBUTTON)
If mlngVirtualLeft = 0 Then
mlngVirtualLeft = VK_LBUTTON
Else: mlngVirtualLeft = VK_RBUTTON
End If
' Default timer settings
mlngTimerInterval(0) = 500
mlngTimerInterval(1) = 50
End Sub

Private Sub NextButton_Click()
Call DetectState(acNext)
End Sub

Private Sub PreviousButton_Click()
Call DetectState(acPrevious)
End Sub

'**************End code**************

This hasn't been troubleshot completely, yet, and obviously needs some
error handling. Some structural error handling to detect movement to
the First or Last record will be needed to keep from getting error
2105: "You can't go to the specified record." This will happen under
this structure when you navigate all the way to the beginning or end of
the recordset.

If you see any problems or ways to improve the code, please reply.
Uh huh!

Nov 13 '06 #2

P: n/a
Hi Jamey,
While I appreciate an API solution more than the next person, is there a
reason you do not simply insert your CommandButtons onto a Subform to
resolve the Autorepeat issue?
http://www.lebans.com/recnavbuttons.htm
A2KRecordNavigationButtons is an MDB containing code to replace the standard
Navigation Buttons. The custom buttons exactly emulate the standard
navigation bar including the autorepeat property. A2K or higher! Modified by
MVP Graham Mandeno to work properly with multiple SubForm configurations.

A97RecordNavigationButtons is an MDB containing code to replace the standard
Navigation Buttons. The custom buttons exactly emulate the standard
navigation bar including the autorepeat property.

Version 1.7 Oct 06, 2006

Modified by MVP Graham Mandeno to work properly with multiple SubForm
configurations.
--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
"Jamey Shuemaker" <ca*********@yahoo.comwrote in message
news:11**********************@m73g2000cwd.googlegr oups.com...
Howdy,

Saw a couple threads from the past few years on this topic, but didn't
really find any solutions.

Here's one I found:
http://groups.google.com/group/comp....cff0186d12566/

That fella wanted to do pretty well the same thing I did (use a command
button to move between records in a form). Moving from record to record
is easy enough, but continuing to scroll through the records while the
left mouse button is being held down is not so easy.

As I said, none of the other threads had a workable solution, so I'm
providing one for future reference.

The AutoRepeat property of the CommandButton is ignored once you move
to a different record. Attempted various Timer functions, but didn't
like any of them. Tried various methods of recalling a MouseDown or
Click event from MouseUp, but those were unsuccessful, as well. MouseUp
is automatically fired whether it has happened or not when the current
record changes to another.

The only reliable method I found was to go to API calls and fire a
function within the form's class module (or any other class module, for
that matter) to continuously run code to move to the next/previous
record until the left button is released. Here's the code snippet:

'**************Declarations section**************
Private mlngVirtualLeft As Long
' Virtual left mouse button. If the user has elected to swap
' their mouse buttons, the physical buttons will not line up
' with the virtual buttons. To preserve expected behavior of
' apiGetAsyncKeyState calls, this value is detected on
' Form_Load or Class_Initialize for use in subsequent API calls.
Private mlngTimerInterval(1) As Long
' apiSleep timer interval in milliseconds
' (0) First pass interval
' (1) Consecutive pass interval

'**************API Constants**************
Private Const VK_LBUTTON As Long = &H1 ' Left mouse button
Private Const VK_RBUTTON As Long = &H2 ' Right mouse button
Private Const SM_SWAPBUTTON As Long = 23
' When used as nIndex in apiGetSystemMetrics this will be
' nonzero if the meanings of the left and right mouse buttons
' are swapped; otherwise, 0 (zero).

'**************API Functions**************
' The GetAsyncKeyState function determines whether a key is
' up or down at the time the function is called, and whether
' the key was pressed after a previous call to GetAsyncKeyState.
Private Declare Function apiGetAsyncKeyState Lib "user32.dll" _
Alias "GetAsyncKeyState" (ByVal vKey As Long) As Integer
' The GetSystemMetrics function retrieves various system
' metrics (widths and heights of display elements) and system
' configuration settings.
Private Declare Function apiGetSystemMetrics Lib "user32.dll" _
Alias "GetSystemMetrics" (ByVal nIndex As Long) As Long
' The Sleep function suspends the execution of the current
' thread for at least the specified interval.
Private Declare Sub apiSleep Lib "kernel32.dll" Alias "Sleep" _
(ByVal dwMilliseconds As Long)

'**************Functional code**************
Private Sub DetectState(bytRecord As AcRecord)
Dim intBtnState As Integer, blnNotFirstPass As Boolean
Do
' Move to record specified
Call RecordNav(bytRecord)
' Pause code for specified interval
Call Sleep(mlngTimerInterval(Abs(blnNotFirstPass)))
blnNotFirstPass = True
' Detect mouse button
intBtnState = GetAsyncKeyState(mlngVirtualLeft)
' Loop until button released
Loop Until (intBtnState = 0) Or (intBtnState = 1)
End Sub

Private Sub RecordNav(bytRecord As AcRecord)
' This function maintained seperately so that it may
' be called from places other than DetectState
' to provide functionality such as RecordNav(acLast)
DoCmd.GoToRecord , , bytRecord
End Sub

Private Sub Form_Load()
' Should be Class_Initialize if you're using it in a custom class
' Check virtual mouse key settings for virtual left
mlngVirtualLeft = apiGetSystemMetrics(SM_SWAPBUTTON)
If mlngVirtualLeft = 0 Then
mlngVirtualLeft = VK_LBUTTON
Else: mlngVirtualLeft = VK_RBUTTON
End If
' Default timer settings
mlngTimerInterval(0) = 500
mlngTimerInterval(1) = 50
End Sub

Private Sub NextButton_Click()
Call DetectState(acNext)
End Sub

Private Sub PreviousButton_Click()
Call DetectState(acPrevious)
End Sub

'**************End code**************

This hasn't been troubleshot completely, yet, and obviously needs some
error handling. Some structural error handling to detect movement to
the First or Last record will be needed to keep from getting error
2105: "You can't go to the specified record." This will happen under
this structure when you navigate all the way to the beginning or end of
the recordset.

If you see any problems or ways to improve the code, please reply.

Nov 13 '06 #3

P: n/a

Stephen Lebans wrote:
Hi Jamey,
While I appreciate an API solution more than the next person, is there a
reason you do not simply insert your CommandButtons onto a Subform to
resolve the Autorepeat issue?

Hey Stephen,

Honestly, didn't know these existed. I'll check them out. I'm using
them on a class object and didn't know about the subform solution.
Sounds like something worth looking into to avoid the Sleep function
which causes some minor quirkiness depending on the click speed of the
user.

I'll look them over and see if they provide a better solution. I'd like
to stay away from the API calls, and if there's a better solution, I'm
certainly game.

Thanks for the links.

Nov 13 '06 #4

P: n/a
Looks solid. I may adapt that somewhat for my purposes with the custom
class to avoid the repeat quirks.

Thanks, again.

Stephen Lebans wrote:
Hi Jamey,
While I appreciate an API solution more than the next person, is there a
reason you do not simply insert your CommandButtons onto a Subform to
resolve the Autorepeat issue?
http://www.lebans.com/recnavbuttons.htm
A2KRecordNavigationButtons is an MDB containing code to replace the standard
Navigation Buttons. The custom buttons exactly emulate the standard
navigation bar including the autorepeat property. A2K or higher! Modified by
MVP Graham Mandeno to work properly with multiple SubForm configurations.

A97RecordNavigationButtons is an MDB containing code to replace the standard
Navigation Buttons. The custom buttons exactly emulate the standard
navigation bar including the autorepeat property.

Version 1.7 Oct 06, 2006

Modified by MVP Graham Mandeno to work properly with multiple SubForm
configurations.
--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
"Jamey Shuemaker" <ca*********@yahoo.comwrote in message
news:11**********************@m73g2000cwd.googlegr oups.com...
Howdy,

Saw a couple threads from the past few years on this topic, but didn't
really find any solutions.

Here's one I found:
http://groups.google.com/group/comp....cff0186d12566/

That fella wanted to do pretty well the same thing I did (use a command
button to move between records in a form). Moving from record to record
is easy enough, but continuing to scroll through the records while the
left mouse button is being held down is not so easy.

As I said, none of the other threads had a workable solution, so I'm
providing one for future reference.

The AutoRepeat property of the CommandButton is ignored once you move
to a different record. Attempted various Timer functions, but didn't
like any of them. Tried various methods of recalling a MouseDown or
Click event from MouseUp, but those were unsuccessful, as well. MouseUp
is automatically fired whether it has happened or not when the current
record changes to another.

The only reliable method I found was to go to API calls and fire a
function within the form's class module (or any other class module, for
that matter) to continuously run code to move to the next/previous
record until the left button is released. Here's the code snippet:

'**************Declarations section**************
Private mlngVirtualLeft As Long
' Virtual left mouse button. If the user has elected to swap
' their mouse buttons, the physical buttons will not line up
' with the virtual buttons. To preserve expected behavior of
' apiGetAsyncKeyState calls, this value is detected on
' Form_Load or Class_Initialize for use in subsequent API calls.
Private mlngTimerInterval(1) As Long
' apiSleep timer interval in milliseconds
' (0) First pass interval
' (1) Consecutive pass interval

'**************API Constants**************
Private Const VK_LBUTTON As Long = &H1 ' Left mouse button
Private Const VK_RBUTTON As Long = &H2 ' Right mouse button
Private Const SM_SWAPBUTTON As Long = 23
' When used as nIndex in apiGetSystemMetrics this will be
' nonzero if the meanings of the left and right mouse buttons
' are swapped; otherwise, 0 (zero).

'**************API Functions**************
' The GetAsyncKeyState function determines whether a key is
' up or down at the time the function is called, and whether
' the key was pressed after a previous call to GetAsyncKeyState.
Private Declare Function apiGetAsyncKeyState Lib "user32.dll" _
Alias "GetAsyncKeyState" (ByVal vKey As Long) As Integer
' The GetSystemMetrics function retrieves various system
' metrics (widths and heights of display elements) and system
' configuration settings.
Private Declare Function apiGetSystemMetrics Lib "user32.dll" _
Alias "GetSystemMetrics" (ByVal nIndex As Long) As Long
' The Sleep function suspends the execution of the current
' thread for at least the specified interval.
Private Declare Sub apiSleep Lib "kernel32.dll" Alias "Sleep" _
(ByVal dwMilliseconds As Long)

'**************Functional code**************
Private Sub DetectState(bytRecord As AcRecord)
Dim intBtnState As Integer, blnNotFirstPass As Boolean
Do
' Move to record specified
Call RecordNav(bytRecord)
' Pause code for specified interval
Call Sleep(mlngTimerInterval(Abs(blnNotFirstPass)))
blnNotFirstPass = True
' Detect mouse button
intBtnState = GetAsyncKeyState(mlngVirtualLeft)
' Loop until button released
Loop Until (intBtnState = 0) Or (intBtnState = 1)
End Sub

Private Sub RecordNav(bytRecord As AcRecord)
' This function maintained seperately so that it may
' be called from places other than DetectState
' to provide functionality such as RecordNav(acLast)
DoCmd.GoToRecord , , bytRecord
End Sub

Private Sub Form_Load()
' Should be Class_Initialize if you're using it in a custom class
' Check virtual mouse key settings for virtual left
mlngVirtualLeft = apiGetSystemMetrics(SM_SWAPBUTTON)
If mlngVirtualLeft = 0 Then
mlngVirtualLeft = VK_LBUTTON
Else: mlngVirtualLeft = VK_RBUTTON
End If
' Default timer settings
mlngTimerInterval(0) = 500
mlngTimerInterval(1) = 50
End Sub

Private Sub NextButton_Click()
Call DetectState(acNext)
End Sub

Private Sub PreviousButton_Click()
Call DetectState(acPrevious)
End Sub

'**************End code**************

This hasn't been troubleshot completely, yet, and obviously needs some
error handling. Some structural error handling to detect movement to
the First or Last record will be needed to keep from getting error
2105: "You can't go to the specified record." This will happen under
this structure when you navigate all the way to the beginning or end of
the recordset.

If you see any problems or ways to improve the code, please reply.
Nov 13 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.