WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: sdorn on August 25, 2013, 02:56:39 PM

Title: Aquiring the Position of a Child Window
Post by: sdorn on August 25, 2013, 02:56:39 PM
I am trying to get a screenshot of a window control and I have all the pieces except for the position of the child window. It is a small video window in a larger application; I have the handle from cWndByID(), does anyone know of a way to obtain the cWnd's position?
Title: Re: Aquiring the Position of a Child Window
Post by: ....IFICantBYTE on August 25, 2013, 04:30:25 PM
If you are using and wanting WinBatch's 1000x1000 screen coordinates (which I personally dislike), then the WinPositionChild() function might be what you are after.

However, if you want real pixel coordinates, then the following UDF might be of help:

Code (winbatch) Select
;-----------------------------------------------------------------------------------------------------------------------------------------;
;GetWindowRect : Retrieves the dimensions of the bounding rectangle of a specified window and Returns them in a delimited string.         ;
;                The dimensions are given in screen coordinates (Window's pixels) that are relative to the upper-left corner of the       ;
;                second window handle specified.                                                                                          ;
;v1.1 by IFICantBYTE (2004)                                                                                                               ;
;-----------------------------------------------------------------------------------------------------------------------------------------;
;hWindow1 : Window handle we want to get the relative coordinates for (Usually a Child Window - but not always)                           ;
;hWindow2 : Window handle we want the returned coordinates to be relative to (Usually the Parent window - but again, doesn't have to be)  ;
;    NOTE : Passing a NULL (0) as hWindow2 will return the coordinates of hWindow1 as compared to the desktop                             ;
;           Passing the same window handle for both - ie: comparing it to itself will basically return the size of the window.            ;
;delim    : The delimiter you want to use between the Returned X and Y values - eg: "," or @TAB or @CRLF or " " (space)                   ;
;-----------------------------------------------------------------------------------------------------------------------------------------;
;Returns : Returns a delimited string containing the rectangular coordinates (in Windows' pixels - not Winbatch's 1K units) for hWindow1  ;
;          relative to the Window specified by the handle hWindow2.                                                                       ;
;   NOTE : 0 0 is top Left corner. Values can go into negatives and the window specified does not have to be the topmost, active or       ;
;          focused. This will not Return correct results with a mirrored Window using a Right to Left ExStyle                             ;
;-----------------------------------------------------------------------------------------------------------------------------------------;
#DefineFunction GetWindowRect(hWindow1,hWindow2,delim)
User32 = DllLoad(StrCat(DirWindows(1),"user32.dll"))
   ;--- Make RECT structure --- will contain the top-left and bottom-right coordinates and therefore the rectangle size of the window ---
   RECT=BinaryAlloc(16)    ; Create buffer for structure
   ;BinaryPoke4(RECT,0,0)  ; Left x coordinate (pixel) 
   ;BinaryPoke4(RECT,4,0)  ; Top y coordinate (pixel)
   ;BinaryPoke4(RECT,8,0)  ; Right x
   ;BinaryPoke4(RECT,12,0) ; Bottom y
   ;NOTE : above BinaryPokes are commented out to save some processing time - contents will be overwritten with new values on dll call)
   ;-------------------------------------------------------------------------------------------------------
DllCall(user32,long:"GetWindowRect",long:hWindow1,lpbinary:RECT)
   ;----- Make POINT structure ---- will contain the bottom X and Y coordinates -------------------
   POINT=BinaryAlloc(8)    ; Create buffer for structure
   ;BinaryPoke4(RECT,0,0)  ; Left x coordinate (pixel) 
   ;BinaryPoke4(RECT,4,0)  ; Top y coordinate (pixel)
   ;NOTE : above BinaryPokes are commented out to save some processing time - contents will be overwritten with new values on dll call)
   ;-------------------------------------------------------------------------------------------------------
BinaryCopy(POINT,0,RECT,8,8)
DllCall(user32,long:"ScreenToClient",long:hWindow2,lpbinary:RECT)
DllCall(user32,long:"ScreenToClient",long:hWindow2,lpbinary:POINT)
topx = BinaryPeek4(RECT,0)
topy = BinaryPeek4(RECT,4)
bottomx = BinaryPeek4(POINT,0)
bottomy = BinaryPeek4(POINT,4)
BinaryFree(RECT)
BinaryFree(POINT)
DllFree(User32)
Return StrCat(topx,delim,topy,delim,bottomx,delim,bottomy)
#EndFunction
;##########################################################################################################################################
Title: Re: Aquiring the Position of a Child Window
Post by: sdorn on August 25, 2013, 05:24:41 PM
Sorry, I probably used the wrong terminology. I don't need the position of an application window (as reported by WinPositionChild); I need the position of a window control (handle obtained by cWndByID from the Control Manager extender).

To think of this another way, I could want the position of an application's status bar (handle also obtained from cWndByID) so that I could send a mouse click to a particular point on the status bar.

Does anyone know how to obtain position information of a control from a control handle reported from cWndByID? Thanks.
Title: Re: Aquiring the Position of a Child Window
Post by: ....IFICantBYTE on August 25, 2013, 06:19:59 PM
That is exactly what the suggestions I gave you can do.
A control inside an application's window IS a child control and IS a "window" of sorts... you can receive a control's size and position using the UDF I gave you by passing the handle of the control and any other handle you want it referenced to.. eg. the parent window or the desktop window etc.
Title: Re: Aquiring the Position of a Child Window
Post by: sdorn on August 25, 2013, 08:06:00 PM
Yep the UDF got it. Sorry, I read the WinPositionChild() suggestion at the beginning of your message and didn't follow through as I had already been down that road.

Seems your UDF strays pretty far from WinBatch so I'm guessing that the functionality doesn't exist in WinBatch. I guess I'm lucky that someone's needed the same capability before. Thanks.
Title: Re: Aquiring the Position of a Child Window
Post by: Deana on August 26, 2013, 09:41:56 AM
Here is a code sample the uses the Control Manager Extender function to convert the controls window Handle to a Window ID, then uses WinPosition to move the mouse to over the center of the control.

Code (winbatch) Select

AddExtender("wwctl44i.dll", 0,"wwctl64i.dll" )
title= 'WIL Type Viewer'

wbdir = FilePath(FileLocate('winbatch.exe'))


;Launch Program
Run(wbdir:'WIL Type Viewer.exe','')
WinWaitExist(title, 5)

window1=DllHwnd('WIL Type Viewer')
window2=cWndByName(window1,`Viewer~`)
;ControlHandle=cWndByName(window2,`Get Members~`)
ControlHandle=cWndByName(window2,`Get Library~`)

;result=cWndInfo(ControlHandle,0)     ;Reads the title/text of a control
;Message("Window Title/Text",result)     

;Convert to Window ID
childwinid = cWinIdConvert(ControlHandle)

pos = WinPosition( childwinid )
xulc = ItemExtract(1, pos, ",")
yulc = ItemExtract(2, pos, ",")
xbrc = ItemExtract(3, pos, ",")
ybrc = ItemExtract(4, pos, ",")

;middle of control
width = xbrc - xulc
height = ybrc - yulc
x = xulc + (width/2)
y = yulc + (height/2)

MouseMove(x, y, '', '')
Exit