Excel 2013 Windows类名称

必须为我的VBA项目学习一点API,所以我正在试验。 interwebsbuild议这个代码应该在一个子工作,以find一个窗口句柄

Private Declare PtrSafe Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr Public Sub Test() Dim P As String P = Windows(1).Caption MsgBox P MsgBox FindWindowA("", P) End Sub 

当我运行这个代码的时候,打开一个带有“Book1.xlsm”标题的工作表,我得到“Book1.xlsm”,然后是“0”

我究竟做错了什么? 如果我尝试使用“EXCEL7”作为类名而不是空string,我会得到同样的结果。

感谢那些年龄更大,更聪明的人

以下讨论后添加….这不是一个真正的答案我的问题,因为它不知道为什么窗口无法通过FindWindowAfind(这就是它声称做的,因为我读它)但进一步的研究表明,我不能直接通过FindWindowA获得窗口句柄,但必须考虑到,他们可能是子窗口。 所以这个代码至less可以find我的窗口句柄:

 Private Declare Function FindWindow _ Lib "user32" _ Alias "FindWindowA" ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) _ As Long Private Declare Function FindWindowEx _ Lib "user32" _ Alias "FindWindowExA" ( _ ByVal hWnd1 As Long, _ ByVal hWnd2 As Long, _ ByVal lpsz1 As String, _ ByVal lpsz2 As String) _ As Long Dim hWndParent As Long, hWndDskTop As Long, hWndChild As Long, hWndMine As Long Sub Test() hWndParent = FindWindow("XLMAIN", vbNullString) hWndDskTop = FindWindowEx(hWndParent, 0&, "XLDESK", vbNullString) hWndMine = FindWindowEx(hWndDskTop, 0&, "EXCEL7", vbNullString) MsgBox hWndMine 

这就是我最初想要的Book1.xlsm的窗口句柄。

问题是,如果要在调用FindWindowA时忽略lpClassName,则需要将它传递给一个空指针。 尝试这个:

 Public Sub Test() Dim P As String P = Windows(1).Caption MsgBox P MsgBox FindWindowA(vbNullString, P) End Sub 

这实际上是一个完美的例子,为什么你应该使用vbNullString而不是“”来表示一个空string。 当使用“”时,编译器实际上构造一个长度为零的string并为其指定一个指针。 当你使用vbNullString时,你会得到一个通用的空string指针。 此代码演示:

 Public Sub StringAddresses() MsgBox StrPtr("") MsgBox StrPtr(vbNullString) End Sub 

编辑:这是困扰我,所以我做了一些挖掘,并findExcel使用的MDI窗口的类名称。 该代码应该返回在该类中注册的第一个窗口。 请注意,如果有多个窗口打开,这可能不会给你一个你之后的窗口:

 Public Sub Test() MsgBox FindWindowA("MS-SDIb", vbNullString) End Sub 

编辑2:不知道为什么花了这么长时间才发生 – 如果没有find您的标题,请将其设置为您的search字词(:facepalm :)。

 Private Sub Test() Dim hWnd As Long, cache As String cache = Windows(1).Caption Windows(1).Caption = "FindME!" hWnd = FindWindowA(vbNullString, "FindME!") Windows(1).Caption = cache Debug.Print hWnd End Sub 

您不应该在32位Office上使用FindWindowA的64位PtrSafe版本。 使用32位版本或使用编译器指令,以便工作簿和VBA项目将在32位和64位Office安装上工作。

 #If VBA7 Then Private Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" ( _ ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr #Else Private Declare Function FindWindow Lib "USER32" Alias "FindWindowA" ( _ ByVal lpClassName As String, ByVal lpWindowName As String) As Long #End If 

编译但我没有testing过这个操作。

附录:

经过testing,可以在32位和64位系统上运行:

 Debug.Print FindWindow("Notepad", vbNullString) ' works OK when Notepad is open 

给出这样的输出

 Order Level WindowText ClassName HWnd ParentHWnd ProcessID ParentProcessID ThreadID ModuleNameHWin EXENameProcess 1 0 «No Window Text 0» msvb_lib_tooltips 67334 67334 3000 2616 3592 C:\Windows\system32\MSCOMCTL.OCX Ed.exe 2 0 «No Window Text 0» msvb_lib_tooltips 67332 67334 3000 2616 3592 C:\Windows\system32\MSCOMCTL.OCX Ed.exe 3 0 «No Window Text 0» msvb_lib_tooltips 67330 67334 3000 2616 3592 C:\Windows\system32\MSCOMCTL.OCX Ed.exe 4 0 «No Window Text 0» msvb_lib_tooltips 67328 67334 3000 2616 3592 C:\Windows\system32\MSCOMCTL.OCX Ed.exe 5 0 «No Window Text 0» tooltips_class32 4195002 67334 2616 508 1924 C:\Windows\WinSxS\x86_microsoft.windows.common-controls_ 

级别是查看父/子窗口之间关系的选项卡数量。

 1 0 «No Window Text 0» msvb_lib_tooltips 2 1 «No Window Text 0» 

