【问题标题】:Hide close [X] button on excel vba userform for my progress bar在我的进度条的 excel vba 用户窗体上隐藏关闭 [X] 按钮
【发布时间】:2013-02-15 16:53:32
【问题描述】:

我创建了一个用户窗体来在宏仍在导入工作表时显示进度条

问题是用户可以按下红色的 [X] 按钮,该按钮将关闭并中断已完成的处理。

有没有办法隐藏这个厄运的红色按钮,这样潜在用户在它运行时就不会有任何令人困惑的按钮可以点击。

编辑:

我试过了

'Find the userform's Window
Private Declare Function FindWindow Lib "user32" _
        Alias "FindWindowA" ( _
        ByVal lpClassName As String, _
        ByVal lpWindowName As String) As Long

'Get the current window style
Private Declare Function GetWindowLong Lib "user32" _
        Alias "GetWindowLongA" ( _
        ByVal hWnd As Long, _
        ByVal nIndex As Long) As Long

'Set the new window style
Private Declare Function SetWindowLong Lib "user32" _
        Alias "SetWindowLongA" ( _
        ByVal hWnd As Long, _
        ByVal nIndex As Long, _
        ByVal dwNewLong As Long) As Long

Const GWL_STYLE = -16
Const WS_SYSMENU = &H80000

我在 userform_initialize 上使用了这个

   Dim hWnd As Long, lStyle As Long

   'Which type of userform
   If Val(Application.Version) >= 9 Then
      hWnd = FindWindow("ThunderDFrame", Me.Caption)
   Else
      hWnd = FindWindow("ThunderXFrame", Me.Caption)
   End If

   'Get the current window style and turn off the Close button
   lStyle = GetWindowLong(hWnd, GWL_STYLE)
   SetWindowLong hWnd, GWL_STYLE, (lStyle And Not WS_SYSMENU)

我收到此错误消息

此代码取自 here。我不知道我做错了什么,我已经删除了 cmets。这是我发现的最简单的代码,所以我想将它集成到我的用户表单中。任何帮助表示赞赏。

【问题讨论】:

  • 这个问题的答案是我的热门搜索结果。你有没有尝试过?
  • 更新了更多信息
  • 如果您打算这样做,您能否澄清并将“禁用”一词更改为“隐藏和禁用”?禁用该功能相对简单。隐藏它似乎不是。
  • @forums:你试过下面的代码了吗?
  • 要解决您在屏幕截图中显示的问题:将所有 API 声明移至模块顶部!

标签: excel userform vba


【解决方案1】:

你可以从下面的sn-ps算出来:

选择cmdClose 按钮 在菜单栏上,选择View | Code 在光标闪烁的地方,输入以下代码:

Private Sub cmdClose_Click()
  Unload Me
End Sub

在菜单栏上,选择View | Object,返回用户窗体。

允许用户按 Esc 键关闭表单:

选择 cmd 关闭按钮 在“属性”窗口中,将Cancel 属性更改为True

防止用户通过点击 X 按钮关闭表单

UserForm 打开时,右上角有一个X。除了使用关闭表单按钮之外,人们还可以使用 X 关闭表单。如果您想阻止这种情况,请按照以下步骤操作。

右键单击用户窗体的空白部分 选择View | Code 从右上方的“过程”下拉列表中,选择“查询关闭”

在光标闪烁的地方,粘贴以下示例中突出显示的代码

Private Sub UserForm_QueryClose(Cancel As Integer, _
  CloseMode As Integer)
  If CloseMode = vbFormControlMenu Then
    Cancel = True
    MsgBox "Please use the Close Form button!"
  End If
End Sub

在菜单栏上,选择View | Object,返回用户窗体。 现在,如果有人点击用户窗体中的X,他们就会看到您的消息。

来自http://www.contextures.com/xlUserForm01.html

【讨论】:

  • 我需要的是关闭按钮完全消失。当我用谷歌搜索它时,这是一个常见的答案,但我需要一种隐藏 [X] 标记的方法。
  • 隐藏按钮纯粹是为了美观。尽管如此,这个答案并没有隐藏按钮,而是禁用它,并且是最容易实现的(没有 API 的东西)。这是我最喜欢的解决方案。但是,“不要点击这里!”消息框过度设计。 UserForm_QueryClose 过程中所需的最少编码就是 Cancel = True
  • 更正我上面的评论:最小代码是If CloseMode = vbFormControlMenu Then Cancel = True。如果您解释 CloseMode,答案会更好。
【解决方案2】:

下面是一个可以这样调用的例程:

subRemoveCloseButton MyForm

或在您的表单中:

subRemoveCloseButton Me 

这是您需要的代码:

Private Const mcGWL_STYLE = (-16)
Private Const mcWS_SYSMENU = &H80000

'Windows API calls to handle windows
#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
#Else
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
#End If

#If VBA7 Then
    Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
#Else
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
#End If

#If VBA7 Then
    Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#Else
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#End If


