# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  Image & Text On A Standard Command Button (Not Graphical Style!)- XP/2K/98

## RobDog888

After searching a long time for code that would align the text and the image in a standard command button 
without using the graphcal style or a picture of a button I decided to write my own.

I got the text alignment working with the help of Merrion here in this post and this post.

Next I needed to get the image to align also, but that seemed impossible so I figured out a workaround.

If you use a picture box control and nest it inside a command button (not just drawn on the top of it) 
you can place an image anywhere you want on the button in relation to the text. I also found that this 
would keep the button (in standard style) compatible with XP and its Visual Styles which are ever so popular.

Note: The XP Visual Style is achieved by using a manifest file and running on Windows XP.

I think its actually quite simple once you think about it.

One of the issues I had to figure out was when it was running under Windows 2000 or below the button click simulates 
a 3D effect of a push button. So I had to find the correct offset, in pixels, to the right and down. Then if its running 
under Windows XP there is no offset. So I added code to determine the OS and offset the image when pressed accordingly.



1. is the MouseOver effect in XP
2. is when the button has the focus in XP
3. is when the button is in the up position under Windows 2000 or below
4. is when the button is depressed  :Frown:  under Windows 2000 or below


I attached a zip file of the complete working demo too.

Let me know what you think. I hope you enjoy this code.  :Thumb: 


VB Code:
'BEHIND A FORM (FORM1)
Option Explicit
'<10/21/2004 ROBDOG888 VB/OUTLOOK GURU>
Private mlX As Long
Private mlY As Long
 Private Sub Command1_Click()
    Picture1.Refresh
    MsgBox "Look Manavo11, a standard command button with an aligned image and text in it!", vbOKOnly + vbInformation, _
    "RobDog888's Picture Button Demo" '
End Sub
 Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Picture1.Move Picture1.Left + mlX, Picture1.Top + mlY
    Picture1.Refresh
End Sub
 Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Picture1.Move Picture1.Left - mlX, Picture1.Top - mlY
    Picture1.Refresh
End Sub
 Private Sub Form_Load()
    Select Case GetFullVersion
        Case "2.5.1", "2.5.2" 'XP, SERVER 2003, +
            'OFF - NO OFFSET WHEN CLICKED
            mlX = 0
            mlY = 0
        Case Else
            'ON - OFFSET WHEN CLICKED
            mlX = 15
            mlY = 15
    End Select
    'DISABLE THE PICTUREBOX TO AVOID THE PICTUREBOX CLICK EVENT CAUSING ISSUES - THANKS JOACIM :)
    [color=red]Picture1.Enabled = False[/color] 'ADDED IN THIS POSTED CODE BUT ATTACHMENT CODE NOT UPDATED YET
    'CHANGE THE LAST PARAMETER TO CHANGE THE ALIGNMENT
    MakeGraphicalOutOfStandardButton Command1, Picture1, BS_LEFT
    'ALIGN THE TEXT OPPOSITE OF THE PICTURE ALIGNMENT
    AlignButtonText Command1, BS_RIGHT
End Sub
 'NO LONGER NEEDED
'Private Sub Picture1_Click()
'    Command1_Click
'End Sub
  'INSIDE A STANDARD MODUE (MODULE1)
Option Explicit
'<10/21/2004 ROBDOG888 VB/OUTLOOK GURU>
Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
 Public Const BS_LEFT    As Long = &H100&
Public Const BS_RIGHT   As Long = &H200&
Public Const BS_CENTER  As Long = &H300&
Public Const BS_TOP     As Long = &H400&
Public Const BS_BOTTOM  As Long = &H800&
Public Const BS_vCENTER As Long = &HC00
 Private Const GWL_STYLE  As Long = (-16)
 Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
 Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
 Private Type OSVERSIONINFO
  dwOSVersionInfoSize   As Long
  dwMajorVersion        As Long
  dwMinorVersion        As Long
  dwBuildNumber         As Long
  dwPlatformId          As Long '1 = Windows 95. '2 = Windows NT
  szCSDVersion          As String * 128
End Type
 Private Declare Function GetVersionExA Lib "kernel32" (lpVersionInformation As OSVERSIONINFO) As Integer
 Public Function AlignButtonText(ByRef oCmdBtn As CommandButton, ByVal lStyle As Long)
