Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Custom Command Buttons

How to

Custom Command Buttons

by  Beard36  Posted    (Edited  )
Introduction
In Access, command buttons are generally restricted to the old generic Windows style - even in XP we still have to deal with those dull, grey, square controls. I've come across many questions and answers while I was trying to find what I thought would be the best way to implement "Custom Buttons", which I will share here.

Custom Buttons use images in place of the standard button. In this case there are three - one for the button, untouched, one for the button while the user presses the left mouse button down over it, and one for while the cursor is hovering over the button but the mouse button isn't actually depressed. These three images relate to "up" (standard), "down" (pressed) and "hover" states of the button.

The following technique varies from most others I have read in that once it is set up, it is very easy to add a new custom button to a form, generally no extra code must be written, while most other instruction sets require new entries into the form code for each button placed.

Instructions
Create a new module with the following code in it

Public Function cmdButton_MoveUp(cmdButton As String, strForm As String)
Forms(strForm).Controls(cmdButton & "_Up").Visible = True
Forms(strForm).Controls(cmdButton & "_Down").Visible = False
Forms(strForm).Controls(cmdButton & "_Hover").Visible = False
End Function

Public Function cmdButton_MoveDown(cmdButton As String, strForm As String)
Forms(strForm).Controls(cmdButton & "_Down").Visible = True
Forms(strForm).Controls(cmdButton & "_Up").Visible = False
Forms(strForm).Controls(cmdButton & "_Hover").Visible = False
End Function

Public Function cmdButton_Hover(cmdButton As String, strForm As String, Optional strLastLit As String)
' Turn off hover effect of last button (if applicable)
If (Nz(strLastLit) <> "") Then
TurnOffLastHover strForm, strLastLit
End If

' Set up current button as highlighted
Forms(strForm).Controls(cmdButton & "_Hover").Visible = True
Forms(strForm).Controls(cmdButton & "_Up").Visible = False
Forms(strForm).Controls(cmdButton & "_Down").Visible = False

' Update mouse move events for Detail and all of the buttons
UpdateMouseMoves strForm, cmdButton
End Function

Private Sub UpdateMouseMoves(strForm As String, strLastLit As String)
Dim ctrl As Control

For Each ctrl In Forms(strForm).Controls
If (ctrl.Tag = "cmdButton") Then
If (ctrl.Name = strLastLit) Then
' Disable mouse move event for currently-lit button
ctrl.OnMouseMove = vbNullString
Else
' Update other buttons' events with the name of the current button
ctrl.OnMouseMove = "=cmdButton_Hover(" & Chr(34) & ctrl.Name & Chr(34) & ",Form.Name," & Chr(34) & strLastLit & Chr(34) & ")"
End If
End If
Next

' Update Detail mouse move event with currently lit button's name
Forms(strForm).Detail.OnMouseMove = "=TurnOffLastHoverDetail(Form.Name," & Chr(34) & strLastLit & Chr(34) & ")"
End Sub

Public Function TurnOffLastHover(strForm As String, strLastLit As String)
' Restore the state of the last button that was made highlighted to standard (ie. not
' highlighted, not depressed)
If (Forms(strForm).Controls(strLastLit).Visible) Then
Forms(strForm).Controls(strLastLit & "_Up").Visible = True
Forms(strForm).Controls(strLastLit & "_Down").Visible = False
Forms(strForm).Controls(strLastLit & "_Hover").Visible = False
End If
' Reenable that button's mouse move event
Forms(strForm).Controls(strLastLit).OnMouseMove = "=cmdButton_Hover(" & Chr(34) & strLastLit & Chr(34) & "," & Chr(34) & strForm & Chr(34) & ")"
End Function

Public Function TurnOffLastHoverDetail(strForm As String, strLastLit As String)
' The Detail's mouse move event has called this function - it will now turn off the high-
' lighted effect of that last button, and then its mouse move event will be disabled to
' prevent unnecessary repeat events.
TurnOffLastHover strForm, strLastLit
Forms(strForm).Detail.OnMouseMove = vbNullString
End Function

Public Sub InitButtons(Form As Form)
Dim ctrl As Control

For Each ctrl In Form.Controls
If (ctrl.Tag = "cmdButton") Then
' Create Mouse Events
ctrl.OnMouseUp = "=cmdButton_MoveUp(" & Chr(34) & ctrl.Name & Chr(34) & ",Form.Name)"
ctrl.OnMouseDown = "=cmdButton_MoveDown(" & Chr(34) & ctrl.Name & Chr(34) & ",Form.Name)"
ctrl.OnMouseMove = "=cmdButton_Hover(" & Chr(34) & ctrl.Name & Chr(34) & ",Form.Name)"
' Set image visibilities
Form.Controls(ctrl.Name & "_Up").Visible = True
Form.Controls(ctrl.Name & "_Down").Visible = False
Form.Controls(ctrl.Name & "_Hover").Visible = False
End If
Next

Form.Detail.OnMouseMove = vbNullString
End Sub

Open a form that you want to place a custom button onto. To illustrate, say we wanted a button for "Discard changes". This command button will be called "cmdDiscard". Create 3 image controls, one for each of the button states. Size and locate them accordingly (all of them perfectly overlapping with each other). Naming them "cmdDiscard_Up", "cmdDiscard_Down" and "cmdDiscard_Hover". Then create a command button control, size it so that it overlaps these images and call it "cmdDiscard". Go into it's properties and set "Transparent" to "yes" and set "Tag" to "cmdButton".

Go into the form's code and add a line into Form_Load -

InitButtons Me

And that's it!
You will still need to add the _Click code to the command button as usual, but this is unaffected by the code here which uses the _MouseMove, _MouseUp and _MouseDown events.

Additional Notes
This code also uses the _MouseMove event of "Detail" - the form's background, so that can not be used for any other purpose. However, that shouldn't be a problem as I haven't come across anyone using the Detail_MouseMove unless it is with custom buttons.

A further note - some of the code above could have been made simpler in some respects. For example, instead of me keeping a record of which button was "set to hover" last, and only adjusting the visibility properties for the images on that button from Detail_MouseMove, I could have just reset all of the images, which would have made the code easier to follow. Similarly, in the code here, once Detail_MouseMove has been called, it is then disabled until another button is highlighted - this is to prevent the _MouseMove event from firing repeatedly while the cursor is moved around the form. In normal circumstances, these added complications aren't really necessary, but I have been using this code with code from FAQ705-2562 which hides the Access Window (the grey background, etc..). For some reason, when doing so, the flicker on the buttons was much more obvious so I wanted to restrict the redraws and event firings as much as possible.

One more note - you may be wondering why in "TurnOffLastHover" there is a check that the last button that was highlighted is visible before changing the image visibility properties. There is a good reason for this. On one of the forms that I use this code for, the layout of the form can be changed by clicking one of a few buttons. In this case, the form changes from "View" mode to "Entry" mode. Pressing "Edit" enables the fields for editing, and replaces the "Edit" button with "Save" and "Discard Changes" buttons. The Edit_Click event hides the "Edit" button. Without this mystery line in "TurnOffLastHover", as soon as the Edit button was hidden, Detail_MouseMove would be triggered and it would try to set the "Edit" button to be in its _Up state. Clearly this would be undesirable behaviour.

The End.. finally :)
Well, hopefully this will be of some help to someone. As I said, the advantage of this method is that once it's set up, it is very easy to add new buttons to a form. It's pretty robust, I've been using it for a little while now, and it's pretty flexible.

Beard36.
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top