PDA

View Full Version : UserForm has Minimize Button. How do I execute it via code.



gmaxey
10-16-2017, 11:06 PM
I have a userform with functioning minimize\restore buttons. I would like to minimize the form with a command button click event.




'APIs for adding minimize button to userform.
#If Win64 Then
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32.dll" Alias "GetWindowLongPtrA" ( _
ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "user32.dll" Alias "SetWindowLongPtrA" ( _
ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function FindWindowA Lib "user32.dll" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As LongPtr) As Long
#Else
Private Declare Function GetWindowLongA Lib "user32.dll" ( _
ByVal hWnd As Long, ByVal nIndex As Long) As Long

Private Declare Function SetWindowLongA Lib "user32.dll" ( _
ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function FindWindowA Lib "user32.dll" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As Long) As Long
#End If

Private Sub UserForm_Initialize()
Caption = "Minimize Button
AddMinimizeButton Caption
lbl_Exit:
Exit Sub
End Sub

Sub AddMinimizeButton(UserFormCaption As String)
#If Win64 Then
Dim hWnd As LongPtr
Dim exLong As LongPtr
hWnd = FindWindowPtr(vbNullString, UserFormCaption)
exLong = GetWindowLongPtr(hWnd, -16)
If (exLong And &H20000) = 0 Then
SetWindowLongPtr hWnd, -16, exLong Or &H20000
End If
#Else
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 If
End Sub

Sub cmd_Click()
'Minimimize me."


Can anyone offer any ideas? Thanks.

snb
10-17-2017, 12:37 AM
Hi @Gmaxey

That's an interesting question.
I did some testing in the examples I keep on my system.
Alas, I wasn't able to produce what you are after.
I hope someone else (KH is 'our' API-adept/specialist) can shed some light.
I am also very interested in how this could be done.

Aflatoon
10-17-2017, 01:04 AM
You can use ShowWindow for that:


Option ExplicitConst SW_MINIMIZE = 6
'APIs for adding minimize button to userform.
#If Win64 Then
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32.dll" Alias "GetWindowLongPtrA" ( _
ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hWnd As LongPtr, _
ByVal nCmdShow As Long) As Long

Private Declare PtrSafe Function SetWindowLongPtr Lib "user32.dll" Alias "SetWindowLongPtrA" ( _
ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function FindWindowA Lib "user32.dll" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As LongPtr) As Long
Dim hWnd As LongPtr
#Else
Private Declare Function GetWindowLongA Lib "user32.dll" ( _
ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, _
ByVal nCmdShow As Long) As Long

Private Declare Function SetWindowLongA Lib "user32.dll" ( _
ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function FindWindowA Lib "user32.dll" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hWnd As Long) As Long
Dim hWnd As Long
#End If

Private Sub UserForm_Initialize()
Caption = "Minimize Button "
AddMinimizeButton Caption
lbl_Exit:
Exit Sub
End Sub

Sub AddMinimizeButton(UserFormCaption As String)
#If Win64 Then
Dim exLong As LongPtr
hWnd = FindWindowPtr(vbNullString, UserFormCaption)
exLong = GetWindowLongPtr(hWnd, -16)
If (exLong And &H20000) = 0 Then
SetWindowLongPtr hWnd, -16, exLong Or &H20000
End If
#Else
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 If
End Sub
Private Sub cmd_Click()


ShowWindow hWnd, SW_MINIMIZE
End Sub

gmaxey
10-17-2017, 04:53 AM
Aftaloon,

Thanks!! I am a total nub with API so of course I put your simple one liner in my code and it failed three times. First on hWnd, then in SW_MINIMIZE then on ShowWindow ;-)

I've changed to


#If Win64 Then
Private hwnd As LongPtr
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32.dll" Alias "GetWindowLongPtrA" ( _
ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "user32.dll" Alias "SetWindowLongPtrA" ( _
ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Private Declare PtrSafe Function FindWindowA Lib "user32.dll" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function DrawMenuBar Lib "user32.dll" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function ShowWindow Lib "user32.dll" (ByVal hwnd As LongPtr, ByVal nCmdShow As LongPtr) As Long
#Else
Private hwnd As Long
Private Declare Function GetWindowLongA Lib "user32.dll" ( _
ByVal hwnd As Long, ByVal nIndex As Long) As Long

Private Declare Function SetWindowLongA Lib "user32.dll" ( _
ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function FindWindowA Lib "user32.dll" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function DrawMenuBar Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
#End If
Private Const SW_MINIMIZE As Long = 6

... and now it works.

Couple of follow on questions:

1. I don't have a 64 bit system to test with. Can you advise if I used the correct declarations in the that section of the declarations is correct.
2. I found the code to add the minimize button through a Google search. When the form displays, it has the active minimize button, an inactive maximize button, and an active Close button. When minimized, it has an active restore up button, an inactive maximize button and an active Close button. Is it possible to suppress the inactive maximize button? What change in the code is required.

Thanks!
file:///C:/Users/Maxey/AppData/Local/Temp/SNAGHTML1ca35ed8.PNG

Aflatoon
10-17-2017, 05:07 AM
I'm confused - I gave you the full code including all the declarations earlier.

Not sure about the other part - will have a think.

snb
10-17-2017, 05:08 AM
I used:


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

And it did what I expected.

gmaxey
10-17-2017, 05:19 AM
Aflatoon,

Because I confused you. Yes you did. I'm just bleary eyed. I'm sorry. If you think of something, please let me know.

BREAK

snb, Thanks.

Paul_Hossler
10-17-2017, 07:58 AM
I have a userform with functioning minimize\restore buttons. I would like to minimize the form with a command button click event.

Can anyone offer any ideas? Thanks.

Seems like it'd be easier and safer (not 32/64 bit dependent) to just .Hide it ???

Aflatoon
10-17-2017, 10:52 AM
I used:


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

And it did what I expected.

I appreciate that is how you like to code, but IMO no one in their right mind tries to obfuscate API code. In reality you should be checking handles for validity (though I didn’t here) not trying to condense everything.

gmaxey
10-17-2017, 04:56 PM
Paul,

It is a modeless form that takes a bit to load and users may want it out of the way "minimized" rather that have to call it again. Thanks for the suggestions though.
Best Regards,
Greg Maxey
Wars are won by will, by readiness to die, and by skill in killing, not by advantages, however lopsided, in numbers.
~ War and Remembrance Herman Wouk

Paul_Hossler
10-18-2017, 07:21 AM
Paul,
It is a modeless form that takes a bit to load and users may want it out of the way "minimized" rather that have to call it again. Thanks for the suggestions though.


Dumb question #2 -- why can't they just use the UF's [Minimize] button?

gmaxey
10-18-2017, 02:23 PM
Not dumb at all, reasonable in fact. The form lets a user select and insert a building block. The add-in setup options are After Insert 1) Close, 2) Minimize or 3 Leave as is. If the user choose 2 in set up then I wanted the code automatically minimized.