'<10/21/2004 ROBDOG888 VB/OUTLOOK GURU>
'Note: Align text to make room for the image. Depends on type of alignment passed
    Dim lRet As Long
    If lStyle = BS_RIGHT Then
        lRet = GetWindowLong(oCmdBtn.hwnd, GWL_STYLE) And Not lStyle
        oCmdBtn.Caption = oCmdBtn.Caption & Chr(32)
    ElseIf lStyle = BS_LEFT Then
        lRet = GetWindowLong(oCmdBtn.hwnd, GWL_STYLE) And Not lStyle
        oCmdBtn.Caption = Chr(32) & oCmdBtn.Caption
    ElseIf lStyle = BS_CENTER Then
        lRet = GetWindowLong(oCmdBtn.hwnd, GWL_STYLE) And Not BS_RIGHT Or BS_LEFT
    End If
    lRet = SetWindowLong(oCmdBtn.hwnd, GWL_STYLE, lRet Or lStyle)
    oCmdBtn.Refresh
End Function
 Public Function MakeGraphicalOutOfStandardButton(ByRef oCmdBtn As CommandButton, ByRef oPic As PictureBox, ByVal lStyle As Long)
'<10/21/2004 ROBDOG888 VB/OUTLOOK GURU>
'Note: If running XP+ then dont need to adjust pic left and down when the button is clicked
'      In the Button_Click, Button_MouseDown, and the Button_MouseUp events place a refresh method for the pic
    SetParent oPic.hwnd, oCmdBtn.hwnd
    If lStyle = BS_RIGHT Then
        '95 IS THE BUFFER SPACING WHEN RIGHT ALIGNED
        oPic.Move (oCmdBtn.Width - oPic.Width) - 95, (oCmdBtn.Height / 2) - (oPic.Height / 2)
    ElseIf lStyle = BS_LEFT Then
        '95 IS THE BUFFER SPACING WHEN LEFT ALIGNED
        oPic.Move 95, (oCmdBtn.Height / 2) - (oPic.Height / 2)
    ElseIf lStyle = BS_CENTER Then
        oPic.Move (oCmdBtn.Width / 2) - (oPic.Width / 2), (oCmdBtn.Height / 2) - (oPic.Height / 2)
    End If
    oPic.Refresh
End Function
 Public Function GetFullVersion() As String
'<07/07/2004 ROBDOG888 VB/OUTLOOK GURU>
    Dim osinfo  As OSVERSIONINFO
    Dim lRetVal As Integer
    osinfo.dwOSVersionInfoSize = 148
    osinfo.szCSDVersion = Space$(128)
    lRetVal = GetVersionExA(osinfo)
    GetFullVersion = osinfo.dwPlatformId & "." & osinfo.dwMajorVersion & "." & osinfo.dwMinorVersion
End Function
VB/Office Guru

 :Alien Frog:

----------


## manavo11

So the XP style is actually generated from the manifest file, right? I guess you forgot to mention it?  :Ehh:  

And it's manavo, not Manovo  :Big Grin:

----------


## manavo11

1) While testing I noticed something... You can click on the picturebox  :Smilie: 
2) The SetParent declaration isn't needed in the form  :Smilie:

----------


## RobDog888

Arrrg! I forgot to remove it because I had started ouyt all in one form. I also forgot to include the picture box 
events for when they are clicked, but you just need to acll the command1_click event in the 
Picture1_Clickevent. Nothing involved there. 

The XP style is set by the manifest file but this depends if you are running on XP or not. Plus if you have any 
visual style applied, then there is nothing more to do. Best results are when your using an image with a 
transparent background.

I will make the changes and upload a new attachment.

Sorry about the typ-o  :Wink:

----------


## RobDog888

Changes applied Manavo11 or is Manavo your alter ego?  :Stick Out Tongue:

----------


## lintz

RobDog888, this is exactly what I was looking for however I noticed that if you click on the command button and then move your mouse off the button (while still holding down left mouse button) the image disappears.

----------


## RobDog888

