Consulting

Results 1 to 9 of 9

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

  1. #1
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location

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

    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
    Attached Files Attached Files
    Greg

    Visit my website: http://gregmaxey.com

  2. #2
    Distinguished Lord of VBAX VBAX Grand Master Bob Phillips's Avatar
    Joined
    Apr 2005
    Posts
    25,453
    Location
    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).
    ____________________________________________
    Nihil simul inventum est et perfectum

    Abusus non tollit usum

    Last night I dreamed of a small consolation enjoyed only by the blind: Nobody knows the trouble I've not seen!
    James Thurber

  3. #3
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location
    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
    Attached Files Attached Files
    Greg

    Visit my website: http://gregmaxey.com

  4. #4
    VBAX Master Aflatoon's Avatar
    Joined
    Sep 2009
    Location
    UK
    Posts
    1,720
    Location
    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.
    Be as you wish to seem

  5. #5
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location
    Personally preference I suppose. I've used the intercept process before but prefer to just get rid of the X.

    Thanks!
    Greg

    Visit my website: http://gregmaxey.com

  6. #6
    VBAX Master Aflatoon's Avatar
    Joined
    Sep 2009
    Location
    UK
    Posts
    1,720
    Location
    AFAIK, you can't actually remove it, but only disable it.
    Be as you wish to seem

  7. #7
    Knowledge Base Approver VBAX Wizard
    Joined
    Apr 2012
    Posts
    5,645
    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.

  8. #8
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location
    snb,

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

    Visit my website: http://gregmaxey.com

  9. #9
    Knowledge Base Approver VBAX Wizard
    Joined
    Apr 2012
    Posts
    5,645
    You might use your declaration section instead of mine

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •