Link to home
Start Free TrialLog in
Avatar of Bruj
BrujFlag for United States of America

asked on

accessing a 3rd party's toolbarwindow32 from VBA

I am trying to control a running app from VBA.
I have it's handle, I have its name and I can place things in the "edit" fields.
What I have been trying to do is to press buttons on toolbarwindow32 toolbars.
I can even get is handle.
From my reading, the easiest way is using rect and press its center, but I cannot find how to get its rect.
Classname for the app is:Afx:00400000:8:00010013:00000000:000105CB
In the current running the handle is:0x0005044C (328780 dec)
The classname for toolbar is  toolbarwindow32 (I can enum and get the hwnd, but I am not sure WHICH toolbarwindow32 item I want, it lists 4) (using Wininspector, I know that it is currently the FIRST one with an hWnd of 132926)
First, HOW can I identify which toolbar is the correct one?
Next, how would I press one of the "buttons" on the toolbar?

Thanks in Advance!
Bruj
Avatar of Scott McDaniel (EE MVE )
Scott McDaniel (EE MVE )
Flag of United States of America image

Can you show the code you're using to get a handle on the app, and the code you're using to get a handle on that app's Toolbar?
Avatar of Bruj

ASKER

Here is some code I have been whittling together. I have taken snippets from anything that looked like it would work. It is true Frankenstien code. Sorry...

I have made this very generic and should allow testing with ANY program that has tollbarwindows. To do this, I have 3 inputbox for which Window to look for, How many buttons  the desired toolbar has (need to get this by running trough 1 time.... Need a better way to id the toolbar - Any ideas?
the 3rd box is to tell the program which button to push.
I am hopeing I might be able to create a routine that would be simple to call to press a toolbarwindow button with a syntax like
TB_PressButt(winapp,Toolbar,Button)

What I would LIKE, is:
1.) a reliable way to find WHICH toolbar, The method I am using does select the correct toolbar, but is not very robust or reliable (if there are 2 or more with the same # of buttons)
2.) way to IDENTIFY the correct button (I tried TB_getButtoninfo, TB_getButtoninfow and TB_getButtoninfoa, but could not get these to work)
3.) Press that button.
I am sure most of my issues are with the pointer, memory and retrieving the data, as this is the part that I least understand. Ofcourse, syntax of the sendmessage and the particular message code my also be wrong..

HELP!
Thanks!
Bruj

Option Compare Database

Option Explicit
Private Const WM_USER As Long = &H400
Private Const WM_COMMAND As Long = &H111
Private Const TB_BUTTONCOUNT As Long = (WM_USER + 24)
Private Const TB_GETBUTTON As Long = (WM_USER + 23)
Public Const TB_COMMANDTOINDEX As Integer = (WM_USER + 25)
Public Const TB_GETBUTTONTEXTA As Integer = (WM_USER + 45)
Public Const TB_GETBUTTONTEXTW As Long = (WM_USER + 75)
Public Const TB_GETBUTTONINFO As Long = (WM_USER + 65)
Private PlatformKnown As Boolean  ' have we identified the platform?
Private NTflag As Boolean    ' if so, are we NT family (NT, 2K,XP) or non-NT (9x)?
Public myBTNCnt As Integer
Public myBTNtoPress As Integer
Private Const TBSTATE_HIDDEN As Long = &H8

Private Type TrayMore
    SyshWnd As Long
    SysIconId As Long
End Type

Private Type TBBUTTON
    iBitmap As Long
    idCommand As Long
    fsState As Byte
    fsStyle As Byte
    bReserved1 As Byte
    bReserved2 As Byte
    dwData As Long
    iString As Long
