PDA

View Full Version : APIs for Hiding UserForm "X" and\or Adding UserForm Minimize (32 & 64 bit)



gmaxey
10-19-2017, 08:31 AM
I realize that the subject post isn't restricted to Excel, but I recently got valuable assistance in this forum on a the topic and hope for more.

My project requires one userform with a minimize button that is auto "Clicked" following the command button execution and another userform that required the "X" close button to be removed.

When it comes to APIs, I am strictly Monkey see Monkey do. I have absolutely zero understanding how they actually work. Anyway, I have pieced together (from examples posted in this an other forums) some code that works and attached an example file.

I have Windows 7 Office 2106 32 bit so I am unable to confirm that my declarations would work in a 64 bit system or a system using VBA6.

I have made some of the declarations Public because they are used in the in both the standard module and the userform module. Not sure if this is a good or best practice.

If anyone with experience in this area or who has a 64 bit system can comment I appreciate it.


Private Const mcGWL_STYLE = (-16)
Private Const mcWS_SYSMENU = &H80000
Public Const SW_MINIMIZE = 6
'APIs for adding minimize button to userform or removing X button.
#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function GetWindowLongPtr Lib "USER32" Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Public Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Public Declare PtrSafe Function ShowWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal nCmdShow As Long) As Long
Private hWnd As LongPtr
Private lngStyle As LongPtr
#Else
Private Declare PtrSafe Function GetWindowLongPtr Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Public Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Public Declare PtrSafe Function ShowWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal nCmdShow As Long) As Long
Public hWnd As LongPtr
Private lngStyle As LongPtr
#End If
#Else
Private Declare Function GetWindowLongPtr Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function ShowWindow Lib "USER32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Public hWnd As Long
Private lngStyle As Long
#End If

Sub RemoveCloseButton(strUFCaption As String)
hWnd = FindWindow(vbNullString, strUFCaption)
lngStyle = GetWindowLongPtr(hWnd, mcGWL_STYLE)
If lngStyle And mcWS_SYSMENU > 0 Then
SetWindowLongPtr hWnd, mcGWL_STYLE, (lngStyle And Not mcWS_SYSMENU)
End If
lbl_Exit:
Exit Sub
End Sub
Sub AddMinimizeButton(strUFCaption As String)
hWnd = FindWindow(vbNullString, strUFCaption)
lngStyle = GetWindowLongPtr(hWnd, mcGWL_STYLE)
If (lngStyle And &H20000) = 0 Then
SetWindowLongPtr hWnd, mcGWL_STYLE, lngStyle Or &H20000
End If
lbl_Exti:
Exit Sub
End Sub

Bob Phillips
10-19-2017, 11:25 AM
Bit hard to check Greg, it uses two classes, clslreeView and clsNode, which are't in the workbook.

But, 64 bit testing should be #If VBA7, not #If VB7 (just saw that the posted code is VBA7, the actual code is VB7).

gmaxey
10-19-2017, 01:49 PM
xld,

I can only guess the wrong file was attached. The attached has two very simple userforms and a standard module. No classes or reference to classes.

Thanks

Aflatoon
10-19-2017, 02:36 PM
As a matter of interest, why do you need to remove the X to close, rather than simply intercepting its click, which is far simpler?

You can simplify your code a little as the FindWindow, ShowWindow and two variable declarations are the same whether Win64 or not, so they only need to be in there once.

gmaxey
10-19-2017, 06:06 PM
Personally preference I suppose. I've used the intercept process before but prefer to just get rid of the X.

Thanks!

Aflatoon
10-20-2017, 12:33 AM
AFAIK, you can't actually remove it, but only disable it.

snb
10-20-2017, 01:14 AM
You could use:


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

Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

Private Sub UserForm_Initialize()
SetWindowLongA FindWindowA(vbNullString, Caption), -16, &H0
End Sub

Private Sub knop_min_Click()
ShowWindow FindWindowA(vbNullString, Caption), 6
End Sub

There's also the option to open a userform without any caption bar at all, but containing a minimize button.

gmaxey
10-20-2017, 04:36 AM
snb,

... and how would that provide compatibility between both 32 and 64 bit systems?

snb
10-20-2017, 05:04 AM
You might use your declaration section instead of mine