【问题标题】:Excel Useform: How to hide application but have icon in the taskbarExcel Userform:如何隐藏应用程序但在任务栏中有图标
【发布时间】:2014-09-04 04:23:51
【问题描述】:

我想要的是 Application.Visible = False,这样我的用户就看不到 excel/工作表,只能看到用户表单。

我已经通过使用此代码来实现这一点:

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

但是,这只会让用户窗体在后台浮动。我的用户将打开其他应用程序,我希望他们通过在任务栏上显示一个图标轻松更改为用户表单。

我在网上找到了以下示例,但我似乎找不到放置此代码的位置。对此仍然很陌生,所以希望我有适合这项工作的代码。如果我这样做,有人可以告诉我将它放在哪里,因为当我将它粘贴到我的代码中时它不起作用?

(即它应该放在“用户表单”或“此工作簿:声明”等下)

谢谢你,

Option Explicit
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
Private Const GWL_STYLE As Long = -16
Private Const GWL_EXSTYLE As Long = -20
Private Const WS_CAPTION As Long = &HC00000
Private Const WS_MINIMIZEBOX As Long = &H20000
Private Const WS_MAXIMIZEBOX As Long = &H10000
Private Const WS_POPUP As Long = &H80000000
Private Const WS_VISIBLE As Long = &H10000000
Private Const WS_EX_DLGMODALFRAME As Long = &H1
Private Const WS_EX_APPWINDOW As Long = &H40000
Private Const SW_SHOW As Long = 5

Private Sub UserForm_Activate()
Application.Visible = False
Application.VBE.MainWindow.Visible = False
    Dim lngHwnd As Long
    Dim lngCurrentStyle As Long, lngNewStyle As Long
    If Val(Application.Version) < 9 Then
        lngHwnd = FindWindow("ThunderXFrame", Me.Caption)  'XL97
    Else
        lngHwnd = FindWindow("ThunderDFrame", Me.Caption)  'XL2000, XP, 2003?
    End If
    'Set the Windows style so that the userform has a minimise and maximise button
    lngCurrentStyle = GetWindowLong(lngHwnd, GWL_STYLE)
    lngNewStyle = lngCurrentStyle Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
    lngNewStyle = lngNewStyle And Not WS_VISIBLE And Not WS_POPUP
    SetWindowLong lngHwnd, GWL_STYLE, lngNewStyle

    'Set the extended style to provide a taskbar icon
    lngCurrentStyle = GetWindowLong(lngHwnd, GWL_EXSTYLE)
    lngNewStyle = lngCurrentStyle Or WS_EX_APPWINDOW
    SetWindowLong lngHwnd, GWL_EXSTYLE, lngNewStyle
    ShowWindow lngHwnd, SW_SHOW
End Sub
Private Sub UserForm_Terminate()
Application.Visible = True
End Sub

