Maximize and Minimize Buttons on UserForms

ttt123

Board Regular
Joined
May 31, 2006
Messages
120
Office Version
  1. 365
Platform
  1. Windows
Hello,

I found an API example for how to add Minimize and Maximize buttons on a userform. But I'd like to know how to programically Maximize the user form and also how to capture when the minimize and maximize buttons are pressed.

So for programically Maximizing the userform I used:
Code:
Application.WindowState = xlMaximized
Me.height = Application.height
Me.width = Application.width

while this does Maximize the form, it doesn't quite Maximize the same way(or size) as the button in the top right corner (added through API calls in links below) and hence I still see Maximize after calling this code instead of seeing the Restore button.

I'd also like to be able to capture when the Maximize Button is clicked (in something like a BeforeMaximize() function) so that I can adjust the size of some of the controls on the form accordingly. Likewise for the Minimize button I would like to override the default behaviour of minimizing the Excel application with just hiding the form.

Does anyone know how to do this?

Thanks

Here are the links to the Windows API calls I used to get the Maximize/Minimize buttons on the form:
site: http://www.cpearson.com/excel/formcontrol.aspx
download: http://www.cpearson.com/Zips/UserFormControl.zip
 
Last edited by a moderator:

Excel Facts

What is the fastest way to copy a formula?
If A2:A50000 contain data. Enter a formula in B2. Select B2. Double-click the Fill Handle and Excel will shoot the formula down to B50000.
i have been going over this myself for a while, never found a way to test when max/min, i think the problem is its a windows min/max button not a vba button.

as far as making it maxed by code:

ShowWindow lFormHandle, SW_SHOWMAXIMIZED
 
Upvote 0
thanks for your response, it got me on the right track and now I have devised a solution to this problem.

The following code will start a UserForm in a Maximized state with the Minimize/Restore/Maximize buttons enabled and also with Form Resizing enabled. The behaviour of the Minimize button is overridden so that now the Minimize button Hides the UserForm. If the UserForm is re-shown (after being minimized), it will restore its previous position and size.

Code In the UserForm:
Code:
'*********************************************************************************************************
' The following UserForm will start in a Maximized state, with the Minimize/Restore/Maximize
' Buttons enabled (and shown in the top right corner of the screen) and form resizing enabled. The behaviour
' of the Minimize button is overridden from its default behaviour and instead now hides the UserForm instead.
' When the form is reshown (after being Minimized), it will restore it's previous size(.Height, .Width)
' and position(.Top, .Left)
'*********************************************************************************************************
Option Explicit

Const SW_SHOWNORMAL = 1
Const SW_SHOWMINIMIZED = 2
Const SW_SHOWMAXIMIZED = 3

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
    
Private Declare Function ShowWindow Lib "user32" ( _
    ByVal hwnd As Long, _
    ByVal nCmdShow As Long) As Long

Private rMaxHeight As Double
Private rMaxWidth As Double
Private rMinimizedWidth As Double
Private rMinimizedHeight As Double
Private rPreviousHeight As Double
Private rPreviousWidth As Double
Private rPreviousTop As Double
Private rPreviousLeft As Double
Private bFormInit As Boolean
Private bFormMinimized As Boolean

Private Sub UserForm_Activate()
    With Me
        If bFormInit Then
            'Minimize the form so as to identify the width and height when it is minimized again.
            'This allows us to capture the minimize event in UserForm_Resize().
            Call ShowWindow(FindWindow("ThunderDFrame", .Caption), SW_SHOWMINIMIZED)
            rMinimizedWidth = .Width
            rMinimizedHeight = .Height
            'Maximize Form
            Call ShowWindow(FindWindow("ThunderDFrame", .Caption), SW_SHOWMAXIMIZED)
            bFormInit = False
        ElseIf Not (.Height = rMaxHeight And .Width = rMaxWidth) Then
            .Top = rPreviousTop
            .Left = rPreviousLeft
        End If
    End With
End Sub

Private Sub UserForm_Initialize()
    Call ShowMaximizeButton(Me, False)
    Call ShowMinimizeButton(Me, False)
    Call MakeFormResizable(Me, True)
    With Me
        'get a nice viewing size for when the form's Restore button is first clicked
        Application.WindowState = xlMaximized
        .Height = Application.Height - 10
        .Width = Application.Width - 10
        .Left = 0
        .Top = 0
        rMaxHeight = Application.Height
        rMaxWidth = Application.Width
        bFormInit = True
        'UserForm_Activate() is called immediately after this
    End With