Yes, I have that issue too. I think the only way to get rid of it is to subclass the button and do it a more proper way. But this way is very simple for most programmers.  :Wink:

----------


## |2eM!x

why dont you lockwindowupdate it so it cant dissapear?

----------


## RobDog888

Because it needs to update to show the depressed state and then again the raised.  :Wink: 

Did you see I updated my Shortcut Target Path CodeBank thread?

----------


## |2eM!x

yes i saw it, i meant to thank you..so thank you  :Smilie: 

Well on mouse down you could lwu it then undo it on the mouseup, am i right?

----------


## RobDog888

Not sure since there seems to be some internal animation when the button is pushed down. This is the part that creates the issue since if you didnt update the button window you may loose the animated effect.

----------


## manavo11

I still don't like the fact that when you press the image you don't get the "pressed" down effect of the button  :Big Grin:

----------


## RobDog888

You could make it elaborate and write some code to programmatically animate the push down and up effects if someone clicks on the image, but I'll leave that up to you.  :Big Grin:   :Wink:

----------


## manavo11

I did think about it, but I'm not up for it at the moment... Maybe at some point I will  :Big Grin:

----------


## RobDog888

Probably way too much work. It would be easier to use BadgerBoys XP button code to manually draw the entire thing.  :Wink: 
Mine is for the beginners or the lazy  :Big Grin:

----------


## manavo11

Custom made especially for me. right?  :Big Grin:

----------


## Joacim Andersson

> You could make it elaborate and write some code to programmatically animate the push down and up effects if someone clicks on the image, but I'll leave that up to you.


Yes, you will need some very complicated code for that effect.... Or you could just set the Enabled property of the PicBox to False  :Smilie: . Since a PictureBox doesn't change it's apperance when you disable it will not be noticable, but all mouse events will be delegated to the control under it, which would be the command button.

----------


## RobDog888

Ok, but that still wont produce the animation push down and up effect, correct?
But it will reduce the need for calling the click event of the button.  :Smilie: 


Ps, man! Its been 2 years since I wrote this code.  :Big Grin:

----------


## Joacim Andersson

Of course you get the pushed down/up effect since the mouse messages will be sent to the button instead of to the picture box. You'll get the same effect as if the picture box wasn't there.


> Ps, man! Its been 2 years since I wrote this code.


It's only 1 year since you posted it here, and you linked to this thread from another today. I've totally missed this thread earlier.

----------


## RobDog888

Ok, cool. I didnt read your post that way. Was thinking it was meant as a compromise.  So guess that answers my question.  :Thumb:

----------


## Joacim Andersson

That I said that "you would need some very complicated code" was meant as a joke since you only need to disable the picture box  :Smilie: .

----------


## RobDog888

:LOL:  Ok, you got me on that one.  :Smilie:  But you are always a day ahead of me.  :Frown:

----------


## silkworm

> RobDog888, this is exactly what I was looking for however I noticed that if you click on the command button and then move your mouse off the button (while still holding down left mouse button) the image disappears.





> Yes, I have that issue too. I think the only way to get rid of it is to subclass the button and do it a more proper way. But this way is very simple for most programmers.


Hello Folks,

I am sorry for reviving this very old thread. But since there are many people that still use the good ol' VB6, I think it's worth that I should tell everybody how to solve the issue above.

The "disappearing picture" issue is not encountered when using XP Visual Styles (with the manifest file).
But the workaround should be applied anyway, because when the application is executed under Windows Vista or W7, the will be no Visual Styles even with the manifest file (actually, there is a hack for this, but I haven't tried it yet).

This issue can be solved in two ways.
The simpler way is this (no code modification is need): set the "DragMode" property of the "Command1" control to "1 - Automatic".

But as a side efect, this will show a rectangle when you click the button and drag the mouse while the left mouse button is still pressed.

The less simple way is described below.
It relies on the following workaround: whe set the focus to another control (we can even use the picture as a dummy control), then we set the focus back to the Command1 button).

However, as (yet another) side effect, the picture won't update its offeset properly because some events are disturbed this way (especially the MouseUp event), but I resolved this by saving the picture box absolute position in two variables and modified the code as needed (I tried to bold each modificatin):



