Aquiring the Position of a Child Window

Started by sdorn, August 25, 2013, 02:56:39 PM

Previous topic - Next topic

sdorn

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?

....IFICantBYTE

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
;##########################################################################################################################################
Regards,
....IFICantBYTE

Nothing sucks more than that moment during an argument when you realize you're wrong. :)

sdorn

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.

....IFICantBYTE

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.
Regards,
....IFICantBYTE

Nothing sucks more than that moment during an argument when you realize you're wrong. :)

sdorn

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.

Deana

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
Deana F.
Technical Support
Wilson WindowWare Inc.