End Sub

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    'Ideally for this we would want to capture the event where the menu bar was dragged.
    'But let's assume that the mouse went over the form before it was minimized.
    'Store the form position for when we reshow the form
    With Me
        rPreviousTop = .Top
        rPreviousLeft = .Left
    End With
End Sub

Private Sub UserForm_Resize()
    With Me
        'Check If Minimize was pressed and if so, Hide the form instead
        If .Width = rMinimizedWidth And .Height = rMinimizedHeight Then
            bFormMinimized = True
            If rPreviousHeight = rMaxHeight And rPreviousWidth = rMaxWidth Then
                Call ShowWindow(FindWindow("ThunderDFrame", .Caption), SW_SHOWMAXIMIZED)
            Else
                Call ShowWindow(FindWindow("ThunderDFrame", .Caption), SW_SHOWNORMAL)
            End If
            bFormMinimized = False
            .Hide
        ElseIf Not bFormMinimized Then 'Condition to make sure this isn't set during a Form Minimize
            rPreviousHeight = .Height
            rPreviousWidth = .Width
            rPreviousTop = .Top
            rPreviousLeft = .Left
        End If
    End With
End Sub

Code In a Module:
Code:
Option Explicit
Option Compare Text
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' modFormControl
' By Chip Pearson, chip@cpearson.com, www.cpearson.com
' 21-March-2008
' URL: http://www.cpearson.com/Excel/FormControl.aspx
' Requires: modWindowCaption at http://www.cpearson.com/Excel/FileExtensions.aspx
'
' ----------------------------------
' Functions In This Module:
' ----------------------------------
'   SetFormParent
'       Sets a userform's parent to the Application or the ActiveWindow.
'   IsCloseButtonVisible
'       Returns True or False indicating whether the userform's Close button
'       is visible.
'   ShowCloseButton
'       Displays or hides the userform's Close button.
'   IsCloseButtonEnabled
'       Returns True or False indicating whether the userform's Close button
'       is enabled.
'   EnableCloseButton
'       Enables or disables a userform's Close button.
'   ShowTitleBar
'       Displays or hides a userform's Title Bar. The title bar cannot be
'       hidden if the form is resizable.
'   IsTitleBarVisible
'       Returns True or False indicating if the userform's Title Bar is visible.
'   MakeFormResizable
'       Makes the form resizable or not resizable. If the form is made resizable,
'       the title bar cannot be hidden.
'   IsFormResizable
'       Returns True or False indicating whether the userform is resizable.
'   SetFormOpacity
'       Sets the opacity of a form from fully opaque to fully invisible.
'   HasMaximizeButton
'       Returns True or False indicating whether the userform has a
'       maximize button.
'   HasMinimizeButton
'       Returns True or False indicating whether the userform has a
'       minimize button.
'   ShowMaximizeButton
'       Displays or hides a Maximize Window button on the userform.
'   ShowMinimizeButton
'       Displays or hides a Minimize Window button on the userform.
'   HWndOfUserForm
'       Returns the window handle (HWnd) of a userform.
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Const C_USERFORM_CLASSNAME = "ThunderDFrame"
Private Const C_EXCEL_APP_CLASSNAME = "XLMain"
Private Const C_EXCEL_DESK_CLASSNAME = "XLDesk"
Private Const C_EXCEL_WINDOW_CLASSNAME = "Excel7"
Private Const MF_BYPOSITION = &H400
Private Const MF_REMOVE = &H1000
Private Const MF_ENABLED = &H0&
Private Const MF_DISABLED = &H2&
Private Const MF_GRAYED = &H1&
Private Const GWL_EXSTYLE = (-20)
Private Const GWL_STYLE = (-16)
Private Const GWL_HWNDPARENT = (-8)
Private Const WS_CAPTION = &HC00000
Private Const WS_SYSMENU = &H80000
Private Const WS_EX_LAYERED = &H80000
Private Const LWA_ALPHA = &H2&
Private Const C_ALPHA_FULL_TRANSPARENT As Byte = 0
Private Const C_ALPHA_FULL_OPAQUE As Byte = 255
Private Const WS_DLGFRAME = &H400000
Private Const WS_THICKFRAME = &H40000
Private Const WS_SIZEBOX = WS_THICKFRAME
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000

Public Enum FORM_PARENT_WINDOW_TYPE
    FORM_PARENT_NONE = 0
    FORM_PARENT_APPLICATION = 1
    FORM_PARENT_WINDOW = 2
End Enum

Private Declare Function SetParent Lib "user32" ( _
    ByVal hWndChild As Long, _
    ByVal hWndNewParent As Long) As Long

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
    
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 Declare Function SetLayeredWindowAttributes Lib "user32" ( _
    ByVal hwnd As Long, _
    ByVal crey As Byte, _
    ByVal bAlpha As Byte, _
    ByVal dwFlags As Long) As Long

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
    ByVal hWnd1 As Long, _
    ByVal hWnd2 As Long, _
    ByVal lpsz1 As String, _
    ByVal lpsz2 As String) As Long

Private Declare Function GetActiveWindow Lib "user32" () As Long

Private Declare Function DrawMenuBar Lib "user32" ( _
    ByVal hwnd As Long) As Long

Private Declare Function GetMenuItemCount Lib "user32" ( _
    ByVal hMenu As Long) As Long

Private Declare Function GetSystemMenu Lib "user32" ( _
    ByVal hwnd As Long, _
    ByVal bRevert As Long) As Long
    
Private Declare Function RemoveMenu Lib "user32" ( _
    ByVal hMenu As Long, _
    ByVal nPosition As Long, _
    ByVal wFlags As Long) As Long
    
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
    ByVal hwnd As Long, _
    ByVal lpString As String, _
    ByVal cch As Long) As Long
    
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" ( _
    ByVal hwnd As Long) As Long

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
    ByVal hwnd As Long, _
    ByVal lpClassName As String, _
    ByVal nMaxCount As Long) As Long

Private Declare Function EnableMenuItem Lib "user32" ( _
    ByVal hMenu As Long, _
    ByVal wIDEnableItem As Long, _
    ByVal wEnable As Long) As Long