【问题讨论】:

    标签: vba excel userform


    【解决方案1】:

    尝试将此代码放在用户表单代码模块中:

    Option Explicit
    
    'API functions
    Private Declare Function GetWindowLong Lib "user32" _
                                           Alias "GetWindowLongA" _
                                          (ByVal hwnd As Long, _
                                            ByVal nIndex As Long) 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 SetWindowPos Lib "user32" _
                                          (ByVal hwnd As Long, _
                                           ByVal hWndInsertAfter As Long, _
                                           ByVal X As Long, _
                                           ByVal Y As Long, _
                                           ByVal cx As Long, _
                                           ByVal cy As Long, _
                                           ByVal wFlags 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 GetActiveWindow Lib "user32.dll" _
                                             () As Long
    Private Declare Function SendMessage Lib "user32" _
                                         Alias "SendMessageA" _
                                         (ByVal hwnd As Long, _
                                          ByVal wMsg As Long, _
                                          ByVal wParam As Long, _
                                          lParam As Any) As Long
    Private Declare Function DrawMenuBar Lib "user32" _
                                         (ByVal hwnd As Long) As Long
    
    
    
    'Constants
    Private Const SWP_NOMOVE = &H2
    Private Const SWP_NOSIZE = &H1
    Private Const GWL_EXSTYLE = (-20)
    Private Const HWND_TOP = 0
    Private Const SWP_NOACTIVATE = &H10
    Private Const SWP_HIDEWINDOW = &H80
    Private Const SWP_SHOWWINDOW = &H40
    Private Const WS_EX_APPWINDOW = &H40000
    Private Const GWL_STYLE = (-16)
    Private Const WS_MINIMIZEBOX = &H20000
    Private Const SWP_FRAMECHANGED = &H20
    Private Const WM_SETICON = &H80
    Private Const ICON_SMALL = 0&
    Private Const ICON_BIG = 1&
    
    Private Sub AppTasklist(myForm)
    
    'Add this userform into the Task bar
        Dim WStyle As Long
        Dim Result As Long
        Dim hwnd As Long
        hwnd = FindWindow(vbNullString, myForm.Caption)
        WStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
        WStyle = WStyle Or WS_EX_APPWINDOW
        Result = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, _
                              SWP_NOMOVE Or _
                              SWP_NOSIZE Or _
                              SWP_NOACTIVATE Or _
                              SWP_HIDEWINDOW)
        Result = SetWindowLong(hwnd, GWL_EXSTYLE, WStyle)
        Result = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, _
                              SWP_NOMOVE Or _
                              SWP_NOSIZE Or _
                              SWP_NOACTIVATE Or _
                              SWP_SHOWWINDOW)
    
    End Sub
    
    Private Sub UserForm_Activate()
    
    Application.Visible = False
    Application.VBE.MainWindow.Visible = False
    AppTaskList Me
    
    End Sub
    
    Private Sub UserForm_Terminate()
    
    Application.Visible = True
    
    End Sub 
    

    免责声明:这不是我的代码,是在我不再有链接的论坛上找到的。

    【讨论】:

    • 感谢您的解决方案。我收到以下编译错误:“只有 cmets 可能出现在 End Sub、End Function 或 End Property 之后”。在添加您的代码之前,我没有出现此错误。我还从您的代码中删除了所有 cmets,但仍然没有,有什么想法吗?
    • 我刚刚对其进行了测试,它对我有用。确保将其放在模块的顶部,并且不要重复 Option Explicit 语句。
    • 我把我的代码弄得一团糟,试图让它工作。我会尝试重新检查它,以确保我没有任何令人困惑的东西(所以感谢您的测试)。你能和我确认一下'useform code module'是什么意思吗?我应该把它放在用户窗体和激活标签下吗?或者我应该创建一个新模块?对不起新手。
    • 在项目资源管理器窗口中右键单击用户窗体并选择查看代码,然后将该代码粘贴进去。
    • 谢谢你——我意识到我犯了一些愚蠢的家务错误。这就是为什么它不起作用。谢谢两位,高分。
    【解决方案2】:

    因此,您可能会注意到这不适用于 64 位版本的 excel。

    我通过在从here 获取的代码中添加条件来使其兼容。

    如果您想知道如何使 API 函数与 64 位版本的 Excel here 兼容,这是一篇可以帮助您完成的优秀文章。

    Option Explicit
    
    'API functions
    #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
        #Else
            Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongA" _
                (ByVal hWnd As LongPtr, _
                 ByVal nIndex As Long _
                ) As LongPtr
        #End If
    
        #If Win64 Then
            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 SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" _
                (ByVal hWnd As LongPtr, _
                 ByVal nIndex As Long, _
                 ByVal dwNewLong As LongPtr _
                ) As LongPtr
        #End If
    
        Private Declare PtrSafe Function SetWindowPos Lib "user32" _
            (ByVal hWnd As LongPtr, _
             ByVal hWndInsertAfter As LongPtr, _
             ByVal X As Long, ByVal Y As Long, _
             ByVal cx As Long, ByVal cy As Long, _
             ByVal wFlags As Long _
            ) As LongPtr
        Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
            (ByVal lpClassName As String, _
             ByVal lpWindowName As String _
            ) As LongPtr
        Private Declare PtrSafe Function GetActiveWindow Lib "user32.dll" () As Long
        Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal hWnd As LongPtr, _
             ByVal wMsg As Long, _
             ByVal wParam As Long, _
             lParam As Any _
            ) As LongPtr
        Private Declare PtrSafe Function DrawMenuBar Lib "user32" _
            (ByVal hWnd As LongPtr) As LongPtr
    
    #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
        Private Declare Function SetWindowPos Lib "user32" _
            (ByVal hWnd As Long, _
             ByVal hWndInsertAfter As Long, _
             ByVal X As Long, ByVal Y As Long, _
             ByVal cx As Long, ByVal cy As Long, _
             ByVal wFlags 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 GetActiveWindow Lib "user32.dll" () As Long
        Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal hWnd As Long, _
             ByVal wMsg As Long, _
             ByVal wParam As Long, _
             lParam As Any _
            ) As Long
        Private Declare Function DrawMenuBar Lib "user32" _
            (ByVal hWnd As Long) As Long
    
    #End If
    
    
    'Constants
    Private Const SWP_NOMOVE = &H2
    Private Const SWP_NOSIZE = &H1
    Private Const GWL_EXSTYLE = (-20)
    Private Const HWND_TOP = 0
    Private Const SWP_NOACTIVATE = &H10
    Private Const SWP_HIDEWINDOW = &H80
    Private Const SWP_SHOWWINDOW = &H40
    Private Const WS_EX_APPWINDOW = &H40000
    Private Const GWL_STYLE = (-16)
    Private Const WS_MINIMIZEBOX = &H20000
    Private Const SWP_FRAMECHANGED = &H20
    Private Const WM_SETICON = &H80
    Private Const ICON_SMALL = 0&
    Private Const ICON_BIG = 1&
    

    然后使用以下子程序:

    Private Sub UserForm_Activate()
        AddIcon    'Add an icon on the titlebar
        AddMinimizeButton   'Add a Minimize button to Userform
        AppTasklist Me    'Add this userform into the Task bar
    End Sub
    
    Private Sub AddIcon()
    'Add an icon on the titlebar
        Dim hWnd As Long
        Dim lngRet As Long
        Dim hIcon As Long
        hIcon = Sheet1.Image1.Picture.Handle
        hWnd = FindWindow(vbNullString, Me.Caption)
        lngRet = SendMessage(hWnd, WM_SETICON, ICON_SMALL, ByVal hIcon)
        lngRet = SendMessage(hWnd, WM_SETICON, ICON_BIG, ByVal hIcon)
        lngRet = DrawMenuBar(hWnd)
    End Sub
    
    Private Sub AddMinimizeButton()
    'Add a Minimize button to Userform
        Dim hWnd As Long
        hWnd = GetActiveWindow
        Call SetWindowLongPtr(hWnd, GWL_STYLE, _
                           GetWindowLongPtr(hWnd, GWL_STYLE) Or _
                           WS_MINIMIZEBOX)
        Call SetWindowPos(hWnd, 0, 0, 0, 0, 0, _
                          SWP_FRAMECHANGED Or _
                          SWP_NOMOVE Or _
                          SWP_NOSIZE)
    End Sub
    
    Private Sub AppTasklist(myForm)
    'Add this userform into the Task bar
        #If VBA7 Then
            Dim WStyle As LongPtr
            Dim Result As LongPtr
            Dim hWnd As LongPtr
        #Else
            Dim WStyle As Long
            Dim Result As Long
            Dim hWnd As Long
        #End If
    
        hWnd = FindWindow(vbNullString, myForm.Caption)
        WStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE)
        WStyle = WStyle Or WS_EX_APPWINDOW
        Result = SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, _
                              SWP_NOMOVE Or _
                              SWP_NOSIZE Or _
                              SWP_NOACTIVATE Or _
                              SWP_HIDEWINDOW)
        Result = SetWindowLongPtr(hWnd, GWL_EXSTYLE, WStyle)
        Result = SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, _
                              SWP_NOMOVE Or _
                              SWP_NOSIZE Or _
                              SWP_NOACTIVATE Or _
                              SWP_SHOWWINDOW)
    End Sub
    

    我尚未在 32 位版本的 excel 上对此进行测试,但它应该可以正常工作。

    【讨论】:

    • 这将在 64 位版本上引发类型不匹配,其中 FindWindow 返回 LongPtr 但在 AddIcon 中,hWnd 被声明为 Long 而不是 LongPtr
    猜你喜欢
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 2012-04-16
    • 2012-01-04
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    相关资源
    最近更新 更多