Announcement

Collapse
No announcement yet.

FindButtonInWindow with some kinks

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

  • #21
    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.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #22
      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.
      Norbert Doerre

      Comment


      • #23
        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

        Comment


        • #24
          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.
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #25
            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

            Comment


            • #26
              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
              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #27
                > 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
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #28
                  You're right, memo to self: read this

                  Comment

                  Working...
                  X