-
1 Attachment(s)
Get Msgbox's text?
I am working on a Routine to extract the text from a label on a Msgbox from another aplpication. The ultimate goal is to create a web-based interface for registering server scriptlets(through Scrobj.dll) on a server. I've used a variety of API's to shell out to RegSvr32.exe, but I need to retreive the result of any UI-based Error Messages. I can't use a batch file to spool output because I'd need someone sitting at the server to click the 'OK' button. (If I had that, then I might as well tell them to just manually register the scriptlet)
So far I've used EnumWindows to obtain a list of all the window handles, then GetClassName to get the window's class name, then once i find the class (Spy++ tells me that it's called "Static"), I call GetWindowText with the current handle, but it returns nothing.
I've also tried Using SendMessage, supplying the constants WM_GETTEXTLENGTH and WM_GETTTEXT, but they return nothing as well.
-
Try something along the lines of:
In a Module:
Code:
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 EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Const WM_GETTEXT = &HD
Private Const CONST_MSGBOX_CLASS = "#32770"
Private Const CONST_MSGBOX_TEXT = "Static"
Private lMsgHwnd As Long
Private sMsgText As String
Private bMsgBox As Boolean
Public Function GetMsgBoxText(ByRef sMsg As String) As Boolean
lMsgHwnd = 0
Call EnumWindows(AddressOf EnumWindowProc, 0&)
If lMsgHwnd = 0 Then Exit Function
sMsgText = ""
Call EnumChildWindows(lMsgHwnd, AddressOf EnumChildWindowProc, 0&)
GetMsgBoxText = True
sMsg = sMsgText
End Function
' Enumerate Top Level Windows looking for the Dialog Class
Private Function EnumWindowProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
Dim sClass As String
sClass = Space(255)
sClass = Left(sClass, GetClassName(hWnd, ByVal sClass, 255))
If LCase(Left(sClass, Len(CONST_MSGBOX_CLASS))) = LCase(CONST_MSGBOX_CLASS) Then
' When a potential Dialog is found verify it's a standard Msgbox style dialog.
If IsMsgBoxDialog(hWnd) Then
lMsgHwnd = hWnd
hWnd = 0
End If
End If
EnumWindowProc = hWnd
End Function
' Enumerate Child Windows Looking for the "Static" (Label) Class
' We want the 2nd Instance as the first is for the Icon. (Where there are more than one.)
Private Function EnumChildWindowProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
Dim sClass As String
sClass = Space(255)
sClass = Left(sClass, GetClassName(hWnd, ByVal sClass, 255))
If LCase(Left(sClass, Len(CONST_MSGBOX_TEXT))) = LCase(CONST_MSGBOX_TEXT) Then
sMsgText = Space(255)
sMsgText = Left(sMsgText, SendMessage(hWnd, WM_GETTEXT, 255, ByVal sMsgText))
' Don't Skip out of the Loop at this point, if there's an Icon, we want the
' 2nd Static Window, not the first which would be the Icon.
End If
EnumChildWindowProc = hWnd
End Function
' Check to see if Dialog qualifies as a regular "MsgBox" type Dialog
' Other applications, like Outlook Express use a "Dialog" class for other processes.
Private Function IsMsgBoxProc(ByVal hWnd As Long, ByVal lParam As Long) As Long
Dim sClass As String
Dim sCaption As String
' Extract the class name of this Child Window
sClass = Space(255)
sClass = Left(sClass, GetClassName(hWnd, ByVal sClass, 255))
' If it's a Button Class, see if it's Caption qualifies as a Msgbox button caption
If InStr(LCase(sClass), "button") Then
sCaption = Space(255)
sCaption = Left(sCaption, SendMessage(hWnd, WM_GETTEXT, 255, ByVal sCaption))
If InStr(",OK,ABORT,RETRY,YES,NO,CANCEL,IGNORE,", "," & Replace(UCase(sCaption), "&", "") & ",") Then
hWnd = 0
bMsgBox = True
End If
End If
IsMsgBoxProc = hWnd
End Function
Private Function IsMsgBoxDialog(ByVal hWnd As Long) As Boolean
bMsgBox = False
Call EnumChildWindows(hWnd, AddressOf IsMsgBoxProc, 0&)
IsMsgBoxDialog = bMsgBox
End Function
Usage:
Code:
Private Sub Form_Load()
Timer1.Interval = 100
End Sub
Private Sub Timer1_Timer()
Dim sMsg As String
If GetMsgBoxText(sMsg) Then
Debug.Print sMsg
End If
End Sub
-
You Rule Dude!!!
I am very much now happy happy! :):D (yes I speak English)
This rocks!
Now I can just send it the terminate code and return the reslt in a web page! Awesome!
Any idea why it was that the GetWindow API's wouldn't work?
-
Re: Get Msgbox's text?
I am trying to close all open message boxes and i have adjusted the code to use a sendmessage to close the window if it's a message box, BUT it only seems to work IF the message box is another application. If the message box is in the calling application it does not appear to aork. Any ideas?