Floating worksheet buttons - Different approach !

Jaafar Tribak

Well-known Member
Joined
Dec 5, 2002
Messages
9,797
Office Version
  1. 2016
Platform
  1. Windows
I have set up this Class called CFloatingButton which uses a simple standard UserForm with a CommandButton in it.

With some API trickery, the result you get with this Class is the possibility to create any number of concomitant floating buttons even on sheets that are not active .

See Workbook Demo here.

Once an instance of the Class is created, you can assign to it the following Properties & Methods :

-Caption.
-PositionAtRange.
-ClickMacro.

Here is an example of how to create two floating buttons on a worksheet: (code goes in a standard module)

Code:
Option Explicit
 
Private FloatingButton1 As New CFloatingButton
Private FloatingButton2 As New CFloatingButton
 
'first example.
'==============
'--------------------------------------------
'\Adding first floating button
'\to Cell B6.
 
Sub AddFloatingButton1()
 
    With FloatingButton1
        .Caption = "FloatingButton1"
        .PositionAtRange Sheets(1).Range("B6")
        .ClickMacro = "MyMacro1"
        .Show
    End With
 
End Sub
 
Sub MyMacro1()
 
    MsgBox "hello!"
 
End Sub
 
Sub RemoveFloatingButton1()
 
    Set FloatingButton1 = Nothing
 
End Sub
 
'----------------------------------------------
'second example.
'==============
'-----------------------------------------------
'\Adding another concomitant floating button
'\to Cell A14.
 
Sub AddFloatingButton2()
 
With FloatingButton2
    .Caption = "FloatingButton2"
    .PositionAtRange Sheets(1).Range("A14")
    .ClickMacro = "MyMacro2"
    .Show
End With
 
End Sub
 
Sub MyMacro2()
 
    MsgBox "hello again!"
 
End Sub
 
Sub RemoveFloatingButton2()
 
    Set FloatingButton2 = Nothing
 
End Sub

Code for the Class Module :

Code:
'\This class uses a standard VBA UserForm with
'\a single CommandButton to create any
'\number of floating worksheet Buttons.
'\Via its intuitive interface,(Properties & Methods)
'\one can easily set the caption and the Click Macro
'\of the Buttons as well as their initial position
'\in relation to a chosen range.
'\The Class also allows adding the Buttons
'\to non active sheets.
'\tested on Excel 2003.
 
Option Explicit
 
Private sCaption As String
Private oRangePos As Range
Private oUF  As UserForm1
 
Private Sub Class_Initialize()
 
    Set oUF = New UserForm1
 
End Sub
 
Private Sub Class_Terminate()
 
    Unload oUF
 
End Sub
 
Public Property Let Caption(ByVal ButtonCaption As String)
 
    sCaption = ButtonCaption
 
End Property
 
Public Sub PositionAtRange(RangePos As Range)
 
    Set oRangePos = RangePos
    oUF.Position RangePos
 
End Sub
 
Public Property Let ClickMacro(ByVal MacroName As String)
 
    oUF.ButtonMacro = MacroName
 
End Property
 
Public Sub Show()
 
    oUF.CommandButton1.Caption = sCaption
 
    If oRangePos.Parent Is ActiveSheet Then
        If Intersect(ActiveWindow.VisibleRange, oRangePos) _
        Is Nothing Then
            Application.Goto oRangePos
        End If
        oUF.Show vbModeless
    End If
 
End Sub

Code in the UserForm module :

Code:
Option Explicit
 
Private WithEvents wbEvents As Workbook
 
Private Type POINTAPI
  x As Long
  y As Long
End Type
 
Private Declare Function FindWindow Lib "user32.dll" Alias _
"FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
 
Private Declare Function FindWindowEx Lib "user32.dll" Alias _
"FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
 
Private Declare Function GetWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
 
Private Declare Function ShowWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nCmdShow 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 Declare Function GetWindowLong Lib "user32.dll" Alias _
"GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function DrawMenuBar Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function MoveWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
 
Private Declare Function SetParent Lib "user32.dll" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
 
Private Declare Function SetFocus Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
 