Function ShowMaximizeButton(UF As MSForms.UserForm, _
    HideButton As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShowMaximizeButton
' Displays (if HideButton is False) or hides (if HideButton is True)
' a maximize window button.
' NOTE: If EITHER a Minimize or Maximize button is displayed,
' BOTH buttons are visible but may be disabled.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    ShowMaximizeButton = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)
If HideButton = False Then
    WinInfo = WinInfo Or WS_MAXIMIZEBOX
Else
    WinInfo = WinInfo And (Not WS_MAXIMIZEBOX)
End If
R = SetWindowLong(UFHWnd, GWL_STYLE, WinInfo)

ShowMaximizeButton = (R <> 0)

End Function

Function ShowMinimizeButton(UF As MSForms.UserForm, _
    HideButton As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShowMinimizeButton
' Displays (if HideButton is False) or hides (if HideButton is True)
' a minimize window button.
' NOTE: If EITHER a Minimize or Maximize button is displayed,
' BOTH buttons are visible but may be disabled.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    ShowMinimizeButton = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)
If HideButton = False Then
    WinInfo = WinInfo Or WS_MINIMIZEBOX
Else
    WinInfo = WinInfo And (Not WS_MINIMIZEBOX)
End If
R = SetWindowLong(UFHWnd, GWL_STYLE, WinInfo)

ShowMinimizeButton = (R <> 0)

End Function

Function HasMinimizeButton(UF As MSForms.UserForm) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' HasMinimizeButton
' Returns True if the userform has a minimize button, False
' otherwise.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    HasMinimizeButton = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)

If WinInfo And WS_MINIMIZEBOX Then
    HasMinimizeButton = True
Else
    HasMinimizeButton = False
End If

End Function

Function HasMaximizeButton(UF As MSForms.UserForm) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' HasMaximizeButton
' Returns True if the userform has a maximize button, False
' otherwise.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    HasMaximizeButton = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)

If WinInfo And WS_MAXIMIZEBOX Then
    HasMaximizeButton = True
Else
    HasMaximizeButton = False
End If

End Function


Function SetFormParent(UF As MSForms.UserForm, _
    Parent As FORM_PARENT_WINDOW_TYPE) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' SetFormParent
' Set the UserForm UF as a child of (1) the Application, (2) the
' Excel ActiveWindow, or (3) no parent. Returns TRUE if successful
' or FALSE if unsuccessful.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WindHWnd As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    SetFormParent = False
    Exit Function
End If

Select Case Parent
    Case FORM_PARENT_APPLICATION
        R = SetParent(UFHWnd, Application.hwnd)
    Case FORM_PARENT_NONE
        R = SetParent(UFHWnd, 0&)
    Case FORM_PARENT_WINDOW
        If Application.ActiveWindow Is Nothing Then
            SetFormParent = False
            Exit Function
        End If
        WindHWnd = WindowHWnd(Application.ActiveWindow)
        If WindHWnd = 0 Then
            SetFormParent = False
            Exit Function
        End If
        R = SetParent(UFHWnd, WindHWnd)
    Case Else
        SetFormParent = False
        Exit Function
End Select
SetFormParent = (R <> 0)

End Function


Function IsCloseButtonVisible(UF As MSForms.UserForm) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsCloseButtonVisible
' Returns TRUE if UserForm UF has a close button, FALSE if there
' is no close button.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    IsCloseButtonVisible = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)
IsCloseButtonVisible = (WinInfo And WS_SYSMENU)

End Function

Function ShowCloseButton(UF As MSForms.UserForm, HideButton As Boolean) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShowCloseButton
' This displays (if HideButton is FALSE) or hides (if HideButton is
' TRUE) the Close button on the userform
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)
If HideButton = False Then
    ' set the SysMenu bit
    WinInfo = WinInfo Or WS_SYSMENU
Else
    ' clear the SysMenu bit
    WinInfo = WinInfo And (Not WS_SYSMENU)
End If

R = SetWindowLong(UFHWnd, GWL_STYLE, WinInfo)
ShowCloseButton = (R <> 0)

End Function


Function IsCloseButtonEnabled(UF As MSForms.UserForm) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsCloseButtonEnabled
' This returns TRUE if the close button is enabled or FALSE if
' the close button is disabled.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim hMenu As Long
Dim ItemCount As Long
Dim PrevState As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    IsCloseButtonEnabled = False
    Exit Function
End If
' Get the menu handle
hMenu = GetSystemMenu(UFHWnd, 0&)
If hMenu = 0 Then
    IsCloseButtonEnabled = False
    Exit Function
End If

ItemCount = GetMenuItemCount(hMenu)
' Disable the button. This returns MF_DISABLED or MF_ENABLED indicating
' the previous state of the item.
PrevState = EnableMenuItem(hMenu, ItemCount - 1, MF_DISABLED Or MF_BYPOSITION)

If PrevState = MF_DISABLED Then
    IsCloseButtonEnabled = False
Else
    IsCloseButtonEnabled = True
End If
' restore the previous state
EnableCloseButton UF, (PrevState = MF_DISABLED)

DrawMenuBar UFHWnd

End Function


Function EnableCloseButton(UF As MSForms.UserForm, Disable As Boolean) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' EnableCloseButton
' This function enables (if Disable is False) or disables (if
' Disable is True) the "X" button on a UserForm UF.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim hMenu As Long
Dim ItemCount As Long
Dim Res As Long

' Get the HWnd of the UserForm.
UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    EnableCloseButton = False
    Exit Function
End If
' Get the menu handle
hMenu = GetSystemMenu(UFHWnd, 0&)
If hMenu = 0 Then
    EnableCloseButton = False
    Exit Function
End If

ItemCount = GetMenuItemCount(hMenu)
If Disable = True Then
    Res = EnableMenuItem(hMenu, ItemCount - 1, MF_DISABLED Or MF_BYPOSITION)
Else
    Res = EnableMenuItem(hMenu, ItemCount - 1, MF_ENABLED Or MF_BYPOSITION)
End If
If Res = -1 Then
    EnableCloseButton = False
    Exit Function
End If
DrawMenuBar UFHWnd

EnableCloseButton = True


End Function

Function ShowTitleBar(UF As MSForms.UserForm, HideTitle As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ShowTitleBar
' Displays (if HideTitle is FALSE) or hides (if HideTitle is TRUE) the
' title bar of the userform UF.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    ShowTitleBar = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)

If HideTitle = False Then
    ' turn on the Caption bit
    WinInfo = WinInfo Or WS_CAPTION
Else
    ' turn off the Caption bit
    WinInfo = WinInfo And (Not WS_CAPTION)
End If
R = SetWindowLong(UFHWnd, GWL_STYLE, WinInfo)
ShowTitleBar = (R <> 0)
End Function

Function IsTitleBarVisible(UF As MSForms.UserForm) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsTitleBarVisible
' Returns TRUE if the title bar of UF is visible or FALSE if the
' title bar is not visible.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    IsTitleBarVisible = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)

IsTitleBarVisible = (WinInfo And WS_CAPTION)

End Function

Function MakeFormResizable(UF As MSForms.UserForm, Sizable As Boolean) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' MakeFormResizable
' This makes the userform UF resizable (if Sizable is TRUE) or not
' resizable (if Sizalbe is FALSE). Returns TRUE if successful or FALSE
' if an error occurred.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    MakeFormResizable = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)
If Sizable = True Then
    WinInfo = WinInfo Or WS_SIZEBOX
Else
    WinInfo = WinInfo And (Not WS_SIZEBOX)
End If

R = SetWindowLong(UFHWnd, GWL_STYLE, WinInfo)
MakeFormResizable = (R <> 0)


End Function

Function IsFormResizable(UF As MSForms.UserForm) As Boolean
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsFormResizable
' Returns TRUE if UF is resizable, FALSE if UF is not resizable.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim UFHWnd As Long
Dim WinInfo As Long
Dim R As Long

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    IsFormResizable = False
    Exit Function
End If

WinInfo = GetWindowLong(UFHWnd, GWL_STYLE)

IsFormResizable = (WinInfo And WS_SIZEBOX)

End Function


Function SetFormOpacity(UF As MSForms.UserForm, Opacity As Byte) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' SetFormOpacity
' This function sets the opacity of the UserForm referenced by the
' UF parameter. Opacity specifies the opacity of the form, from
' 0 = fully transparent (invisible) to 255 = fully opaque. The function
' returns True if successful or False if an error occurred. This
' requires Windows 2000 or later -- it will not work in Windows
' 95, 98, or ME.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim UFHWnd As Long
Dim WinL As Long
Dim Res As Long

SetFormOpacity = False

UFHWnd = HWndOfUserForm(UF)
If UFHWnd = 0 Then
    Exit Function
End If

WinL = GetWindowLong(UFHWnd, GWL_EXSTYLE)
If WinL = 0 Then
    Exit Function
End If

Res = SetWindowLong(UFHWnd, GWL_EXSTYLE, WinL Or WS_EX_LAYERED)
If Res = 0 Then
    Exit Function
End If

Res = SetLayeredWindowAttributes(UFHWnd, 0, Opacity, LWA_ALPHA)
If Res = 0 Then
    Exit Function
End If

SetFormOpacity = True

End Function


Function HWndOfUserForm(UF As MSForms.UserForm) As Long
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' HWndOfUserForm
' This returns the window handle (HWnd) of the userform referenced
' by UF. It first looks for a top-level window, then a child
' of the Application window, then a child of the ActiveWindow.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim AppHWnd As Long
Dim DeskHWnd As Long
Dim WinHWnd As Long
Dim UFHWnd As Long
Dim Cap As String
Dim WindowCap As String

Cap = UF.Caption

' First, look in top level windows
UFHWnd = FindWindow(C_USERFORM_CLASSNAME, Cap)
If UFHWnd <> 0 Then
    HWndOfUserForm = UFHWnd
    Exit Function
End If
' Not a top level window. Search for child of application.
AppHWnd = Application.hwnd
UFHWnd = FindWindowEx(AppHWnd, 0&, C_USERFORM_CLASSNAME, Cap)
If UFHWnd <> 0 Then
    HWndOfUserForm = UFHWnd
    Exit Function
End If
' Not a child of the application.
' Search for child of ActiveWindow (Excel's ActiveWindow, not
' Window's ActiveWindow).
If Application.ActiveWindow Is Nothing Then
    HWndOfUserForm = 0
    Exit Function
End If
WinHWnd = WindowHWnd(Application.ActiveWindow)
UFHWnd = FindWindowEx(WinHWnd, 0&, C_USERFORM_CLASSNAME, Cap)
HWndOfUserForm = UFHWnd

End Function


Function ClearBit(Value As Long, ByVal BitNumber As Long) As Long
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ClearBit
' Clears the specified bit in Value and returns the result. Bits are
' numbered, right (most significant) 31 to left (least significant) 0.
' BitNumber is made positive and then MOD 32 to get a valid bit number.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim SetMask As Long
Dim ClearMask As Long

BitNumber = Abs(BitNumber) Mod 32

SetMask = Value
If BitNumber < 30 Then
    ClearMask = Not (2 ^ (BitNumber - 1))
    ClearBit = SetMask And ClearMask
Else
    ClearBit = Value And &H7FFFFFFF
End If

End Function

Code in a Module:
Code:
Option Explicit
Option Compare Text
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' modWindowCaption
' By Chip Pearson, 15-March-2008, chip@cpearson.com, www.cpearson.com
' http://www.cpearson.com/Excel/FileExtensions.aspx
'
' This module contains code for working with Excel.Window captions. This code
' is necessary if you are going to use the FindWindowEx API call to get the
' HWnd of an Excel.Window.  Windows has a property called "Hide extensions of
' known file types". If this setting is TRUE, the file extension is not displayed
' (e.g., "Book1.xls" is displayed as just "Book1"). However, the Caption of an
' Excel.Window always includes the ".xls" file extension, regardless of the hide
' extensions setting. FindWindowEx requires that the ".xls" extension be removed
' if the "hide extensions" setting is True.
'
' This module contains a function named DoesWindowsHideFileExtensions, which returns
' TRUE if Windows is hiding file extensions or FALSE if Windows is not hiding file
' extensions. This is determined by a registry key. The module also contains a
' function named WindowCaption that returns the Caption of a specified Excel.Window
' with the ".xls" removed if necessary. The string returned by this function
' is suitable for use in FindWindowEx regardless of the value of the Windows
' "Hide Extensions" setting.
'
' This module also contains a function named WindowHWnd which returns the HWnd of
' a specified Excel.Window object. This function works regardless of the value of the
' Windows "Hide Extensions" setting.
'
' This module also includes the functions WindowText and WindowClassName which are
' just wrappers for the GetWindowText and GetClassName API functions.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
    ByVal hWnd1 As Long, _
    ByVal hWnd2 As Long, _
    ByVal lpsz1 As String, _
    ByVal lpsz2 As String) As Long

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" ( _
    ByVal hwnd As Long, _
    ByVal lpString As String, _
    ByVal cch As Long) As Long

Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" ( _
    ByVal HKey As Long, _
    ByVal lpSubKey As String, _
    ByVal ulOptions As Long, _
    ByVal samDesired As Long, _
    phkResult As Long) As Long
    
Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" ( _
    ByVal HKey As Long, _
    ByVal lpValueName As String, _
    ByVal lpReserved As Long, _
    LPType As Long, _
    LPData As Any, _
    lpcbData As Long) As Long