```
Option Explicit
'<10/21/2004 ROBDOG888 VB/OUTLOOK GURU>
Private mlX As Long
Private mlY As Long

' these two variables will keep the position of the picture after the execution of "MakeGraphicalOutOfStandardButton" sub
Private pictop As Long
Private picleft As Long

Private Sub Command1_Click()
    Picture1.Move picleft, pictop
    Picture1.Refresh
    MsgBox "Look Manavo11, a standard command button with an aligned image and text in it!", vbOKOnly + vbInformation, _
    "RobDog888's Picture Button Demo" '
End Sub

Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Picture1.Move picleft + mlX, pictop + mlY
    Picture1.Refresh
End Sub

Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  If X < 0 Or Y < 0 Or X > Command1.Width Or Y > Command1.Height Then
    Picture1.Enabled = True  ' if using Picture1 as a dummy control, we'll make sure it is enabled, otherwise the SetFocus method will trigger an error
    Picture1.SetFocus
    Command1.SetFocus
    Picture1.Enabled = False  ' disable the Picture1
    Picture1.Move picleft, pictop
    Picture1.Refresh
  End If
End Sub

Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Picture1.Move picleft, pictop
    Picture1.Refresh
End Sub

Private Sub Form_Load()
    Select Case GetFullVersion
        Case "2.5.1", "2.5.2" 'XP, SERVER 2003, +
            'OFF - NO OFFSET WHEN CLICKED  - oh no, wait... let's create an effect, though
            mlX = 1 * Screen.TwipsPerPixelX
            mlY = 1 * Screen.TwipsPerPixelY
        Case Else        Case Else
            'ON - OFFSET WHEN CLICKED
            mlX = 15
            mlY = 15
    End Select
    'CHANGE THE LAST PARAMETER TO CHANGE THE ALIGNMENT
    MakeGraphicalOutOfStandardButton Command1, Picture1, BS_LEFT
    ' Saving picture position
    picleft = Picture1.Left
    pictop = Picture1.Top
    'ALIGN THE TEXT OPPOSITE OF THE PICTURE ALIGNMENT
    AlignButtonText Command1, BS_RIGHT
End Sub
```

As a "bonus", I modified the code to create a "pressed" effect for XP and 2K3.
Please note that I assumed that the "Enabled" property of the Picture1 control is set to false.

I hope this may be useful to someone some day.

Yes, I know there are custom controls that mimic XP visual style. But those controls are immune to any other style/theme made for XP. Moreover, applications using those custom controls won't display Vista/W7 styles (providing the hack in the link above will work).

----------


## Joacim Andersson

Or you can simply do as I suggested 6 years ago and disable the picture box.  :Smilie:

----------


## silkworm

Disabling the picture box doesn't prevent it from beign hidden when the user clicks the button and moves the mouse.

But the picture box must be disabled indeed, because otherwise any click above it will be interpreted as a click on the picture box itself and not on the command button.

----------


## Krool

I would like to share some improvements I have made. (changes in bold)



```
Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If X < 0 Or Y < 0 Or X > EventsCommandButton.Width Or Y > EventsCommandButton.Height Then
    If Button = vbLeftButton Then
        Picture1.Enabled = True  ' if using Picture1 as a dummy control, we'll make sure it is enabled, otherwise the SetFocus method will trigger an error
        Picture1.SetFocus
        Command1.SetFocus
        Picture1.Enabled = False  ' disable the Picture1
        Picture1.Move picleft, pictop
        Picture1.Refresh
    End If
End If
End Sub
```



```
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        Picture1.Move picleft, pictop
        Picture1.Refresh
    End If
End Sub
```



```
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button = vbLeftButton Then
        Picture1.Move picleft, pictop
        Picture1.Refresh
    End If
End Sub
```

This I have added to react when hitting the space key on the command button (like mouse clicking):


```
Private Sub Command1_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeySpace Then Picture1.Move picleft + 15, pictop + 15
End Sub

Private Sub Command1_KeyPress(KeyAscii As Integer)
If KeyAscii = vbKeySpace Then Picture1.Refresh
End Sub

Private Sub Command1_KeyUp(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeySpace Then Picture1.Move picleft, pictop
End Sub
```

----------

