WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Tutorials
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Control Manager - Windows Analysis

 Keywords: Windows Analysis Tutorial Control Manager

Windows Analysis - Tutorial

Window Analysis - Tutorial

How to enter text into an EditBox control

This tutorial is going to teach you how to write text into the EditBox (control) of Notepads 'File | Save As' dialog.

Step 1:

Before you begin writing the script, you will need to bring the dialog you are interested in interrogating, up on the screen. To launch Notepad, simply go to the Start Menu, select Run, and type notepad.exe. At this point Notepad should be launched and on the screen. (if not, please repeat step one)

Step 2:

Now that Notepad is launched and on the screen, we need to bring up the 'File | Save As' dialog. This can be done, by selecting the File menu, then select 'Save As' from the menu. At this point you should see a dialog, with the window title 'Save As' on the screen. (if not, please repeat steps one and two)

Step 3:

Now that the Notepad 'Save As' dialog is on the screen, we are ready to interrogate the dialog with the Windows Analyis Script.

What does the Windows Analysis script do?

The Windows Analysis script (analysis.wbt see below) creates a report on the windows visible at the time the report is run. The basic technique is to open the application and get the dialog boxes you are interested in displayed on the screen.

The Window Analysis script will display output detailing the contents of the window in question.

How do I use it?

Run the script, by double clicking on analysis.wbt (which is most likely located in the WinBatch\Samples subdirectory).

A dialog will appear that is asking you whether or not to ignore hidden windows. Generally you will choose Yes, which will only display visible windows. Press the Yes button on this dialog.

A dialog with all the visible window titles, will appear. Choose the window title 'Save As' from the dialog, then press Ok.

The Window Analysis script will process and output a dialog displaying Information about the Save As Window.

It will look some thing like this…

The Parent and Child columns display the sequence of the various controls in the Window. The rest of the columns display information about each control, such as: CLASS, ID, NAME, as well as other helpful information.

Step 4:

At this point the Windows Analysis' output should be on the screen. (if not, please repeat step three)

Explanation of the Windows Analysis output…

Information is listed by columns.

The parent and child columns will tell you where a particular control falls in the hierarchical scheme of things. Meaning, relationship of parent-to-child, and their sequential order.

CLASS column lists the 'types' of controls.

ID column lists each individual controls identifer. In other words, an id number that is associated to that particular control.

NAME column lists the title of the control, if any.

WNDSTYLE column lists the Window style.

WNDSTYLEEX column lists the Window extended style.

CLASSSTYLE column lists the Class style.

Step 5:

Now, that we understand the structure of the Windows Analysis output, a little better….

For this example, we are interested in six things, the top level parent, DUIViewWndClassName control, DirectUIHWND control, FloatNotifySync control, ComboBox control and Edit Control.

You will always need to get a handle to a top level parent window first. This can be done using the DLLHwnd function. As follows:

parentHwnd = DLLHwnd( 'Save As' )
DUIViewWndClassName, DirectUIHWND, FloatNotifySync and ComboBox (under the column heading CLASS) are important because we will need to get a handle to it in order to drill down to the Edit control.

Edit ( under the column heading CLASS) is important because that is the control that we want to fill in with the filename into Notepad.

The very first row of any Window Analysis script output should always contain information about the PARENT Window.

Now that we have a handle to the parent window using DllHwnd. We are interested in the Edit control.

You will notice the first GREEN column of that row is the Child5 column. What this tells you, is that the edit box control is the 5th child window in the list of sequential controls. The CLASS is Edit, which is the same as the type Edit. The ID number is 1001. And there is no TITLE, in this case.

It is important to know, that this control falls under the 5th child window in the list of sequential controls because, it tells us how far we need to 'drill down' to get the handle to the control. This will be explained more thoroughly at a later point.

Step 6:

Lets begin to write the script.

We are using the Control Manager extender, therefore we need to include the following statement, that adds the extender:

	AddExtender( 'WWCTL44i.DLL',0,'WWCTL64i.DLL' )
	
As mentioned previously, we first need to get a handle to the top level parent window. This can be done as follows:
	parentHwnd = DLLHwnd( 'Save As' )
	
