posted December 15, 2002 09:20 AM
This is an attempt to demonstrate how EnumWindows and EnumChildWindows works
and how to get/change text in an other window not belonging to us.
We will try to get and change the text in PB/Win 7 - PB/CC 3
PowerBASIC COM Browser Interface Prefix textbox.
Have fun...
The starting point of this was http://www.powerbasic.com/support/forums/Forum4/HTML/004169.html
'Compiler: PB/Win 7.00
'WinApi: 2002/12/03
#COMPILE EXE
#DIM ALL
#INCLUDE "Win32Api.Inc"
'We will use this home brewed TYPE to send and extract info
'from both EnumWindowProc and EnumControl, since we can
'only send one LONG, we are going to use a pointer to a
'variable of this type.
TYPE EnumType
hndl AS DWORD
zClass AS ASCIIZ * %Max_Path
zCaption AS ASCIIZ * %Max_Path
id AS DWORD
hParent AS DWORD
count AS DWORD
END TYPE
'______________________________________________________________________________
'Retreive windows controls via class
FUNCTION EnumControl(BYVAL hWindowProc AS LONG, BYVAL lParam AS LONG) AS LONG
'---------------------------------------------------------------------------
'This function is called via the code line...
' EnumChildWindows EnumTry1.hndl, CODEPTR(EnumControl), Varptr(EnumTry2)
' EnumTry1.hndl refer to the parent window
' EnumTry2 is our variable to get/set info we need.
'The way it work is that Windows will do a kind of DO-LOOP with us,
'so this function will be executed many times by Windows,
'each time putting a new child (control) handle in the hWindowProc variable,
'the loop will continue until every child (control) handle
'are enumerated if the function return %True.
'If the function return %False then the enumeration
'is stopped, it's our job to set the Function to return
'%False when we have what we where searching for.
'The code in this function depend of what you want to achieve,
'usually it's retrieving handle, caption text, class, control id...
'---------------------------------------------------------------------------
LOCAL LenClass AS LONG
LOCAL LenCaption AS LONG
LOCAL zClass AS ASCIIZ * %Max_Path
LOCAL zCaption AS ASCIIZ * %Max_Path
LOCAL EnumTryPtr AS EnumType POINTER
STATIC Counter AS LONG
'Retreive the pointer of EnumTry2 so we can read and change it
EnumTryPtr = lParam
'Get the class of the control
LenClass = GetClassName(hWindowProc, zClass, %MAX_PATH)
'Get the text of the control
SendMessage hWindowProc, %WM_GETTEXT, %Max_Path, VARPTR(zCaption)
'Did we found our control class?
IF UCASE$(zClass) = UCASE$(@EnumTryPtr.zClass) THEN
INCR Counter 'We want the third Edit control
IF Counter = @EnumTryPtr.Count THEN 'Found the "Interface Prefix" text box
@EnumTryPtr.hndl = hWindowProc 'Put handle in EnumTry2
@EnumTryPtr.zCaption = zCaption 'Put caption in EnumTry2
@EnumTryPtr.zClass = zClass 'Put class in EnumTry2
@EnumTryPtr.id = GetDlgCtrlID(hWindowProc) 'Get the control id and put it EnumTry2
FUNCTION = %False : EXIT FUNCTION 'Stop enumeration and exit
END IF
END IF
FUNCTION = %True 'True, so Function will recall itself until last window found
END FUNCTION
'______________________________________________________________________________
'Retreive windows handle via caption
FUNCTION EnumWindowProc(BYVAL hWindowProc AS LONG, BYVAL lParam AS LONG) AS LONG
'---------------------------------------------------------------------------
'This function is called via the code line...
' EnumWindows CODEPTR(EnumWindowProc), Varptr(EnumTry1)
' EnumTry1 is our variable to get/set info we need.
'The way it work is that Windows will do a kind of DO-LOOP with us,
'so this function will be executed many times by Windows,
'each time putting a new window handle in the hWindowProc variable,
'The loop will continue until every window handle
'are enumerated if the function return %True.
'If the function return %False then the enumeration
'is stopped, it's our job to set the Function to return
'%False when we have what we where searching for.
'The code in this function depend of what you want to achieve,
'usually it's retrieving a window handle by it's caption text or class name.
'---------------------------------------------------------------------------
LOCAL zCaption AS ASCIIZ * %Max_Path
LOCAL zClass AS ASCIIZ * %Max_Path
LOCAL EnumTryPtr AS EnumType POINTER
LOCAL LenClass AS LONG
LOCAL LenCaption AS LONG
'Retreive the pointer of EnumTry1 so we can read and change it
EnumTryPtr = lParam
IF IsWindowVisible(hWindowProc) THEN 'Get only visible windows
IF GetParent(hWindowProc) = @EnumTryPtr.hParent THEN 'Under desktop if 0 or under parent
IF IsWindowEnabled(hWindowProc) THEN 'Get only enabled windows
LenClass = GetClassName (hWindowProc, zClass, %MAX_PATH) 'Get the class of the dialog
LenCaption = GetWindowText(hWindowProc, zCaption, %MAX_PATH) 'Get the caption of the dialog
'Did we found a dialog with our text?
IF UCASE$(zCaption) = UCASE$(@EnumTryPtr.zCaption) THEN
@EnumTryPtr.hndl = hWindowProc 'Put handle in EnumTry1
@EnumTryPtr.zCaption = zCaption 'Put caption in EnumTry1
@EnumTryPtr.zClass = zClass 'Put class in EnumTry1
FUNCTION = %False : EXIT FUNCTION 'Stop enumeration and exit
END IF
END IF
END IF
END IF
FUNCTION = %True 'True, so Function will recall itself until last window found
END FUNCTION
'______________________________________________________________________________
FUNCTION PBMAIN
LOCAL SomeText AS ASCIIZ * 50
LOCAL EnumTry1 AS EnumType
LOCAL EnumTry2 AS EnumType
'The dialog title that we want to find
EnumTry1.zCaption = "PowerBASIC COM Browser"
'Zero mean that we want a window under the desktop
EnumTry1.hParent = 0
'If window exist EnumTry will be filled with window handle
EnumWindows CODEPTR(EnumWindowProc), VARPTR(EnumTry1)
'EnumTry1.hndl <- Window handle
'EnumTry1.zCaption <- Window caption
'EnumTry1.zClass <- Window class
'Maybe we now have the window handle
IF EnumTry1.hndl THEN 'Not zero, so we found it
'We want a control with a "Edit" class
EnumTry2.zClass = "Edit"
'We want the third control with a "Edit" class
EnumTry2.count = 3 'Try it with one or two for other Edit control
'Start the search for controls
EnumChildWindows EnumTry1.hndl, CODEPTR(EnumControl), VARPTR(EnumTry2)
'Did we find it ?
IF EnumTry2.hndl THEN 'Not zero, so we found it
'EnumTry2.id <- Control ID
'EnumTry2.hndl <- Control handle
'EnumTry2.zClass <- Class name
'EnumTry2.zCaption <- Caption text
'Write text to this control
SomeText = "Play it again Sam... At " & TIME$
SendMessage EnumTry2.hndl, %WM_SETTEXT, 0 ,VARPTR(SomeText)
MSGBOX "Done!" & $CRLF & _
"The text was: " & $TAB & EnumTry2.zCaption & $CRLF & _
"The new text is: " & $TAB & SomeText & $CRLF & _
"Control handle is: " & $TAB & HEX$(EnumTry2.hndl) & " hex" & $CRLF & _
"Control id is: " & $TAB & FORMAT$(EnumTry2.id) & " dec" & $CRLF & _
"Control class is: " & $TAB & EnumTry2.zClass & $CRLF & _
"Window handle is: " & $TAB & HEX$(EnumTry1.hndl) & " hex" & $CRLF & _
"Window caption is: " & $TAB & EnumTry1.zCaption & $CRLF & _
"Window class is: " & $TAB & EnumTry1.zClass _
, %MB_ICONINFORMATION OR %MB_OK OR %MB_TOPMOST, SomeText
ELSE
MSGBOX "Sorry, edit control handle not found!" _
,%MB_ICONEXCLAMATION OR %MB_OK OR %MB_TOPMOST, "We have a problem !"
END IF
ELSE
MSGBOX "Did you started the ""PowerBASIC COM Browser"" ?" & $CRLF & _
"(In PB ide, Tool, PowerBASIC COM Browser)" _
, %MB_ICONQUESTION OR %MB_OK OR %MB_TOPMOST, "Handle not found!"
END IF
END FUNCTION
'______________________________________________________________________________
------------------
Pierre Bellisle
[This message has been edited by Pierre Bellisle (edited February 27, 2004).]