获取Excel InputBox方法的hwnd

我想我有一个相当简单的问题。 我正在寻找一种方法来获得一个Excelinput框的HWND。 我正在自动化一个进程,我注意到一个8型input框一直在excel窗口下面(如果有帮助的话,我会从另一个应用程序自动执行excel)。 显然,我希望它显示在上面,我试图使用SetForegroundWindow函数。 有什么build议?

根据要求,我发现的唯一事情似乎值得尝试:

Public Function GetHwnd() as Long GetHwnd = Excel.Application.InputBox.hwnd End Function 

这不是一个简单的问题 – 而且答案是围绕着VBA中几个令人沮丧的空白。

VBA.InputBox函数创build一个“modal dialog”,在你需要VBA抓取窗口句柄并调用一些或其他API函数的时刻,应用程序的VBA代码处于等待状态。

当“模态”状态被释放时,允许VBA再次运行命令和API函数,InputBox已经消失。

幸运的是,'manish1239'在2003年10月发现了一个解决方法,他在Xtreme Visual Basic Talk上发表了一个巧妙的技巧:他把你需要运行的代码运行在VBA函数中,运行在等待状态,使用来自API定时器。

我使用他的代码在VBA InputBox中设置“PasswordChars”:这是一个需要InputBox窗口句柄的API调用,并且可以根据需要调整代码

公共函数InputBoxPassword(提示为string,_
                                 可选的默认为string= vbNullString,_
                                 可选的XPos,可选的YPos,_
                                 可选的HelpFile,可选的HelpContext _
                                  )作为string
在错误恢复下一步 

'复制用户的VBA InputBox函数的function
'键入的input显示为星号。 对话框的“标题”参数
在这个实现中,标题被硬编码为“需要密码”。

'REQUIRED函数:TimerProcInputBox
'需要的API声明:FindWindow,FindWindowEx,SetTimer,KillTimer

“Nigel Heffernan,2015年1月,

'**** **** **** ***此代码在公共领域**** **** **** ****

'基于用户'manish1239'在Xtreme Visual Basic Talk中发布的代码
'2003年10月http://www.xtremevbtalk.com/archive/index.php/t-112708.html

'编码注意:我们发送'Set PasswordChar'消息到文本框编辑
'VBA'InputBox'对话框中的窗口。 这不是一个简单的任务:
'InputBox是同步的,'modal dialog'离开了我们的应用程序
'在等待状态的VBA代码正好在我们需要调用发送
'消息API函数。 所以它通过API定时器的延迟callback来运行

'警告:在线发布的许多64位API声明不正确
'并且它们都不能用于指针安全的定时器API函数。

在错误恢复下一步

SetTimer 0&,0&,10&,AddressOf TimerProcInputBox

InputBoxPassword = InputBox(提示,_
PASSBOX_INPUT_CAPTION,_
默认,_
XPos,YPos,_
HelpFile,HelpContext)

结束function

#如果VBA7和Win64那么64位窗口下的64位Excel使用LongLong和LongPtr
'请注意,wMsg总是WM_TIMER消息,它符合Long
Public Sub TimerProcInputBox(ByVal hwnd As LongPtr,_
ByVal wMsg只要,_
ByVal idEvent As LongPtr,_
ByVal dwTime As LongLong)
在错误恢复下一步

 ' REQUIRED for Function InputBoxPassword ' https://msdn.microsoft.com/en-US/library/windows/desktop/ms644907(v=vs.85).aspx KillTimer hWndIbox, idEvent Dim hWndIbox As LongPtr ' Handle to VBA InputBox hWndIbox = FindWindowEx(FindWindow("#32770", PASSBOX_INPUT_CAPTION), 0, "Edit", "") If hWndIbox <> 0 Then SendMessage hWndIbox, EM_SETPASSWORDCHAR, Asc("*"), 0& End If End Sub 