Notice: the window TITLE, we handed to the function DLLHwnd is EXACTLY the same as, it is output by the Windows Analysis.

We now need to 'drill-down' to the control, using the cWndby__ functions.

What is meant by drill-down?

It means that we need to get a handle to every 'top-level' control, starting with the top level parent and working our way down through the child hierarchy. You can work down from the parent to the desired lower level 'child' window by using the cWndBy__ functions to do this.

Listed by ease-of-use (easiest/best choice to most complex):

	cWndById
	cWndByName
	cWndByClass
	cWndBySeq
	
First, I see if a window at a particular level has a unique ID. If so I prefer to use that. If two windows at the same level have the same ID, then I see if the window names (or titles) are different. If not, then I check the class of the windows. And finally resort to the sequence number of the window.

Since the control we are attempting to get the handle to, does not have a distinctive ID or NAME, we can then simply use the cWndbyClass function to drill down and retrieve the handle to the edit box control.

As you can see from the output the Edit control is buried under the DUIViewWndClassName, DirectUIHWND, FloatNotifySink and ComboBox controls. This means that we must first get handle to these controls. This can be done as follows:

C1 = cWndByClass ( parentHwnd, 'DUIViewWndClassName')
C2 = cWndByClass ( C1, 'DirectUIHWND')
C3 = cWndByClass ( C2, 'FloatNotifySink' )
C4 = cWndByClass ( C3, 'ComboBox' )
editHwnd = cWndByClass ( C4, 'Edit' )
We now have a handle to the editbox control. Using the function cSetEditText we can fill in the control with the file name, we would like to save the file as…
cSetEditText( editHwnd, 'C:\Temp\Test.txt')
At this point your code should read as follows:
AddExtender( 'wwctl44i.dll' )
parentHwnd = DllHwnd( 'Save As' )
C1 = cWndByClass ( parentHwnd, 'DUIViewWndClassName')
C2 = cWndByClass ( C1, 'DirectUIHWND')
C3 = cWndByClass ( C2, 'FloatNotifySink' )
C4 = cWndByClass ( C3, 'ComboBox' )
editHwnd = cWndByClass ( C4, 'Edit' )
cSetEditText( editHwnd, 'C:\Temp\Test.txt' )

Step 7:

Lets add to the script.

At this point we have the basic code that will get a handle to the 'Save As' dialog, then it gets a handle to the edit control and finally put the line 'C:\Temp\Test.txt' into the edit control.

There are a few more things we may want to add. For instance, we probably want our WinBatch script to launch Notepad, wait for the window to appear and bring up the 'Save As' dialog, automatically. The code to do this, looks like the following:

Run('notepad.exe','')
SendMenusTo('~Notepad','FileSaveAs')
WinWaitExist('Save As',5)
We have now completed the script. Here is what the completed script should look like:
AddExtender( 'wwctl44i.dll',0,'wwctl64i.dll' )
Run("notepad.exe","")
SendMenusTo("~Notepad","FileSaveAs")
WinWaitExist("Save As",5)
parentHwnd = DllHwnd( 'Save As' )
C1 = cWndbyclass ( parentHwnd, 'DUIViewWndClassName')
C2 = cWndbyclass ( C1, 'DirectUIHWND')
C3 = cWndbyclass ( C2, 'FloatNotifySink')
C4 = cWndbyclass ( C3, 'ComboBox' )
editHwnd = cWndbyclass ( C4, 'Edit' )
cSetEditText( editHwnd, 'C:\Temp\Test.txt' )
Exit


Analysis.wbt