Private Declare Function RegCloseKey Lib "advapi32.dll" ( _
    ByVal HKey As Long) As Long

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
    ByVal hwnd As Long, _
    ByVal lpClassName As String, _
    ByVal nMaxCount As Long) As Long

Private Const HKEY_CURRENT_USER As Long = &H80000001
Private Const HKEY_LOCAL_MACHINE As Long = &H80000002
Private Const HKEY_CLASSES_ROOT  As Long = &H80000000
Private Const HKEY_CURRENT_CONFIG  As Long = &H80000005
Private Const HKEY_DYN_DATA  As Long = &H80000006
Private Const HKEY_PERFORMANCE_DATA  As Long = &H80000004
Private Const HKEY_USERS  As Long = &H80000003
Private Const KEY_ALL_ACCESS  As Long = &H3F
Private Const ERROR_SUCCESS  As Long = 0&
Private Const HKCU  As Long = HKEY_CURRENT_USER
Private Const HKLM  As Long = HKEY_LOCAL_MACHINE

Private Enum REG_DATA_TYPE
    REG_DATA_TYPE_DEFAULT = 0   ' Default based on data type of value.
    REG_INVALID = -1            ' Invalid
    REG_SZ = 1                  ' String
    REG_DWORD = 4               ' Long
End Enum

