:Start of EnumWindows
![]() | ![]() |
|---|
If you are viewing this script in your browser you can save it as a VDS 5.x source file (*.dsc) to run it.
#
# DragonSphere Software's Home Page
#
# All Source Files for this demo
###############################################################################
# #
# This demo shows how to use GadgetX'es CallBack functions by using the #
# EnumWindows and EnumChildWindows API functions to retrieve a list of all #
# windows and controls opened on your PC. #
# #
###############################################################################
Option Decimalsep,.
Title Window Info
External gadgetx.dll,@Sysinfo(DSVER)
If @Greater(@Name(@Sysinfo(DSVER)),4)
#DEFINE COMMAND,GADGETX,DEFINE,SET,CALL,FREEDLL,PRINTDIALOG,StopCB,SetCallback,SLEEP
#DEFINE FUNCTION,GADGETX,LOADDLL,GET,ADDROF,SPACE,CALL,GetCallback
End
Define Variable,Handle,user32
Set user32,@LoadDLL(user32.dll)
Define Function,Handle,user32,GetParent,GetParent,Handle|hWndParent
Define Command,EnumWindows_Done,user32,EnumWindows,EnumWindows,Pointer|lpEnumFunc,DWORD|lParam
Define Command,EnumChildWindows_Done,user32,EnumChildWindows,EnumChildWindows,Handle|hWndParent,Pointer|lpEnumChildFunc,DWORD|lParam
Define Variable,String,MyEvent
Define Variable,Handle,ParentHwnd
Define Variable,Pointer,EnumWinProc
Define Variable,Pointer,EnumChildWinProc
Define Variable,QWORD,LstCount
Define Variable,BYTE,cnt
Define Variable,String,CBParams
Define Variable,String,CBParamsChild
Define Variable,String,Item
Define Variable,String,Title
Define Variable,String,Class
Define Variable,String,Text
Rem Describe to Gadget what Parameters are supposed to be passed to our fuction
rem by the external DLL and give Gadget a user defined VDS event name that will
rem be trigered each time the external function calls our Callback function
Define CallBack,0,Integer,EnumWindowsProc,Handle,Integer
Define CallBack,1,Integer,EnumChildWins,Handle,Integer
Rem Get the memory address of 1 of the 5 callback functions inside of Gadget.
rem they are numbered similar to VDS List but the Callback ID's start at 0,1,2,3,4
Set EnumWinProc,@AddrOf(CallBack,0)
Set EnumChildWinProc,@AddrOf(CallBack,1)
Rem Initialize all String variables...
#Set MyEvent,@Space(256)
#Set CBParams,@Space(256)
#Set CBParamsChild,@Space(256)
#Set Item,@Space(256)
#Set Title,@Space(256)
#Set Class,@Space(256)
#Set Text,@Space(256)
:Main
DIALOG CREATE,Test Callback,-1,0,599,266,PAINT,RESIZABLE
REM *** Modified by Dialog Designer on 3/18/2004 - 12:51 ***
DIALOG ADD,STYLE,BK,,,,WHITE,
DIALOG ADD,TEXT,BACKGROUND,0,0,599,246,,,BK
DIALOG ADD,TEXT,TEXT1,12,48,,,Click the button to get a list of all top level Windows.,,BK
If @Greater(@Name(@Sysinfo(DSVER)),4)
DIALOG ADD,TABLE,TABLE1,36,0,599,156,Handle[25]|Class[80]|Title/Parent[125]
Else
DIALOG ADD,LIST,TABLE1,36,0,599,156
End
DIALOG ADD,BUTTON,BUTTON1,208,108,64,24,Get List
DIALOG ADD,BUTTON,BUTTON2,208,400,64,24,Close
DIALOG ADD,BUTTON,WinInfo,208,256,64,24,&Info
DIALOG ADD,STATUS,STATUS1,Click Get List...
DIALOG SHOW
rem %%Stat_hwnd = @winexists(~STATUS1)
Rem Make a temp list to hold the CallBack parameters.
List create,1
List create,2
:evloop
Rem Ok be warned if you use a Timer event then expect this
rem to be very slow.
rem If you need to use a Timer then use Gadget FireEvent,Timer
wait event
Set MyEvent,@Event()
if @Greater(@Len(@Get(MyEvent)),0)
goto @Get(MyEvent)
End
goto evloop
:TIMER
If @Equal(%%CheckEnumWindows,1)
DIALOG CURSOR,WAIT
End
If @Equal(%%CheckChildEnumWindows,1)
DIALOG CURSOR,WAIT
End
goto evloop
:RESIZE
:PAINT
goto evloop
:BUTTON1BUTTON
Gosub QUITCOMMANDS
%%CheckEnumWindows = 1
rem DIALOG CURSOR,WAIT
Rem Make sure the List box is cleared.
List Clear,TABLE1
List Clear,2
Set LstCount,0
Rem Kick off the EnumWindows function. Passing it the memory address of our Callback function.
Rem Note: If you want the function to run Asyncronously then you must call it as a VDS command.
rem This is because Gadget calls the function from a seperate thread when called as a VDS
rem command.
rem I did this so that Gadget's callback functions will work like other languages.
Call EnumWindows,EnumWinProc,0
goto evloop
:EnumWindows_Done
DIALOG CURSOR
DIALOG SET,TEXT1,Wow that took a bit of work but I am finished now.
Dialog Set,STATUS1,There are @Get(LstCount) windows open on your PC dang your busy call ya later...
%%CheckEnumWindows = 0
goto evloop
:EnumChildWindows_Done
DIALOG CURSOR
%%CheckEnumChildWindows = 0
SetCallBack Return,0,1
goto evloop
:WinInfoBUTTONBAD
DIALOG HIDE,BUTTON1
DIALOG HIDE,BUTTON2
DIALOG HIDE,WinInfo
DIALOG HIDE,STATUS1
%%bkW = @dlgpos(BACKGROUND,W)
%%bkH = @dlgpos(BACKGROUND,H)
%%tblW = @dlgpos(TABLE1,W)
%%tblh = @dlgpos(TABLE1,H)
WINDOW MAXIMIZE,@winexists(Test Callback)
%%Width = @diff(@dlgpos(,W),2)
%%Height = @diff(@dlgpos(,H),2)
DIALOG SETPOS,BACKGROUND,,,%%Width,%%Height
DIALOG SETPOS,TABLE1,,,%%Width,%%Height
PrintDialog @winexists(Test Callback),"Test doc"
WINDOW NORMAL,@winexists(Test Callback)
DIALOG SETPOS,BACKGROUND,,,%%bkW,%%bkH
DIALOG SETPOS,TABLE1,,,%%tblW,%%tblH
DIALOG SHOW,BUTTON1
DIALOG SHOW,BUTTON2
DIALOG SHOW,WinInfo
DIALOG SHOW,STATUS1
If @Ok()
Info Go check the printer
End
goto evloop
:WinInfoBUTTON
Set Item,@Item(TABLE1)
If @Null(@Get(Item))
Set Item,@Item(TABLE1,0)
End
%%OldFsep = @fsep()
Option FieldSep,@Tab()
Parse "%%Hwnd;%%Class;%%Titletxt",@Get(Item)
if @Greater(@Pos(->,%%Hwnd),0)
Rem This is a child window
%%Hwnd = @SubStr(%%Hwnd,3,@len(%%Hwnd))
%%Status = @WinPos(%%Hwnd,S)
If @Equal(%%Status,1)
%%Status = Normal
ElsIf @Equal(%%Status,2)
%%Status = Iconized
ElsIf @Equal(%%Status,3)
%%Status = Maximized
End
If @Equal(%%Class,##32770)
If @Equal(#@WinClass(@Call(GetParent,%%Hwnd)),##32770)
Rem Use Title text for both child and parent
Info Handle: %%Hwnd@CR()Title: %%Titletxt@CR()Parent Title: @WinText(@Call(GetParent,%%Hwnd))@CR()Status: %%Status@CR()Top: @WinPos(%%Hwnd,T)@CR()Left: @WinPos(%%Hwnd,L)@CR()Width: @WinPos(%%Hwnd,W)@CR()Height: @WinPos(%%Hwnd,H)
Else
Rem Else just use the child's title text
Info Handle: %%Hwnd@CR()Title: %%Titletxt@CR()Parent: #@WinClass(@Call(GetParent,%%Hwnd))@CR()Status: %%Status@CR()Top: @WinPos(%%Hwnd,T)@CR()Left: @WinPos(%%Hwnd,L)@CR()Width: @WinPos(%%Hwnd,W)@CR()Height: @WinPos(%%Hwnd,H)
End
Else
If @Equal(#@WinClass(@Call(GetParent,%%Hwnd)),##32770)
Rem Use Title text for parent
Info Handle: %%Hwnd@CR()Class: %%Class@CR()Parent Title: @WinText(@Call(GetParent,%%Hwnd))@CR()Status: %%Status@CR()Top: @WinPos(%%Hwnd,T)@CR()Left: @WinPos(%%Hwnd,L)@CR()Width: @WinPos(%%Hwnd,W)@CR()Height: @WinPos(%%Hwnd,H)
Else
Rem Else use the child and Parent class
Info Handle: %%Hwnd@CR()Class: %%Class@CR()Parent: #@WinClass(@Call(GetParent,%%Hwnd))@CR()Status: %%Status@CR()Top: @WinPos(%%Hwnd,T)@CR()Left: @WinPos(%%Hwnd,L)@CR()Width: @WinPos(%%Hwnd,W)@CR()Height: @WinPos(%%Hwnd,H)
End
End
Else
Rem This is a Top level window
%%Status = @WinPos(%%Hwnd,S)
If @Equal(%%Status,1)
%%Status = Normal
ElsIf @Equal(%%Status,2)
%%Status = Iconized
ElsIf @Equal(%%Status,3)
%%Status = Maximized
End
If @Equal(%%Class,##32770)
Info Handle: %%Hwnd@CR()Title: %%Titletxt@CR()Status: %%Status@CR()Top: @WinPos(%%Hwnd,T)@CR()Left: @WinPos(%%Hwnd,L)@CR()Width: @WinPos(%%Hwnd,W)@CR()Height: @WinPos(%%Hwnd,H)
Else
Info Handle: %%Hwnd@CR()Class: %%Class@CR()Status: %%Status@CR()Top: @WinPos(%%Hwnd,T)@CR()Left: @WinPos(%%Hwnd,L)@CR()Width: @WinPos(%%Hwnd,W)@CR()Height: @WinPos(%%Hwnd,H)
End
End
End
Option FieldSep,%%OldFsep
goto evloop
:EnumWindowsProc
Rem This sub-routine is the event that Gadget trigered due to the EnumWindows API
rem function calling one of Gadget's callback routines.
Rem Ok here is the strange part of this. Because Gadget can only emulate
rem Callback functions due to the fact that
rem 1) You cannot build functions with VDS source code.
rem 2) You cannot get the memory address of a VDS sub-routine.
rem We have to emulate them with some generic functions that I put in Gadget.
rem In this case EnumWindows requires a return value of '1' to enumerate all the window
rem handles on the PC.
Rem @GetCallback() returns all parameters passed to the callback as a VDS List
rem Gadget will sit and wait until you collect the value with the GetCallback function.
rem If you never collect the value then when you exit the VDS script it will generate and ERROR.
rem This is due to the thread that is left open because the callback is waiting for the signal
rem to set the return value and finish processing.
Set CBParams,@GetCallback(0)
rem If @Null(@Gadget(CBParams))
Rem Just a redundant check to make sure Gadget is returning information
rem SetCallBack Return,0,0
rem Info This should not have been called @CR()@Item(2,@pred(@count(2)))
If @Get(CBParams)
# Info @Get(CBParams)@CR()
Rem Clear List 1
List clear,1
Rem Assign the Parameters that was passed to Gadget's CallBack function
rem to list 1.
List Assign,1,@Get(CBParams)
REM Info @Text(1)@CR()
REM Gadget CBParams,NULL
Rem Place in a loop to get each parameter in turn
Set cnt,0
Repeat
Set Item,@Item(1,@Get(cnt))
if @Greater(@Pos(@chr(37),@Get(Item)),0)
Rem Make sure the Item that we are getting is the Window Handle and not
rem our second parameter which in this case we don't care about.
rem Normally the second parameter you would be able to set so you can tell
rem your CallBack function when to stop but because we are remotely controlling
rem our CallBack function we don't need this.
Rem Get the Window's Title bar text
# Info VDS @Get(Item)@CR()
Set Title,@WinText(@Get(Item))
Set Class,#@WinClass(@Get(Item))
Set ParentHwnd,Item
if @Greater(@len(@Get(Title)),0)
Rem If the Window has a title bar or some kind of text then display the text
Set Text,@Get(Item)@Tab()@Get(Class)@Tab()@Get(Title)
Else
Rem If the window does not have any text then just display "No Title"
Set Text,@Get(Item)@Tab()@Get(Class)@Tab()No Title
End
End
Until @Greater(@Get(cnt,++),@count(1))
Rem Add the Window info to our list box.
if @Greater(@Match(2,@Get(Text)),-1)
Else
List ADD,2,@Get(Text)
List ADD,TABLE1,@Get(Text)
Dialog Set,STATUS1,There are @Get(LstCount,++) windows open on your PC...
End
List Seek,2,0
Call EnumChildWindows,ParentHwnd,EnumChildWinProc,0
%%CheckEnumChildWindows = 1
# SetCallBack Return,0,1
rem SetCallBack Return,0,1
End
Goto Evloop
:EnumChildWins
rem %E = @event()
Rem This sub-routine is the event that Gadget trigered due to the EnumChildWindows API
rem function calling one of Gadget's callback routines.
Rem Ok here is the strange part of this. Because Gadget can only emulate
rem Callback functions due to the fact that
rem 1) You cannot build functions with VDS source code.
rem 2) You cannot get the memory address of a VDS sub-routine.
rem We have to emulate them with some generic functions that I put in Gadget.
rem In this case EnumChildWindows requires a return value of '1' to enumerate all the
rem child window handles on the current window.
Rem @Gadget(GetCallback,) returns all parameters passed to the callback as a VDS List
rem Gadget will sit and wait until you collect the value with the GetCallback function.
rem If you never collect the value then when you exit the VDS script it will generate and ERROR.
rem This is due to the thread that is left open because the callback is waiting for the signal
rem to set the return value and finish processing.
Set CBParamsChild,@GetCallback(1)
If @Get(CBParamsChild)
Rem Clear List 1
List clear,1
Rem Assign the Parameters that was passed to Gadget's CallBack function
rem to list 1.
List Assign,1,@Get(CBParamsChild)
Rem Place in a loop to get each parameter in turn
Set cnt,0
Repeat
Set Item,@Item(1,@Get(cnt))
if @Greater(@Pos(@chr(37),@Get(Item)),0)
Rem Make sure the parameter that we are getting is the Child Window Handle and not
rem our second parameter which in this case we don't care about.
rem Normally the second parameter you would be able to set so you can tell
rem your CallBack function when to stop but because we are remotely controlling
rem our CallBack function we don't need this.
Rem Get the Window's Title bar text
# Info @Get(Item)@CR()
Set Title,@Call(GetParent,Item)
rem Gadget Title,Nothing to see
Set Class,#@WinClass(@Get(Item))
rem Gadget Class,#NoClass
if @Greater(@len(@Get(Title)),0)
Rem If the Window has a title bar or some kind of text then display the text
Set Text,"->"@Get(Item)@Tab()@Get(Class)@Tab()@Get(Title)
Else
Rem If the window does not have any text then just display "No Title"
Set Text,"->"@Get(Item)@Tab()@Get(Class)@Tab()No Title
End
End
Until @Greater(@Get(cnt,++),@count(1))
Rem Add the Window info to our list box.
if @Greater(@Match(2,@Get(Text)),-1)
else
List ADD,TABLE1,@Get(Text)
List ADD,2,@Get(Text)
Dialog Set,STATUS1,There are @Get(LstCount,++) windows open on your PC...
rem Info @Text(2)
end
List Seek,2,0
Rem Set the CallBack return value.
End
SetCallBack Return,1,1
Goto Evloop
:QUITCOMMANDS
%E =
If @Equal(%%CheckEnumChildWindows,1)
%%CheckEnumChildWindows = 0
SetCallBack Return,1,0
repeat
wait event,0.1
%E = @Event()
IF @Equal(%E,EnumWindows_Done)
Info EnumChildwindows is done
End
Until @Equal(%E,EnumWindows_Done)
End
if @Equal(%%CheckEnumWindows,1)
%%CheckEnumWindows = 0
SetCallBack Return,0,0
repeat
wait event,0.1
%E = @Event()
IF @Equal(%E,EnumWindows_Done)
Info Enumwindows is done
End
Until @Equal(%E,EnumWindows_Done)
End
WAIT 0.5
Rem Added this to clear the memory addresses and close the callback handles.
StopCB
Rem After you stop all CallBacks you have to re-establish their memory addresses
rem and callback handles.
Set EnumWinProc,@AddrOf(CallBack,0)
Set EnumChildWinProc,@AddrOf(CallBack,1)
Exit
:BUTTON2BUTTON
:CLOSE
DIALOG CURSOR
Rem Just incase the Callbacks are hung release them...
Gosub QUITCOMMANDS
Rem Clear your list...
List clear,TABLE1
List clear,1
List close,1
List clear,2
List close,2
FreeDLL user32
Stop
copyright © DragonSphere Software 2000-2006
Terms and Conditions