;***************************************************************************
;**   Window Analysis Script
;**
;** This script creates a report on the windows visible at the time
;** the report is run.  Run the script.  Choose a top-level
;** window of interest, and it will show pertinent information
;** that may be necessary to use the Control Manager extender.
;**
;** Note that Tabbed dialogs sometimes must be displayed before
;** their controls are brought into existence.  So when using
;** tabbed dialogs, tab to the correct dialog first.  The
;** cWndInfo example shows how to move through a tabbed dialog.
;**
;** Revisions:
;**  6.0 July 7th 2011
;**      Load 64 bit Control manager when running 64 bit version of WinBatch.
;**
;**  5.0 Jan 7th 2010
;**      FIX: Handle titles with embedded double quotes. Fixes issue with
;**      ItemExtractCSV returning error 1707.
;**
;**  4.0 Sept 4th 2009
;**      FIX: Handle strings with embedded linefeeds. Fixes issue with
;**      ArrayFileGetCSV returning error 1808.
;**
;**  3.0 Sept 29th 2008
;**      FIX: Handle Windows Names that contain a comma.
;**
;**  2.0
; **     Initial Release
;**
;***************************************************************************
thisver = '6.0'
thistitle = 'Window Analysis'
csvfile ='Analysis.csv'
htmfile ='Analysis.htm'
; Application Data directory to store CSV file output
appdatadir = ShortCutDir( 'AppData', 0 , @TRUE ) : 'WinBatch\Temp\'
;Check if dir exists. it not create it
If !DirExist( appdatadir ) Then DirMake( appdatadir )
;if this is already running then exit
If WinExist( thistitle )
   WinActivate( thistitle )
   Exit
EndIf
;Tell Winbatch to be greedy
Exclusive(@ON)
;Load the Control Manager Extender
If WinMetrics(-3) == 5 Then AddExtender( 'wwctl64i.dll' )
Else AddExtender( 'wwctl44i.dll' )
;Handle errors
;Intcontrol( 73, 1, 0, 0, 0 )                    ; Use Goto ErrorHndlr
;Change to current working directory
wbtdir = FilePath( IntControl( 1004, 0, 0, 0, 0 ) )
DirChange( wbtdir )
;Get list of all windows currently on the screen
wins = WinItemize( )
If AskYesNo( 'Ok to Ignore', 'Duplicate, hidden and iconized windows will be removed from the list' ) == @YES
   AskMsg = 'Duplicate, hidden and iconized windows are not shown.'
   AskList = ''
   aCnts = ItemCount(wins, @TAB)
   For aCnt = 1 To aCnts
      Win = ItemExtract(aCnt, wins, @TAB)
      If (WinState(Win)!=-1 && WinState(Win)!=1)
         If !ItemLocate(Win, AskList, @TAB) Then AskList = ItemInsert(Win, -1, AskList, @TAB)
      EndIf
   Next
Else
   AskMsg = 'Showing all windows.'
   Asklist = wins
EndIf
trgWnd = AskItemlist(AskMsg, AskList, @TAB, @SORTED, @SINGLE)
;Get chosen window handle
hWnd=DllHwnd(trgWnd)
; Some error checking from the help file to make sure we have a valid handle to the target window.
hwndChk = DllHwnd(trgWnd)
Spec    = cWndGetWndSpec(hwndChk)         ; Get the window specification.
hWnd    = cWndByWndSpec(%Spec%)           ; Get the handle by the window specification.
If hWnd!=hwndChk                          ; Make sure the result matches the original handle
   Pause('ERROR!', "Could not get valid handle for %trgWnd% window.%@crlf%Exiting program.")
   ClipPut(Spec)
   Goto CANCEL
