vba在打开时显示用户表单,隐藏工作表,但保留任务栏图标

Posted

技术标签:

【中文标题】vba在打开时显示用户表单,隐藏工作表,但保留任务栏图标【英文标题】:vba show userform upon opening, hide worksheet, but keep taskbar icon 【发布时间】:2017-03-06 11:49:22 【问题描述】:

我有一个在打开工作簿时打开的用户窗体。 Excel 也被隐藏,因此用户表单就是向用户显示的全部内容。

Private Sub Workbook_Open()
Application.Visible = False
UserForm1.Show vbModeless
End Sub

但是,这也会隐藏任务栏上的 Excel 图标,因此当用户点击离开用户表单时,除非使用 alt+tab 或关闭/最小化用户表单前面的其他窗口,否则他们无法返回。我不希望用户这样做,有些人甚至可能会尝试再次打开表单(假设它已关闭),导致重新打开提示和我也不想要的错误。

基本上,我需要用户窗体的任务栏上的图标。

一旦用户窗体关闭,我就拥有它以便 Excel 关闭

Unload UserForm1
Application.Quit

我在互联网上找到的有关此问题的示例并不能完全实现我想要做的事情。 将表单更改为最小化并以模式打开以将图标保留在任务栏中,并且不允许用户编辑工作表

Application.WindowState = xlMinimized
UserForm1.Show (1)

但这有两个问题.....第一个 - 用户表单没有成为焦点,第二个 - 用户可以单击任务栏图标并且工作表现在在用户表单后面可见,这不是我想要的他们能够做到。

【问题讨论】:

这个怎么样:***.com/questions/15949023/… 我刚刚尝试过,但它似乎没有做任何事情。我不熟悉类模块,所以它的实现可能有问题。我将它粘贴到用户窗体的新类模块中(右键单击>插入>类模块),保存并再次运行工作簿。 我知道问题中的解决方案不是直截了当的,但它非常看起来与您的问题重复。该问题中的代码位于 Userform 模块中 - 这实际上是一个类。 现在我在AppActivate ("Microsoft Excel") 行收到错误“无效的过程调用或参数” 【参考方案1】:

我在开发 Excel-Visio 应用程序的过程中花了相当多的时间在这个任务上,并面临同样的问题(Visio/Excel 和 VBA 编辑器上方的 Excel 表单被隐藏 - 但用户很容易失去焦点并且只能返回- Alt-Tabbing)。同样的问题!

我解决这个问题的算法是这样的(Userform 类中的所有代码):

Private Sub UserForm_Initialize()

    'some init's above
    ToggleExcel         'Toggle excel, all windows are hidden now!
    ActivateVisio       'Visio fired and on top
    SetStandAloneForm   'Let's customize form
End Sub

所以在启动时,我们就有了我们想要的 Visio 和 Form。在Terminate 事件上再次ToggleExcel 并最小化Visio。

ToggleExcel

Private Function ToggleExcel()
    Static IsVBEWasVisible As Boolean

    With Application
        If .Visible = True Then
            IsVBEWasVisible = .VBE.MainWindow.Visible
            If IsVBEWasVisible Then _
                    .VBE.MainWindow.Visible = False
            .WindowState = xlMinimized
            .Visible = False
        Else
            If IsVBEWasVisible Then _
                    .VBE.MainWindow.Visible = True
            .WindowState = xlMaximized
            .Visible = True
        End If
    End With
End Function

SetStandAloneForm

为了 SetStandAloneForm 我声明了这个 API 函数块:

#If VBA7 Then
    Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare PtrSafe Function SetFocus Lib "user32" (ByVal hWnd As Long) As Long
#Else
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (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 FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) 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 SetFocus Lib "user32" (ByVal hWnd As Long) As Long
#End If

实际SetStandAloneForm:

Private Function SetStandAloneForm()
    Const GWL_STYLE As Long = -16
    Const GWL_EXSTYLE As Long = -20
    Const WS_CAPTION As Long = &HC00000
    Const WS_MINIMIZEBOX As Long = &H20000
    Const WS_MAXIMIZEBOX As Long = &H10000
    Const WS_POPUP As Long = &H80000000
    Const WS_VISIBLE As Long = &H10000000
    Const WS_EX_DLGMODALFRAME As Long = &H1
    Const WS_EX_APPWINDOW As Long = &H40000
    Const SW_SHOW As Long = 5

    Dim Hwnd As Long
    Dim CurrentStyle As Long
    Dim NewStyle As Long

    If Val(Application.Version) < 9 Then
        Hwnd = FindWindow("ThunderXFrame", Me.Caption)  'XL97
    Else
        Hwnd = FindWindow("ThunderDFrame", Me.Caption)  '>XL97
    End If

    'Let's give to userform minimise and maximise buttons
    CurrentStyle = GetWindowLong(Hwnd, GWL_STYLE)
    NewStyle = CurrentStyle Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
    NewStyle = NewStyle And Not WS_VISIBLE And Not WS_POPUP
    Call SetWindowLong(Hwnd, GWL_STYLE, NewStyle)

    'Let's give to userform a taskbar icon
    CurrentStyle = GetWindowLong(Hwnd, GWL_EXSTYLE)
    NewStyle = CurrentStyle Or WS_EX_APPWINDOW
    Call SetWindowLong(Hwnd, GWL_EXSTYLE, NewStyle)
    Call ShowWindow(Hwnd, SW_SHOW)

End Function

【讨论】:

您的第三部分代码 (SetStandAloneForm) 位于何处?放入 Userform 类时会出现错误 @Demo,嘿,哪个错误?这个块可以放在任何你想要的地方(但在 API 函数的范围内),你只需要传递表单的 Caption 并替换里面的 Me.Caption 部分。 我将它们按顺序放置,因此我将其放在第一个框中代码的 End Function 之后和第三个代码框中的 Private Funtion ToggleExcel() 之前。错误是Compile Error: Only comments may appear after End Sub, End Function, End Property 想说Private Function SetStandAloneForm()抱歉 看来我们误会了。如果您的带有 api 函数('#if vba7...#end if')的位置块不在类/模块的顶部,则可能会发生此错误。你确定把它放在开头和后面的所有其他函数中吗?【参考方案2】:

Gareth 就这个问题发表的答案:

Excel Useform: How to hide application but have icon in the taskbar

努力给我一个任务栏图标,是一个简单的复制和粘贴。

感谢大家的帮助。

【讨论】:

【参考方案3】:

与其隐藏应用程序,不如将工作簿最小化:

ThisWorkbook.Windows(1).WindowState = xlMinimized

【讨论】:

对不起,我应该包括这个,因为我已经有了。问题是用户可以单击任务栏图标再次最大化工作表

以上是关于vba在打开时显示用户表单,隐藏工作表,但保留任务栏图标的主要内容,如果未能解决你的问题,请参考以下文章

适用于 Chrome 但不适用于 Safari - 一个隐藏的 DIV,仅在提交包含所有必填字段的表单时显示

vba日历控件只能在一个单元格用怎么办

向下滚动时隐藏导航栏并在用户使用 jquery 向上滚动页面时显示它,不能正常工作

如何在用户注销时隐藏侧边栏并在用户登录时显示侧边栏?

MFC下最大化时显示PC的任务栏

使用 VBA 保存时显示“是不是要覆盖文件”对话框