#Else If VBA7 Then'VBA7 in 32-Bit Office'只能使用LongPtr

 Public Sub TimerProcInputBox(ByVal hwnd As LongPtr, _ ByVal wMsg As Long, _ ByVal idEvent As LongPtr, _ ByVal dwTime As Long) On Error Resume Next ' REQUIRED for Function InputBoxPassword ' https://msdn.microsoft.com/en-US/library/windows/desktop/ms644907(v=vs.85).aspx Dim hWndIbox As LongPtr ' Handle to VBA InputBox KillTimer hwnd, idEvent hWndIbox = FindWindowEx(FindWindow("#32770", PASSBOX_INPUT_CAPTION), 0, "Edit", "") If hWndIbox <> 0 Then SendMessage hWndIbox, EM_SETPASSWORDCHAR, Asc("*"), 0& End If End Sub 

#Else'32位Excel

 Public Sub TimerProcInputBox(ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal idEvent As Long, _ ByVal dwTime As Long) On Error Resume Next ' REQUIRED for Function InputBoxPassword ' https://msdn.microsoft.com/en-US/library/windows/desktop/ms644907(v=vs.85).aspx Dim hWndIbox As Long ' Handle to VBA InputBox KillTimer hwnd, idEvent hWndIbox = FindWindowEx(FindWindow("#32770", PASSBOX_INPUT_CAPTION), 0&, "Edit", "") If hWndIbox <> 0 Then SendMessage hWndIbox, EM_SETPASSWORDCHAR, Asc("*"), 0& End If End Sub 

#万一

您将需要以下声明:

选项显式
选件专用模块 

#如果VBA7和Win64那么64位窗口下的64位Excel使用LongLong和LongPtr

 Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _ (ByVal hWnd1 As LongPtr, _ ByVal hWnd2 As LongPtr, _ ByVal lpsz1 As String, _ ByVal lpsz2 As String _ ) 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 SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As LongPtr, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ ByRef lParam As Any _ ) As LongPtr Private Declare PtrSafe Function SetTimer Lib "user32" _ (ByVal hwnd As LongPtr, _ ByVal nIDEvent As LongPtr, _ ByVal uElapse As Long, _ ByVal lpTimerFunc As LongPtr _ ) As Long Public Declare PtrSafe Function KillTimer Lib "user32" _ (ByVal hwnd As LongPtr, _ ByVal nIDEvent As LongPtr _ ) As Long 

#Else If VBA7 Then'VBA7 in 32-Bit Office'只使用LongPtr,LongLong不可用

 Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" _ (ByVal hWnd1 As LongPtr, _ ByVal hWnd2 As LongPtr, _ ByVal lpsz1 As String, _ ByVal lpsz2 As String _ ) 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 SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As LongPtr, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ ByRef lParam As Any _ ) As LongPtr Private Declare PtrSafe Function SetTimer Lib "user32" _ (ByVal hwnd As LongPtr, _ ByVal nIDEvent As Long, _ ByVal uElapse As Long, _ ByVal lpTimerFunc As LongPtr) As LongPtr Private Declare PtrSafe Function KillTimer Lib "user32" _ (ByVal hwnd As LongPtr, _ ByVal nIDEvent As Long) As Long 

#Else'32位Excel

 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 Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ ByRef lParam As Any _ ) As Long Private Declare Function SetTimer Lib "user32" _ (ByVal hwnd As Long, _ ByVal nIDEvent As Long, _ ByVal uElapse As Long, _ ByVal lpTimerFunc As Long) As Long Public Declare Function KillTimer Lib "user32" _ (ByVal hwnd As Long, _ ByVal nIDEvent As Long) As Long 

#万一

Private Const PASSBOX_INPUT_CAPTION As String =“需要密码”
Private Const EM_SETPASSWORDCHAR As Long =&HCC
Private Const NV_INPUTBOX As Long =&H5000&

我把这个贴在我的博客Excellerando的标题下:

星号Galling:使用VBA InputBox()用于密码

一如往常,注意代码中不需要的换行符。