EndIf
GoSub InitUDFs
;Get maximum number of child levels
maxlevel = udfMaxLevelCount( hWnd, 1, 0 )  ;include parent by setting level to one
;Get total number of child windows
wincnt = udfWinCount( hWnd, 0 )
;Initialize database
; Format:
; RowNumber, MaxLevels, ParentCount,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
staticcols = 9
data =  ArrDimension( wincnt, maxlevel + staticcols - 1  ) ; Subtract one because Parent is included in maxlevel
ArrInitialize(data, '')
;Get Window data
info = udfGetWndInfo( hWnd )
name =  ItemExtractCSV( 1, info, 1 )
name = StrReplace( name, @LF, ' ' ) ; 4.0 fix
id =  ItemExtractCSV( 2, info, 1 )
class = ItemExtractCSV( 3, info, 1 )
wndsytle = ItemExtractCSV( 11, info, 1 )
wndstyleex = ItemExtractCSV( 12, info, 1 )
classstyle = ItemExtractCSV( 13, info, 1 )
; RowNumber, MaxLevels , ParentCount,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
data[0, 0] = 0 ;RowNumber
data[0, 1] =  maxlevel ;MaxLevels
data[0, 2] =  0  ;Parent
;data[0, 3] =  level  ; ;*Ignore* Child Windows
data[0, maxlevel+2 ]  = class ;Class
data[0, maxlevel+3 ]  = id    ;ID
data[0, maxlevel+4 ]  = name  ;Title
data[0, maxlevel+5 ]  = wndsytle ;WndStyle
data[0, maxlevel+6 ]  = wndstyleex  ;WndStyleEx
data[0, maxlevel+7 ]  = classstyle  ;ClassStyle
;Initalize Level
level = 0
;Gather CSV data about the window into the data array
udfGetWinData( hWnd, level, maxlevel, data )
; Write out CSV  the Application Data\Temp (C:\Documents and Settings\Deana\Application Data\WinBatch\Temp)
appdatadir = ShortCutDir( 'AppData', 0 , @TRUE ) : 'WinBatch\Temp\'
;Check if dir exists. it not create it
If !DirExist( appdatadir ) Then DirMake( appdatadir )
ArrayFilePutCSV( appdatadir : csvfile, data )
;Run(appdatadir : csvfile, '')
;Run('Notepad.exe', appdatadir : csvfile )
;***************************************************************************
;**
;**  Read CSV create HTML Table
;**
;***************************************************************************
headcolor = '#C0C0C0'
colcolors = '#EEEEFF,#DDDDFF,#CCCCFF,#BBBBFF,#AAAAFF,#9999FF'
greytext =  '#808080'
greybkgrnd = '#DBEADC'
greenbkgrnd = '#BAFEA3'
; Write out CSV  the Application Data\Temp (C:\Documents and Settings\Deana\Application Data\WinBatch\Temp)
appdatadir = ShortCutDir( 'AppData', 0 , @TRUE ) : 'WinBatch\Temp\'
;Check if dir exists. it not create it
If !DirExist( appdatadir ) Then DirMake( appdatadir )
csvdata = ArrayFileGetCSV(appdatadir : csvfile, 0)
; Database Format:
; RowNumber, MaxLevels, Parent,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
;Read max level from data
maxlevel = csvdata[0,1]
;Read parent windowname
topwin = csvdata[0,maxlevel + 4]
handle  = FileOpen( appdatadir: htmfile, 'Write')
FileWrite(handle, '<HTML>')
FileWrite(handle, '<HEAD></HEAD>')
FileWrite(handle, '<TITLE>' : thistitle: '</TITLE>')
FileWrite(handle, ' <!-- <DEFANGED_STYLE type="text/css"><!--p {font-family: Courier, monospace;font-size: 9pt;}TD{font-family: Courier, monospace; font-size: 9pt;}TH{font-family: Courier, monospace; font-size: 9pt;}--> --> </DEFANGED_STYLE>')
FileWrite(handle, '<BODY>')
FileWrite(handle, '<H2>': thistitle : ' ' :  thisver : '</H2><P>' : 'Windowname : ': topwin: '<BR>')
FileWrite(handle, 'Max Level : ' :  maxlevel : '<P>' )
FileWrite(handle, '<TABLE border="1" cellpadding="5">' )
; Write header for table
FileWrite(handle, '<TR bgcolor="':headcolor:'">' )
FileWrite(handle, '<TH>Parent<BR>&nbsp</TH>' )
For count = 1 To maxlevel-1
  FileWrite(handle, '<TH>Child<BR>': count :'</TH>' )
  If count == maxlevel - 1
      FileWrite(handle, '<TH>&nbsp</TH>' ) ; Write a blank col at the end of all the child windows
  EndIf
