Search code examples
vb.netpopupwindow

How can I get properties of controls contained in a popup message box using VB.Net


I'm working on a VB.Net project where in part of it I catch a pop up message box when it's displayed and handle it in some way. My problem is that I have to know what buttons are included in this pop up window (their captions mainly). Is this possible? Can someone please tell me how this can be done? A sample would be much appreciated.

Thanks.

Update: Since I got a down vote, and Ed Cottrell told me that this is because of not adding any code related to my question. Now I have the answer to my question so I'm adding some code:

My app catches a pop-up window displayed by another windows application, I used EnumWindows API to know when a new pop-up window is displayed.

Public Declare Function EnumWindows Lib "User32.dll" (ByVal WNDENUMPROC As EnumWindowDelegate, ByVal lparam As IntPtr) As Boolean
Delegate Function EnumWindowDelegate(ByVal hWnd As IntPtr, ByVal Lparam As IntPtr) As Boolean

When I catch this window, I use its handle that I got from EnumWindows result and get its child windows using EnumChildWindows (which are the controls I'm looking for , since controls are kind of windows too):

APIs I used

    <DllImport("User32.dll")> _
    Public Function EnumChildWindows _
        (ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
        ByVal lParam As IntPtr) As Boolean
    End Function

    Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean

' Get window text length signature.
Public Declare Function SendMessage _
 Lib "user32" Alias "SendMessageA" _
 (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32

' Get window text signature.
Public Declare Function SendMessage _
 Lib "user32" Alias "SendMessageA" _
 (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As StringBuilder) As Int32

Structure ApiWindow

Public Structure ApiWindow
    Public MainWindowTitle As String
    Public ClassName As String
    Public hWnd As Int32
End Structure

Functions

Public Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
    Dim ChildrenList As New List(Of IntPtr)
    Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
    Try
        EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
    Finally
        If ListHandle.IsAllocated Then ListHandle.Free()
    End Try
    Return ChildrenList.ToArray
End Function

Public Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
    Dim ChildrenList As List(Of IntPtr) = GCHandle.FromIntPtr(Parameter).Target
    If ChildrenList Is Nothing Then Throw New Exception("GCHandle Target could not be cast as List(Of IntPtr)")
    ChildrenList.Add(Handle)
    Return True
End Function

Now when I have the handle of pop-up window (parentHandle), I can get its children windows:

Dim hndls() As IntPtr = GetChildWindows(parentHandle)
Dim window As ApiWindow

For Each hnd In hndls
    window = GetWindowIdentification(hnd)
    'Add Code Here 
Next

Where GetWindowIdentification is:

''' <summary>
''' Build the ApiWindow object to hold information about the Window object.
''' </summary>
Public Function GetWindowIdentification(ByVal hwnd As Integer) As ApiWindow

    Const WM_GETTEXT As Int32 = &HD
    Const WM_GETTEXTLENGTH As Int32 = &HE

    Dim window As New ApiWindow()

    Dim title As New StringBuilder()

    ' Get the size of the string required to hold the window title.
    Dim size As Int32 = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0)

    ' If the return is 0, there is no title.
    If size > 0 Then
        title = New StringBuilder(size + 1)

        SendMessage(hwnd, WM_GETTEXT, title.Capacity, title)
    End If

    ' Set the properties for the ApiWindow object.
    window.MainWindowTitle = title.ToString()
    window.hWnd = hwnd

    Return window

End Function

Solution

  • I found this answer on the net on another website, I thought I should share it in case someone sees this question in the future:

    Buttons are nothing but more windows. You just look for more child windows of the message box window you found. You can NOT just get the handle from a window and then try to cast it to a Form object and expect all the properties to work. It just doesn't work that way.