Private Const C_EXCEL_APP_CLASSNAME = "XLMain"
Private Const C_EXCEL_DESK_CLASSNAME = "XLDesk"
Private Const C_EXCEL_WINDOW_CLASSNAME = "EXCEL7"


Function DoesWindowsHideFileExtensions() As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' DoesWindowsHideFileExtensions
' This function looks in the registry key
'   HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
' for the value named "HideFileExt" to determine whether the Windows Explorer
' setting "Hide Extensions Of Known File Types" is enabled. This function returns
' TRUE if this setting is in effect (meaning that Windows displays "Book1" rather
' than "Book1.xls"), or FALSE if this setting is not in effect (meaning that Windows
' displays "Book1.xls").
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim Res As Long
Dim RegKey As Long
Dim V As Long

Const KEY_NAME = "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
Const VALUE_NAME = "HideFileExt"

''''''''''''''''''''''''''''''''''''''''''''''''''
' Open the registry key to get a handle (RegKey).
''''''''''''''''''''''''''''''''''''''''''''''''''
Res = RegOpenKeyEx(HKey:=HKCU, _
                    lpSubKey:=KEY_NAME, _
                    ulOptions:=0&, _
                    samDesired:=KEY_ALL_ACCESS, _
                    phkResult:=RegKey)