Next
FileWrite(handle, '<TH>Class</TH>' )
FileWrite(handle, '<TH>Id</TH>' )
FileWrite(handle, '<TH>Name</TH>' )
FileWrite(handle, '<TH>WndStyle</TH>' )
FileWrite(handle, '<TH>WndStyleEx</TH>' )
FileWrite(handle, '<TH>ClassStyle</TH>' )
FileWrite(handle, '</TR>' )
greenflag = 0
For darow = 0 To ArrInfo(csvdata, 1 )-1
   FileWrite(handle, '<TR>' )
   For dacol = 2 To ArrInfo(csvdata, 2 )-1
      data = csvdata[darow, dacol]
      ;Compare to previous data if one of the parent/child columns
      If dacol <= maxlevel+1
         ;Special Handling for first row
         If darow == 0 Then prevrow = ''
         Else prevrow = csvdata[darow-1, dacol]
         ;Need to decide Whether to Write in grey or green.
         If data == prevrow && greenflag == 0  ; if previous row matches current rowdata and green flag set to false
            ;if data == csvdata[darow-1, dacol];if previous row matches current rowdata
            FileWrite(handle, '<TD bgcolor="':greybkgrnd:'"><FONT COLOR="':greytext:'">' ); Grey
         Else
            FileWrite(handle, '<TD bgcolor="':greenbkgrnd:'">' ); Green
            greenflag = 1
         EndIf
         If data == ''
            FileWrite(handle, '&nbsp' )
         Else
            FileWrite(handle, data )
         EndIf
         FileWrite(handle, '</FONT></TD>' )
         If dacol == maxlevel+1 ; Write a blank col at the end of all the child windows
            FileWrite(handle, '<TD bgcolor="':greybkgrnd:'">&nbsp</TD>' ); Grey Empty Col
         EndIf
      Else
         ;Colorize all non - child window columns
         ;Get RGB
         rgb = ItemExtract( dacol-maxlevel-1, colcolors, ',' )
         FileWrite(handle, '<TD bgcolor=': rgb : '>' )
         If data == ''
            FileWrite(handle, '&nbsp' )
         Else
            FileWrite(handle, data )
         EndIf
         FileWrite(handle, '</TD>' )
      EndIf
   Next
   greenflag = 0
   FileWrite(handle, '</TR>' )
Next
FileWrite(handle, '</TABLE>' )
FileWrite(handle, '</BODY>')
FileWrite(handle, '</HTML>')
FileClose( handle )
Run( appdatadir: htmfile, '')
Exit
;***************************************************************************
;**
;**                User Defined Functions
;**
;***************************************************************************
:InitUDFs
#DefineFunction udfMaxLevelCount( WorkWnd, Level, MaxLevel )
   level = level + 1
   ;Locate child
   nextchild = cWndinfo( workwnd, 8 )
   While nextchild
      ;Keep track of the highest level number
      If level > MaxLevel
         MaxLevel = level
      EndIf
      ;Recurse
      MaxLevel = udfMaxLevelCount( nextchild, level, MaxLevel )
      ;Get next Sibling
      nextchild =  cWndinfo( nextchild, 6 )
   EndWhile
   Return MaxLevel
#EndFunction ;udfMaxLevelCount
#DefineFunction udfWinCount( WorkWnd, count )
   count = count + 1
   ;Locate child
   nextchild = cWndinfo( workwnd, 8 )
   While nextchild
      ;Recurse
      count = udfWinCount( nextchild, count )
      ;Get next Sibling
      nextchild =  cWndinfo( nextchild, 6 )
   EndWhile
   Return count