Private Declare Function GetDC Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function GetWindowDC Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function GetDeviceCaps Lib "gdi32" _
(ByVal hDC As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function ReleaseDC Lib "user32" _
(ByVal hwnd As Long, _
ByVal hDC As Long) As Long
 
Private Declare Function ScreenToClient Lib "user32.dll" _
(ByVal hwnd As Long, _
ByRef lpPoint As POINTAPI) As Long
 
Private Const WS_CAPTION As Long = &HC00000
Private Const GWL_STYLE As Long = -16
Private Const GWL_EXSTYLE As Long = (-20)
Private Const WS_EX_DLGMODALFRAME As Long = &H1&
Private Const GW_CHILD As Long = 5
Private Const LOGPIXELSX As Long = 88
Private Const LOGPIXELSY As Long = 90
 
Private tPt As POINTAPI
Private lApphwnd As Long
Private lEXCEL7 As Long
Private lXLDESK As Long
Private lMehwnd As Long
Private ldc As Long
Private lClienthwnd As Long
Private sButtonMacro As String
Private bSkipActivateEvent As Boolean
Private oPosition As Range
 
Private Sub CommandButton1_Click()
 
    Application.Run sButtonMacro
 
    SetFocus lApphwnd
 
End Sub
 
Private Sub UserForm_Activate()
 
If Not bSkipActivateEvent Then
 
    bSkipActivateEvent = True
 
    Me.StartUpPosition = 0
 
    lClienthwnd = GetWindow(lMehwnd, GW_CHILD)
 
    ldc = GetWindowDC(lClienthwnd)
 
    tPt = TopLeftPoint(oPosition)
 
    ScreenToClient lEXCEL7, tPt
 
    LockWindowUpdate lMehwnd
 
    MoveWindow lMehwnd, tPt.x, tPt.y, _
    Me.CommandButton1.Width * _
    (GetDeviceCaps(ldc, LOGPIXELSX) / 72), _
    Me.CommandButton1.Height * _
    (GetDeviceCaps(ldc, LOGPIXELSY) / 72), True
 
    ReleaseDC lClienthwnd, ldc
 
    LockWindowUpdate 0
 
    SetParent lMehwnd, lEXCEL7
 
    SetFocus lApphwnd
 
End If
 
End Sub
 
Private Sub UserForm_Initialize()
 
    lApphwnd = FindWindow("XLMAIN", Application.Caption)
 
    lXLDESK = FindWindowEx _
    (lApphwnd, 0, "XLDESK", vbNullString)
 
    lEXCEL7 = FindWindowEx _
    (lXLDESK, 0, "EXCEL7", vbNullString)
 
    Set wbEvents = ThisWorkbook
 
    Call SetUpUserForm
 
End Sub
 
Private Sub SetUpUserForm()
 
    Dim lStyle As Long
    Dim lExStyle As Long
 
    With Me
        CommandButton1.Left = 0
        CommandButton1.Top = 0
        Height = 0
        Width = 0
    End With
 
    lMehwnd = FindWindow(vbNullString, Me.Caption)
 
    lStyle = GetWindowLong(lMehwnd, GWL_STYLE)
    lStyle = lStyle And Not (WS_CAPTION)
 
    SetWindowLong lMehwnd, GWL_STYLE, lStyle
 
    lExStyle = GetWindowLong(lMehwnd, GWL_EXSTYLE)
    lExStyle = lExStyle And Not (WS_EX_DLGMODALFRAME)
 
    SetWindowLong lMehwnd, GWL_EXSTYLE, lExStyle
 
    DrawMenuBar lMehwnd
 
End Sub
 
Public Sub Position(R As Range)
 
    Set oPosition = R
 
End Sub
 
Public Property Let ButtonMacro(ByVal ClickMacro As String)
 
    sButtonMacro = ClickMacro
 
End Property
 
Private Sub wbEvents_BeforeClose(Cancel As Boolean)
 
    SetFocus lApphwnd
 
    bSkipActivateEvent = False
 
    Unload Me
 
End Sub
 
Private Sub wbEvents_SheetActivate(ByVal Sh As Object)
 
    If Sh Is oPosition.Parent Then _
    ShowWindow lMehwnd, 1 Else ShowWindow lMehwnd, 0
 
End Sub
 
Private Function TopLeftPoint(rng As Range) As POINTAPI
 
    Dim ldc As Long
    Dim lCurrentZoom As Long
 
    ldc = GetDC(0)
    lCurrentZoom = ActiveWindow.Zoom / 100
 
    With TopLeftPoint
        .x = ActiveWindow.PointsToScreenPixelsX(rng.Left * _
        (GetDeviceCaps(ldc, LOGPIXELSX) / 72 * lCurrentZoom))
 
        .y = ActiveWindow.PointsToScreenPixelsY(rng.Top * _
        (GetDeviceCaps(ldc, LOGPIXELSY) / 72 * lCurrentZoom))
    End With
 
    ReleaseDC 0, ldc
 
End Function

Tested this on Excel 2003 - WinXP and worked well. Not sure about other versions.

Regards.
 
Last edited:

Excel Facts

Can you AutoAverage in Excel?
There is a drop-down next to the AutoSum symbol. Open the drop-down to choose AVERAGE, COUNT, MAX, or MIN
Jaafar,

The xls workbook, opend in Excel 2007, functions the same as in Excel 2003.

Your sheet, Class Module, Forms Module, and code, copied to a new Excel 2007 workbook, works the same as Excel 2003.

Thanks again.

Have a great day and weekend,
hiker95
 
Upvote 0
Thanks again.

here is a much more versatile version :
Demo workbook.

I changed the Class ClikMacro Property into a Method to be able to pass each floating Button's unique index as the second Parameter. That way one can flexibly use one single Click Macro for all the buttons !

This is the magic of using Class modules as each instance runs in its own independent memory space and one can create as many instances as the system memory can handle.

here is the new code for the record:

Adding 15 floating Buttons at once ! : (code in a Standard module)

Code:
Option Explicit
 
Private oCol As New Collection
 
Sub AddFloatingButton1()
 
    Dim oButton As CFloatingButton
    Dim i As Long
 
    For i = 1 To 15
 
        Set oButton = New CFloatingButton
 
    With oButton
        .Caption = "Click Button " & i
        .PositionAtRange Cells(i * 2, 4)
        .ClickMacro "GenericMacro", i
        .Show
        oCol.Add oButton
    End With
 
    Next
 
End Sub
 
'Generic Macro
Sub GenericMacro(index As Long)
 
    'One generic Macro for any number of Buttons !
    MsgBox "You clicked Button " & index
 
End Sub
 
Sub RemoveFloatingButton1()
 
    Set oCol = Nothing
 
End Sub


Code for the CFloatingButton Class :

Code:
'\This class uses a standard VBA UserForm with
'\a single CommandButton to create any
'\number of floating worksheet Buttons.
'\Via its intuitive interface,(Properties & Methods)
'\one can easily set the caption and the Click Macro
'\of the Buttons as well as their initial position
'\in relation to a chosen range.
'\The Class also allows adding the Buttons
'\to non active sheets.
'\tested on Excel 2003.
 
Option Explicit
 
Private sCaption As String
Private oRangePos As Range
Private oUF  As UserForm1
 
Private Sub Class_Initialize()
 
    Set oUF = New UserForm1
 
End Sub
 
Private Sub Class_Terminate()
 
    Unload oUF
 
End Sub
 
Public Property Let Caption(ByVal ButtonCaption As String)
 
    sCaption = ButtonCaption
 
End Property
 
Public Sub PositionAtRange(RangePos As Range)
 
    Set oRangePos = RangePos
    oUF.Position RangePos
 
End Sub
 
Public Sub ClickMacro _
(ByVal MacroName As String, ButtonIndex As Long)
    oUF.ButtonMacro MacroName, ButtonIndex
 
End Sub
 
Public Sub Show()
 
    oUF.CommandButton1.Caption = sCaption
 
    If oRangePos.Parent Is ActiveSheet Then
        If Intersect(ActiveWindow.VisibleRange, oRangePos) _
        Is Nothing Then
            Application.Goto oRangePos
        End If
        oUF.Show vbModeless
    End If
 
End Sub

Code for the UserForm :

Code:
Option Explicit
 
Private WithEvents wbEvents As Workbook
 
Private Type POINTAPI
  x As Long
  y As Long
End Type
 
Private Declare Function FindWindow Lib "user32.dll" Alias _
"FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
 
Private Declare Function FindWindowEx Lib "user32.dll" Alias _
"FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
 
Private Declare Function GetWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
 
Private Declare Function ShowWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nCmdShow 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 Declare Function GetWindowLong Lib "user32.dll" Alias _
"GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function DrawMenuBar Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function MoveWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
 
Private Declare Function SetParent Lib "user32.dll" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
 
Private Declare Function SetFocus Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
 
Private Declare Function GetDC Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function GetWindowDC Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare Function GetDeviceCaps Lib "gdi32" _
(ByVal hDC As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function ReleaseDC Lib "user32" _
(ByVal hwnd As Long, _
ByVal hDC As Long) As Long
 
Private Declare Function ScreenToClient Lib "user32.dll" _
(ByVal hwnd As Long, _
ByRef lpPoint As POINTAPI) As Long
 
Private Const WS_CAPTION As Long = &HC00000
Private Const GWL_STYLE As Long = -16
Private Const GWL_EXSTYLE As Long = (-20)
Private Const WS_EX_DLGMODALFRAME As Long = &H1&
Private Const GW_CHILD As Long = 5
Private Const LOGPIXELSX As Long = 88
Private Const LOGPIXELSY As Long = 90
 
Private tPt As POINTAPI
Private lApphwnd As Long
Private lEXCEL7 As Long
Private lXLDESK As Long
Private lMehwnd As Long
Private lButtonIndex As Long
Private ldc As Long
Private lClienthwnd As Long
Private sButtonMacro As String
Private bSkipActivateEvent As Boolean
Private oPosition As Range
 
Private Sub CommandButton1_Click()
 
    Application.Run sButtonMacro, lButtonIndex
 
    SetFocus lApphwnd
 
End Sub
 
Private Sub UserForm_Activate()
 
If Not bSkipActivateEvent Then
 
    bSkipActivateEvent = True
 
    Me.StartUpPosition = 0
 
    lClienthwnd = GetWindow(lMehwnd, GW_CHILD)
 
    ldc = GetWindowDC(lClienthwnd)
 
    tPt = TopLeftPoint(oPosition)
 
    ScreenToClient lEXCEL7, tPt
 
    LockWindowUpdate lMehwnd
 
    MoveWindow lMehwnd, tPt.x, tPt.y, _
    Me.CommandButton1.Width * _
    (GetDeviceCaps(ldc, LOGPIXELSX) / 72), _
    Me.CommandButton1.Height * _
    (GetDeviceCaps(ldc, LOGPIXELSY) / 72), True
 
    ReleaseDC lClienthwnd, ldc
 
    LockWindowUpdate 0
 
    SetParent lMehwnd, lEXCEL7
 
    SetFocus lApphwnd
 
End If
 
End Sub
 
Private Sub UserForm_Initialize()
 
    lApphwnd = FindWindow("XLMAIN", Application.Caption)
 
    lXLDESK = FindWindowEx _
    (lApphwnd, 0, "XLDESK", vbNullString)
 
    lEXCEL7 = FindWindowEx _
    (lXLDESK, 0, "EXCEL7", vbNullString)
 
    Set wbEvents = ThisWorkbook
 
    Call SetUpUserForm
 
End Sub
 
Private Sub SetUpUserForm()
 
    Dim lStyle As Long
    Dim lExStyle As Long
 
    With Me
        CommandButton1.Left = 0
        CommandButton1.Top = 0
        Height = 0
        Width = 0
    End With
 
    lMehwnd = FindWindow(vbNullString, Me.Caption)
 
    lStyle = GetWindowLong(lMehwnd, GWL_STYLE)
    lStyle = lStyle And Not (WS_CAPTION)
 
    SetWindowLong lMehwnd, GWL_STYLE, lStyle
 
    lExStyle = GetWindowLong(lMehwnd, GWL_EXSTYLE)
    lExStyle = lExStyle And Not (WS_EX_DLGMODALFRAME)
 
    SetWindowLong lMehwnd, GWL_EXSTYLE, lExStyle
 
    DrawMenuBar lMehwnd
 
End Sub
 
Public Sub Position(R As Range)
 
    Set oPosition = R
 
End Sub
 
Public Sub ButtonMacro _
(ByVal ClickMacro As String, ButtonIndex As Long)
 
    sButtonMacro = ClickMacro
    lButtonIndex = ButtonIndex
 
End Sub
 
Private Sub wbEvents_BeforeClose(Cancel As Boolean)
 
    SetFocus lApphwnd
 
    bSkipActivateEvent = False
 
    Unload Me
 
End Sub
 
Private Sub wbEvents_SheetActivate(ByVal Sh As Object)
 
    If Sh Is oPosition.Parent Then _
    ShowWindow lMehwnd, 1 Else ShowWindow lMehwnd, 0
 
End Sub
 
Private Function TopLeftPoint(rng As Range) As POINTAPI
 
    Dim ldc As Long
    Dim lCurrentZoom As Long
 
    ldc = GetDC(0)
    lCurrentZoom = ActiveWindow.Zoom / 100
 
    With TopLeftPoint
        .x = ActiveWindow.PointsToScreenPixelsX(rng.Left * _
        (GetDeviceCaps(ldc, LOGPIXELSX) / 72 * lCurrentZoom))
 
        .y = ActiveWindow.PointsToScreenPixelsY(rng.Top * _
        (GetDeviceCaps(ldc, LOGPIXELSY) / 72 * lCurrentZoom))
    End With
 
    ReleaseDC 0, ldc
 
End Function

Regards.
 
Upvote 0
Hi, I am using this floating button code to create a navigation button on each page of the workbook and it works amazing in excel 2010, for the most part... the one problem I am having is that when I scroll through the pages using the ctrl + Page Up/Down keyboard shortcut the worksheets get stuck as if the floating button deselects the worksheet when I move from sheet to sheet. I tried adding a 'Application.ActiveCell.Select' command at the end of all the Subs to see if that would work but it doesn't. Any advice???

Class Module "ClassFloatingButton":
Code:
Option Explicit


'\This class uses a standard VBA UserForm with
'\a single CommandButton to create any
'\number of floating worksheet Buttons.
'\Via its intuitive interface,(Properties & Methods)
'\one can easily set the caption and the Click Macro
'\of the Buttons as well as their initial position
'\in relation to a chosen range.
'\The Class also allows adding the Buttons
'\to non active sheets.
'\tested on Excel 2010.
 
Private sCaption As String
Private oRangePos As Range
Private oUF  As UserForm1
 
Private Sub Class_Initialize()
 
    Set oUF = New UserForm1
    
    Application.ActiveCell.Select
 
End Sub
 
Private Sub Class_Terminate()
 
    Unload oUF
    
    Application.ActiveCell.Select
 
End Sub
 
Public Property Let Caption(ByVal ButtonCaption As String)
 
    sCaption = ButtonCaption
    
    Application.ActiveCell.Select
 
End Property
 
Public Sub PositionAtRange(RangePos As Range)
 
    Set oRangePos = RangePos
    oUF.Position RangePos
    
    Application.ActiveCell.Select
 
End Sub
 
Public Sub ClickMacro _
(ByVal MacroName As String, ButtonIndex As Long)
    oUF.ButtonMacro MacroName, ButtonIndex
    
    Application.ActiveCell.Select
 
End Sub
 
Public Sub Show()
 
    oUF.CommandButton1.Caption = sCaption
 
    If oRangePos.Parent Is ActiveSheet Then
        If Intersect(ActiveWindow.VisibleRange, oRangePos) _
        Is Nothing Then
            Application.Goto oRangePos
        End If
        oUF.Show vbModeless
    End If
 
    Application.ActiveCell.Select
End Sub
Standard Module "FloatingButton":
Code:
Option Explicit


Private oCol As New Collection


Sub AddFloatingButton1()


    Dim oButton As ClassFloatingButton
    Dim i As Long
    Dim wb As Workbook
    Dim ws As Worksheet
    
    Set wb = ActiveWorkbook
    i = 1
    For Each ws In wb.Worksheets
        Range("A1").Select
        Set oButton = New ClassFloatingButton
        With oButton
            .Caption = "Click Button for Navigation"
            .PositionAtRange Sheets(i).Range("A1")
            .ClickMacro "MyMacro", i
            .Show
            oCol.Add oButton
        End With
        Range("A1").Select
        i = i + 1
    Next
    Application.ActiveCell.Select
End Sub






Sub MyMacro(index As Long)
 
    Call ShowNav
    
    Application.ActiveCell.Select
 
End Sub
 
Sub RemoveFloatingButton1()
 
    Set oCol = Nothing
    
    Application.ActiveCell.Select
 
End Sub

UserForm "FloatingButton":
Code:
Option Explicit
 
Private WithEvents wbEvents As Workbook
 
Private Type POINTAPI
  x As Long
  y As Long
End Type
 
Private Declare PtrSafe Function FindWindow Lib "user32.dll" Alias _
"FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
 
Private Declare PtrSafe Function FindWindowEx Lib "user32.dll" Alias _
"FindWindowExA" _
(ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
 
Private Declare PtrSafe Function GetWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
 
Private Declare PtrSafe Function ShowWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
 
Private Declare PtrSafe Function SetWindowLong Lib "user32.dll" Alias _
"SetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
 
Private Declare PtrSafe Function GetWindowLong Lib "user32.dll" Alias _
"GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
 
Private Declare PtrSafe Function DrawMenuBar Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare PtrSafe Function MoveWindow Lib "user32.dll" _
(ByVal hwnd As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
 
Private Declare PtrSafe Function SetParent Lib "user32.dll" _
(ByVal hWndChild As Long, _
ByVal hWndNewParent As Long) As Long
 
Private Declare PtrSafe Function SetFocus Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare PtrSafe Function LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
 
Private Declare PtrSafe Function GetDC Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare PtrSafe Function GetWindowDC Lib "user32.dll" _
(ByVal hwnd As Long) As Long
 
Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" _
(ByVal hDC As Long, _
ByVal nIndex As Long) As Long
 
Private Declare PtrSafe Function ReleaseDC Lib "user32" _
(ByVal hwnd As Long, _
ByVal hDC As Long) As Long
 
Private Declare PtrSafe Function ScreenToClient Lib "user32.dll" _
(ByVal hwnd As Long, _
ByRef lpPoint As POINTAPI) As Long
 
Private Const WS_CAPTION As Long = &HC00000
Private Const GWL_STYLE As Long = -16
Private Const GWL_EXSTYLE As Long = (-20)
Private Const WS_EX_DLGMODALFRAME As Long = &H1&
Private Const GW_CHILD As Long = 5
Private Const LOGPIXELSX As Long = 88
Private Const LOGPIXELSY As Long = 90
 
Private tPt As POINTAPI
Private lApphwnd As Long
Private lEXCEL7 As Long
Private lXLDESK As Long
Private lMehwnd As Long
Private lButtonIndex As Long
Private ldc As Long
Private lClienthwnd As Long
Private sButtonMacro As String
Private bSkipActivateEvent As Boolean
Private oPosition As Range
 
Private Sub CommandButton1_Click()
 
    Application.Run sButtonMacro, lButtonIndex
 
    SetFocus lApphwnd
    
    Application.ActiveCell.Select
 
End Sub
 
Private Sub UserForm_Activate()
 
    If Not bSkipActivateEvent Then
     
        bSkipActivateEvent = True
     
        Me.StartUpPosition = 0
     
        lClienthwnd = GetWindow(lMehwnd, GW_CHILD)
     
        ldc = GetWindowDC(lClienthwnd)
     
        tPt = TopLeftPoint(oPosition)
     
        ScreenToClient lEXCEL7, tPt
     
        LockWindowUpdate lMehwnd
     
        MoveWindow lMehwnd, tPt.x, tPt.y, _
        Me.CommandButton1.Width * _
        (GetDeviceCaps(ldc, LOGPIXELSX) / 72), _
        Me.CommandButton1.Height * _
        (GetDeviceCaps(ldc, LOGPIXELSY) / 72), True
     
        ReleaseDC lClienthwnd, ldc
     
        LockWindowUpdate 0
     
        SetParent lMehwnd, lEXCEL7
     
        SetFocus lApphwnd
        
        Application.ActiveCell.Select
     
    End If
    
    Application.ActiveCell.Select
    
End Sub
 
Private Sub UserForm_Initialize()
 
    lApphwnd = FindWindow("XLMAIN", Application.Caption)
 
    lXLDESK = FindWindowEx _
    (lApphwnd, 0, "XLDESK", vbNullString)
 
    lEXCEL7 = FindWindowEx _
    (lXLDESK, 0, "EXCEL7", vbNullString)
 
    Set wbEvents = ThisWorkbook
 
    Call SetUpUserForm
    
    Application.ActiveCell.Select
 
End Sub
 
Private Sub SetUpUserForm()
 
    Dim lStyle As Long
    Dim lExStyle As Long
 
    With Me
        CommandButton1.Left = 0
        CommandButton1.Top = 0
        Height = 0
        Width = 0
    End With
 
    lMehwnd = FindWindow(vbNullString, Me.Caption)
 
    lStyle = GetWindowLong(lMehwnd, GWL_STYLE)
    lStyle = lStyle And Not (WS_CAPTION)
 
    SetWindowLong lMehwnd, GWL_STYLE, lStyle
 
    lExStyle = GetWindowLong(lMehwnd, GWL_EXSTYLE)
    lExStyle = lExStyle And Not (WS_EX_DLGMODALFRAME)
 
    SetWindowLong lMehwnd, GWL_EXSTYLE, lExStyle
 
    DrawMenuBar lMehwnd
    
    Application.ActiveCell.Select
 
End Sub
 
Public Sub Position(R As Range)
 
    Set oPosition = R
    
    Application.ActiveCell.Select
 
End Sub
 
Public Sub ButtonMacro _
(ByVal ClickMacro As String, ButtonIndex As Long)
 
    sButtonMacro = ClickMacro
    lButtonIndex = ButtonIndex
    
    Application.ActiveCell.Select
 
End Sub
 
Private Sub wbEvents_BeforeClose(Cancel As Boolean)
 
    SetFocus lApphwnd
 
    bSkipActivateEvent = False
 
    Unload Me
    
    Application.ActiveCell.Select
 
End Sub
 
Private Sub wbEvents_SheetActivate(ByVal Sh As Object)
 
    If Sh Is oPosition.Parent Then _
    ShowWindow lMehwnd, 1 Else ShowWindow lMehwnd, 0
    
    Application.ActiveCell.Select
 
End Sub
 
Private Function TopLeftPoint(rng As Range) As POINTAPI
 
    Dim ldc As Long
    Dim lCurrentZoom As Long
 
    ldc = GetDC(0)
    lCurrentZoom = ActiveWindow.Zoom / 100
 
    With TopLeftPoint
        .x = ActiveWindow.PointsToScreenPixelsX(rng.Left * _
        (GetDeviceCaps(ldc, LOGPIXELSX) / 72 * lCurrentZoom))
 
        .y = ActiveWindow.PointsToScreenPixelsY(rng.Top * _
        (GetDeviceCaps(ldc, LOGPIXELSY) / 72 * lCurrentZoom))
    End With
 
    ReleaseDC 0, ldc
    
    Application.ActiveCell.Select
 
End Function
Standard Module "CallNavigation":
Code:
Option Explicit


Sub ShowNav()
    frmNavigation.Show
    
    Application.ActiveCell.Select
End Sub
UserForm "NavigationForm":
Code:
Option Explicit


Private Sub cmdClose2_Click()
    'unload the userform
     Unload Me
     Application.ActiveCell.Select
End Sub


Private Sub cmdReset_Click()
    'reset the form
    Unload Me
    frmNavigation.Show
    Application.ActiveCell.Select
End Sub


Private Sub lstSheet_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
    'declare the variables
    Application.ScreenUpdating = False
    
    Dim i As Integer, Sht As String
    
    'for loop
    For i = 0 To lstSheet.ListCount - 1
        'get the name of the selected sheet
        If lstSheet.Selected(i) = True Then
            Sht = lstSheet.List(i)
        End If
    Next i


    'test if sheet is already open
    If ActiveSheet.Name = Sht Then
        MsgBox "This sheet is already open!"
        Exit Sub
    End If


    'select the sheet
    Sheets(Sht).Select
    'reset the userform
    Unload Me
    frmNavigation.Show
    Application.ActiveCell.Select
End Sub




Private Sub UserForm_Initialize()
    'declare the variable
    Dim Sh As Variant
    
    'for each loop the add visible sheets
    For Each Sh In ActiveWorkbook.Sheets
        'only visible sheetand exclude login sheet
        If Sh.Visible = True And Sh.Name <> "Login" Then
            'add sheets to the listbox
            Me.lstSheet.AddItem Sh.Name
        End If
    Next Sh
    Application.ActiveCell.Select
End Sub
 
Upvote 0

Forum statistics

Threads
1,223,984
Messages
6,175,786
Members
452,670
Latest member
nogarth

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top