手段

 1 0 «No Window Text 0» msvb_lib_tooltips 2 1 «No Window Text 0» 

显示第2行是第1行的孩子

我用MsgBoxreplace插入到RTF控件使用TOM。

 Public Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long Public Declare Function GetWindowModuleFileName Lib "user32" Alias "GetWindowModuleFileNameA" (ByVal hwnd As Long, ByVal WinModule As String, StringLength As Long) As Long Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long ' Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long Private Declare Function CloseHandle Lib "Kernel32.dll" (ByVal Handle As Long) As Long Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long Private Type PROCESSENTRY32 dwSize As Long cntUsage As Long th32ProcessID As Long ' This process th32DefaultHeapID As Long th32ModuleID As Long ' Associated exe cntThreads As Long th32ParentProcessID As Long ' This process's parent process pcPriClassBase As Long ' Base priority of process threads dwFlags As Long szExeFile As String * 260 ' MAX_PATH End Type Private Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long '1 = Windows 95 2 = Windows NT szCSDVersion As String * 128 End Type Private Const PROCESS_QUERY_INFORMATION = 1024 Private Const PROCESS_VM_READ = 16 Private Const MAX_PATH = 260 Private Const STANDARD_RIGHTS_REQUIRED = &HF0000 Private Const SYNCHRONIZE = &H100000 'STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF Private Const PROCESS_ALL_ACCESS = &H1F0FFF Private Const TH32CS_SNAPPROCESS = &H2& Private Const hNull = 0 Private Const GW_CHILD = 5 Private Const GW_HWNDNEXT = 2 Sub Main() ' WindowChain = 0 Dim hwnd As Long hwnd = GetTopWindow(0) If hwnd <> 0 Then AddChildWindows hwnd, 0 End If End Sub Private Function AddChildWindows(ByVal hwndParent As Long, ByVal Level As Long) As String Dim gwfnhwnd As Long, X As Long, WT As String, CN As String, Length As Long, hwnd As Long, TID As Long, PID As Long, MN As String, Ret As Long, Parenthwnd As Long Static Order As Long Static FirstTime As Long Parenthwnd = hwndParent If Level = 0 Then hwnd = hwndParent Else hwnd = GetWindow(hwndParent, GW_CHILD) End If Do While hwnd <> 0 WT = Space(512) Length = GetWindowText(hwnd, WT, 508) WT = Left$(WT, Length) If WT = "" Then WT = Chr(171) & "No Window Text " & Err.LastDllError & Chr(187) CN = Space(512) Length = GetClassName(hwnd, CN, 508) CN = Left$(CN, Length) If CN = "" Then CN = "Error=" & Err.LastDllError TID = GetWindowThreadProcessId(hwnd, PID) MN = Space(512) Length = GetWindowModuleFileName(hwnd, MN, 508) If Length = 0 Then MN = Chr(171) & "Not Available Error=" & Err.LastDllError & Chr(187) Else MN = Left$(MN, Length) End If Dim f As Long, sname As String, PList As String, PPID As Long Dim hSnap As Long, proc As PROCESSENTRY32, Temp As String hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) If hSnap = hNull Then Exit Function proc.dwSize = LenB(proc) ' Iterate through the processes f = Process32First(hSnap, proc) Do If PID = proc.th32ProcessID Then sname = StrZToStr(proc.szExeFile) PPID = proc.th32ParentProcessID End If f = Process32Next(hSnap, proc) Loop While f = 1 Order = Order + 1 ' CStr(Order) & " HWnd=" & FormatNumber$(hwnd, 0, vbFalse, vbFalse, vbFalse) & " Parent HWnd=" & FormatNumber$(Parenthwnd, 0, vbFalse, vbFalse, vbFalse) & " Level=" & CStr(Level) & WT & " (" & CN & ")" & " PID=" & FormatNumber$(PID, 0, vbFalse, vbFalse, vbFalse) & " TID=" & FormatNumber$(TID, 0, vbFalse, vbFalse, vbFalse) & " Module Name:" & MN & " ExeName:" & sname & vbCrLf If FirstTime = 0 Then MsgBox vbCrLf & "Order" & vbTab & "Level" & vbTab & "WindowText" & vbTab & "ClassName" & vbTab & "HWnd" & vbTab & "ParentHWnd" & vbTab & "ProcessID" & vbTab & "ParentProcessID" & vbTab & "ThreadID" & vbTab & "ModuleNameHWin" & vbTab & "EXENameProcess" FirstTime = 1 End If MsgBox vbCrLf & CStr(Order) & vbTab & CStr(Level) & vbTab & WT & vbTab & CN & vbTab & CStr(hwnd) & vbTab & CStr(Parenthwnd) & vbTab & CStr(PID) & vbTab & CStr(PPID) & vbTab & CStr(TID) & vbTab & MN & vbTab & sname AddChildWindows hwnd, Level + 1 hwnd = GetWindow(hwnd, GW_HWNDNEXT) Loop End Function Function StrZToStr(S As String) As String StrZToStr = Left$(S, Len(S) - 1) End Function