#EndFunction ;udfWinCount
#DefineFunction udfGetWinData( WorkWnd, level, maxlevel, data )
   delim = ','
   level = level + 1
   ;Keep track of row number
   ptr_rowcount = PtrPersistent( rowcount, 0 )
   *ptr_rowcount = *ptr_rowcount + 1
   ;Locate child
   nextchild = cWndinfo( workwnd, 8 )
   count = 0
   While nextchild
      count = count+1 ;Keeps track of Childcount windows
      ;Pause(count, *ptr_prevchild)
      ; Get Window Data
      info = udfGetWndInfo( nextchild )
      name =  ItemExtractCSV( 1, info, 1 )
      name = StrReplace( name, @LF, ' ' ) ; 4.0 fix
      id =  ItemExtractCSV( 2, info, 1 )
      class = ItemExtractCSV( 3, info, 1 )
      wndsytle = ItemExtractCSV( 11, info, 1 )
      wndstyleex = ItemExtractCSV( 12, info, 1 )
      classstyle = ItemExtractCSV( 13, info, 1 )
      ; RowNumber, MaxLevels , ParentCount,  [Child1, Child2, Child3, Etc ] , Class , Id , Title , WndStyle, WndStyleEx, ClassStyle
      row = *ptr_rowcount
      data[row, 0] = row+1      ;RowNumber -  add one because parent already written
      data[row, 1] = maxlevel ;MaxLevels
      data[row, 2] = 0             ;ParentCount will always be zero
      ; HandleChild Windows
      ; Keep track of previous childs
      For col = 3 To level+2 ;Loop once for each child
      ;Grab data from previous rows column
      prevdata = data[row-1, col]
      ;Check if col is equal to the current level plus 2
      If col == level+2
         data[row, level+2] = count ; insert child count number
      Else
         data[row, col] = prevdata ; insert data from previous line
      EndIf
      Next
      data[row, maxlevel+2 ]  = class ;Class
      data[row, maxlevel+3 ]  = id    ;ID
      data[row, maxlevel+4 ]  = name  ;Title
      data[row, maxlevel+5 ]  = wndsytle ;WndStyle
      data[row, maxlevel+6 ]  = wndstyleex  ;WndStyleEx
      data[row, maxlevel+7 ]  = classstyle  ;ClassStyle
      ;Recurse
      data = udfGetWinData( nextchild, level, maxlevel, data )
      ;Get next Sibling
      nextchild =  cWndinfo( nextchild, 6 )
   EndWhile
   Return data
#EndFunction ;udfGetWinData
#DefineFunction udfGetWndInfo( WorkWnd )
   ;Returns a delimited list of Window information
   delim = ','
   Title           = cWndinfo(WorkWnd, 0)
   Title = StrReplace( Title, '"', '""' ); 5.0 fix : Replace any embedded doublequotes in the title with double doublequotes
   ID              = cWndinfo(WorkWnd, 1)
   Class           = cWndinfo(WorkWnd, 2)
   Parent          = cWndinfo(WorkWnd, 3)
   FirstSibling    = cWndinfo(WorkWnd, 4)
   PreviousSibling = cWndinfo(WorkWnd, 5)
   NextSibling     = cWndinfo(WorkWnd, 6)
   LastSibling     = cWndinfo(WorkWnd, 7)
   FirstChild      = cWndinfo(WorkWnd, 8)
   Owner           = cWndinfo(WorkWnd, 9)
   WndStyle        = cWndinfo(WorkWnd, 20)
   WndStyleEx      = cWndinfo(WorkWnd, 21)
   ClassStyle      = cWndinfo(WorkWnd, 22)
   info = '"':Title:'"':delim:ID:delim:Class:delim:Parent:delim:FirstSibling:delim:PreviousSibling:delim:NextSibling:delim:LastSibling:delim:FirstChild:delim:Owner:delim:WndStyle:delim:WndStyleEx:delim:ClassStyle
   Return info
#EndFunction ;udfGetWndInfo
Return
;***************************************************************************
;**
;**             Cancel and Error Handling
;**
;***************************************************************************
:CANCEL
Exit
:WBERRORHANDLER
wErrFile = thisVer
wError=LastError()
wErrStr = IntControl(34,wError,0,0,0)
wErrLine = wberrorhandlerline
wErrOffset = wberrorhandleroffset
wErrAssign  = wberrorhandlerassignment
wErrMessage = 'Please email this info:%@CRLF%%@tab%"%wErrRptFile%"%@CRLF%to support@winbatch.com with the Subject line "Analysis Error"'
wErrTxt = StrCat(`wErrFile = `, wErrFile, @CRLF, `wError = `, wError, @CRLF, `wErrStr= `, wErrStr, @CRLF, `wErrLine = `, wErrLine, @CRLF, `wErrOffset = `, wErrOffset,@CRLF, `wErrAssign = `, wErrAssign, @CRLF, @CRLF, wErrMessage)
Pause( 'Notice', wErrTxt)
ClipPut(wErrTxt)
Goto CANCEL

Article ID:   W17509
Filename:   Control Manager - Windows Analysis.txt
File Created: 2019:08:14:08:51:50
Last Updated: 2019:08:14:08:51:50