Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.


How to

Custom Command Buttons by Beard36
Posted: 14 Jul 04

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.

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
     ' 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
  ' 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
  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.


Back to Microsoft: Access Forms FAQ Index
Back to Microsoft: Access Forms Forum

My Archive


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close