Home |
Search |
Today's Posts |
#1
Posted to microsoft.public.excel.programming
|
|||
|
|||
Get Tooltip Text, 3rd Party App
All,
Has anyone ever tried to get the tooltip text from a third party application's button? (I'm working with an application called "Research Wizard," but the code works just as well for Internet Explorer). I'm willing to post the code (which is rather lengthy) if someone feels they can help (but please read on to see if you think that you should reply to this post). [Besides, this post is rather lengthy to begin with, even without the code.] I am able to do the following (with help from a number of other posts): - Enumerate the windows to get the target window handle - Get the toolbar handle from the window handle - Count the number of buttons on the toolbar (for looping purposes) - Loop through each button - Click each button Despite being able to click the button, I can't seem to get the tooltip text for the button. To give you an idea of some of the APIs involved, I'm using the following: FindWindow EnumChildWindows GetClassName SendMessage OpenProcess VirtualAllocEx VirtualFreeEx ReadProcessMemory CloseHandle GetWindowThreadProcessId Here are some of the SendMessage wMsg arguments Im using: TB_BUTTONCOUNT TB_GETBUTTON WM_COMMAND TTM_ENUMTOOLS (trying to get this to work properly) TTM_GETTEXT (trying to get this to work properly) Structures used: TBBUTTON TOOLINFO I found a post that suggests sending TTM_ENUMTOOLS with a pointer to the TOOLINFO structure (Type TOOLINFO...End Type) and then passing TOOLINFO with TTM_GETTEXT to get lpszText. The post also mentioned that memory needs to be allocated that both processes can access. (Unfortunately, the post didn't provide any syntax, just the concept written down). I have been unsuccessful in this getting lpszText from TOOLINFO (despite being able to get TBBUTTON.idCommand or TBBUTTON.iString when sending TB_GETBUTTON). (Maybe the toolbar class I'm working with doesn't provide information for TOOLINFO). As an aside: This code (and the concept behind it) is completely new to me, and Ive had to do a lot of learning along the way. There is a lot of information that I'm still picking up. Let me know if you can help. Thanks, Matthew Herbert |
#2
Posted to microsoft.public.excel.programming
|
|||
|
|||
Get Tooltip Text, 3rd Party App
Matthew,
Here is an answer from, well, yourself. I'm sure that there will be others out there who will be looking to do the same sort of thing, i.e. going across process to get data from a third-party application. With a lot of researching and forum digging, I was able to come across some code to get tooltip text from a third-party application (depending on whether that application will actually return the text). The handle feeded to the function can be any handle, but if a TTM_GETTOOLCOUNT message (from SendMessage) returns a count, then there is a greater likelihood that the function below will return a tooltip text for the given tooltip handle and specified zero-based index for the tooltip class. (I have yet to comment the code, but may do so later). Enjoy, Matthew Herbert Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId 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 WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long 'last parameter data type changed from Any to 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 Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long Private Type TOOLINFO cbSize As Long uFlags As Long hWnd As Long uId As Long RC As RECT hInst As Long lpszText As Long 'String lParam As Long End Type Private Const PAGE_READWRITE As Long = &H4 Private Const MEM_RESERVE As Long = &H2000& Private Const MEM_RELEASE As Long = &H8000& Private Const MEM_COMMIT As Long = &H1000& Private Const PROCESS_VM_OPERATION As Long = &H8 Private Const PROCESS_VM_READ As Long = &H10 Private Const PROCESS_VM_WRITE As Long = &H20 Private Const WM_USER As Long = &H400& Private Const TTM_ENUMTOOLSA = (WM_USER + 14) Private Const TTM_ENUMTOOLSW = (WM_USER + 58) Private Const TTM_GETTEXTA As Long = (WM_USER + 11) Private Const TTM_GETTEXTW = (WM_USER + 56) Private Const LPSTR_TEXTCALLBACK As Long = -1 Private Const lngTEXTMAX As Long = 256 Function GetTooltipText(lngHwnd As Long, _ lngIndex As Long) As String Dim TI As TOOLINFO Dim lngPtrTI As Long Dim lngPtrTIText As Long Dim lngRes As Long Dim lngThreadId As Long Dim lngID As Long Dim lngProcess As Long Dim lngCnt As Long Dim lngCntBtn As Long Dim strText As String Dim bytArr() As Byte Dim lngPos As Long lngThreadId = GetWindowThreadProcessId(lngHwnd, lngID) lngProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, lngID) lngPtrTI = VirtualAllocEx(lngProcess, ByVal 0&, Len(TI), MEM_COMMIT Or MEM_RESERVE, PAGE_READWRITE) lngPtrTIText = VirtualAllocEx(lngProcess, ByVal 0&, lngTEXTMAX, MEM_COMMIT Or MEM_RESERVE, PAGE_READWRITE) With TI .cbSize = Len(TI) .lpszText = lngPtrTIText End With ReDim bytArr(lngTEXTMAX - 1) WriteProcessMemory lngProcess, ByVal lngPtrTI, TI, Len(TI), 0 WriteProcessMemory lngProcess, ByVal lngPtrTIText, bytArr(0), lngTEXTMAX, 0 lngRes = SendMessageLong(lngHwnd, TTM_ENUMTOOLSW, lngIndex, lngPtrTI) If lngRes 0 Then ReadProcessMemory lngProcess, ByVal lngPtrTI, TI, Len(TI), 0 If TI.lpszText = LPSTR_TEXTCALLBACK Then TI.lpszText = lngPtrTIText WriteProcessMemory lngProcess, ByVal lngPtrTI, TI, Len(TI), 0 SendMessageLong lngHwnd, TTM_GETTEXTW, ByVal lngTEXTMAX, ByVal lngPtrTI End If ReadProcessMemory lngProcess, ByVal lngPtrTIText, ByVal VarPtr(bytArr(0)), lngTEXTMAX, 0 strText = bytArr lngPos = InStr(1, strText, vbNullChar) If lngPos = 0 Then strText = strText Else strText = Left$(strText, lngPos - 1) End If End If VirtualFreeEx lngProcess, ByVal lngPtrTI, Len(TI), MEM_RELEASE VirtualFreeEx lngProcess, ByVal lngPtrTIText, lngTEXTMAX, MEM_RELEASE CloseHandle lngProcess GetTooltipText = strText End Function "Matthew Herbert" wrote: All, Has anyone ever tried to get the tooltip text from a third party application's button? (I'm working with an application called "Research Wizard," but the code works just as well for Internet Explorer). I'm willing to post the code (which is rather lengthy) if someone feels they can help (but please read on to see if you think that you should reply to this post). [Besides, this post is rather lengthy to begin with, even without the code.] I am able to do the following (with help from a number of other posts): - Enumerate the windows to get the target window handle - Get the toolbar handle from the window handle - Count the number of buttons on the toolbar (for looping purposes) - Loop through each button - Click each button Despite being able to click the button, I can't seem to get the tooltip text for the button. To give you an idea of some of the APIs involved, I'm using the following: FindWindow EnumChildWindows GetClassName SendMessage OpenProcess VirtualAllocEx VirtualFreeEx ReadProcessMemory CloseHandle GetWindowThreadProcessId Here are some of the SendMessage wMsg arguments Im using: TB_BUTTONCOUNT TB_GETBUTTON WM_COMMAND TTM_ENUMTOOLS (trying to get this to work properly) TTM_GETTEXT (trying to get this to work properly) Structures used: TBBUTTON TOOLINFO I found a post that suggests sending TTM_ENUMTOOLS with a pointer to the TOOLINFO structure (Type TOOLINFO...End Type) and then passing TOOLINFO with TTM_GETTEXT to get lpszText. The post also mentioned that memory needs to be allocated that both processes can access. (Unfortunately, the post didn't provide any syntax, just the concept written down). I have been unsuccessful in this getting lpszText from TOOLINFO (despite being able to get TBBUTTON.idCommand or TBBUTTON.iString when sending TB_GETBUTTON). (Maybe the toolbar class I'm working with doesn't provide information for TOOLINFO). As an aside: This code (and the concept behind it) is completely new to me, and Ive had to do a lot of learning along the way. There is a lot of information that I'm still picking up. Let me know if you can help. Thanks, Matthew Herbert |
Reply |
Thread Tools | Search this Thread |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Forum | |||
To show the whole text in a tooltip text | Excel Programming | |||
Change the tooltip text for a datapoint | Charts and Charting in Excel | |||
tooltip text | Links and Linking in Excel | |||
Tooltip text over a label | Excel Programming | |||
How to add Tooltip text to Treeview | Excel Programming |