If Res <> ERROR_SUCCESS Then
    Exit Function
End If
''''''''''''''''''''''''''''''''''''''''''''''''''
' Get the value of the "HideFileExt" named value.
''''''''''''''''''''''''''''''''''''''''''''''''''
Res = RegQueryValueEx(HKey:=RegKey, _
                    lpValueName:=VALUE_NAME, _
                    lpReserved:=0&, _
                    LPType:=REG_DWORD, _
                    LPData:=V, _
                    lpcbData:=Len(V))

If Res <> ERROR_SUCCESS Then
    RegCloseKey RegKey
    Exit Function
End If

''''''''''''''''''''''''''''''''''''''''''''''''''
' Close the key and return the result.
''''''''''''''''''''''''''''''''''''''''''''''''''
RegCloseKey RegKey
DoesWindowsHideFileExtensions = (V <> 0)


End Function


Function WindowCaption(W As Excel.Window) As String
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' WindowCaption
' This returns the Caption of the Excel.Window W with the ".xls" extension removed
' if required. The string returned by this function is suitable for use by
' the FindWindowEx API regardless of the value of the Windows "Hide Extensions"
' setting.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim HideExt As Boolean
Dim Cap As String
Dim Pos As Long

HideExt = DoesWindowsHideFileExtensions()
Cap = W.Caption
If HideExt = True Then
    Pos = InStrRev(Cap, ".")
    If Pos > 0 Then
        Cap = Left(Cap, Pos - 1)
    End If
End If

WindowCaption = Cap

End Function

Function WindowHWnd(W As Excel.Window) As Long
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' WindowHWnd
' This returns the HWnd of the Window referenced by W.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim AppHWnd As Long
Dim DeskHWnd As Long
Dim WHWnd As Long
Dim Cap As String

AppHWnd = Application.hwnd
DeskHWnd = FindWindowEx(AppHWnd, 0&, C_EXCEL_DESK_CLASSNAME, vbNullString)
If DeskHWnd > 0 Then
    Cap = WindowCaption(W)
    WHWnd = FindWindowEx(DeskHWnd, 0&, C_EXCEL_WINDOW_CLASSNAME, Cap)
End If
WindowHWnd = WHWnd

End Function

Function WindowText(hwnd As Long) As String
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' WindowText
' This just wraps up GetWindowText.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Dim S As String
    Dim N As Long
    N = 255
    S = String$(N, vbNullChar)
    N = GetWindowText(hwnd, S, N)
    If N > 0 Then
        WindowText = Left(S, N)
    Else
        WindowText = vbNullString
    End If
End Function

Function WindowClassName(hwnd As Long) As String
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' WindowClassName
' This just wraps up GetClassName.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    Dim S As String
    Dim N As Long
    N = 255
    S = String$(N, vbNullChar)
    N = GetClassName(hwnd, S, N)
    If N > 0 Then
        WindowClassName = Left(S, N)
    Else
        WindowClassName = vbNullString
    End If

