Vba 确定VBE是否打开

Vba 确定VBE是否打开,vba,excel,vbe,Vba,Excel,Vbe,我试图开发一个“自动运行”宏来确定VBE是否打开(不一定是焦点窗口,只是打开)。如果这是真的那么。。。采取一些行动 如果此宏连接到CommandButton,则它可以工作,但我无法使其在ThisWorkbook中的任何位置运行: Sub CloseVBE() 'use the MainWindow Property which represents ' the main window of the Visual Basic Editor - open the code windo

我试图开发一个“自动运行”宏来确定VBE是否打开(不一定是焦点窗口,只是打开)。如果这是真的那么。。。采取一些行动

如果此宏连接到CommandButton,则它可以工作,但我无法使其在ThisWorkbook中的任何位置运行:

Sub CloseVBE()
    'use the MainWindow Property which represents
    ' the main window of the Visual Basic Editor - open the code window in VBE,
    ' but not the Project Explorer if it was closed previously:
    If Application.VBE.MainWindow.Visible = True Then
        MsgBox ""
        'close VBE window:
        Application.VBE.MainWindow.Visible = False
    End If

End Sub
我被赋予以下功能来执行相同的操作,但我也无法使其工作:

Option Explicit

Private Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowText Lib "User32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "User32" Alias "GetWindowTextLengthA" (ByVal hWnd As Long) As Long
Private Declare Function GetWindow Lib "User32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long

Private Const GW_HWNDNEXT = 2

Function VBE_IsOpen() As Boolean

    Const appName       As String = "Visual Basic for Applications"

    Dim stringBuffer    As String
    Dim temphandle      As Long

    VBE_IsOpen = False

    temphandle = FindWindow(vbNullString, vbNullString)
    Do While temphandle <> 0
        stringBuffer = String(GetWindowTextLength(temphandle) + 1, Chr$(0))
        GetWindowText temphandle, stringBuffer, Len(stringBuffer)
        stringBuffer = Left$(stringBuffer, Len(stringBuffer) - 1)
        If InStr(1, stringBuffer, appName) > 0 Then
            VBE_IsOpen = True
            CloseVBE
        End If
        temphandle = GetWindow(temphandle, GW_HWNDNEXT)
    Loop

End Function

好消息:只需两个小改动即可使其在我的系统上正常工作(Win 8.1 x64上的Excel 2013 x86):

  • 注释掉有问题的行(!)
  • 在模块顶部添加以下声明:

    Private Declare Function UnhookWinEvent Lib "user32.dll" (ByVal hHook As Long)
    
Set x=y
将对象变量
x
设置为引用对象实例
y
。因此,它不能用于
Long
String
或其他非对象类型。这就是为什么在该行运行时会出现
所需对象
错误的原因。有关
Set
的详细信息,请参见的答案

另外,我不确定代码是从哪里获得的,但是如果
StopEventHook
函数起作用,那么错误行会使它成为一个不可操作的函数:

Public Sub StopEventHook(lHook As Long)
    Dim LRet As Long
    On Error Resume Next
    Set lHook = 0  '<<<- The error line --- throws away the input parameter!
    If lHook = 0 Then Exit Sub    ' ... then this always causes the Sub to exit.
    LRet = UnhookWinEvent(lHook)    

    Exit Sub ' note: don't need this; you can remove it if you want.
End Sub
公共子StopEventHook(lHook尽可能长)
暗淡的LRet尽可能长
出错时继续下一步

设置lHook=0'为什么不将此工作簿模块
工作簿打开事件一起使用

此工作簿中的代码
代码模块

 Private Sub Workbook_Open()         ' or...  Sub Workbook_Activate()
   ' checkIsVBEOpen
   If Application.VBE.MainWindow.Visible = True Then
      MsgBox "VBE window is open", vbInformation
      ' do something
      ' ...
      ' close VBE window
        Application.VBE.MainWindow.Visible = False
    Else
      MsgBox "VBE window is NOT open"   ' do nothing else
   End If
End Sub

解释“出错”的含义,包括整个错误消息。和格式化代码-高亮显示代码行,然后按ctrl+k或单击编辑工具栏上的
{}
按钮。这只是一个旁注,但如果不在WinProc中调用CallNextHookEx(),可能会终止钩子链。错误消息为:Object required。请理解,我对使用API的了解不多。这些功能位于“网络”上。我所说的“完全按照我的需要执行”是。。。如果焦点从工作表上移开,它将提供此类通知。我需要API代码来检测VBE是否有焦点或处于打开状态,并发出相同的通知。从此。。我可以用调用宏来代替通知,以执行后续所需的操作。有趣的问题。出于好奇,您为什么要这样做?谢谢您的回复。我正在运行Win 10/Excel 2007。代码“试图工作”,但这里有犹豫和崩溃。我决定使用一种不同的方法合并一个类似于T.M.T.M.下面列出的宏。感谢您的回复。我采纳了您的建议,并在其中添加了一个计时函数,将代码放在例程模块中。计时器根据需要检查并触发操作。再次感谢所有回复的人。我是否需要将此线程标记为“已解决”或类似的内容?如果是的话。。。如何?至于您的问题:SO邀请您将答案标记为已接受,并对有用或经过充分研究的答案进行投票,因为这可能也会帮助其他用户(参见)
Private Declare Function UnhookWinEvent Lib "user32.dll" (ByVal hHook As Long)
Public Sub StopEventHook(lHook As Long)
    Dim LRet As Long
    On Error Resume Next
    Set lHook = 0  '<<<- The error line --- throws away the input parameter!
    If lHook = 0 Then Exit Sub    ' ... then this always causes the Sub to exit.
    LRet = UnhookWinEvent(lHook)    

    Exit Sub ' note: don't need this; you can remove it if you want.
End Sub
 Private Sub Workbook_Open()         ' or...  Sub Workbook_Activate()
   ' checkIsVBEOpen
   If Application.VBE.MainWindow.Visible = True Then
      MsgBox "VBE window is open", vbInformation
      ' do something
      ' ...
      ' close VBE window
        Application.VBE.MainWindow.Visible = False
    Else
      MsgBox "VBE window is NOT open"   ' do nothing else
   End If
End Sub