Client rectangle coordinates on screen
Solution 1
Yes, you can do this with the ClientToScreen
function:
RECT rc;
GetClientRect(hWnd, &rc); // get client coords
ClientToScreen(hWnd, reinterpret_cast<POINT*>(&rc.left)); // convert top-left
ClientToScreen(hWnd, reinterpret_cast<POINT*>(&rc.right)); // convert bottom-right
What is the "client" rectangle in a browser depends on the browser implementation. You can use Spy++ to discover this for yourself.
Solution 2
To translate a window's client rectangle to screen coordinates, call the MapWindowPoints function. It implements special handling to always return a valid RECT
, even when used in scenarios that involve windows with right-to-left layout:
If hWndFrom or hWndTo (or both) are mirrored windows (that is, have
WS_EX_LAYOUTRTL
extended style) and precisely two points are passed in lpPoints,MapWindowPoints
will interpret those two points as aRECT
and possibly automatically swap the left and right fields of that rectangle to ensure that left is not greater than right.
Calling ClientToScreen on both points in contrast fails to account for RTL layouts, and can produce an invalid RECT
. It fails to adhere to one of the rectangle coordinate invariants:
The coordinate value of a rectangle's right side must be greater than that of its left side. Likewise, the coordinate value of the bottom must be greater than that of the top.
A reliable function to return a window's client rectangle in screen coordinates would look like this:
RECT client_rect_in_screen_space(HWND const hWnd) {
RECT rc{ 0 };
if (!::GetClientRect(hWnd, &rc)) {
auto const err_val{ ::GetLastError() };
throw std::system_error(err_val, std::system_category());
}
::SetLastError(ERROR_SUCCESS);
if(::MapWindowPoints(hWnd, nullptr, reinterpret_cast<POINT*>(&rc), 2) == 0) {
auto const err_val{ ::GetLastError() };
if (err_val != ERROR_SUCCESS) {
throw std::system_error(err_val, std::system_category());
}
}
return rc;
}
The question update asks for a different, unrelated issue. There is no API built into the system, that allows you to query a web browser's display area for its HTML content. The most promising solution would be to employ UI Automation. The question, however, is too broad to provide a more detailed answer here.
Solution 3
As commented by Raymond Chen
, the preferred way of doing this should be something like the following:
inline POINT get_client_window_position(const HWND window_handle)
{
RECT rectangle;
GetClientRect(window_handle, static_cast<LPRECT>(&rectangle));
MapWindowPoints(window_handle, nullptr, reinterpret_cast<LPPOINT>(& rectangle), 2);
const POINT coordinates = {rectangle.left, rectangle.top};
return coordinates;
}
Related videos on Youtube
Max Yari
Hello there! At the moment I'm a freelance fullstack web developer. I usually work with node.js and angular and enjoy getting my hands dirty with new technology. I also like to fiddle around with python and game engines like unity and unreal engine.
Updated on June 04, 2022Comments
-
Max Yari almost 2 years
How can I get coordinates of a window's client area relative to screen?
I thought about using
GetClientRect
andClientToScreen
. Also, in a browser window what isClientRect
? Only rectangle withHTML
document shown in it, or it includes browser bars and pop-up menus, that can possibly shrink dimension forHTML
doc?I've tried this:
HWND hWnd; RECT rc; if (GetClientRect(hWnd, &rc)) // get client coords { MapWindowPoints(hWnd, NULL, reinterpret_cast<POINT*>(&rc), 2); // converts rect rc points return rc.top; }
But the sad thing is that browser's client rectangle includes all those pop-up browser menus and bars, therefore can't be used to detect accurate coordinates of browsers HTML document space. If anyone got suggestions how it can be done, will try it gladly.
-
Raymond Chen about 11 yearsNote that returns an invalid rectangle on RTL systems. Better is to use
MapWindowPoints
with a length of 2. -
Max Yari about 11 yearsStack around the variable
rc
was corrupted, seems you are right, will tryMapWindowPoints
now -
AbePralle over 10 yearsI don't know what an RTL system is, but would declaring and using a separate POINT struct instead of a cast fix that issue? That seems to work fine for me and my purposes.
-
user2120666 about 8 yearsAs pointed by Mr. Raymond Chen, this snippet causing problem on RTL systems, so please dont use this.
-
Camille Goudeseune about 8 yearsIf RTL means right to left, ScreenToClient can have problems (msdn.microsoft.com/en-us/library/windows/desktop/…) but the docs for ClientToScreen don't mention this.
-
IInspectable about 6 years@AbePralle: RTL is short for right-to-left. It refers to text layouts, that are written from right to left, such as Arabic script. Using a separate
POINT
structure doesn't produce a valid rectangle. -
Admin about 3 yearswhy do you call the
ClientToScreen
two times, one for left and one for right? -
Jonathan Potter about 3 years@Ivanzinho
ClientToScreen
works on aPOINT
(x,y) and a rectangle consists of two POINTs (top-left, bottom-right). But better to use theMapWindowPoints
function as suggested by Raymond Chen. -
Admin about 3 years@JonathanPotter is this not an ugly design?
ClientToScreen
would have returned aPOINT
instead of replacing the input argument with the output result. It's hard to wrap the idea of how it works this way, are they saving some CPU cycles or RAM to chose that unnatural design? -
Jonathan Potter about 3 years@Ivanzinho This API would probably date back to the mid-1980s. C didn't support returning structs then and I'm guessing the API was designed around that limitation.