End Function
 
Last edited by a moderator:
Upvote 0
This also works for minimizing
Code:
Option Explicit
Option Private Module
Option Base 0
Private Declare Function FindWindowA Lib "USER32" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
 
Private Declare Function GetWindowLongA Lib "USER32" _
(ByVal hWnd As Long, _
ByVal nIndex As Long) As Long
 
Private Declare Function SetWindowLongA Lib "USER32" _
(ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
'Add Minimize button to a Userform
Sub FormatUserForm(UserFormCaption As String)
     
    Dim hWnd            As Long
    Dim exLong          As Long
     
    hWnd = FindWindowA(vbNullString, UserFormCaption)
    exLong = GetWindowLongA(hWnd, -16)
    If (exLong And &H20000) = 0 Then
        SetWindowLongA hWnd, -16, exLong Or &H20000
    End If
End Sub
 
Upvote 0
'If you are a bit slow at typing and reading as us old farmers are
'try a shortened version'
'in a module have

Option Explicit
Declare Function GWLi& Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd&, ByVal nIndex&)
Declare Function SWLi& Lib "user32" Alias "SetWindowLongA" (ByVal hwnd&, ByVal nIndex&, ByVal dwNewLong&)
Const GWL_STYLE = (-16)
' to save remembering those constants let it prompt you
Public Enum FoButs
fbMaxBox& = &H10000
fbMinBox& = &H20000
fbSizeab& = &H40000 ' thick frame
fbSysteM& = &H80000 ' system = layered
fbCaption& = &HC00000
fbDLGFRAME = &H400000
fbAll& = &HF0000
End Enum
Function DoAddToForm&(FohWnd&, ItemAdd As FoButs, WantIt As Boolean)
Dim WI&
WI = GWLi(FohWnd, GWL_STYLE)
If WantIt Then WI = WI Or ItemAdd Else WI = WI And (Not ItemAdd)
DoAddToForm = SWLi(FohWnd, GWL_STYLE, WI)
End Function

'make your form carry its own handle with it ...
'In the forms code have these added in the right places

'for form
Public MeHWnd&, MeParent%, MeParentHwnd&
' these show as form properties
'or as object properties if the form is passed to an object

Private Sub CommandButton2_Click()
Unload Me ' some control to kill it when all X are lost
End Sub
Private Sub UserForm_Initialize() ' this code in your initialize
MeHWnd = FindWindow("ThunderDFrame", Me.Caption)
MeParentHwnd = GetDesktopWindow ' or what the parent HWnd you want it to
MeParent = 12 ' or what code integer you use for its parent type
End Sub
' on the topic of change parents... IS EXCEL7 always the first child of the active window ???
'so will this sometimes or always work???
'Dim XL7&, Res&
'Const GW_CHILD = 5
'Const GW_HWNDNEXT = 2
'XL7 = FindWindowEx(Application.hwnd, 0&, "XLDESK", "")
'XL7 = GetWindow(XL7, GW_CHILD) ' to give XL7
'Res = GetWindow(XL7, GW_CHILD) ' to give the Vertical Scroll bar ( Left Bot is Right Bot of sheet)
'Res = GetWindow(XL7, GW_HWNDNEXT) ' gives next .xl?? . looped will end with .xla 's
[/code]
'then call like below for a form UFA that carries its handle

' DoAddToForm UFA.MeHWnd, FoButs.fbCaption, True
'DoAddToForm UFA.MeHWnd, fbAll, True
'DoAddToForm UFA.MeHWnd, fbMinBox, False
'or send first parameter is the window handle you have for it
DoAddToForm MyFormHwnd, fbSizeab, False

' Again And Again

'????? How do you make a shape or OleObject move to the fromt of a USERFORM ??????
' other than making it a child of the form

' and as always
'All our thanks to Chip Pearson for all of his work
' else maybe I would still be trying to advance past VBA like cells(2,5)=cells(3,5)+4
 
Upvote 0
Hi , i had tried your code it works perfect only problem i am facing is when i try to minimize the form it will unload the form from memory. Please help me on this.
Thanks in advance.
 
Upvote 0

Forum statistics

Threads
1,222,764
Messages
6,168,106
Members
452,162
Latest member
strail1972

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