Announcement

Collapse
No announcement yet.

FindButtonInWindow with some kinks

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Chris Holbrook
    replied
    You're right, memo to self: read this

    Leave a comment:


  • Michael Mattias
    replied
    > getModuleFileName ( Curhwnd, szfile, SIZEOF(szfile)-1)

    That works with an hWnd? Doc says it needs a module handle.

    ???

    (Hint: GetWindowThreadProcessID, OpenProcess, EnumProcessModules, GetModuleFilename, CloseHandle)

    MCM

    Leave a comment:


  • Michael Mattias
    replied
    I am officially on vacation as of the close of business today (Friday).

    But I'll be honest, I've been on the glide path since about Tuesday.

    Sunday I leave for Arizona.. I used to go nearly every spring, but I have not been there for seven or eight years.

    While I haven't played a round of golf for about six years, I fully expect to get my score into double digits by the end of the trip. (And NOT on one of the 'executive-length' courses, either... I'm talking the 6500-yd+ things where you have battle the snakes and scorpions to recover that ball you pushed "just a little."

    Then of course, I will attend a couple of baseball games, read a book or two, lollygag at poolside and all the other good stuff.

    I think my blood pressure is already down twenty points just thinking about it.

    When I get back I'll once again be that cool and mellow guy you've come to know and love.

    MCM

    Leave a comment:


  • Chris Holbrook
    replied
    MCM I've added the other attributes as suggested.
    Aren't you on holiday?

    A nice free small icon set would help to improve this, anyone know of one?
    Code:
    ' build a treeview of windows on the desktop and their controls
    '
    ' Chris Holbrook Mar 2008
    #PBFORMS CREATED V1.51
    #COMPILE EXE
    #DIM ALL
    
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #IF NOT %DEF(%COMMCTRL_INC)
        #INCLUDE "COMMCTRL.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS END INCLUDES
    
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 =  101
    %IDC_TV      = 1003
    #PBFORMS END CONSTANTS
    
    #PBFORMS DECLARATIONS
    
    GLOBAL gdwOrigEditProc AS DWORD
    '-----------------------------------------------------------
    FUNCTION TreeViewInsertItem(BYVAL hTree AS DWORD, BYVAL hParent AS DWORD, sItem AS STRING) AS LONG
        LOCAL tTVItem   AS TV_ITEM
        LOCAL tTVInsert AS TV_INSERTSTRUCT
    
        IF hParent THEN
            tTVItem.mask      = %TVIF_CHILDREN OR %TVIF_HANDLE
            tTVItem.hItem     = hParent
            tTVItem.cchildren = 1
            TreeView_SetItem hTree, tTVItem
        END IF
    
        tTVInsert.hParent              = hParent
        tTVInsert.Item.Item.mask       = %TVIF_TEXT
        tTVInsert.Item.Item.pszText    = STRPTR(sItem)
        tTVInsert.Item.Item.cchTextMax = LEN(sItem)
    
        FUNCTION = TreeView_InsertItem(hTree, tTVInsert)
    END FUNCTION
    
    '-------------------------------------------------------------------------------------------------------
    FUNCTION MakeTV(hd AS DWORD, hTV AS DWORD, CurWnd AS DWORD, level AS LONG) AS DWORD
        LOCAL r, rUs AS rect
        LOCAL szbuf AS ASCIZ * 256
        LOCAL l, lvl  AS LONG
        LOCAL CurHwnd, child  AS DWORD
        LOCAL szclass, szTxt, szfile, szmsg AS ASCIIZ * 128
        DIM Length AS LONG, x AS LONG, y AS LONG
    
        curhwnd = curwnd
        lvl = level
        WHILE curhwnd <> 0
            L = GetWindowTextLength(CurHwnd)
            L = GetWindowText(CurHwnd, sztxt, L + 1)
            getclassName ( Curhwnd, szclass, SIZEOF(szclass)-1)
            getModuleFileName ( Curhwnd, szfile, SIZEOF(szfile)-1)
    '
            IF LEN(sztxt)   <> 0 THEN sztxt   = "id: "    + sztxt + " "
            IF LEN(szclass) <> 0 THEN szclass = "class: " + szclass + " "
            IF LEN(szfile)  <> 0 THEN szfile  = "file: "  + szfile
            szmsg = szclass + sztxt + szfile
    
            lvl = TreeViewInsertItem(hTV, level, TRIM$(szmsg))
    
            ' Looking now for the Window's child windows
            Child = GetWindow(CurHwnd, %GW_Child)
            IF Child <> 0 THEN MakeTV ( hd, hTV, Child, lvl)
            CurHwnd = GetWindow(CurHwnd, %GW_HwndNext) 'Keep looking
        WEND
    END FUNCTION
    '---------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
        LOCAL hTV AS DWORD
        LOCAL hW, hroot, lvl AS DWORD
        LOCAL x, y AS LONG
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                hTV = getdlgitem(CBHNDL, %IDC_TV)
                Hw = GetDesktopWindow()            'Get Desktop handle
                Hw = GetWindow(Hw, %GW_Child)
                lvl = TreeViewInsertItem(hTV, 0, "Desktop")
                mAKEtv ( CBHNDL, Htv, hw, lvl)
            
            CASE %WM_MOVE, %WM_SIZE
                DIALOG GET CLIENT CBHNDL TO x,y
                CONTROL SET SIZE CBHNDL, %IDC_TV, x-5, y - 5
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
    
                END SELECT
        END SELECT
    END FUNCTION
    '-------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Windows Treeview", 107, 96, 195, 225, %WS_POPUP OR %WS_CAPTION OR %WS_SYSMENU OR _
            %WS_THICKFRAME OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR  %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, _
            %WS_EX_CONTROLPARENT, TO hDlg
        CONTROL ADD "SysTreeView32", hDlg, %IDC_TV, "SysTreeView32_1", 5, 5, 185, 215, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _
            %TVS_HASBUTTONS OR %TVS_HASLINES OR %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS, %WS_EX_LEFT OR %WS_EX_CLIENTEDGE OR _
            %WS_EX_RIGHTSCROLLBAR
    #PBFORMS END DIALOG
    
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    
    '===============================================================
    FUNCTION PBMAIN()
        PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR %ICC_INTERNET_CLASSES)
    
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION

    Leave a comment:


  • Michael Mattias
    replied
    That's nice how you did the recursion.

    Maybe a couple of goodies to add for some ambitious person..

    If window text length is null, use literal "<No Text>" or something like that.

    For each window found and placed on the tree add a child node (or additional text) to show its classname.

    For super extra credit, show the EXE file associated with each top-level window's process.

    Leave a comment:


  • Chris Holbrook
    replied
    Of course, it is not just a 2-level structure, windows can have windows which have windows and controls are just, well, windows! So you have to use an appropriate methos of searching this tree structure. This bit of code gives a treeview. PB Win 8.04, PBForms friendly.

    Code:
    ' build a treeview of windows on the desktop and their controls
    '
    ' Chris Holbrook Mar 2008
    #PBFORMS CREATED V1.51
    #COMPILE EXE
    #DIM ALL
    
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #IF NOT %DEF(%COMMCTRL_INC)
        #INCLUDE "COMMCTRL.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS END INCLUDES
    
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 =  101
    %IDC_TV      = 1003
    #PBFORMS END CONSTANTS
    
    #PBFORMS DECLARATIONS
    
    GLOBAL gdwOrigEditProc AS DWORD
    '-----------------------------------------------------------
    FUNCTION TreeViewInsertItem(BYVAL hTree AS DWORD, BYVAL hParent AS DWORD, sItem AS STRING) AS LONG
        LOCAL tTVItem   AS TV_ITEM
        LOCAL tTVInsert AS TV_INSERTSTRUCT
    
        IF hParent THEN
            tTVItem.mask      = %TVIF_CHILDREN OR %TVIF_HANDLE
            tTVItem.hItem     = hParent
            tTVItem.cchildren = 1
            TreeView_SetItem hTree, tTVItem
        END IF
    
        tTVInsert.hParent              = hParent
        tTVInsert.Item.Item.mask       = %TVIF_TEXT
        tTVInsert.Item.Item.pszText    = STRPTR(sItem)
        tTVInsert.Item.Item.cchTextMax = LEN(sItem)
    
        FUNCTION = TreeView_InsertItem(hTree, tTVInsert)
    END FUNCTION
    
    '-------------------------------------------------------------------------------------------------------
    FUNCTION MakeTV(hd AS DWORD, hTV AS DWORD, CurWnd AS DWORD, level AS LONG) AS DWORD
        LOCAL r, rUs AS rect
        LOCAL szbuf AS ASCIZ * 256
        LOCAL l, lvl  AS LONG
        LOCAL CurHwnd, child  AS DWORD
        LOCAL  szT AS ASCIIZ * 128
        DIM Length AS LONG, x AS LONG, y AS LONG
    
        curhwnd = curwnd
        lvl = level
        WHILE CurhWnd <> 0
            L = GetWindowTextLength(CurHwnd)
            L = GetWindowText(CurHwnd, szT, L + 1)
            lvl = TreeViewInsertItem(hTV, level, TRIM$(szt))
    
            ' Looking now for the Window's child windows
            Child = GetWindow(CurHwnd, %GW_Child)
            IF Child <> 0 THEN MakeTV ( hd, hTV, Child, lvl)
            CurHwnd = GetWindow(CurHwnd, %GW_HwndNext) 'Keep looking
        WEND
    END FUNCTION
    '---------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
        STATIC hText, hTV AS DWORD
        LOCAL r AS rect
        STATIC intextbox AS pointapi
        LOCAL hW, hroot, lvl AS DWORD
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
            hTV = getdlgitem(CBHNDL, %IDC_TV)
            Hw = GetDesktopWindow()            'Get Desktop handle
            Hw = GetWindow(Hw, %GW_Child)
            lvl = TreeViewInsertItem(hTV, 0, "Desktop")
            mAKEtv ( CBHNDL, Htv, hw, lvl)
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
    
                END SELECT
        END SELECT
    END FUNCTION
    '-------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Windows Treeview", 107, 96, 195, 225, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT _
            OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD "SysTreeView32", hDlg, %IDC_TV, "SysTreeView32_1", 5, 5, 185, 215, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _
            %TVS_HASBUTTONS OR %TVS_HASLINES OR %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS, %WS_EX_LEFT OR %WS_EX_CLIENTEDGE OR _
            %WS_EX_RIGHTSCROLLBAR
    #PBFORMS END DIALOG
    
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    
    '===============================================================
    FUNCTION PBMAIN()
        PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR %ICC_INTERNET_CLASSES)
    
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION

    Leave a comment:


  • norbert doerre
    replied
    Happy vacations!

    Michael,
    first let me whish You happy vacations - and please - leave Your keyboard in Your office and avoid visiting computer shops there.

    You might imagine that i'm just not in vacation and have to work hard currently. I always regret granting time for a simple task like in this thread which reveals to a time consuming monster at the end.
    I always appreciate Your knowledge about Windows programming, while I dont really like Windows, coming from Unix programming. Im more interested in clear technical math solutions far from Windows, not in puzzleing.
    In the mean time however, I nevertheless will try out Your programming syntax and will have a deeper look behind the sceenes.

    Leave a comment:


  • Michael Mattias
    replied
    Then again, you don't HAVE to recurse if you are just looking for the text.

    In the callback, you can query the window class of the passed 'hWnd' (GetClassName() ; if it's "systab32" (or whatever the exact name is), you can query the number of tabs and get the 'tab text', or even start another child enumeration to find all the children of that tab control.

    Fior that matter, you can query for windows of class "button" and just ignore anything which is not a button.

    Or check to see if this button is a child of some specific target window or control (GetParent()).

    Depends how 'generic' or 'application-specific' you want to be. Lots of options if you just use the "Enum" functions.
    Last edited by Michael Mattias; 13 Mar 2008, 11:22 AM.

    Leave a comment:


  • Michael Mattias
    replied
    Well, if what you have ain't working, try it the way I wrote it. My method doesn't give a hoot about DDT SDK or DIALOG DOEVENTS or CurHwnd=0 loops.

    It's not like the CALL syntax I came up with is terribly complicated or anything.

    However, if you have to drill down more than one level (ie beyond simple parent-child) then that function has to be rewritten to recurse, which for sure I can't get to until I get back from vacation.

    MCM

    Leave a comment:


  • norbert doerre
    replied
    It is running...

    Michael,
    the following code finds the hWnd of any control inside a modeless systab control. This is why the function MUST contain 'Dialog DoEvents' in the loop.
    If it is not inserted the fucnction does not succeed.
    This code has become very small because i avoided to make it 'general'.
    So, if for instance the tab areas of the systab control don't have names You have either to scan all tabs by activating them in a loop with 'send' or to use their class name. In the current case I could identify the tab by it's name.
    Code:
    '-------------------------------------------------------------------------------------------------------
    ' FUNCTION FindButtonInWindow
    '-------------------------------------------------------------------------------------------------------
    Function FindButtonInWindow (sWndTitle As String, sTabName As String, sBtnText As String) As Dword
    	'Called by 'VCSetTextUseTextLayer'
    	'INPUT:	sWndTitle	= title of the dialog containing the systab control
    	'			sTabname		= Name of the systab page area containing the button
    	'			sBtnText		= Caption of the button to be searched for
    	'OUTPUT:	Handle of the control to be found
    	Local CurHwnd As Long
    	Local szT As Asciiz * 128
    	Local Length As Long
    	Local szTabName As Asciiz * 128
       Local szChkName As Asciiz * 128
    	Local i As Integer
    	On Error Resume Next
    	Function = 0
    	CurHwnd = GetDesktopWindow()             'Get Desktop handle
    	CurHwnd = GetWindow(CurHwnd, %GW_Child)  'Find Child Windows of Desktop
    	Do Until CurHwnd = 0
    		Dialog DoEvents 'Important to give some loop time
    		Length = GetWindowTextLength(CurHwnd)
    		Length = GetWindowText(CurHwnd, szT, Length + 1)
    		If InStr(szT, sWndTitle) Then 
    			szTabName = sTabName	'the name of the open tab area in SysTab Control
    			CurhWnd = FindWindow("", szTabName)
             szChkName = sBtnText 'the name of the text checkbox in SysTab Control
             CurhWnd = FindWindowEx(CurHwnd, 0, "", szChkName)
    			If CurHwnd Then Function = CurHwnd
           End If
           CurHwnd = GetWindow(CurHwnd, %GW_HwndNext) 'Keep looking
       Loop
    End Function

    Leave a comment:


  • Michael Mattias
    replied
    > either I did it wrong or there are a lot of nameless windows hanging around!

    You did it right. I, too, had a (large) bunch of nameless windows whilst testing the "EnumChildWindows" version I posted above.

    Leave a comment:


  • norbert doerre
    replied
    Chris,
    sorry for the following code looking weird!
    It's too late now to work it out for the forum. But I intended to show You that my first code is running fine finding the checkbox control in the Systab.
    I'll send the complete code tomorrow.
    I had to add some lines as You can see. It is in a very rough state.
    I marked these lines with '# at their end.
    The code to be deleted has a hyphen ' at the start of their lines.

    Code:
    '-------------------------------------------------------------------------------------------------------
    ' FUNCTION FindButtonInWindow
    '-------------------------------------------------------------------------------------------------------
    Function FindButtonInWindow(sWndTitle As String, sBtnText As String) As Dword
    	On Error Resume Next
    	Dim Btn As Long, CurHwnd As Dword, szT As Asciiz * 128
    	Dim Length As Long, x As Long, y As Long 
    	Function = 0
    	' Trying to find the handle of the View Code Button so that
    	' by clicking this program's button, we can see the code
    	' window for this form.
    	CurHwnd = GetDesktopWindow()             'Get Desktop handle
    	CurHwnd = GetWindow(CurHwnd, %GW_Child)  'Find Child Windows of Desktop
    	Do
    		If CurHwnd = 0 Then Exit Do          'No (more) matches found
    		' Find out how long the text in this window is
    		Length = GetWindowTextLength(CurHwnd)
    		Length = GetWindowText(CurHwnd, szT, Length + 1)
    		If InStr(szT, sWndTitle) Then 
    			debug "1", szT, sWndTitle, CurHwnd
    			MsgBox""
    			' The value of sWindowTitle was found in this Window's text
    			Local szTabName As Asciiz * 128  						'#
    			szTabName = "TxtAtbTab"										'#  the name of the open tab area in SysTab Control
    			CurhWnd = FindWindow("", szTabName)						'#
    			debug "2", szTabName, szTabName, CurHwnd     		'#
    			MsgBox""				                           		'#
             Local szChkName As Asciiz * 128  						'#
             szChkName = "Layer als Textlayer verwenden"			'#  the name of the text checkbox in SysTab Control
             CurhWnd = FindWindowEx(CurHwnd, 0, "", szChkName)	'#
    			debug "3", CurhWnd                           		'#
    			MsgBox""				                           		'#
    				
    '            CurHwnd = GetWindow(CurHwnd, %GW_Child)
    '            ' Looking now for the Window's child windows
    '            Do
    '                If CurHwnd = 0 Then Exit Function 'No (more) matches found
    '                ' Find out how long the text in this window is
    '                Length = GetWindowTextLength(CurHwnd)
    '                Length = GetWindowText(CurHwnd, szT, Length + 1)
    '                If InStr(szT, sBtnText) Then
    'debug "3", szT, sBtnText
    '                    ' This is the handle we want
    '                    '### Click(CurHwnd)            'Click the View Code Button
    '                    Function = CurHwnd
    '                    Exit Function                 'Exit the Sub
    '                End If
    '            CurHwnd = GetWindow(CurHwnd, %GW_HwndNext) 'Keep looking
    '            Loop
            End If
            CurHwnd = GetWindow(CurHwnd, %GW_HwndNext) 'Keep looking
        Loop
    End Function

    Leave a comment:


  • Chris Holbrook
    replied
    To look at this problem I built a treeview of the windows & controls. Don't quite understand it though, either I did it wrong or there are a lot of nameless windows hanging around! PB Win 8.04.

    Code:
    ' build a treeview of windows on the desktop and their controls
    '
    ' Chris Holbrook Mar 2008
    #PBFORMS CREATED V1.51
    #COMPILE EXE
    #DIM ALL
    
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #IF NOT %DEF(%COMMCTRL_INC)
        #INCLUDE "COMMCTRL.INC"
    #ENDIF
    #INCLUDE "PBForms.INC"
    #PBFORMS END INCLUDES
    
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 =  101
    %IDC_TV      = 1003
    #PBFORMS END CONSTANTS
    
    #PBFORMS DECLARATIONS
    
    GLOBAL gdwOrigEditProc AS DWORD
    '-----------------------------------------------------------
    FUNCTION TreeViewInsertItem(BYVAL hTree AS DWORD, BYVAL hParent AS DWORD, sItem AS STRING) AS LONG
        LOCAL tTVItem   AS TV_ITEM
        LOCAL tTVInsert AS TV_INSERTSTRUCT
    
        IF hParent THEN
            tTVItem.mask      = %TVIF_CHILDREN OR %TVIF_HANDLE
            tTVItem.hItem     = hParent
            tTVItem.cchildren = 1
            TreeView_SetItem hTree, tTVItem
        END IF
    
        tTVInsert.hParent              = hParent
        tTVInsert.Item.Item.mask       = %TVIF_TEXT
        tTVInsert.Item.Item.pszText    = STRPTR(sItem)
        tTVInsert.Item.Item.cchTextMax = LEN(sItem)
    
        FUNCTION = TreeView_InsertItem(hTree, tTVInsert)
    END FUNCTION
    
    '-------------------------------------------------------------------------------------------------------
    FUNCTION MakeTV(hd AS DWORD, hTV AS DWORD) AS DWORD
        LOCAL r, rUs AS rect
        LOCAL szbuf AS ASCIZ * 256
        LOCAL l, hroot, happ, hchild AS LONG
        LOCAL CurHwnd, child  AS DWORD
        LOCAL  szT AS ASCIIZ * 128
        DIM Length AS LONG, x AS LONG, y AS LONG
    
        getwindowrect(hD, rUS)  ' get rect of our edit control
    
        ' Trying to find the handle of the View Code Button so that
        ' by clicking this program's button, we can see the code
        ' window for this form.
        CurHwnd = GetDesktopWindow()            'Get Desktop handle
        hroot = TreeViewInsertItem(hTV, %NULL, "Desktop")
        CurHwnd = GetWindow(CurHwnd, %GW_Child)  'Find Child Windows of Desktop
        WHILE CurhWnd <> 0
            L = GetWindowTextLength(CurHwnd)
            L = GetWindowText(CurHwnd, szT, L + 1)
            happ = TreeViewInsertItem(hTV, hroot, TRIM$(szt))
    
            ' Looking now for the Window's child windows
            Child = GetWindow(CurHwnd, %GW_Child)
    
            WHILE Child <> 0
                IF child <> hd THEN ' don't do it to ourself
                    getclassname( Child, szbuf, SIZEOF(szbuf))
                    L = GetWindowTextLength(Child)
                    L = GetWindowText(Child, szT, L + 1)
                    hchild = TreeViewInsertItem(hTV, happ, TRIM$(szbuf + ":" + szt))
                END IF
                Child = GetWindow(Child, %GW_HwndNext) 'Keep looking
            WEND
            CurHwnd = GetWindow(CurHwnd, %GW_HwndNext) 'Keep looking
        WEND
    END FUNCTION
    '---------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
        STATIC hText, hTV AS DWORD
        LOCAL r AS rect
        STATIC intextbox AS pointapi
    
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
            hTV = getdlgitem(CBHNDL, %IDC_TV)
            mAKEtv ( CBHNDL, Htv)
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
    
                END SELECT
        END SELECT
    END FUNCTION
    '-------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Windows Treeview", 107, 96, 195, 225, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR _
            %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT _
            OR %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD "SysTreeView32", hDlg, %IDC_TV, "SysTreeView32_1", 5, 5, 185, 215, %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR _
            %TVS_HASBUTTONS OR %TVS_HASLINES OR %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS, %WS_EX_LEFT OR %WS_EX_CLIENTEDGE OR _
            %WS_EX_RIGHTSCROLLBAR
    #PBFORMS END DIALOG
    
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    
    '===============================================================
    FUNCTION PBMAIN()
        PBFormsInitComCtls (%ICC_WIN95_CLASSES OR %ICC_DATE_CLASSES OR %ICC_INTERNET_CLASSES)
    
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION

    Leave a comment:


  • norbert doerre
    replied
    Just coming back from that office needing 'remote access' to the Domus program hidden dialog. Well, I found out today that this it not a simple one but a systab control with one page only. I could get access to all buttons with my spy program.
    The unskilled persons there seem to see no problem with getting access to the checkbox after they saw that I could make the dialog temporary visible with my DDT Spy. The handles of the hoovered controls are visible, and parent info is also correct. But trying to get the handles in forward "GetWindow" mode (from parent to control Wnd) fails by 50%, because controls are not found, as I described yesterday.
    I know that it is not a good deal with systabs. But now i know at least what to search for.

    Leave a comment:


  • Michael Mattias
    replied
    Code:
    ' find_target_window.bas
    ' 03.12.08
    #COMPILE EXE
    #DIM    ALL
    
    
    #INCLUDE "Win32API.INC"
    
    TYPE EnumCHildParamType
        szSearchText AS ASCIIZ * 128
        hWndFound    AS LONG
    END TYPE
    
    
    FUNCTION PBMAIN () AS LONG
    
     LOCAL szParentText AS ASCIIZ * 128, szControlText AS ASCIIZ * 128, hWndStart AS LONG, hWndControl AS LONG
     
     LOCAL S AS STRING
    
     hWndStart     = GetDesktopWindow()
     szParentText   = "PB/Win IDE"
     szControlText  = "D:\Software_Development\pbwin80\work\Find_target_window.bas"
    
     CALL FindHandleToControlGivenParentWindowTextAndControlWindowText(hWndStart, szParentText, szControlText) TO hWndControl
     
     s  = USING$ ("Parent Text '&'" & $CRLF & "Child Text '&'" & $CRLF, szParentTExt, szControlText)
    
      IF ISTRUE hWndControl THEN
         s  = S & USING$ ("Target Window found handle is # ", hWndControl)
    
      ELSE
         s  = S & "target window not found"
      END IF
      MSGBOX S, %MB_ICONINFORMATION, "That wasn't so hard now, was it?"
    
    END FUNCTION
    
    ' returns: FALSE==> no such window found
    '          TRUE ==> handle to target window
    FUNCTION  FindHandleToControlGivenParentWindowTextAndControlWindowText _
        (hWndStart AS LONG, szparentText AS ASCIIZ, szControlText AS ASCIIZ) AS LONG
    
        LOCAL lparam AS LONG, iRet AS LONG, dwCbAddr AS DWORD
        LOCAL P AS EnumChildParamType , whWnd AS LONG
    
        p.szSearchText = szParentText
        p.hWndFound    = %NULL
        FUNCTION       = 0&             ' default ==> not found
    
        lparam   = VARPTR ( P)
        dwcbAddr = CODEPTR (EnumChildFunction)
    
        iRet  = EnumChildWindows (hWndStart, dwCbAddr, BYVAL lparam)
        ' The SDK doc for this function says TRUE= success, FALSE = failed.
        ' That is a little misleading.
        ' It returns TRUE if the enum completes; FALSE if it is terminated.
        ' If it returns FALSE here it was terminated because we got a match on the
        ' parent text which of course to us means "success."
        IF ISFALSE iRET THEN
                 P.szSearchText  = szControlText
                 WhWnd           = P.HwndFound
                 P.hWndFound     = %NULL
                 iret            = EnumChildWindows (whwnd, dwCbAddr, BYVAL lparam)
                 IF ISFALSE iRet THEN             ' we found our child window text, too!
                    FUNCTION =  P.hWndFound       ' will either be zero or not
                 END IF
        END IF  ' if we got a hit on the parent window text
    
    END FUNCTION
    
    
    FUNCTION EnumChildFunction (BYVAL hWnd AS LONG, P AS EnumChildParamType) AS LONG
    
       LOCAL szText AS ASCIIZ * %MAX_PATH, nChar AS LONG
    
       nChar = GetWindowText (hWnd, szText, SIZEOF(szText))
       IF lstrcmp (szText, P.szSearchText) = 0& THEN   ' use lstrcmpi for case-insensitive search
            P.HwndFound = hWnd
            FUNCTION    =  0
       ELSE
            FUNCTION    = %TRUE
       END IF
    
    END FUNCTION
    ' END OF FILE
    MCM

    Leave a comment:


  • Pierre Bellisle
    replied
    Chris is right,
    having both the dialog do/loop and control do/loop
    using the same "CurHwnd" variable will give strange result
    if a dialog with no valid button text is found via "InStr(szT, sWndTitle)"
    becose the GetWindow in the second loop will restart at zero...

    Other than this, the program run fine on my side too,
    anyway, here is a variation that does more checking
    and use 2 differents handles to avoid this problem.
    This routine also make sure that the control text come from a button

    Code:
    %MAX_CLASSNAME   = 256
    %MAX_CAPTIONNAME = 256
    %MAX_CONTROLNAME = 256
    '______________________________________________________________________________
     
    FUNCTION FindButtonInWindow(sDialog AS STRING, sButton AS STRING) AS DWORD
     LOCAL hDialogTry    AS DWORD
     LOCAL hControlTry   AS DWORD
     LOCAL zDialogTry    AS ASCIIZ * %MAX_CAPTIONNAME 
     LOCAL zButtonTry    AS ASCIIZ * %MAX_CONTROLNAME
     LOCAL zClass        AS ASCIIZ * %MAX_CLASSNAME
     LOCAL LenDialogTry  AS LONG
     LOCAL LenButtonTry  AS LONG
     
     hDialogTry = GetTopWindow(%HWND_DESKTOP)
     DO WHILE hDialogTry 
       LenDialogTry = GetWindowText(hDialogTry, zDialogTry, %MAX_CAPTIONNAME)
       IF LenDialogTry THEN
         IF LEFT$(UCASE$(zDialogTry), LenDialogTry) = UCASE$(sDialog) THEN
           hControlTry = GetWindow(hDialogTry, %GW_Child)
           DO WHILE hControlTry
             GetClassName(hControlTry, zClass, %MAX_CLASSNAME)
             IF LEFT$(UCASE$(zClass), 6) = "BUTTON" THEN
               LenButtonTry = GetWindowText(hControlTry, zButtonTry, %MAX_CONTROLNAME)             
               IF LEFT$(UCASE$(zButtonTry), LenButtonTry) = UCASE$(sButton) THEN
                 FUNCTION = hControlTry
                 EXIT, EXIT
               END IF
             END IF
             hControlTry = GetWindow(hControlTry, %GW_HWNDNEXT)
           LOOP
         END IF
       END IF
       hDialogTry = GetWindow(hDialogTry, %GW_HWNDNEXT) 
     LOOP
     
    END FUNCTION
    '______________________________________________________________________________

    Leave a comment:


  • Chris Holbrook
    replied
    Hm. bit suspicious that the parent and child loops use the same window handle.

    Leave a comment:


  • Michael Mattias
    replied
    Oh I see now. It was a programming error we couldn't find because there was insufficient code posted to compile and run. (Mr. Holbrook is far more accommodating than I).

    Still leaves valid the point re MSGBOX: not a good tool when debugging re-entrant code.

    Leave a comment:


  • norbert doerre
    replied
    Originally posted by colin glenn View Post
    This just became a never mind, my SDK broke on this machine.
    Chris, thanks for the hint!!!
    I'll try it out, but tomorrow. Local time is 23:50 now.
    My code is usually compiled to a DLL. May be that this might be the cause for some timing trouble. This is hard to find, hovever, at least without a real time DLL debugger. I will alternatively compile to an EXE and try it again. Just this makes programming interesting - at least for me.

    Leave a comment:


  • norbert doerre
    replied
    Originally posted by Michael Mattias View Post
    I'll bet the MSGBOX is affecting the Z-Order, which directly affects GetWindow() when HWND_NEXT is used.
    Change to the EnumChildWindows and/or replace MSGBOX with STDOUT or "something else"
    Michael, we misunderstood once again:
    I inserted the MSGBOXes only to achieve a proper result.
    As far as I found out in the mean time, only the upper one is necessary. The second one can be commented out. As soon as I aditionally comment out the upper one, the routine delivers a crippled result because the loop is stopped with a zero result after the first correct one was found. After uncommenting the MSGBOX I have just to click the OK button of the MSGBOX to get the next correct result and so on....
    When the desired Window is finally found by the first loop, the second loop is able to run without any delay, and the function's result is a proper and usable handle of the CheckBox.

    Leave a comment:

Working...
X