Public Sub subRemoveCloseButton(frm As Object)
    Dim lngStyle As Long
    Dim lngHWnd As Long

    lngHWnd = FindWindow(vbNullString, frm.Caption)
    lngStyle = GetWindowLong(lngHWnd, mcGWL_STYLE)

    If lngStyle And mcWS_SYSMENU > 0 Then
        SetWindowLong lngHWnd, mcGWL_STYLE, (lngStyle And Not mcWS_SYSMENU)
    End If

End Sub

【讨论】:

  • 我需要添加一个Call DrawMenuBar(HWnd) 及其声明。声明也很混乱,不适用于 Office 64,请参阅jkp-ads.com/articles/apideclarations.asp
  • @amadeus:你需要 DrawMenuBar 做什么?哪个声明搞砸了? (我手头没有 64 位 Excel 可以测试...)谢谢!
  • 如果您在表单已经呈现(即不在 Userform_Initialize() 中)时调用 subRemoveCloseButton(),则菜单不会更改。在这种情况下,您必须调用 DrawMenuBar() 来重新渲染。至于 64 位支持,所有表示指针的 Long 值都必须替换为 LongPtr。例如 FindWindow() 确实返回 LongPtr,而不是 Long。 hwnd 参数也一样。
  • 注意:调用FindWindow(vbNullString, frm.Caption) 可能会发生,如果您的用户窗体与任何其他程序的窗口具有相同的标题,则它的 [x] 按钮将被删除,而不是用户窗体的 [x ] 按钮。我在将 FindWindow 绑定到 UserForms 并包括 x64 安全 API 调用下方发布了一个改进的函数。
【解决方案3】:

询问用户是否要关闭表单 - 并丢失编辑(比如说)。 基于贾斯汀和彼得的想法。

Private Sub UserForm_QueryClose(Cancel As Integer, _
                            CloseMode As Integer)
Dim ans
If CloseMode = vbFormControlMenu Then
    Cancel = True
    ans = Msgbox("Cancel edit?", vbQuestion + vbYesNo)
    If ans = vbYes Then
       Me.Hide
    End if
End If
End Sub

编辑:实际上我意识到这有点离题,因为 OP 想要删除 X 选项 - 但我仍然觉得这对于交互式表单很方便。

【讨论】:

    【解决方案4】:

    我知道这是一个老问题,但是对于 OP 引用的用户表单类型,您不必删除、隐藏或禁用关闭按钮。有一个更简单的方法;)

    对于没有用户交互的任何元素(按钮等)并且在完成其目的后会自行关闭的任何用户表单,只需禁用该表单即可。

    禁用用户表单: 在用户表单的属性中,针对 Enabled 设置 False。用户表单将显示,直到它的代码告诉它隐藏。用户将无法对表单执行任何操作(无法关闭、无法移动等)。

    另请注意,您是否希望用户能够在用户表单仍在显示时在主窗口中执行任何其他操作,这决定了您是否设置 ShowModal。

    【讨论】:

      【解决方案5】:

      这是对@Peter Albert 上述答案的改进

      • Windows API 调用现在是 Office x64 安全的
      • FindWindow 调用已改进为仅查找 Excel 用户窗体。原始答案中的函数搜索每个窗口类(例如资源管理器窗口和其他程序的窗口)。因此,当其他程序或资源管理器窗口的名称与用户窗体同名时,可能会删除 [x] 按钮。

      Private Const mcGWL_STYLE = (-16)
      Private Const mcWS_SYSMENU = &H80000
      
      'Windows API calls to handle windows
      Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
          ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
        
      #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
      #Else
          Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongA" ( _
              ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
          Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" ( _
              ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
      #End If
      
      Public Sub RemoveCloseButton(objForm As Object)
          Dim lngStyle As LongPtr
          Dim lngHWnd As LongPtr
          
          Dim lpClassName As String
          lpClassName = vbNullString
          If Val(Application.Version) >= 9 Then
             lpClassName = "ThunderDFrame"
          Else
             lpClassName = "ThunderXFrame"
          End If
          
          lngHWnd = FindWindow(lpClassName, objForm.Caption)
          lngStyle = GetWindowLongPtr(lngHWnd, mcGWL_STYLE)
      
          If lngStyle And mcWS_SYSMENU > 0 Then
              SetWindowLongPtr lngHWnd, mcGWL_STYLE, (lngStyle And Not mcWS_SYSMENU)
          End If
      End Sub
      

      ThunderDFrame?
      Excel中的UserForms其实是Windows类ThunderDFrame,是2002年以后微软Office应用程序中所有UserFroms的类,之前是ThunderXFrame

      【讨论】:

        【解决方案6】:

        禁用按钮的一种有用方法是执行以下操作:

        Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
            If CloseMode = 0 Then Cancel = True
        End Sub
        

        虽然这并没有摆脱按钮,但它确实让点击它什么都不做。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-07-23
          • 2013-09-06
          • 1970-01-01
          • 2013-01-21
          • 1970-01-01
          • 2019-04-23
          • 1970-01-01
          相关资源
          最近更新 更多