Visual Basic Intrinsic Control Routines
SetWindowLong: Changing Button Caption Alignment (non-graphical only)
Posted:   Saturday January 11, 2003
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows NP
OS restrictions:   None
Author:   Randy Birch, VBnet


SetWindowLong: Changing Button Caption Alignment (non-graphical only)
Pure VB: Mimicking a Command Button ForeColor Property
WM_DRAWITEM: Set Command Button ForeColor
SendMessage: Visually Pressing a Command Button Through Code

VB5 or VB6.

OK ... although this may be totally against Windows design standards, applied judiciously the effect may address specific design requirements.

The methodology here is simple. For each button in a control array the button's style bits are changed via a call to SetWindowLong. The non-Windows constants I've defined below represent the values required by SetWindowLong to cause the button captions to become positioned at points other than centred. The call to set a centred caption is also included, though since this is the button's default position its inclusion below is more for completeness than for practicality. In the demo I've exaggerated the button's height to visually emphasize the offset created through changing these button styles.

An interesting routine in this method is the CreateControlGrid sub. This takes parameters set through a UDT to create a X by Y layout, such as the 3x3 layout shown above. By creating a single control array button (index 0) and setting the UDT's totalRows and totalColumns members, CreateControlGrid loads and positions the controls based on the parameters specified.

And, before I get a ton'o'emails, no, you can not use this method to cause a graphical-style command button to change the alignment of the caption and image such that they appear side-by-side on the same line. Attempting to apply the code below to a graphical-style button will remove the picture.

 BAS Module Code

 Form Code
Add a single command button to a form (Command1) and set its Index property to 0. Add the following code:

Option Explicit
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
Private Const GWL_STYLE As Long = (-16)

'these are not true Windows button styles
Private Const BS_ALIGN_CENTRELEFT As Long = &H100
Private Const BS_ALIGN_CENTRERIGHT As Long = &H200
Private Const BS_ALIGN_CENTRE As Long = &H300
Private Const BS_ALIGN_TOPMIDDLE As Long = &H400
Private Const BS_ALIGN_TOPLEFT As Long = &H500
Private Const BS_ALIGN_TOPRIGHT As Long = &H600
Private Const BS_ALIGN_BOTTOMMIDDLE As Long = &H800
Private Const BS_ALIGN_BOTTOMLEFT As Long = &H900
Private Const BS_ALIGN_BOTTOMRIGHT As Long = &HA00

Private Declare Function GetWindowLong Lib "user32" _
   Alias "GetWindowLongA" _
   (ByVal hwnd As Long, _
   ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" _
   Alias "SetWindowLongA" ( _
   ByVal hwnd As Long, _
   ByVal nIndex As Long, _
   ByVal dwNewLong As Long) As Long

Private Type ControlLayoutData
   totalRows As Long
   totalColumns As Long
   rowPadding As Long
   colPadding As Long
   ctlHeight  As Long
   ctlWidth As Long
   pgridTop As Long
   pgridLeft As Long
End Type

Private Sub Form_Load()

   Dim cnt As Long
   Dim style As Long
   Dim cld As ControlLayoutData
   Dim a()
  'temp array for button captions
   a() = Array("not used", _
               "Top Left", "Top Centre", "Top Right", _
               "Centre Left", "Centre", "Centre Right", _
               "Bottom Left", "Bottom Centre", "Bottom Right")
  'the UDT containing control array
  'layout data
   With cld
      .colPadding = 200
      .ctlHeight = 600
      .ctlWidth = 1575
      .pgridLeft = 300
      .pgridTop = 300
      .totalColumns = 3
      .totalRows = 3
   End With
  'since CreateControlGrid hides Command1(0),
  'the button's style must be retrieved
  'before it is hidden
   style = GetWindowLong(Command1(0).hwnd, GWL_STYLE)
  'create a grid of buttons as per
  'the ControlLayoutData specs and
  'assign the button captions from
  'the array
   CreateControlGrid cld, a()
  'change the button style for each
  'of the nine visible buttons
   Call SetWindowLong(Command1(1).hwnd, GWL_STYLE, style Or BS_ALIGN_TOPLEFT)
   Call SetWindowLong(Command1(2).hwnd, GWL_STYLE, style Or BS_ALIGN_TOPMIDDLE)
   Call SetWindowLong(Command1(3).hwnd, GWL_STYLE, style Or BS_ALIGN_TOPRIGHT)
   Call SetWindowLong(Command1(4).hwnd, GWL_STYLE, style Or BS_ALIGN_CENTRELEFT)
   Call SetWindowLong(Command1(5).hwnd, GWL_STYLE, style Or BS_ALIGN_CENTRE)
   Call SetWindowLong(Command1(6).hwnd, GWL_STYLE, style Or BS_ALIGN_CENTRERIGHT)
   Call SetWindowLong(Command1(7).hwnd, GWL_STYLE, style Or BS_ALIGN_BOTTOMLEFT)
   Call SetWindowLong(Command1(8).hwnd, GWL_STYLE, style Or BS_ALIGN_BOTTOMMIDDLE)
   Call SetWindowLong(Command1(9).hwnd, GWL_STYLE, style Or BS_ALIGN_BOTTOMRIGHT)

End Sub

Private Sub CreateControlGrid(cld As ControlLayoutData, caps() As Variant)

   Dim cnt As Long
   Dim nCol As Long
   Dim nRow As Long
   Dim pixTop As Long
   Dim pixLeft As Long
  'Preload all the required controls.
  'VB's default state for new controls
  'is hidden. Set the initial contro's
  'height and width, avoiding the need
  'to set it in the loop below.
   With Command1(0)
      .Height = cld.ctlHeight
      .Width = cld.ctlWidth
      .Visible = False
   End With
  'load all controls
   For cnt = 1 To (cld.totalRows * cld.totalColumns)
      Load Command1(cnt)
  'position the controls to form
  'a grid
   cnt = 0
   For nRow = 1 To cld.totalRows
      For nCol = 1 To cld.totalColumns
         cnt = cnt + 1
         With Command1(cnt)
            .Top = cld.pgridTop + ((cld.ctlHeight * nRow) - cld.ctlHeight) + _
                                      (cld.rowPadding * (nRow - 1))
            .Left = cld.pgridLeft + ((cld.ctlWidth * nCol) - cld.ctlWidth) + _
                                        (cld.colPadding * (nCol - 1))
            .Caption = caps(cnt)
            .Visible = True

         End With
      Next nCol

End Sub


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter