vbAccelerator - Contents of code file: cReBar.ctl

VERSION 5.00
Begin VB.UserControl cReBar 
   BorderStyle     =   1  'Fixed Single
   ClientHeight    =   525
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   4905
   InvisibleAtRuntime=   -1  'True
   ScaleHeight     =   525
   ScaleWidth      =   4905
   Begin VB.Label lblRebar 
      Caption         =   "'Rebar Control'"
      Height          =   315
      Left            =   60
      TabIndex        =   0
      Top             =   120
      Width           =   3255
   End
End
Attribute VB_Name = "cReBar"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

' =========================================================================
' vbAccelerator Rebar control v3.0
' Copyright  1998-2000 Steve McMahon (steve@vbaccelerator.com)
'
' This is a complete rebar implementation.
'
' -------------------------------------------------------------------------
' Visit vbAccelerator at http://vbaccelerator.com
' =========================================================================

' ==============================================================================
' Declares, constants and types required for toolbar:
' ==============================================================================
Private Type NMREBAR
    hdr As NMHDR
    dwMask As Long
    uBand As Long
    fStyle As Long
    wID As Long
    lParam As Long
End Type
Private Type NMRBAUTOSIZE
    hdr As NMHDR
    fChanged As Long
    rcTarget As RECT
    rcActual As RECT
End Type
Private Type NMREBARCHILDSIZE
    hdr As NMHDR
    uBand As Long
    wID As Long
    rcChild As RECT
    rcBand As RECT
End Type
Private Type NMREBARCHEVRON
   hdr As NMHDR
   uBand As Long
   wID As Long
   lParam As Long
   rcChevron As RECT
End Type
Private Type REBARINFO
    cbSize As Integer
    fMask As Integer
    hIml As Long
End Type
Private Type REBARBANDINFO
    cbSize As Long
    fMask As Long
    fStyle As Long
    clrFore As Long
    clrBack As Long
    lpText As String
    cch As Long
    iImage As Long
    hWndChild As Long
    cxMinChild As Long
    cyMinChild As Long
    cx As Long
    hbmBack As Long
    wID As Long
End Type
Private Type REBARBANDINFO_471
    cbSize As Long
    fMask As Long
    fStyle As Long
    clrFore As Long
    clrBack As Long
    lpText As String
    cch As Long
    iImage As Integer 'Image
    hWndChild As Long
    cxMinChild As Long
    cyMinChild As Long
    cx As Long
    hbmBack As Long 'hBitmap
    wID As Long
    cyChild As Long
    cyMaxChild As Long
    cyIntegral As Long
    cxIdeal As Long
    lParam As Long
    cxHeader As Long
End Type
Private Type REBARBANDINFO_NOTEXT_471
    cbSize As Long
    fMask As Long
    fStyle As Long
    clrFore As Long
    clrBack As Long
    lpText As Long
    cch As Long
    iImage As Integer 'Image
    hWndChild As Long
    cxMinChild As Long
    cyMinChild As Long
    cx As Long
    hbmBack As Long 'hBitmap
    wID As Long
    cyChild As Long
    cyMaxChild As Long
    cyIntegral As Long
    cxIdeal As Long
    lParam As Long
    cxHeader As Long
End Type

'Rebar Styles
Private Const RBS_TOOLTIPS = &H100&
Private Const RBS_VARHEIGHT = &H200&
Private Const RBS_BANDBORDERS = &H400&
Private Const RBS_FIXEDORDER = &H800&
Private Const RBS_AUTOSIZE = &H2000&
Private Const RBS_VERTICALGRIPPER = &H4000& '  // this always has the vertical
 gripper (default for horizontal mode)
Private Const RBS_DBLCLKTOGGLE = &H8000&

Private Const RBBS_BREAK = &H1               ' break to new line
Private Const RBBS_FIXEDSIZE = &H2           ' band can't be sized
Private Const RBBS_CHILDEDGE = &H4           ' edge around top & bottom of
 child window
Private Const RBBS_NOVERT = &H10             ' don't show when vertical
Private Const RBBS_FIXEDBMP = &H20           ' bitmap doesn't move during band
 resize
Private Const RBBS_VARIABLEHEIGHT = &H40
Private Const RBBS_GRIPPERALWAYS = &H80      ' always show the gripper
Private Const RBBS_NOGRIPPER = &H100 '// never show the gripper
Private Const RBBS_CHEVRON = &H200& ' // If you set cxIdeal, version 5.00
 only...

Private Const RBS_EX_OFFICE9 = &H1&     '// new gripper, chevron, focus handling

Private Const RBBIM_COLORS = &H2
Private Const RBBIM_TEXT = &H4
Private Const RBBIM_IMAGE = &H8
Private Const RBBIM_CHILDSIZE = &H20
Private Const RBBIM_SIZE = &H40
Private Const RBBIM_BACKGROUND = &H80
Private Const RBBIM_ID = &H100
' 4.72 +
Private Const RBBIM_IDEALSIZE = &H200
Private Const RBBIM_LPARAM = &H400
Private Const RBBIM_HEADERSIZE = &H800

Private Const RB_INSERTBANDA = (WM_USER + 1)
Private Const RB_DELETEBAND = (WM_USER + 2)
Private Const RB_GETBARINFO = (WM_USER + 3)
Private Const RB_SETBARINFO = (WM_USER + 4)
Private Const RB_SETBANDINFOA = (WM_USER + 6)
Private Const RB_SETPARENT = (WM_USER + 7)
Private Const RB_HITTEST = (WM_USER + 8)
Private Const RB_GETRECT = (WM_USER + 9)
Private Const RB_INSERTBANDW = (WM_USER + 10)
Private Const RB_SETBANDINFOW = (WM_USER + 11)
Private Const RB_GETROWCOUNT = (WM_USER + 13)
Private Const RB_GETROWHEIGHT = (WM_USER + 14)

Private Const RB_IDTOINDEX = (WM_USER + 16)    '// wParam == id
Private Const RB_GETTOOLTIPS = (WM_USER + 17)
Private Const RB_SETTOOLTIPS = (WM_USER + 18)
Private Const RB_SETBKCOLOR = (WM_USER + 19)
Private Const RB_GETBKCOLOR = (WM_USER + 20)
Private Const RB_SETTEXTCOLOR = (WM_USER + 21)
Private Const RB_GETTEXTCOLOR = (WM_USER + 22)
Private Const RB_SIZETORECT = (WM_USER + 23)   '// resize the rebar/break bands
 and such to this rect (lparam)

Private Const RB_BEGINDRAG = (WM_USER + 24)
Private Const RB_ENDDRAG = (WM_USER + 25)
Private Const RB_DRAGMOVE = (WM_USER + 26)
Private Const RB_GETBARHEIGHT = (WM_USER + 27)

Private Const RB_GETBANDINFOA = (WM_USER + 29)

Private Const RB_MINIMIZEBAND = (WM_USER + 30)
Private Const RB_MAXIMIZEBAND = (WM_USER + 31)

Private Const RB_SHOWBAND = (WM_USER + 35)         '// show/hide band
Private Const RB_SETPALETTE = (WM_USER + 37)
Private Const RB_GETPALETTE = (WM_USER + 38)
Private Const RB_MOVEBAND = (WM_USER + 39)         ' // move band

Private Const RB_SETBANDFOCUS = (WM_USER + 40) '// (UINT) wParam == band index 
     lParam == TRUE/FALSE
                                        '// returns TRUE if gave band focus,
                                         else FALSE
Private Const RB_GETBANDFOCUS = (WM_USER + 41) '// returns index of band with
 focus (-1 if none)
Private Const RB_CYCLEFOCUS = (WM_USER + 42)    '// (UINT) wParam == band index
      (BOOL) lParam == back/forward
                                                '// returns index of band that
                                         got focus (-1 if none)
Private Const RB_SETEXTENDEDSTYLE = (WM_USER + 43)


Private Const RBHT_NOWHERE = &H1
Private Const RBHT_CAPTION = &H2
Private Const RBHT_CLIENT = &H3
Private Const RBHT_GRABBER = &H4
Private Const RBHT_CHEVRON = &H8

Private Const RB_INSERTBAND = RB_INSERTBANDA
Private Const RB_SETBANDINFO = RB_SETBANDINFOA
Private Const RB_GETBANDINFO471 = RB_GETBANDINFOA

Private Const RBN_FIRST = H_MAX - 831                  '// rebar
Private Const RBN_LAST = H_MAX - 859
Private Const RBN_HEIGHTCHANGE = (RBN_FIRST - 0)
Private Const RBN_GETOBJECT = (RBN_FIRST - 1)
Private Const RBN_LAYOUTCHANGED = (RBN_FIRST - 2)
Private Const RBN_AUTOSIZE = (RBN_FIRST - 3)
Private Const RBN_BEGINDRAG = (RBN_FIRST - 4)
Private Const RBN_ENDDRAG = (RBN_FIRST - 5)
Private Const RBN_DELETINGBAND = (RBN_FIRST - 6)       '// Uses NMREBAR
Private Const RBN_DELETEDBAND = (RBN_FIRST - 7)        '// Uses NMREBAR
Private Const RBN_CHILDSIZE = (RBN_FIRST - 8)
Private Const RBN_SETFOCUS = (RBN_FIRST - 9)            '// Uses NMREBAR
Private Const RBN_CHEVRONPUSHED = (RBN_FIRST - 10)

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd
 As Long) As Long

' ==============================================================================
' INTERFACE
' ==============================================================================
' Enumerations:
Public Enum ERBPositionConstants
   erbPositionTop
   erbPositionLeft
   erbPositionRight
   erbPositionBottom
End Enum
Public Enum ECRBImageSourceTypes
    CRBResourceBitmap
    CRBLoadFromFile
    CRBPicture
End Enum

' Internal Implementation:
Private m_hWnd As Long ' Rebar
Private m_hWndCtlParent As Long ' Rebar window parent
Private m_hWndMsgParent As Long ' Where messages are sent
Private m_bSubclassing As Boolean
Private m_bInTerminate As Boolean
Private m_bKillChildren As Boolean
Private m_lMajor As Long, m_lMinor As Long

' Position:
Private m_ePosition As ERBPositionConstants

' Background imaage:
Private m_sPicture As String
Private m_lResourceID As Long
Private m_hInstance As Long
Private m_pic As StdPicture
Private m_hBmp As Long
Private m_eImageSourceType As ECRBImageSourceTypes

' Band original location information:
Private Type tRebarWndStore
   hwndItem As Long
   hWndItemParent As Long
   tR As RECT
End Type
Private m_tWndStore() As tRebarWndStore
Private m_iWndItemCount As Integer

' Band keys:
Private Type tRebarDataStore
   wID As Long
   vData As Variant
End Type
Private m_tDataStore() As tRebarDataStore
Private m_lIDCount As Long

Private m_bVisible As Boolean

Private m_sCtlName As String

Implements ISubclass

' Events:
Public Event HeightChanged(lNewHeight As Long)
Public Event BeginBandDrag(ByVal wID As Long, ByRef bCancel As Boolean)
Public Event EndBandDrag(ByVal wID As Long)
Public Event BandChildResize(ByVal wID As Long, ByVal lBandLeft As Long, ByVal
 lBandTop As Long, ByVal lBandRight As Long, ByVal lBandBottom As Long, ByRef
 lChildLeft As Long, ByRef lChildTop As Long, ByRef lChildRight As Long, ByRef
 lChildBottom As Long)
Public Event LayoutChanged()
Public Event ChevronPushed(ByVal wID As Long, ByVal lLeft As Long, ByVal lTop
 As Long, ByVal lRight As Long, ByVal lBottom As Long)


Public Sub Autosize()
Dim lWidth As Long
Dim lHeight As Long
Dim rc As RECT, rcP As RECT
   If (m_ePosition = erbPositionBottom) Or (m_ePosition = erbPositionTop) Then
      GetWindowRect m_hWndCtlParent, rcP
      lWidth = rcP.Right - rcP.Left
      lHeight = RebarHeight
   Else
      GetWindowRect m_hWndCtlParent, rcP
      lHeight = rcP.Bottom - rcP.Top
      lWidth = RebarWidth
   End If
   rc.Right = lWidth
   rc.Bottom = lHeight
   SendMessage m_hWnd, RB_SIZETORECT, 0, rc
End Sub

Public Property Get Position() As ERBPositionConstants
   Position = m_ePosition
End Property
Public Property Let Position(ByVal ePosition As ERBPositionConstants)
Dim dwStyle As Long
Dim dwNewStyle As Long
Dim hWndP As Long
Dim rc As RECT
   If (m_ePosition <> ePosition) Then
      m_ePosition = ePosition
      
      If (m_hWnd <> 0) Then
         SetProp m_hWnd, "vbal:cRebarPosition", m_ePosition
         
         ' Move...
         dwStyle = GetWindowLong(m_hWnd, GWL_STYLE)
         dwNewStyle = dwStyle
         dwNewStyle = dwNewStyle And Not (CCS_LEFT Or CCS_TOP Or CCS_RIGHT Or
          CCS_BOTTOM)
         Select Case m_ePosition
         Case erbPositionTop
            dwNewStyle = dwNewStyle Or CCS_TOP
         Case erbPositionRight
            dwNewStyle = dwNewStyle Or CCS_RIGHT
         Case erbPositionLeft
            dwNewStyle = dwNewStyle Or CCS_LEFT
         Case erbPositionBottom
            dwNewStyle = dwNewStyle Or CCS_BOTTOM
         End Select
         If dwNewStyle <> dwStyle Then
            SetWindowLong m_hWnd, GWL_STYLE, dwNewStyle
         End If
         
         RebarSize
         RaiseEvent HeightChanged(RebarHeight)
         RebarSize
         
      End If
      
   End If
End Property

Private Sub pCreateSubClass()
   If Not (m_bSubclassing) Then
      If m_hWnd <> 0 Then
         m_hWndMsgParent = UserControl.Parent.hwnd
         If (m_hWndMsgParent > 0) Then
            ' Debug.Print "Subclassing window: " & m_hWndMsgParent
            AttachMessage Me, m_hWndMsgParent, WM_NOTIFY
            AttachMessage Me, m_hWnd, WM_DESTROY
            AttachMessage Me, m_hWndMsgParent, WM_DESTROY
            m_bSubclassing = True
         End If
         SendMessageLong m_hWnd, RB_SETPARENT, m_hWndMsgParent, 0
      End If
   End If
End Sub

Private Sub pDestroySubClass()
   If (m_bSubclassing) Then
      DetachMessage Me, m_hWndMsgParent, WM_NOTIFY
      DetachMessage Me, m_hWnd, WM_DESTROY
      DetachMessage Me, m_hWndMsgParent, WM_DESTROY
      m_hWndMsgParent = 0
      m_bSubclassing = False
   End If
End Sub

' Interface properties
Private Property Get ISUbClass_MsgResponse() As EMsgResponse
   Select Case CurrentMessage
   Case WM_DESTROY
      ISUbClass_MsgResponse = emrPreprocess
   Case Else
      ISUbClass_MsgResponse = emrPreprocess
   End Select
End Property
Private Property Let ISUbClass_MsgResponse(ByVal emrA As EMsgResponse)
   '
End Property

Private Function ISUbClass_WindowProc(ByVal hwnd As Long, _
                                      ByVal iMsg As Long, _
                                      ByVal wParam As Long, _
                                      ByVal lParam As Long) As Long
Dim lHeight As Long
Dim tNMH As NMHDR
Dim tNMR As NMREBAR
Dim tNMRBA As NMRBAUTOSIZE
Dim tNMRCS As NMREBARCHILDSIZE
Dim tNMRC As NMREBARCHEVRON
Dim tNMMouse As NMMOUSE
Dim tR As RECT
Dim bCancel As Boolean
Dim rcChild As RECT
Dim i As Long
Dim lhWnd As Long
Dim wID As Long
   
   ' Don't try to raise events when the control is terminating -
   ' you will crash!
   'If Not (m_bInTerminate) And Not (m_hWnd = 0 Or m_hWndMsgParent = 0) Then
   
      If iMsg = WM_NOTIFY Then
         CopyMemory tNMH, ByVal lParam, Len(tNMH)
         If tNMH.hwndFrom = m_hWnd Then
         
            Select Case tNMH.code
            Case NM_NCHITTEST
               ' NC hittest.  Apparently we can return alternative HT_ values
               ' here but I cannot get it to do anything
               CopyMemory tNMMouse, ByVal lParam, Len(tNMMouse)
               ' ...
               
            Case RBN_HEIGHTCHANGE
               ' Height change notification:
               RebarSize
               lHeight = RebarHeight
               RaiseEvent HeightChanged(lHeight)
            
            Case RBN_AUTOSIZE
               ' Autosize notification, 4.71+
               If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
                  CopyMemory tNMRBA, ByVal lParam, Len(tNMRBA)
                  ' This event isn't of any use because the CCS_NORESIZE style
                  ' is set.  I do not recommend turning CCS_NORESIZE off as it
                  ' is very easy to get infinite loops during resize code
                   without
                  ' it...
               End If
               
            Case RBN_BEGINDRAG, RBN_ENDDRAG
               ' Band dragging notifications, 4.71+
               If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
                  ' user began dragging a band:
                  CopyMemory tNMR, ByVal lParam, Len(tNMR)
                  If tNMR.uBand > -1 Then
                     If tNMH.code = RBN_BEGINDRAG Then
                        bCancel = False
                        RaiseEvent BeginBandDrag(tNMR.wID, bCancel)
                        If bCancel Then
                           ISUbClass_WindowProc = 1
                        Else
                           ISUbClass_WindowProc = 0
                        End If
                     Else
                        RaiseEvent EndBandDrag(tNMR.wID)
                     End If
                  Else
                     ' no band affected.
                     RaiseEvent EndBandDrag(-1)
                  End If
               End If
            
            Case RBN_CHILDSIZE
               ' Child size change notifications, 4.71+
               If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
                  ' user began dragging a band:
                  CopyMemory tNMRCS, ByVal lParam, Len(tNMRCS)
                  LSet rcChild = tNMRCS.rcChild
                  RaiseEvent BandChildResize(tNMRCS.wID, tNMRCS.rcBand.Left,
                   tNMRCS.rcBand.Top, tNMRCS.rcBand.Right,
                   tNMRCS.rcBand.Bottom, rcChild.Left, rcChild.Top,
                   rcChild.Right, rcChild.Bottom)
                  If rcChild.Left <> tNMRCS.rcChild.Left Or rcChild.Top <>
                   tNMRCS.rcChild.Top Or rcChild.Right <> tNMRCS.rcChild.Right
                   Or rcChild.Bottom <> tNMRCS.rcChild.Bottom Then
                     LSet tNMRCS.rcChild = rcChild
                     CopyMemory ByVal lParam, tNMRCS, Len(tNMRCS)
                  End If
                  'Debug.Print tNMRCS.rcBand.left, tNMRCS.rcBand.top,
                   tNMRCS.rcBand.right, tNMRCS.rcBand.bottom
                  ISUbClass_WindowProc = 1
               End If
            
            Case RBN_DELETEDBAND, RBN_DELETINGBAND
               ' band deletion notifications, 4.71+
               If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
                  ' A band has just been deleted:
                  CopyMemory tNMR, ByVal lParam, Len(tNMR)
                  If tNMH.code = RBN_DELETEDBAND Then
                     pRemoveID tNMR.wID
                  Else
                     lhWnd = plGetHwndOfBandChild(m_hWnd, tNMR.uBand, wID)
                     If lhWnd <> 0 Then
                        pResetParent lhWnd
                     End If
                  End If
               End If
                     
            Case RBN_LAYOUTCHANGED
               ' layout changed notification, 4.71+
               If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
                  RaiseEvent LayoutChanged
               End If
            
            Case RBN_CHEVRONPUSHED
               Debug.Print "Chevron Pushed"
               If m_lMajor >= 5 Then
                  CopyMemory tNMRC, ByVal lParam, Len(tNMRC)
                  LSet tR = tNMRC.rcChevron
                  MapWindowPoints m_hWnd, HWND_DESKTOP, tR, 2
                  tR.Left = tR.Left * Screen.TwipsPerPixelX
                  tR.Top = tR.Top * Screen.TwipsPerPixelY
                  tR.Right = tR.Right * Screen.TwipsPerPixelX
                  tR.Bottom = tR.Bottom * Screen.TwipsPerPixelY
                  RaiseEvent ChevronPushed(tNMRC.wID, tR.Left, tR.Top,
                   tR.Right, tR.Bottom)
               End If
            
            'Case Else
            '   Debug.Print tNMH.code
               
            End Select
         
         Else
            Select Case tNMH.code
            Case TBN_QUERYINSERT
               ISUbClass_WindowProc = g_lCustomiseResponse
            Case TBN_QUERYDELETE
               ISUbClass_WindowProc = g_lCustomiseResponse
            End Select
         End If
         
      ElseIf iMsg = WM_DESTROY Then
         debugmsg m_sCtlName & ":WM_DESTROY," & Hex$(hwnd)
         DestroyRebar
         
      End If
   
   'End If

End Function

Public Property Get BandVisible(ByVal lBand As Long) As Boolean
Dim lStyle As Long
    If (lBand >= 0) And (lBand < BandCount) Then
        If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE, fStyle:=lStyle))
         Then
            BandVisible = ((lStyle And RBBS_HIDDEN) <> RBBS_HIDDEN)
        End If
    Else
        BandVisible = False
    End If
   
End Property
Public Property Let BandVisible(ByVal lBand As Long, ByVal bState As Boolean)
Dim lS As Long
   If (lBand >= 0) And (lBand < BandCount) Then
      lS = Abs(bState)
      SendMessageLong m_hWnd, RB_SHOWBAND, lBand, lS
   End If
End Property
Public Property Get BandChildEdge(ByVal lBand As Long) As Boolean
Dim lStyle As Long
   If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
      If (lBand >= 0) And (lBand < BandCount) Then
          If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE, fStyle:=lStyle))
           Then
              BandChildEdge = ((lStyle And RBBS_CHILDEDGE) = RBBS_CHILDEDGE)
          End If
      Else
          BandChildEdge = False
      End If
   Else
      'Unsupported
   End If
   
End Property
Public Property Let BandChildEdge(ByVal lBand As Long, ByVal bState As Boolean)
Dim lStyle As Long
Dim bCurrent As Boolean
Dim tRbbi471 As REBARBANDINFO_NOTEXT_471

   If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
      If (lBand >= 0) And (lBand < BandCount) Then
         If pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE, fStyle:=lStyle)
          Then
            bCurrent = ((lStyle And RBBS_CHILDEDGE) = RBBS_CHILDEDGE)
            If bState <> bCurrent Then
               If bCurrent Then
                  lStyle = lStyle And Not RBBS_CHILDEDGE
               Else
                  lStyle = lStyle Or RBBS_CHILDEDGE
               End If
               With tRbbi471
                  .cbSize = LenB(tRbbi471)
                  .fMask = RBBIM_STYLE
                  .fStyle = lStyle
               End With
               SendMessage m_hWnd, RB_SETBANDINFO, lBand, tRbbi471
            End If
         End If
      End If
   Else
      'Unsupported
   End If
End Property
Public Property Get BandGripper(ByVal lBand As Long) As Boolean
Dim lStyle As Long
   If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
      If (lBand >= 0) And (lBand < BandCount) Then
          If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE, fStyle:=lStyle))
           Then
              BandGripper = ((lStyle And RBBS_NOGRIPPER) <> RBBS_NOGRIPPER)
          End If
      Else
         ' IncorrectBand
      End If
   Else
      'Unsupported
   End If
End Property
Public Property Let BandGripper(ByVal lBand As Long, ByVal bState As Boolean)
Dim lStyle As Long
Dim bCurrent As Boolean
Dim tRbbi471 As REBARBANDINFO_NOTEXT_471

   If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
      If (lBand >= 0) And (lBand < BandCount) Then
         If pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE, fStyle:=lStyle)
          Then
            bCurrent = ((lStyle And RBBS_NOGRIPPER) <> RBBS_NOGRIPPER)
            If bState <> bCurrent Then
               If bCurrent Then
                  lStyle = lStyle Or RBBS_NOGRIPPER
               Else
                  lStyle = lStyle And Not RBBS_NOGRIPPER
               End If
               With tRbbi471
                  .cbSize = LenB(tRbbi471)
                  .fMask = RBBIM_STYLE
                  .fStyle = lStyle
               End With
               SendMessage m_hWnd, RB_SETBANDINFO, lBand, tRbbi471
            End If
         End If
      Else
         ' IncorrectBand
      End If
   Else
      'Unsupported
   End If
End Property
Public Property Get BandChevron(ByVal lBand As Long) As Boolean
Dim lStyle As Long
   If m_lMajor >= 5 Then
      If (lBand >= 0) And (lBand < BandCount) Then
          If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE, fStyle:=lStyle))
           Then
              BandChevron = ((lStyle And RBBS_CHEVRON) = RBBS_CHEVRON)
          End If
      Else
         ' IncorrectBand
      End If
   Else
      'Unsupported
   End If
End Property
Public Property Let BandChevron(ByVal lBand As Long, ByVal bState As Boolean)
Dim lStyle As Long
Dim lCX As Long
Dim bCurrent As Boolean
Dim tRbbi471 As REBARBANDINFO_NOTEXT_471

   If m_lMajor >= 5 Then
      If (lBand >= 0) And (lBand < BandCount) Then
         If pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_STYLE Or RBBIM_CHILDSIZE,
          cxMinChild:=lCX, fStyle:=lStyle) Then
            bCurrent = ((lStyle And RBBS_CHEVRON) = RBBS_CHEVRON)
            If bState <> bCurrent Then
               If bCurrent Then
                  lStyle = lStyle And Not RBBS_CHEVRON
               Else
                  lStyle = lStyle Or RBBS_CHEVRON
               End If
               With tRbbi471
                  .cbSize = LenB(tRbbi471)
                  .fMask = RBBIM_STYLE Or RBBIM_IDEALSIZE
                  .fStyle = lStyle
                  .cxIdeal = lCX
               End With
               SendMessage m_hWnd, RB_SETBANDINFO, lBand, tRbbi471
            End If
         End If
      Else
         ' IncorrectBand
      End If
   Else
      'Unsupported
   End If
End Property

Public Property Get BandChildMinHeight(ByVal lBand As Long) As Long
Dim cy As Long
   If (lBand >= 0) And (lBand < BandCount) Then
      If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_CHILDSIZE, cyMinChild:=cy))
       Then
         BandChildMinHeight = cy
      End If
   Else
      BandChildMinHeight = -1
      ' IncorrectBand
   End If
End Property
Public Property Let BandChildMinHeight(ByVal lBand As Long, lHeight As Long)
   If (lBand >= 0) And (lBand < BandCount) Then
      Dim tRbbi As REBARBANDINFO_NOTEXT
      Dim lR As Long
      tRbbi.fMask = RBBIM_CHILDSIZE Or RBBIM_CHILD
      tRbbi.cbSize = Len(tRbbi)
      lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRbbi)
      If (lR <> 0) Then
         If (tRbbi.hWndChild <> 0) Then
            tRbbi.fMask = RBBIM_CHILDSIZE
            tRbbi.cyMinChild = lHeight
            lR = SendMessage(m_hWnd, RB_SETBANDINFOA, lBand, tRbbi)
         End If
      End If
   Else
      ' IncorrectBand
   End If
End Property
Public Property Get BandChildMaxHeight(ByVal lBand As Long) As Long
Dim cy As Long
   If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
      If (lBand >= 0) And (lBand < BandCount) Then
         If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_CHILDSIZE,
          cyMaxChild:=cy)) Then
            BandChildMaxHeight = cy
         End If
      Else
         BandChildMaxHeight = -1
         ' IncorrectBand
      End If
   Else
      ' Unsupported
   End If
End Property
Public Property Let BandChildMaxHeight(ByVal lBand As Long, lHeight As Long)
   If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
      If (lBand >= 0) And (lBand < BandCount) Then
         Dim tRbbi As REBARBANDINFO_NOTEXT_471
         Dim lR As Long
         tRbbi.fMask = RBBIM_CHILDSIZE Or RBBIM_CHILD
         tRbbi.cbSize = Len(tRbbi)
         lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRbbi)
         If (lR <> 0) Then
            If (tRbbi.hWndChild <> 0) Then
               tRbbi.fMask = RBBIM_CHILDSIZE
               tRbbi.cyMaxChild = lHeight
               lR = SendMessage(m_hWnd, RB_SETBANDINFOA, lBand, tRbbi)
            End If
         End If
      Else
         ' IncorrectBand
      End If
   Else
      ' Unsupported
   End If
End Property
Public Property Get BandChildMinWidth(ByVal lBand As Long) As Long
Dim cx As Long
   If (lBand >= 0) And (lBand < BandCount) Then
      If (pbGetBandInfo(m_hWnd, lBand, fMask:=RBBIM_CHILDSIZE, cxMinChild:=cx))
       Then
         BandChildMinWidth = cx
      End If
   Else
      BandChildMinWidth = -1
      ' IncorrectBand
   End If

End Property
Public Property Let BandChildMinWidth(ByVal lBand As Long, lWidth As Long)
   If (lBand >= 0) And (lBand < BandCount) Then
      Dim tRbbi As REBARBANDINFO_NOTEXT
      Dim lR As Long
      Dim tR As RECT
      
      tRbbi.fMask = RBBIM_CHILDSIZE Or RBBIM_CHILD
      tRbbi.cbSize = Len(tRbbi)
      lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRbbi)
      If (lR <> 0) Then
         If (tRbbi.hWndChild <> 0) Then
            tRbbi.fMask = RBBIM_CHILDSIZE
            tRbbi.cxMinChild = lWidth
            lR = SendMessage(m_hWnd, RB_SETBANDINFOA, lBand, tRbbi)
            SendMessageLong m_hWnd, RB_MINIMIZEBAND, lBand, 0
         End If
      End If
   Else
      ' IncorrectBand
   End If
End Property
Public Property Get BandChildIdealWidth(ByVal lBand As Long) As Long
Dim cx As Long
   If (lBand >= 0) And (lBand < BandCount) Then
      If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
         Dim tRbbi As REBARBANDINFO_NOTEXT_471
         Dim lR As Long
         Dim tR As RECT
      
         tRbbi.fMask = RBBIM_IDEALSIZE Or RBBIM_CHILD
         tRbbi.cbSize = Len(tRbbi)
         lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRbbi)
         If (lR <> 0) Then
            BandChildIdealWidth = tRbbi.cxIdeal
         End If
      Else
         ' unsupported
      End If
   Else
      BandChildIdealWidth = -1
      ' IncorrectBand
   End If

End Property
Public Property Let BandChildIdealWidth(ByVal lBand As Long, lWidth As Long)
Static s_bLock As Boolean
Dim j As Long
   
   If (lBand >= 0) And (lBand < BandCount) Then
      If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
         Dim tRbbi As REBARBANDINFO_NOTEXT_471
         Dim lR As Long
         Dim tR As RECT
      
         tRbbi.fMask = RBBIM_IDEALSIZE Or RBBIM_CHILD
         tRbbi.cbSize = Len(tRbbi)
         lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRbbi)
         If (lR <> 0) Then
            If (tRbbi.hWndChild <> 0) Then
               tRbbi.fMask = RBBIM_IDEALSIZE
               tRbbi.cxIdeal = lWidth
               lR = SendMessage(m_hWnd, RB_SETBANDINFOA, lBand, tRbbi)
               SendMessageLong m_hWnd, RB_MINIMIZEBAND, lBand, 0
            End If
         End If
      Else
         ' unsupported
      End If
   Else
      ' IncorrectBand
   End If
End Property

Public Sub BandChildResized(ByVal lBand As Long, ByVal lWidth As Long, ByVal
 lHeight As Long)
   If (lBand >= 0) And (lBand < BandCount) Then
      
      Dim tRBandNT As REBARBANDINFO_NOTEXT
      Dim tRBandNT471 As REBARBANDINFO_NOTEXT_471
      Dim lR As Long
      Dim tR As RECT
      
      If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
         tRBandNT471.fMask = RBBIM_CHILDSIZE Or RBBIM_CHILD Or RBBIM_STYLE
         tRBandNT471.cbSize = LenB(tRBandNT471)
         lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRBandNT471)
      Else
         tRBandNT.fMask = RBBIM_CHILDSIZE Or RBBIM_CHILD Or RBBIM_STYLE
         tRBandNT.cbSize = Len(tRBandNT)
         lR = SendMessage(m_hWnd, RB_GETBANDINFO, lBand, tRBandNT)
      End If
      
      If (lR <> 0) Then
         If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
            If (tRBandNT471.hWndChild <> 0) Then
               tRBandNT471.cyMinChild = lHeight
               tRBandNT471.cx = lWidth
               If (tRBandNT471.fStyle And RBBS_CHEVRON) = RBBS_CHEVRON Then
                  tRBandNT471.cxMinChild = 24
                  tRBandNT471.fMask = tRBandNT471.fMask Or RBBIM_IDEALSIZE
                  tRBandNT471.cxIdeal = lWidth
               Else
                  tRBandNT471.cxMinChild = lWidth
               End If
               lR = SendMessage(m_hWnd, RB_SETBANDINFOA, lBand, tRBandNT471)
               GetWindowRect m_hWnd, tR
               MapWindowPoints 0, GetParent(m_hWnd), tR, 2
               MoveWindow m_hWnd, tR.Left, tR.Top, tR.Right - tR.Left + 2,
                tR.Bottom - tR.Top + 1, 1
               MoveWindow m_hWnd, tR.Left, tR.Top, tR.Right - tR.Left + 1,
                tR.Bottom - tR.Top + 1, 1
               SendMessageLong m_hWnd, RB_MINIMIZEBAND, lBand, 0
            End If
         Else
            If (tRBandNT.hWndChild <> 0) Then
               tRBandNT.fMask = RBBIM_CHILDSIZE
               tRBandNT.cxMinChild = lWidth
               tRBandNT.cyMinChild = lHeight
               tRBandNT.cx = lWidth
               lR = SendMessage(m_hWnd, RB_SETBANDINFOA, lBand, tRBandNT)
               SendMessageLong m_hWnd, RB_MINIMIZEBAND, lBand, 0
            End If
         End If
      End If
   End If
End Sub

Public Sub BandMove(ByVal lBand As Long, ByVal lIndexTo As Long)
    If (lBand >= 0) And (lBand < BandCount) Then
      If (lIndexTo >= 0) And (lIndexTo < BandCount) Then
         SendMessageLong m_hWnd, RB_MOVEBAND, lBand, lIndexTo
      Else
         ' Incorrectband
      End If
   Else
      ' Incorrectband
   End If
End Sub
Public Sub BandMinimise(ByVal lBand As Long)
    If (lBand >= 0) And (lBand < BandCount) Then
        SendMessageLong m_hWnd, RB_MINIMIZEBAND, lBand, 0
    Else
      ' IncorrectBand
    End If
End Sub
Public Sub BandMaximise(ByVal lBand As Long)
    If (lBand >= 0) And (lBand < BandCount) Then
        SendMessageLong m_hWnd, RB_MAXIMIZEBAND, lBand, 0
    Else
      ' IncorrectBand
    End If
End Sub
Public Sub GetBandRectangle( _
      ByVal lBand As Long, _
      Optional ByRef lLeft As Long, _
      Optional ByRef lTop As Long, _
      Optional ByRef lRight As Long, _
      Optional ByRef lBottom As Long _
   )
Dim tR As RECT
   If (lBand >= 0) And (lBand <= BandCount) Then
      SendMessage m_hWnd, RB_GETRECT, lBand, tR
      lLeft = tR.Left
      lTop = tR.Top
      lRight = tR.Right
      lBottom = tR.Bottom
   Else
      ' IncorrectBand
   End If
End Sub
Property Get BandCount() As Long
    BandCount = SendMessage(m_hWnd, RB_GETBANDCOUNT, 0&, ByVal 0&)
End Property

Private Function pbGetBandInfo( _
        ByVal lhWnd As Long, _
        ByVal lBand As Long, _
        Optional ByRef fMask As Long, _
        Optional ByRef fStyle As Long, _
        Optional ByRef clrFore As Long, _
        Optional ByRef clrBack As Long, _
        Optional ByRef cch As Long, _
        Optional ByRef iImage As Integer, _
        Optional ByRef hWndChild As Long, _
        Optional ByRef cxMinChild As Long, _
        Optional ByRef cyMinChild As Long, _
        Optional ByRef cx As Long, _
        Optional ByRef hbmpBack As Long, _
        Optional ByRef wID As Long, _
        Optional ByRef cyIntegral As Long, _
        Optional ByRef cyChild As Long, _
        Optional ByRef cyMaxChild As Long, _
        Optional ByRef lParam As Long, _
        Optional ByRef cxHeader As Long _
    ) As Boolean
Dim tRbbi As REBARBANDINFO_NOTEXT
Dim tRbbi471 As REBARBANDINFO_NOTEXT_471
Dim lR As Long

   If m_lMajor < 4 Or (m_lMajor = 4 And m_lMinor < 71) Then
      ' Use old version
      tRbbi.cbSize = LenB(tRbbi)
      tRbbi.fMask = fMask
      lR = SendMessage(lhWnd, RB_GETBANDINFO, lBand, tRbbi)
      If (lR <> 0) Then
         With tRbbi
            fMask = .fMask
            fStyle = .fStyle
            clrFore = .clrFore
            clrBack = .clrBack
            cch = .cch
            iImage = .iImage
            hWndChild = .hWndChild
            cxMinChild = .cxMinChild
            cyMinChild = .cyMinChild
            cx = .cx
            hbmpBack = .hbmBack
            wID = .wID
         End With
         pbGetBandInfo = True
      End If
   Else
      tRbbi471.cbSize = LenB(tRbbi471)
      tRbbi471.fMask = fMask
      lR = SendMessage(lhWnd, RB_GETBANDINFO471, lBand, tRbbi471)
      If (lR <> 0) Then
         With tRbbi471
            fMask = .fMask
            fStyle = .fStyle
            clrFore = .clrFore
            clrBack = .clrBack
            cch = .cch
            iImage = .iImage
            hWndChild = .hWndChild
            cxMinChild = .cxMinChild
            cyMinChild = .cyMinChild
            cx = .cx
            hbmpBack = .hbmBack
            cyIntegral = .cyIntegral
            cyChild = .cyChild
            cyMaxChild = .cyMaxChild
            cyMinChild = .cyMinChild
            cxHeader = .cxHeader
            lParam = .lParam
            wID = .wID
         End With
         pbGetBandInfo = True
       End If
   End If
End Function
Public Property Get HasBitmap() As Boolean
   HasBitmap = (BackgroundBitmapHandle <> 0)
End Property

Public Property Let ImageSource( _
        ByVal eType As ECRBImageSourceTypes _
    )
    m_eImageSourceType = eType
End Property
Public Property Let ImageResourceID(ByVal lResourceId As Long)
   ClearPicture
   m_lResourceID = lResourceId
End Property
Public Property Let ImageResourcehInstance(ByVal hInstance As Long)
   m_hInstance = hInstance
End Property
Public Property Let ImageFile(ByVal sFile As String)
   ClearPicture
   m_sPicture = sFile
End Property
Public Property Let ImagePicture(ByVal picThis As StdPicture)
   ClearPicture
   Set m_pic = picThis
End Property
Public Property Get BackgroundBitmap() As String
   BackgroundBitmap = m_sPicture
End Property
Public Property Let BackgroundBitmap(ByVal sFile As String)
   ImageSource = CRBLoadFromFile
   ImageFile = sFile
End Property
Private Property Get BackgroundBitmapHandle() As Long

   ' Set up the picture if we don't already have one:
   If (m_hBmp = 0) Then
      Select Case m_eImageSourceType
      Case CRBPicture
         If Not (m_pic Is Nothing) Then
            m_hBmp = hBmpFromPicture(m_pic)
         End If
      Case CTBLoadFromFile
         If (m_sPicture <> "") Then
            m_hBmp = LoadImage(0, m_sPicture, IMAGE_BITMAP, 0, 0, _
                     LR_LOADFROMFILE Or LR_LOADMAP3DCOLORS Or
                      LR_LOADTRANSPARENT)
         End If
      Case CTBResourceBitmap
         m_hBmp = LoadImageLong(m_hInstance, m_lResourceID, IMAGE_BITMAP, 0, 0,
          _
                     LR_LOADMAP3DCOLORS Or LR_LOADTRANSPARENT)
      End Select
   End If

   BackgroundBitmapHandle = m_hBmp
   
End Property

Public Function AddBandByHwnd( _
        ByVal hwnd As Long, _
        Optional ByVal sBandText As String = "", _
        Optional ByVal bBreakLine As Boolean = True, _
        Optional ByVal bFixedSize As Boolean = False, _
        Optional ByVal vData As Variant _
    ) As Long
Dim hBmp As Long
Dim lX As Long
Dim lBand As Long
Dim hWndP As Long
Dim wID As Long
    
   If (m_hWnd = 0) Then
      debugmsg m_sCtlName & ",Call To AddBandByHWnd before rebar created."
   End If
   
   If (m_hWnd <> 0) Then
      hBmp = BackgroundBitmapHandle()
      
      hWndP = GetParent(hwnd)
      If (hWndP <> 0) Then
         pAddWnds hwnd, hWndP
      End If
      wID = plAddId(vData)
      If (Not (pbRBAddBandByhWnd(m_hWnd, wID, hwnd, sBandText, hBmp,
       bBreakLine, bFixedSize, lBand))) Then
         debugmsg m_sCtlName & ",Failed to add Band"
         pRemoveID wID
      Else
         AddBandByHwnd = wID
         If Not (m_bSubclassing) Then
             ' Start subclassing:
             'Debug.Print "Start subclassing"
             pCreateSubClass
         End If
         RebarSize
      End If
   End If
End Function
Private Function pbRBAddBandByhWnd( _
        ByVal hWndRebar As Long, _
        ByVal wID As Long, _
        Optional ByVal hWndChild As Long = 0, _
        Optional ByVal sBandText As String = "", _
        Optional ByVal hBmp As Long = 0, _
        Optional ByVal bBreakLine As Boolean = True, _
        Optional ByVal bFixedSize As Boolean = False, _
        Optional ByRef ltRBand As Long _
    ) As Boolean

If hWndRebar = 0 Then
    MsgBox "No hWndRebar!"
    Exit Function
End If

Dim sClassName As String
Dim hWndReal As Long
Dim tRBand As REBARBANDINFO
Dim tRBand471 As REBARBANDINFO_471
Dim tRBandNT As REBARBANDINFO_NOTEXT
Dim tRBandNT471 As REBARBANDINFO_NOTEXT_471
Dim bNoText As Boolean
Dim rct As RECT
Dim fMask As Long
Dim fStyle As Long
Dim dwStyle As Long
Dim bListStyle As Boolean

   hWndReal = hWndChild
   
   If Not (hWndChild = 0) Then
      'Check to see if it's a toolbar (so we can
      'make if flat)
      fMask = RBBIM_CHILD Or RBBIM_CHILDSIZE
      sClassName = Space$(255)
      GetClassName hWndChild, sClassName, 255
      'see if it's a real Windows toolbar
      If InStr(UCase$(sClassName), "TOOLBARWINDOW32") Then
         dwStyle = GetWindowLong(hWndChild, GWL_STYLE)
         dwStyle = dwStyle Or TBSTYLE_FLAT Or TBSTYLE_TRANSPARENT
         SetWindowLong hWndChild, GWL_STYLE, dwStyle
      End If
      'Could be a VB Toolbar -- make it flat anyway.
      If InStr(UCase$(sClassName), "TOOLBARWNDCLASS") Then
         hWndReal = GetWindow(hWndChild, GW_CHILD)
         dwStyle = GetWindowLong(hWndReal, GWL_STYLE)
         dwStyle = dwStyle Or TBSTYLE_FLAT Or TBSTYLE_TRANSPARENT
         SetWindowLong hWndReal, GWL_STYLE, dwStyle
      End If
   End If
   
   GetWindowRect hWndReal, rct
   
   If hBmp <> 0 Then
       fMask = fMask Or RBBIM_BACKGROUND
   End If
   fMask = fMask Or RBBIM_STYLE Or RBBIM_ID Or RBBIM_COLORS Or RBBIM_SIZE
   If sBandText <> "" Then
      fMask = fMask Or RBBIM_TEXT
      tRBand.lpText = sBandText
      tRBand.cch = Len(sBandText)
   Else
      bNoText = True
   End If
   
   fStyle = RBBS_FIXEDBMP ' or RBBS_CHILDEDGE
   If bBreakLine = True Then
      fStyle = fStyle Or RBBS_BREAK
   End If
   If bFixedSize = True Then
      fStyle = fStyle Or RBBS_FIXEDSIZE
   Else
      fStyle = fStyle And Not RBBS_FIXEDSIZE
   End If
   
   If (bNoText) Then
      With tRBandNT
         .fMask = fMask
         .fStyle = fStyle
         'Only set if there's a child window
         If hWndReal <> 0 Then
            .hWndChild = hWndReal
            If m_ePosition = erbPositionLeft Or m_ePosition = erbPositionRight
             Then
               .cxMinChild = rct.Bottom - rct.Top
               .cyMinChild = rct.Right - rct.Left
            Else
               .cxMinChild = rct.Right - rct.Left
               .cyMinChild = rct.Bottom - rct.Top
            End If
         End If
         'Set the rest OK
         .wID = wID
         .clrBack = GetSysColor(COLOR_BTNFACE)
         .clrFore = GetSysColor(COLOR_BTNTEXT)
         .cx = 200
         .hbmBack = hBmp
         'The length of the type
         .cbSize = LenB(tRBandNT)
      End With
      If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
         CopyMemory tRBandNT471, tRBandNT, LenB(tRBandNT)
         tRBandNT471.cbSize = LenB(tRBandNT471)
         tRBandNT471.fMask = tRBandNT471.fMask Or RBBIM_IDEALSIZE
         tRBandNT471.cxIdeal = tRBandNT471.cxMinChild
         tRBandNT471.fStyle = tRBandNT471.fStyle Or RBBS_CHEVRON
         pbRBAddBandByhWnd = (SendMessage(hWndRebar, RB_INSERTBAND, -1,
          tRBandNT471) <> 0)
      Else
         pbRBAddBandByhWnd = (SendMessage(hWndRebar, RB_INSERTBAND, -1,
          tRBandNT) <> 0)
      End If
   Else
      With tRBand
         .fMask = fMask
         .fStyle = fStyle
         'Only set if there's a child window
         If hWndReal <> 0 Then
            .hWndChild = hWndReal
            If m_ePosition = erbPositionLeft Or m_ePosition = erbPositionRight
             Then
               .cxMinChild = rct.Bottom - rct.Top
               .cyMinChild = rct.Right - rct.Left
            Else
               .cxMinChild = rct.Right - rct.Left
               .cyMinChild = rct.Bottom - rct.Top
            End If
         End If
         'Set the rest OK
         .wID = wID
         .clrBack = GetSysColor(COLOR_BTNFACE)
         .clrFore = GetSysColor(COLOR_BTNTEXT)
         .cx = 200
         .hbmBack = hBmp
         'The length of the type
         .cbSize = LenB(tRBand)
      End With
      If m_lMajor > 4 Or (m_lMajor = 4 And m_lMinor >= 71) Then
         CopyMemory tRBand471, tRBand, LenB(tRBandNT)
         tRBand471.cbSize = LenB(tRBand471)
         tRBand471.fStyle = tRBand471.fStyle Or RBBS_CHEVRON
         tRBand471.fMask = tRBand471.fMask Or RBBIM_IDEALSIZE
         tRBand471.cxIdeal = tRBand471.cxMinChild
         pbRBAddBandByhWnd = (SendMessage(hWndRebar, RB_INSERTBAND, -1,
          tRBand471) <> 0)
      Else
         pbRBAddBandByhWnd = (SendMessage(hWndRebar, RB_INSERTBAND, -1, tRBand)
          <> 0)
      End If
   End If
   
   ltRBand = BandCount

End Function

Private Sub pRemoveID( _
        ByVal wID As Long _
    )
Dim lItem As Long
Dim lTarget As Long
    
   For lItem = 1 To m_lIDCount
      If (m_tDataStore(lItem).wID = wID) Then
      Else
         lTarget = lTarget + 1
         If (lTarget <> lItem) Then
            LSet m_tDataStore(lTarget) = m_tDataStore(lItem)
         End If
      End If
   Next lItem
   If lTarget = 0 Then
      debugmsg m_sCtlName & ",Removed all IDs and data"
      m_lIDCount = 0
      Erase m_tDataStore
   Else
      If (lTarget <> m_lIDCount) Then
         debugmsg m_sCtlName & ",Reduced ID Count to : " & lTarget
         m_lIDCount = lTarget
         ReDim Preserve m_tDataStore(1 To m_lIDCount) As tRebarDataStore
      End If
   End If
    
End Sub
Public Property Get BandIndexForId( _
        ByVal wID As Long _
    ) As Long
Dim lItem As Long
Dim tRbbi As REBARBANDINFO_NOTEXT
Dim lIndex As Long
Dim lR As Long

   If m_lMajor < 4 Or (m_lMajor = 4 And m_lMinor < 71) Then
      lIndex = -1
      tRbbi.cbSize = Len(tRbbi)
      tRbbi.fMask = RBBIM_ID
      For lItem = 0 To BandCount - 1
          lR = SendMessage(m_hWnd, RB_GETBANDINFO, lItem, tRbbi)
          If (lR <> 0) Then
              If (wID = tRbbi.wID) Then
                  lIndex = lItem
                  Exit For
              End If
          End If
      Next lItem
      BandIndexForId = lIndex
   Else
      BandIndexForId = SendMessageLong(m_hWnd, RB_IDTOINDEX, wID, 0)
   End If
End Property
Public Property Get BandIDForIndex( _
      ByVal lIndex As Long _
   ) As Long
Dim lR As Long
Dim tRbbi As REBARBANDINFO_NOTEXT

   tRbbi.cbSize = Len(tRbbi)
   tRbbi.fMask = RBBIM_ID
   lR = SendMessage(m_hWnd, RB_GETBANDINFO, lIndex, tRbbi)
   BandIDForIndex = tRbbi.wID
   
End Property
Public Property Get BandData( _
      ByVal wID As Long _
   ) As Variant
Dim lItem As Long
   For lItem = 1 To m_lIDCount
      If m_tDataStore(lItem).wID = wID Then
         BandData = m_tDataStore(lItem).vData
         Exit For
      End If
   Next lItem
End Property

Public Property Get BandIndexForData( _
        ByVal vData As Variant _
    ) As Long
Dim lItem As Long
Dim lAt As Long
Dim vitem As Variant
On Error Resume Next
    lAt = -1
    For lItem = 1 To m_lIDCount
      If IsMissing(m_tDataStore(lItem).vData) Then
         vitem = ""
      ElseIf IsObject(m_tDataStore(lItem).vData) Then
         If (vData Is m_tDataStore(lItem).vData) Then
            lAt = lItem
            Exit For
         End If
      Else
         If vData = m_tDataStore(lItem).vData Then
            lAt = lItem
            Exit For
         End If
      End If
      
    Next lItem
    If (lAt > 0) Then
        lAt = BandIndexForId(m_tDataStore(lAt).wID)
    End If
    BandIndexForData = lAt
End Property
Private Function plAddId( _
        ByVal vData As Variant _
    ) As Long
    m_lIDCount = m_lIDCount + 1
    ReDim Preserve m_tDataStore(1 To m_lIDCount) As tRebarDataStore
    m_tDataStore(m_lIDCount).wID = m_lIDCount
    m_tDataStore(m_lIDCount).vData = vData
    plAddId = m_lIDCount
End Function
Private Sub pAddWnds( _
        ByVal hwndItem As Long, _
        ByVal hWndParent As Long _
    )
   m_iWndItemCount = m_iWndItemCount + 1
   ReDim Preserve m_tWndStore(1 To m_iWndItemCount) As tRebarWndStore
   With m_tWndStore(m_iWndItemCount)
      .hwndItem = hwndItem
      .hWndItemParent = hWndParent
      GetWindowRect hwndItem, .tR
   End With
End Sub
Private Sub pResetParent( _
        ByVal hwndItem As Long _
    )
Dim iItem As Long
Dim iTarget As Long
Dim bSuccess As Boolean
    
   For iItem = 1 To m_iWndItemCount
      If (m_tWndStore(iItem).hwndItem = hwndItem) Then
         ' Set the parent back to the original:
         SetParent m_tWndStore(iItem).hwndItem,
          m_tWndStore(iItem).hWndItemParent
         ' send a message to destroy the object:
         If m_bKillChildren Then
            ShowWindow m_tWndStore(iItem).hwndItem, SW_HIDE
            SendMessageLong m_tWndStore(iItem).hwndItem, WM_DESTROY, 0, 0
         End If
         ' Reset the size to original:
         SetWindowPos m_tWndStore(iItem).hwndItem, 0,
          m_tWndStore(iItem).tR.Left, m_tWndStore(iItem).tR.Top,
          m_tWndStore(iItem).tR.Right - m_tWndStore(iItem).tR.Left,
          m_tWndStore(iItem).tR.Bottom - m_tWndStore(iItem).tR.Top,
          SWP_NOREDRAW Or SWP_NOZORDER Or SWP_NOOWNERZORDER
         'MoveWindow m_tWndStore(iItem).hWndItem, m_tWndStore(iItem).tR.Left,
          m_tWndStore(iItem).tR.Top, m_tWndStore(iItem).tR.Right -
          m_tWndStore(iItem).tR.Left, m_tWndStore(iItem).tR.Bottom -
          m_tWndStore(iItem).tR.Top, 1
         bSuccess = True
      Else
         iTarget = iTarget + 1
         If iTarget <> iItem Then
            LSet m_tWndStore(iTarget) = m_tWndStore(iItem)
         End If
      End If
   Next iItem
   
   If (iTarget = 0) Then
      debugmsg m_sCtlName & ",Successfully reset all parents"
      m_iWndItemCount = 0
      Erase m_tWndStore
   Else
      If iTarget <> m_iWndItemCount Then
         debugmsg m_sCtlName & ",Decrease wnd count to " & iTarget
         m_iWndItemCount = iTarget
         ReDim Preserve m_tWndStore(1 To m_iWndItemCount) As tRebarWndStore
      End If
   End If
   
   
   If Not bSuccess Then
      debugmsg m_sCtlName & ",Failed to reset parent.."
      ' At least ensure it won't stop the rebar terminating:
      ShowWindow hwndItem, SW_HIDE
      SetParent hwndItem, 0
   End If
End Sub
Public Sub RebarSize()
Dim lLeft As Long, lTop As Long
Dim cx As Long, cy As Long
Dim rc As RECT, rcb As RECT, rcI As RECT, rcP As RECT
   
   If (m_hWnd <> 0) Then
      GetWindowRect m_hWnd, rcb
      OffsetRect rcb, -rcb.Left, -rcb.Top
      GetClientRect m_hWndCtlParent, rcP
      If (m_ePosition = erbPositionBottom) Or (m_ePosition = erbPositionTop)
       Then
         cx = rcP.Right - rcP.Left
         cy = RebarHeight
         If m_ePosition = erbPositionBottom Then
            lTop = rcP.Bottom - rc.Top - cy
         End If
         AdjustForOtherRebars m_hWnd, lLeft, lTop, cx, cy
         SetWindowPos m_hWnd, 0, lLeft, lTop, cx, cy, SWP_NOZORDER Or
          SWP_NOACTIVATE
      Else
         cy = rcP.Bottom - rcP.Top
         cx = RebarHeight
         If m_ePosition = erbPositionRight Then
            lLeft = rcP.Right - rcP.Left - cx
         End If
         AdjustForOtherRebars m_hWnd, lLeft, lTop, cx, cy
         SetWindowPos m_hWnd, 0, lLeft, lTop, cx, cy, SWP_NOZORDER Or
          SWP_NOACTIVATE
      End If
      GetWindowRect m_hWnd, rc
      OffsetRect rc, -rc.Left, -rc.Top
      UnionRect rcI, rc, rcb
      InvalidateRect m_hWnd, rcI, True
      UpdateWindow m_hWnd
   End If
   
End Sub
Public Property Get hwnd() As Long
    hwnd = UserControl.hwnd
End Property
Public Property Get RebarHwnd() As Long
    RebarHwnd = m_hWnd
End Property
Public Property Get RebarHeight() As Long
Dim tC As RECT
    'If (m_hWnd <> 0) Then
    '  GetWindowRect m_hWnd, tc
    '  RebarHeight = (tc.Bottom - tc.Top)
    'End If
    ' Get the height that would be good for the rebar:
   If m_bVisible Then
      RebarHeight = SendMessageLong(m_hWnd, RB_GETBARHEIGHT, 0, 0) + 4
   Else
      RebarHeight = 0
   End If
End Property
Public Property Get RebarWidth() As Long
Dim tC As RECT
   If (m_hWnd <> 0) Then
      If m_bVisible Then
         GetWindowRect m_hWnd, tC
         RebarWidth = (tC.Right - tC.Left)
      Else
         RebarWidth = 0
      End If
   End If
End Property
Private Function pbLoadCommCtls() As Boolean
Dim ctEx As CommonControlsEx

    ctEx.dwSize = Len(ctEx)
    ctEx.dwICC = ICC_COOL_CLASSES Or _
        ICC_USEREX_CLASSES Or ICC_WIN95_CLASSES
    
    pbLoadCommCtls = (InitCommonControlsEx(ctEx) <> 0)

End Function

Public Function CreateRebar(ByVal hWndParent As Long) As Boolean
   If (UserControl.Ambient.UserMode) Then
      DestroyRebar
      ' Set up the rebar:
      If (pbCreateRebar(hWndParent)) Then
         SetProp m_hWnd, "vbal:cRebarPosition", m_ePosition
         m_hWndCtlParent = hWndParent
         AddRebar m_hWnd, m_hWndCtlParent
      End If
   End If
End Function
Public Function AddResizeObject(ByVal hWndParent As Long, ByVal hwnd As Long,
 ByVal ePosition As ERBPositionConstants)
   AddRebar hwnd, hWndParent
   SetProp hwnd, "vbal:cRebarPosition", ePosition
End Function
Private Function pbCreateRebar(ByVal hWndParent As Long) As Boolean
Dim lWidth As Long
Dim lHeight As Long
Dim bVertical As Boolean
Dim hwndCoolBar As Long
Dim lResult As Long
Dim dwStyle As Long
Dim dwExStyle As Long
Dim lExStyle As Long
Dim rc As RECT

    If (UserControl.Ambient.UserMode) Then
    
      ' Try to load the Common Controls support for the
      ' rebar control:
      If (pbLoadCommCtls()) Then
         'Debug.Print "Loaded Coolbar support"
         ' If we have done this, then build a rebar:
         'lWidth = UserControl.Parent.ScaleWidth \ Screen.TwipsPerPixelX
         'lHeight = UserControl.Height \ Screen.TwipsPerPixelY
         GetWindowRect hWndParent, rc
         lWidth = rc.Right - rc.Left
         lHeight = rc.Bottom - rc.Top

         ComCtlVersion m_lMajor, m_lMinor
         dwStyle = WS_CHILD Or WS_BORDER Or _
             WS_CLIPCHILDREN Or WS_CLIPSIBLINGS Or _
             WS_VISIBLE
         Select Case m_ePosition
         Case erbPositionTop
            dwStyle = dwStyle Or CCS_TOP
         Case erbPositionRight
            dwStyle = dwStyle Or CCS_RIGHT Or CCS_VERT
         Case erbPositionLeft
            dwStyle = dwStyle Or CCS_LEFT Or CCS_VERT
         Case erbPositionBottom
            dwStyle = dwStyle Or CCS_BOTTOM
         End Select
         dwStyle = dwStyle Or CCS_NORESIZE
         dwStyle = dwStyle Or CCS_NODIVIDER
         
         dwStyle = dwStyle Or RBS_DBLCLKTOGGLE
         dwStyle = dwStyle Or RBS_VARHEIGHT Or RBS_BANDBORDERS
         dwStyle = dwStyle Or RBS_AUTOSIZE
   
         dwExStyle = WS_EX_TOOLWINDOW
         lExStyle = GetWindowLong(hWndParent, GWL_EXSTYLE)
         lExStyle = lExStyle And (WS_EX_RIGHT Or WS_EX_RTLREADING)
         dwExStyle = dwExStyle Or lExStyle
   
         m_hWnd = CreateWindowEx(dwExStyle, _
                              REBARCLASSNAME, "", _
                              dwStyle, 0, 0, lWidth, lHeight, _
                              hWndParent, ICC_COOL_CLASSES, App.hInstance,
                               ByVal 0&)
         If (m_hWnd <> 0) Then
            ' Debug.Print "Created Rebar Window"
            AddToToolTip m_hWnd
            If m_lMajor >= 5 Then
               SendMessageLong m_hWnd, RB_SETEXTENDEDSTYLE, 0, RBS_EX_OFFICE9
            End If
            pbCreateRebar = True
         End If
      End If
    End If
    
End Function
Public Sub DestroyRebar()
   pDestroyRebar True
End Sub
Public Sub DestroyRebarDontDestroyChildren()
   pDestroyRebar False
End Sub
Private Sub pDestroyRebar(ByVal bKillChildren As Boolean)
   If (m_hWnd <> 0) Then
      m_bKillChildren = bKillChildren
      
      debugmsg m_sCtlName & ",pDestroyRebar"
      RemoveRebar m_hWnd
      
      RemoveFromToolTip m_hWnd
      RemoveAllRebarBands
      
      DeleteObject m_hBmp
      m_hBmp = 0
      
      pDestroySubClass
      RemoveProp m_hWnd, "vbal:cRebarPosition"
      
      ShowWindow m_hWnd, SW_HIDE
      SetParent m_hWnd, 0
      DestroyWindow m_hWnd
      m_hWnd = 0
      m_hWndCtlParent = 0
      
      m_bKillChildren = True
   End If
End Sub

Public Sub RemoveAllRebarBands()
Dim lBands As Long
Dim lBand As Long
    If (m_hWnd <> 0) Then
        lBands = BandCount
        For lBand = 0 To lBands - 1
            RemoveBand 0
        Next lBand
        pDestroySubClass
    End If
End Sub
Public Sub RemoveBand( _
        ByVal lBand As Long _
    )
Dim lhWnd As Long
Dim wID As Long

    If (m_hWnd <> 0) Then
        ' If a valid band:
        If (lBand >= 0) And (lBand < BandCount) Then
            If m_lMajor < 4 Or (m_lMajor = 4 And m_lMinor < 71) Then
               ' Remove the child from this band:
               lhWnd = plGetHwndOfBandChild(m_hWnd, lBand, wID)
               If (lhWnd <> 0) Then
                   pResetParent lhWnd
                   
               End If
               ' Remove the band:
               SendMessageLong m_hWnd, RB_DELETEBAND, lBand, 0&
               ' Remove the id for this band:
               pRemoveID wID
               ' No bands left? Stop subclassing:
               If (BandCount = 0) Then
                  debugmsg m_sCtlName & ",All bands destroyed"
                  pDestroySubClass
               End If
            Else
               SendMessageLong m_hWnd, RB_DELETEBAND, lBand, 0&
               If BandCount = 0 Then
                  debugmsg m_sCtlName & ",All bands destroyed"
                  pDestroySubClass
               End If
            End If
        End If
    End If
End Sub
Private Function plGetHwndOfBandChild( _
        ByVal lhWnd As Long, _
        ByVal lBand As Long, _
        ByRef wID As Long _
    ) As Long
Dim lParam As Long
Dim tRbbi As REBARBANDINFO_NOTEXT
Dim lR As Long

    tRbbi.cbSize = Len(tRbbi)
    tRbbi.fMask = RBBIM_CHILD Or RBBIM_ID
    lR = SendMessage(lhWnd, RB_GETBANDINFO, lBand, tRbbi)
    If (lR <> 0) Then
        plGetHwndOfBandChild = tRbbi.hWndChild
        wID = tRbbi.wID
    End If
End Function

Public Property Get Visible() As Boolean
   Visible = m_bVisible
End Property
Public Property Let Visible(ByVal bState As Boolean)
   m_bVisible = bState
   If m_hWnd <> 0 Then
      If Not bState Then
         ShowWindow m_hWnd, SW_HIDE
         RaiseEvent HeightChanged(0)
      Else
         ShowWindow m_hWnd, SW_SHOW
         RaiseEvent HeightChanged(RebarHeight)
      End If
   End If
   PropertyChanged "Visible"
End Property

Private Sub ClearPicture()
   If (m_hBmp <> 0) Then
      DeleteObject m_hBmp
      m_hBmp = 0
   End If
   m_sPicture = ""
   m_lResourceID = 0
   Set m_pic = Nothing
End Sub

Private Sub UserControl_Initialize()
    debugmsg "cRebar:Initialise"
    m_lMajor = 4
    m_lMinor = 0
    m_bVisible = True
    m_bKillChildren = True
End Sub

Private Sub UserControl_InitProperties()
   ' If init properties we must be in design mode.
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    
    ' Read in properties here:
    ' ...
    On Error Resume Next
    m_sCtlName = UserControl.Extender.Name
    Err.Clear
    On Error GoTo 0
    
End Sub

Private Sub UserControl_Resize()
   If (UserControl.Ambient.UserMode) Then
      UserControl.Width = 0
      UserControl.Height = 0
   End If
End Sub

Private Sub UserControl_Terminate()
    m_bInTerminate = True
    DestroyRebar
    ClearPicture
    debugmsg m_sCtlName & ",cRebar:Terminate"
    'MsgBox "cRebar:Terminate"
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    
    ' Write properties here:
    ' ...
    
End Sub