;***************************************************************************
;**   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 doublequotes. 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