End Type
Private fpHandle As Long    ' the foreign-process instance handle. When we want
' memory on NT platforms, this is returned to us by
' OpenProcess, and we pass it in to VirtualAllocEx.

Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, lParam As Any) As Long
Private TitleToFind As String
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, _
                                                                    ByVal lpString As String, _
                                                                    ByVal cch As Long) As Long
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _
                                                As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _
                                                                  ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Declare Function SendMessageS Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
                                                                 ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Declare Function FindWindowX Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
                                                                 ByVal hWnd2 As Long, ByVal lpsz1 As Long, ByVal lpsz2 As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
                                     (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function ReadProcessMemory Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function OpenProcess Lib "KERNEL32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function VirtualAllocEx Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function CreateFileMapping Lib "KERNEL32" Alias "CreateFileMappingA" (ByVal hFile As Long, ByVal lpFileMappigAttributes As Long, ByVal flProtect As Long, ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As Long, ByVal lpName As String) As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal lpDest As Long, ByVal lpSource As Long, ByVal cBytes As Long)
Private Declare Function MapViewOfFile Lib "KERNEL32" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long
Private Declare Function GetVersionEx Lib "KERNEL32" Alias "GetVersionExA" (LpVersionInformation As OSVERSIONINFO) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long



Public Const WM_GETTEXT = &HD
Const PROCESS_VM_OPERATION = &H8
Const PROCESS_VM_READ = &H10
Const PROCESS_VM_WRITE = &H20
Const MEM_RESERVE = &H2000&
Const MEM_COMMIT = &H1000&
Const PAGE_READWRITE = &H4
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const SECTION_QUERY = &H1
Const SECTION_MAP_WRITE = &H2
Const SECTION_MAP_READ = &H4
Const SECTION_MAP_EXECUTE = &H8
Const SECTION_EXTEND_SIZE = &H10
Const SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE

Const FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS
Public Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type
Public WIN As OSVERSIONINFO
Global MyButton As TBBUTTON, lResult As Long



Sub testTB()
    Dim mytitle As String
    Dim hparent As Long
    mytitle = InputBox("Input a window to find") 'Can be beginning, does not need to be full name
    myBTNCnt = InputBox("How many buttons are in this toolbar?")    ' I am using this to idenify which toolbar. I dont know HOW else to tell them apart. Not very good I know!
    myBTNtoPress = InputBox("Which Button to Press?")

    MsgBox FindWindowByTitle(mytitle)
    hparent = FindWindowByTitle(mytitle)
    EnumChildWindow hparent, 0   ' one call directly to list parent
    EnumChildWindows hparent, AddressOf EnumChildWindow, 0

End Sub

Function FindWindowByTitle(winTitle As String) As Long
'returns the handle of the top window
'with the title "winTitle"

    Dim t As Long

    'set public titletofind to wintitle
    TitleToFind = winTitle
    EnumWindows AddressOf FindWindowByTitlePROC, t
    'reset public titletofind
    TitleToFind = ""

    FindWindowByTitle = t

End Function


Function EnumChildWindow(ByVal hChild As Long, ByVal lParam As Long) As Long

    Dim wClass As String, wText As String
    Dim j As Integer
    Dim TBhWnd As Long
    Dim xpBuffer As Long
    Dim z1 As Variant
    Dim tbcount As Long
    Dim i As Long
    Dim TBBUTT As TBBUTTON

    wClass = Space(64)
    j = GetClassName(hChild, wClass, 63)
    wClass = Left(wClass, j)
    wText = Space(256)
    j = SendMessageS(hChild, WM_GETTEXT, 255, wText)
    wText = Left(wText, j)
    Debug.Print "Enum " & hChild; ", "; wClass;
    If Len(wText) Then Debug.Print ", """; wText; """";
    Debug.Print
    If wClass = "ToolbarWindow32" Then
        tbcount = SendMessageS(hChild, TB_BUTTONCOUNT, 0, 0)
        MsgBox "Button Count:" & tbcount

        If tbcount = myBTNCnt Then  'This will select the correct toolbar - Need to find buttoncount
            For i = 0 To tbcount - 1
                TBhWnd = hChild
                MsgBox i
                If i = myBTNtoPress Then
                    '*********************************************************************
                    'This is the part that I am failing on...
                    xpBuffer = drMemoryAlloc(hChild, 1024)

                    ' lResult = SendMessage(TBhWnd, TB_GETBUTTON, i, xpBuffer)
                    lResult = SendMessage(TBhWnd, TB_GETBUTTONINFO, i, xpBuffer)
                    MsgBox "lResult =" & lResult
                    '  drMemoryRead xpBuffer, VarPtr(i), Len(i)
                    '*********************************************************************
                End If



            Next

        End If
    End If
    EnumChildWindow = 1  ' Continue enumeration
End Function

Function FindWindowByTitlePROC(ByVal hwnd As Long, lParam As Long) As Boolean
'this is the callback function procedure..do not change order
' or type of parameters in the procedure definition

    If hwnd = 0 Then
        lParam = 0
        'stop enumerating
        FindWindowByTitlePROC = False
    End If

    'see if the Hwnd is the one with the title
    If UCase(GetCaption(hwnd)) Like UCase(TitleToFind) & "*" Then
        'set return value
        lParam = CLng(hwnd)
        'stop enumerating
        FindWindowByTitlePROC = False
    Else
        'continue enumerating (not found)
        FindWindowByTitlePROC = True
    End If

End Function
Function GetCaption(ByVal hwnd As Long) As String
'returns the caption of the window with handle "hwnd"

    Dim sTemp As String, c As Integer

    sTemp = String$(255, 0)
    c = GetWindowText(hwnd, sTemp, 256)

    GetCaption = Left$(sTemp, c)

End Function
Public Function drMemoryAlloc(ByVal xpWindow As Long, ByVal nBytes As Long) As Long
'
' Returns pointer to a share-able buffer (size nBytes) in target process
'   that owns xpWindow
'
    Dim xpThread As Long    ' target control's thread id
    Dim xpID As Long        '                  process id
    If WindowsNT Then
        xpThread = GetWindowThreadProcessId(xpWindow, xpID)
        drMemoryAlloc = VirtualAllocNT(xpID, nBytes)
    Else
        drMemoryAlloc = VirtualAlloc9X(nBytes)
    End If
End Function
Public Sub drMemoryRead(ByVal xpBuffer As Long, ByVal myBuffer As Long, ByVal nBytes As Long)
    If WindowsNT Then
        ReadProcessMemory fpHandle, xpBuffer, myBuffer, nBytes, 0
    Else
        CopyMemory myBuffer, xpBuffer, nBytes
    End If
End Sub
Public Function WindowsNT() As Boolean
' return TRUE if NT-like platform (NT, 2000, XP, etc)
    If Not PlatformKnown Then GetWindowsVersion
    WindowsNT = NTflag
End Function
Private Function VirtualAllocNT(ByVal fpID As Long, ByVal memSize As Long) As Long
    fpHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, fpID)
    VirtualAllocNT = VirtualAllocEx(fpHandle, ByVal 0&, ByVal memSize, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
End Function
Private Function VirtualAlloc9X(ByVal memSize As Long) As Long
    fpHandle = CreateFileMapping(&HFFFFFFFF, 0, PAGE_READWRITE, 0, memSize, vbNullString)
    VirtualAlloc9X = MapViewOfFile(fpHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0)
End Function
Public Sub GetWindowsVersion()
    WIN.dwOSVersionInfoSize = Len(WIN)
    If (GetVersionEx(WIN)) = 0 Then Exit Sub  ' in deep doo if this fails
    NTflag = (WIN.dwPlatformId = 2)
    PlatformKnown = True
End Sub

Open in new window

Avatar of Bruj

ASKER

BUMP
Also looking for good source of HOW to work with pointers in VBA, as that may be my issue.

Thanks,
Mc
Sorry about not following up on this.

I have no suggestions for this. I don't see how you can "click" a button in another application unless that application exposes it's own codebase to you through automation, but admittedly I've never really tried to do anything like this.

I'd suggest you click the Request Attention button to ask the Moderators to rezone this. Using API calls is much more common in VB 6 and other languages than it is in VBA, and the syntax is identical.
Have you tried the SendMessage API using

Const WM_KEYDOWN = &H100

something like

Untested

Dim r As Long
r = SendMessage(Handle, WM_KEYDOWN, vbkeyenter, 0)

Open in new window


Sid
Avatar of Bruj

ASKER

Does not work, as the toolbar does not have any shortcut keys:(
Any other ideas?
Thanks!
Shortcut keys?

But we don't need them...

How did you get the handle/hwnd value?

Can you show me the code that you tried to get the hwnd of the toolbar?

Sid
Avatar of Bruj

ASKER

OK, I am a little lost I guess.
Shortcut keys?
How do I control WHICH button to press?


How did you get the handle/hwnd value?

>Currently, very haphazardly. I am enumerating windows till it finds the application, then I am looking for the toolbar that has the correct button count (currently I have a couple input boxes, one asking for app name, one asking for button count and the other asking which button to press)

What is the proper way of finding the correct toolbar? As far as I can tell, there are no identifing way to look for it! I have looked at this with winspector and uuspy (I cant install SPY++ due to needing admin rights)


I am able to get the rectangle for each button, but not sure how to validate the button I want or how to press it.

This code should work with any app that has a toolbar (Class = "ToolbarWindow32")

Function EnumChildWindow is where all testing and attemps to get info are located


 
Option Explicit
Private Const WM_USER As Long = &H400
Private Const WM_COMMAND As Long = &H111
Private Const TB_BUTTONCOUNT As Long = (WM_USER + 24)
Private Const TB_GETBUTTON As Long = (WM_USER + 23)
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type


Public Const TB_COMMANDTOINDEX As Integer = (WM_USER + 25)
Public Const TB_GETBUTTONTEXTA As Integer = (WM_USER + 45)
Public Const TB_GETBUTTONTEXTW As Long = (WM_USER + 75)
Public Const TB_GETBUTTONINFO As Long = (WM_USER + 65)
Private Const TBIF_IMAGE As Long = &H1
Private Const TBIF_TEXT As Long = &H2

Private Const TBSTYLE_BUTTON As Long = &H0
Private Const TBSTYLE_SEP As Long = &H1
Private Const TBSTYLE_CHECK As Long = &H2
Private Const TBSTYLE_GROUP As Long = &H4
Private Const TBSTYLE_CHECKGROUP As Long = (TBSTYLE_GROUP Or TBSTYLE_CHECK)
Private Const TBSTYLE_DROPDOWN As Long = &H8
Private Const TBSTYLE_AUTOSIZE As Long = &H10
Private Const TBSTYLE_WHOLEDROPDOWN As Long = &H80    'IE5 only ?
Private Const TBSTYLE_TOOLTIPS As Long = &H100
Private Const TBSTYLE_FLAT As Long = &H800
Private Const TBSTYLE_LIST As Long = &H1000

Private Const TBSTATE_CHECKED As Long = &H1
Private Const TBSTATE_PRESSED As Long = &H2
Private Const TBSTATE_ENABLED As Long = &H4


Private Const TBSTYLE_EX_DRAWDDARROWS As Long = &H1

Private Const TB_SETSTATE As Long = (WM_USER + 17)
Private Const TB_GETSTATE As Long = (WM_USER + 18)
Private Const TB_ADDBUTTONS As Long = (WM_USER + 20)
Private Const TB_GETITEMRECT As Long = (WM_USER + 29)
Private Const TB_BUTTONSTRUCTSIZE As Long = (WM_USER + 30)
Private Const TB_SETBITMAPSIZE As Long = (WM_USER + 32)
Private Const TB_SETIMAGELIST As Long = (WM_USER + 48)
Private Const TB_SETBUTTONINFO As Long = (WM_USER + 66)
Private Const TB_SETEXTENDEDSTYLE As Long = (WM_USER + 84)
Private Const WM_KEYDOWN As Long = 256


Private PlatformKnown As Boolean  ' have we identified the platform?
Private NTflag As Boolean    ' if so, are we NT family (NT, 2K,XP) or non-NT (9x)?
Public myBTNCnt As Integer
Public myBTNtoPress As Integer
Private Const TBSTATE_HIDDEN As Long = &H8

Private Type TrayMore
    SyshWnd As Long
    SysIconId As Long
End Type

Private Type TBBUTTON
    iBitmap As Long
    idCommand As Long
    fsState As Byte
    fsStyle As Byte
    bReserved1 As Byte
    bReserved2 As Byte
    dwData As Long
    iString As Long
End Type
Private Type TBBUTTONINFO
    cbSize As Long
    dwMask As Long
    idCommand As Long
    iImage As Long
    fsState As Byte
    fsStyle As Byte
    cx As Integer
    lParam As Long
    pszText As Long
    cchText As Long
End Type
'Private fpHandle As Long    ' the foreign-process instance handle. When we want
' memory on NT platforms, this is returned to us by
' OpenProcess, and we pass it in to VirtualAllocEx.

Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, lParam As Any) As Long
Private TitleToFind As String
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, _
                                                                    ByVal lpString As String, _
                                                                    ByVal cch As Long) As Long
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _
                                                As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, _
                                                                  ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

'Declare Function SendMessageS Lib "user32" (ByVal hwnd As Long, _
 ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
'Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long


Declare Function FindWindowX Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
                                                                 ByVal hWnd2 As Long, ByVal lpsz1 As Long, ByVal lpsz2 As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" _
                                     (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function ReadProcessMemory Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function OpenProcess Lib "KERNEL32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function VirtualAllocEx Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function CreateFileMapping Lib "KERNEL32" Alias "CreateFileMappingA" (ByVal hFile As Long, ByVal lpFileMappigAttributes As Long, ByVal flProtect As Long, ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As Long, ByVal lpName As String) As Long
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Long, lpRect As RECT) As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal lpDest As Long, ByVal lpSource As Long, ByVal cBytes As Long)
Private Declare Function MapViewOfFile Lib "KERNEL32" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long
Private Declare Function GetVersionEx Lib "KERNEL32" Alias "GetVersionExA" (LpVersionInformation As OSVERSIONINFO) As Long
'Private Declare Function SendMessageA Lib "user32" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long

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 SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SendMessageS Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, _
                                                                        ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long




Public Const WM_GETTEXT = &HD
Const PROCESS_VM_OPERATION = &H8
Const PROCESS_VM_READ = &H10
Const PROCESS_VM_WRITE = &H20
Const MEM_RESERVE = &H2000&
Const MEM_COMMIT = &H1000&
Const PAGE_READWRITE = &H4
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const SECTION_QUERY = &H1
Const SECTION_MAP_WRITE = &H2
Const SECTION_MAP_READ = &H4
Const SECTION_MAP_EXECUTE = &H8
Const SECTION_EXTEND_SIZE = &H10
Const SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE

Const FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS
Public Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type
Public WIN As OSVERSIONINFO
Global MyButton As TBBUTTON, lResult As Long



Sub testTB()
    Dim mytitle As String
    Dim hparent As Long
    mytitle = InputBox("Input a window to find")    'Can be beginning, does not need to be full name
    myBTNCnt = InputBox("How many buttons are in this toolbar?")    ' I am using this to idenify which toolbar. I dont know HOW else to tell them apart. Not very good I know!
    myBTNtoPress = InputBox("Which Button to Press?")

    MsgBox FindWindowByTitle(mytitle)
    hparent = FindWindowByTitle(mytitle)
    EnumChildWindow hparent, 0   ' one call directly to list parent
    EnumChildWindows hparent, AddressOf EnumChildWindow, 0

End Sub

Function FindWindowByTitle(winTitle As String) As Long
'returns the handle of the top window
'with the title "winTitle"

    Dim t As Long

    'set public titletofind to wintitle
    TitleToFind = winTitle
    EnumWindows AddressOf FindWindowByTitlePROC, t
    'reset public titletofind
    TitleToFind = ""

    FindWindowByTitle = t

End Function


Function EnumChildWindow(ByVal hChild As Long, ByVal lParam As Long) As Long
    Dim tbButtinfo() As TBBUTTONINFO
    Dim atbButt() As TBBUTTON
    Dim tbRect() As RECT

    Dim wClass As String, wText As String
    Dim j As Integer
    Dim TBhWnd As Long
    Dim xpBuffer As Long
    Dim z1 As Variant
    Dim tbcount As Long
    Dim i As Long
    Dim tbButt As TBBUTTON
    Dim uTBBI As TBBUTTONINFO
    Dim aBuff(260) As Byte
    wClass = Space(64)
    j = GetClassName(hChild, wClass, 63)
    wClass = Left(wClass, j)
    wText = Space(256)
    j = SendMessageS(hChild, WM_GETTEXT, 255, wText)
    wText = Left(wText, j)
    Debug.Print "Enum " & hChild; ", "; wClass;
    If Len(wText) Then Debug.Print ", """; wText; """";
    Debug.Print
    If wClass = "ToolbarWindow32" Then

        tbcount = SendMessageS(hChild, TB_BUTTONCOUNT, 0, 0)
        MsgBox "Button Count:" & tbcount


        If tbcount = myBTNCnt Then  'This will select the correct toolbar - Need to find buttoncount
            Dim iIndex As Long
            Dim Results As Long
            Dim xpWindow As Long
            Dim bindex As Long
            Dim cnt As Long
            For i = 0 To tbcount - 1

                Dim rc As RECT
                bindex = i
                'Results = SendMessage(hChild, TB_GETITEMRECT, iIndex + 1, byref rc)

                xpWindow& = hChild
                xpBuffer& = drMemoryAlloc(xpWindow, Len(rc))
                SendMessage xpWindow, TB_GETITEMRECT, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(rc), Len(rc)
                drMemoryFree xpBuffer
                MsgBox "Upper Left" & rc.Left & "," & rc.Top & vbCr & _
                       "Lower Right:" & rc.Right & "," & rc.Bottom
                ReDim Preserve tbRect(i) As RECT
               tbRect(i) = rc
                '************************* Get Button Info 'Not working, but not crashing either!
                xpBuffer& = drMemoryAlloc(xpWindow, Len(uTBBI))
                SendMessage xpWindow, TB_GETBUTTONINFO, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(uTBBI), Len(uTBBI)
                drMemoryFree xpBuffer

                ReDim Preserve tbButtinfo(i) As TBBUTTONINFO
               tbButtinfo(i) = uTBBI


                MsgBox "Button info:" & uTBBI.cbSize & ",  " & uTBBI.dwMask & ",  " & uTBBI.idCommand & ",  " & uTBBI.iImage & ",  " & uTBBI.fsState & ",  " & uTBBI.fsStyle & ",  " & ",  " & uTBBI.cx & ",  " & uTBBI.lParam & ",  " & uTBBI.pszText & ",  " & uTBBI.cchText

                xpBuffer& = drMemoryAlloc(xpWindow, Len(tbButt))
                SendMessage xpWindow, TB_GETBUTTON, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(tbButt), Len(tbButt)
                drMemoryFree xpBuffer
               
                ReDim Preserve atbButt(i) As TBBUTTON
                atbButt(i) = tbButt


            Next
        End If
    End If
    EnumChildWindow = 1  ' Continue enumeration
End Function

Function FindWindowByTitlePROC(ByVal hwnd As Long, lParam As Long) As Boolean
'this is the callback function procedure..do not change order
' or type of parameters in the procedure definition

    If hwnd = 0 Then
        lParam = 0
        'stop enumerating
        FindWindowByTitlePROC = False
    End If

    'see if the Hwnd is the one with the title
    If UCase(GetCaption(hwnd)) Like UCase(TitleToFind) & "*" Then
        'set return value
        lParam = CLng(hwnd)
        'stop enumerating
        FindWindowByTitlePROC = False
    Else
        'continue enumerating (not found)
        FindWindowByTitlePROC = True
    End If

End Function
Function GetCaption(ByVal hwnd As Long) As String
'returns the caption of the window with handle "hwnd"

    Dim sTemp As String, c As Integer

    sTemp = String$(255, 0)
    c = GetWindowText(hwnd, sTemp, 256)

    GetCaption = Left$(sTemp, c)

End Function

Open in new window


I am using drmemory for controlling memory
It's code is below:
 
Option Explicit
Private PlatformKnown As Boolean ' have we identified the platform?
Private NTflag As Boolean ' if so, are we NT family (NT, 2K,XP) or non-NT (9x)?

Private fpHandle As Long ' the foreign-process instance handle. When we want
' memory on NT platforms, this is returned to us by
' OpenProcess, and we pass it in to VirtualAllocEx.

' We must preserve it, as we need it for read/write
' operations, and to release the memory when we've
' finished with it.

' For this reason, on NT/2K/XP platforms this module should only be used to
' interface with ONE TARGET PROCESS at a time. In the future I'll rewrite
' this as a class, which can handle multiple-targets, automatic allocation
' de-allocation, etc
'

'
'================== Platform Identification is necessary!
'
Public Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Public WIN As OSVERSIONINFO

Private Declare Function GetVersionEx Lib "KERNEL32" Alias "GetVersionExA" (LpVersionInformation As OSVERSIONINFO) As Long
'
'================== Win95/98 Process Memory functions
Private Declare Function CreateFileMapping Lib "KERNEL32" Alias "CreateFileMappingA" (ByVal hFile As Long, ByVal lpFileMappigAttributes As Long, ByVal flProtect As Long, ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As Long, ByVal lpName As String) As Long
Private Declare Function MapViewOfFile Lib "KERNEL32" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long
Private Declare Function UnmapViewOfFile Lib "KERNEL32" (lpBaseAddress As Any) As Long
Private Declare Function CloseHandle Lib "KERNEL32" (ByVal hObject As Long) As Long
'
'================== WinNT/2000 Process Memory functions
Private Declare Function OpenProcess Lib "KERNEL32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function VirtualAllocEx Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function WriteProcessMemory Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "KERNEL32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
'
'
'================== Common Platform
'
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long

Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal lpDest As Long, ByVal lpSource As Long, ByVal cBytes As Long)
Private Declare Function lstrlenA Lib "KERNEL32" (ByVal lpsz As Long) As Long
Private Declare Function lstrlenW Lib "KERNEL32" (ByVal lpString 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
Public Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long

' ----------
Const PAGE_READWRITE = &H4
Const MEM_RESERVE = &H2000&
Const MEM_RELEASE = &H8000&
Const MEM_COMMIT = &H1000&
Const PROCESS_VM_OPERATION = &H8
Const PROCESS_VM_READ = &H10
Const PROCESS_VM_WRITE = &H20
Const STANDARD_RIGHTS_REQUIRED = &HF0000
Const SECTION_QUERY = &H1
Const SECTION_MAP_WRITE = &H2
Const SECTION_MAP_READ = &H4
Const SECTION_MAP_EXECUTE = &H8
Const SECTION_EXTEND_SIZE = &H10
Const SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE
Const FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS


Public Function drMemoryAlloc(ByVal xpWindow As Long, ByVal nBytes As Long) As Long
'
' Returns pointer to a share-able buffer (size nBytes) in target process
' that owns xpWindow
'
Dim xpThread As Long ' target control's thread id
Dim xpID As Long ' process id
If WindowsNT Then
xpThread = GetWindowThreadProcessId(xpWindow, xpID)
drMemoryAlloc = VirtualAllocNT(xpID, nBytes)
Else
drMemoryAlloc = VirtualAlloc9X(nBytes)
End If
End Function

Public Sub drMemoryFree(ByVal mPointer As Long)
If WindowsNT Then
VirtualFreeNT mPointer
Else
VirtualFree9X mPointer
End If
End Sub

Public Sub drMemoryRead(ByVal xpBuffer As Long, ByVal myBuffer As Long, ByVal nBytes As Long)
If WindowsNT Then
ReadProcessMemory fpHandle, xpBuffer, myBuffer, nBytes, 0
Else
CopyMemory myBuffer, xpBuffer, nBytes
End If
End Sub

Public Sub drMemoryWrite(ByVal xpBuffer As Long, ByVal myBuffer As Long, ByVal nBytes As Long)
If WindowsNT Then
WriteProcessMemory fpHandle, xpBuffer, myBuffer, nBytes, 0
Else
CopyMemory xpBuffer, myBuffer, nBytes
End If
End Sub

Public Function WindowsNT() As Boolean
' return TRUE if NT-like platform (NT, 2000, XP, etc)
If Not PlatformKnown Then GetWindowsVersion
WindowsNT = NTflag
End Function

Public Function WindowsXP() As Boolean
' return TRUE only if XP
If Not PlatformKnown Then GetWindowsVersion
WindowsXP = NTflag And (WIN.dwMinorVersion <> 0)
End Function

Public Sub GetWindowsVersion()
WIN.dwOSVersionInfoSize = Len(WIN)
If (GetVersionEx(WIN)) = 0 Then Exit Sub ' in deep doo if this fails
NTflag = (WIN.dwPlatformId = 2)
PlatformKnown = True
End Sub

'============================================
' The NT/2000 Allocate and Release functions
'============================================

Private Function VirtualAllocNT(ByVal fpID As Long, ByVal memSize As Long) As Long
fpHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, fpID)
VirtualAllocNT = VirtualAllocEx(fpHandle, ByVal 0&, ByVal memSize, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
End Function

Private Sub VirtualFreeNT(ByVal MemAddress As Long)
Call VirtualFreeEx(fpHandle, ByVal MemAddress, 0&, MEM_RELEASE)
CloseHandle fpHandle
End Sub

'============================================
' The 95/98 Allocate and Release functions
'============================================

Private Function VirtualAlloc9X(ByVal memSize As Long) As Long
fpHandle = CreateFileMapping(&HFFFFFFFF, 0, PAGE_READWRITE, 0, memSize, vbNullString)
VirtualAlloc9X = MapViewOfFile(fpHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0)
End Function

Private Sub VirtualFree9X(ByVal lpMem As Long)
UnmapViewOfFile lpMem
CloseHandle fpHandle
End Sub

Public Function dmWindowClass(ByVal hWindow As Long) As String
Dim className As String, cLen As Long
className = String(64, 0)
cLen = GetClassName(hWindow, className, 63)
If cLen > 0 Then className = Left(className, cLen)
dmWindowClass = className
End Function

Open in new window


Stupid question (I hope or I total am missing the BIG picture!) the handle would change each and every time the application is run, from boot to boot and system to system , correct?
Its not like once I DO get the handle, I can code that handle in to code. I need to test for the tb handle each and every time.

Thanks!
Bruce
Stupid question (I hope or I total am missing the BIG picture!) the handle would change each and every time the application is run, from boot to boot and system to system , correct?
Its not like once I DO get the handle, I can code that handle in to code. I need to test for the tb handle each and every time.

You are right. The handle would change each time.

>Currently, very haphazardly. I am enumerating windows till it finds the application, then I am looking for the toolbar that has the correct button count (currently I have a couple input boxes, one asking for app name, one asking for button count and the other asking which button to press)

How are you enumerating windows?


What is the proper way of finding the correct toolbar? As far as I can tell, there are no identifing way to look for it! I have looked at this with winspector and uuspy (I cant install SPY++ due to needing admin rights)

Use FindWindow API to get the Handle of the Toolbar. But then it would have helped if you had spy++. Would have made the job lot easier...

What third party toolbar,Application is it? Is it something from a program that I can install on my laptop and experiment?

Sid
Avatar of Bruj

ASKER

How are you enumerating windows

Declares:
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent _
                                                As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

From Calling sub:

    EnumChildWindow hparent, 0   ' one call directly to list parent
    EnumChildWindows hparent, AddressOf EnumChildWindow, 0

Function EnumChildWindow(ByVal hChild As Long, ByVal lParam As Long) As Long
    Dim tbButtinfo() As TBBUTTONINFO
    Dim atbButt() As TBBUTTON
    Dim tbRect() As RECT

    Dim wClass As String, wText As String
    Dim j As Integer
    Dim TBhWnd As Long
    Dim xpBuffer As Long
    Dim z1 As Variant
    Dim tbcount As Long
    Dim i As Long
    Dim tbButt As TBBUTTON
    Dim uTBBI As TBBUTTONINFO
    Dim aBuff(260) As Byte
    wClass = Space(64)
    j = GetClassName(hChild, wClass, 63)
    wClass = Left(wClass, j)
    wText = Space(256)
    j = SendMessageS(hChild, WM_GETTEXT, 255, wText)
    wText = Left(wText, j)
    Debug.Print "Enum " & hChild; ", "; wClass;
    If Len(wText) Then Debug.Print ", """; wText; """";
    Debug.Print
    If wClass = "ToolbarWindow32" Then

        tbcount = SendMessageS(hChild, TB_BUTTONCOUNT, 0, 0)
        MsgBox "Button Count:" & tbcount


        If tbcount = myBTNCnt Then  'This will select the correct toolbar - Need to find buttoncount
            Dim iIndex As Long
            Dim Results As Long
            Dim xpWindow As Long
            Dim bindex As Long
            Dim cnt As Long
            For i = 0 To tbcount - 1

                Dim rc As RECT
                bindex = i
                'Results = SendMessage(hChild, TB_GETITEMRECT, iIndex + 1, byref rc)

                xpWindow& = hChild
                xpBuffer& = drMemoryAlloc(xpWindow, Len(rc))
                SendMessage xpWindow, TB_GETITEMRECT, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(rc), Len(rc)
                drMemoryFree xpBuffer
                MsgBox "Upper Left" & rc.Left & "," & rc.Top & vbCr & _
                       "Lower Right:" & rc.Right & "," & rc.Bottom
                ReDim Preserve tbRect(i) As RECT
               tbRect(i) = rc
                '************************* Get Button Info 'Not working, but not crashing either!
                xpBuffer& = drMemoryAlloc(xpWindow, Len(uTBBI))
                SendMessage xpWindow, TB_GETBUTTONINFO, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(uTBBI), Len(uTBBI)
                drMemoryFree xpBuffer

                ReDim Preserve tbButtinfo(i) As TBBUTTONINFO
               tbButtinfo(i) = uTBBI


                MsgBox "Button info:" & uTBBI.cbSize & ",  " & uTBBI.dwMask & ",  " & uTBBI.idCommand & ",  " & uTBBI.iImage & ",  " & uTBBI.fsState & ",  " & uTBBI.fsStyle & ",  " & ",  " & uTBBI.cx & ",  " & uTBBI.lParam & ",  " & uTBBI.pszText & ",  " & uTBBI.cchText

                xpBuffer& = drMemoryAlloc(xpWindow, Len(tbButt))
                SendMessage xpWindow, TB_GETBUTTON, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(tbButt), Len(tbButt)
                drMemoryFree xpBuffer
               
                ReDim Preserve atbButt(i) As TBBUTTON
                atbButt(i) = tbButt


            Next
        End If
    End If
    EnumChildWindow = 1  ' Continue enumeration
End Function

Use FindWindow API to get the Handle of the Toolbar
In this case, the parent has about 5-6 toolbars. From what I can see, there is no place to control which instance.
How would I call this to find the 2nd toolbar?
********************************************************************
Here is the output for Winspector

Properties for window 0x00020722
Item Value
Class Name ToolbarWindow32  
Text  
Rectangle 1395, 156, 1998, 190  
Size 603, 34  
Client Rectangle 0, 0, 580, 24  
Client Size 580, 24  
Styles WS_CHILD
WS_VISIBLE
WS_CLIPSIBLINGS
TBSTYLE_FLAT
TBSTYLE_WRAPABLE
CCS_NOMOVEY
CCS_NORESIZE
CCS_NOPARENTALIGN
CCS_NODIVIDER  
 StylesEx WS_EX_LEFT
WS_EX_LTRREADING
WS_EX_RIGHTSCROLLBAR  
 ID 59402  
 Properties Atom: #43288 0xFFFFFFFF (-1)  
 Class specific Total Rows 1
Window is Ansi
 Owner EXE c:\csg\acsr\XBOI.EXE  
 ********************************************************************

The program is an Customer Relations Manager call "ACSR" (Advanced Customer Service Representative)
Fat Chance I will be able to install that... lolzzz

With the limited scope, we will have to take it real slow :(

Here is the output for Winspector

To begin with Is the above output for 2nd toolbar? If yes then can I see a similar report for the other 5-6 toolbars?

Sid
ASKER CERTIFIED SOLUTION
Avatar of Bruj
Bruj
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bruj

ASKER

OK, I am able to click and activate the button!
Here is how I got that working:
Modified the EnumChildWindow() as noted below
Function EnumChildWindow(ByVal hChild As Long, ByVal lParam As Long) As Long
    Dim tbButtinfo() As TBBUTTONINFO
    Dim atbButt() As TBBUTTON
    Dim tbRect() As RECT

    Dim wClass As String, wText As String
    Dim j As Integer
    Dim TBhWnd As Long
    Dim xpBuffer As Long
    Dim z1 As Variant
    Dim tbcount As Long
    Dim i As Long
    Dim tbButt As TBBUTTON
    Dim uTBBI As TBBUTTONINFO
    Dim aBuff(260) As Byte
    wClass = Space(64)
    j = GetClassName(hChild, wClass, 63)
    wClass = Left(wClass, j)
    wText = Space(256)
    j = SendMessageS(hChild, WM_GETTEXT, 255, wText)
    wText = Left(wText, j)
    Debug.Print "Enum " & hChild; ", "; wClass;
    If Len(wText) Then Debug.Print ", """; wText; """";
    Debug.Print
    If wClass = "ToolbarWindow32" Then

        tbcount = SendMessageS(hChild, TB_BUTTONCOUNT, 0, 0)
        MsgBox "Button Count:" & tbcount


        If tbcount = myBTNCnt Then  'This will select the correct toolbar - Need to find buttoncount
            Dim iIndex As Long
            Dim Results As Long
            Dim xpWindow As Long
            Dim bindex As Long
            Dim cnt As Long
            For i = 0 To tbcount - 1

                Dim rc As RECT
                bindex = i
                'Results = SendMessage(hChild, TB_GETITEMRECT, iIndex + 1, byref rc)

                xpWindow& = hChild
                xpBuffer& = drMemoryAlloc(xpWindow, Len(rc))
                SendMessage xpWindow, TB_GETITEMRECT, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(rc), Len(rc)
                drMemoryFree xpBuffer
                MsgBox "Upper Left" & rc.Left & "," & rc.Top & vbCr & _
                       "Lower Right:" & rc.Right & "," & rc.Bottom
                ReDim Preserve tbRect(i) As RECT
                tbRect(i) = rc
                '************************* Get Button Info 'Not working, but not crashing either!
                xpBuffer& = drMemoryAlloc(xpWindow, Len(uTBBI))
                SendMessage xpWindow, TB_GETBUTTONINFO, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(uTBBI), Len(uTBBI)
                drMemoryFree xpBuffer

                ReDim Preserve tbButtinfo(i) As TBBUTTONINFO
                tbButtinfo(i) = uTBBI


                MsgBox "Button info:" & uTBBI.cbSize & ",  " & uTBBI.dwMask & ",  " & uTBBI.idCommand & ",  " & uTBBI.iImage & ",  " & uTBBI.fsState & ",  " & uTBBI.fsStyle & ",  " & ",  " & uTBBI.cx & ",  " & uTBBI.lParam & ",  " & uTBBI.pszText & ",  " & uTBBI.cchText

                xpBuffer& = drMemoryAlloc(xpWindow, Len(tbButt))
                SendMessage xpWindow, TB_GETBUTTON, bindex, ByVal xpBuffer
                drMemoryRead xpBuffer, VarPtr(tbButt), Len(tbButt)
                drMemoryFree xpBuffer

                ReDim Preserve atbButt(i) As TBBUTTON
                atbButt(i) = tbButt
                If i = myBTNtoPress - 1 Then               '/added 1/20 Testing working for button press
                    lickToolbarButtonByIndex hChild, i      '/added 1/20 Testing working for button press
                End If                                     '/added 1/20 Testing working for button press




            Next
        End If
    End If
    EnumChildWindow = 1  ' Continue enumeration
End Function

Open in new window



Then added:
Private Sub ClickToolbarButtonByIndex(ByVal hToolbar As Long, ByVal lButtonIndex As Long) '/added 1/20 Testing working for button press

    Dim MyButton As TBBUTTON
    Dim xpBuffer As Long    ' Address of cross-process buffer.

    xpBuffer = drMemoryAlloc(hToolbar, 1024)
    SendMessageLong hToolbar, TB_GETBUTTON, lButtonIndex, xpBuffer
    drMemoryRead xpBuffer, VarPtr(MyButton), Len(MyButton)
    PostMessage GetParent(hToolbar), WM_COMMAND, MyButton.idCommand, hToolbar
    drMemoryFree xpBuffer

End Sub

Open in new window


In a NUTSHELL, this is what is REQUIRED, But I do have some of the initial issues. How to validate I have the correct toolbar, and how to ensure I have the correct button.
I "think" for the button, I can test atbButt(i).idCommand andsee if it =  10001  and then press that button. I have not experimented enough to confirm. Still which toolbar... <GRRRRRR>

Thanks for any and all help!

Any ideas?

Thanks!
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bruj

ASKER

Sid, Thank for your assistance. I think I probably should open a new question for the process if IDing the toolbar.
I DO think that the ID is what I want, but I dont see how to get it. There has to be a way.
Thanks for your help!