0

I want to get the (accurate) on-screen X and Y coordinates of a window (the client area). My problem is that I have to define a horizontal shift which has to be added onto the X coordinate to get the correct result:

#include <windows.h>

inline int get_title_bar_thickness(const HWND window_handle)
{
    RECT window_rectangle, client_rectangle;
    GetWindowRect(window_handle, &window_rectangle);
    GetClientRect(window_handle, &client_rectangle);
    const int height = window_rectangle.bottom - window_rectangle.top -
        (client_rectangle.bottom - client_rectangle.top);
    const int width = window_rectangle.right - window_rectangle.left -
        (client_rectangle.right - client_rectangle.left);
    return height - width / 2;
}

#define HORIZONTAL_SHIFT 8

/**
 * Gets the window position of the window handle
 * excluding the title bar and populates the x and y coordinates
 */
inline void get_window_position(const HWND window_handle, int* x, int* y)
{
    RECT rectangle;
    const auto window_rectangle = GetWindowRect(window_handle, &rectangle);
    const auto title_bar_thickness = get_title_bar_thickness(window_handle);
    if (window_rectangle)
    {
        *x = rectangle.left + HORIZONTAL_SHIFT;
        *y = rectangle.top + title_bar_thickness;
    }
}

The issue can be observed by moving the window programmatically:

const auto window_handle = FindWindow(nullptr, "Command Prompt");
SetWindowPos(window_handle, nullptr, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

I would expect this SetWindowPos() call to perfectly place the window into the upper left corner of my screen but there is some space left between the window and the screen border (exactly 8 pixels). Is there a way to assure that this horizontal offset is automatically considered? This might be related to laptops so how to make this behave as expected?

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • it should be just `*x = rectangle.left; *y = rectangle.top;` Also it is not clear how this is related to `SetWindowPos` issues (which I can not reproduce) – user7860670 Jun 13 '19 at 12:05
  • This obviously happens because you add `HORIZONTAL_SHIFT` (which is 8) to the `X`. – user7860670 Jun 13 '19 at 12:21
  • 3
    On Windows 10, the difference is given by GetWindowRect and DwmGetWindowAttribute with **DWMWA_EXTENDED_FRAME_BOUNDS**, which is usually = 7 – Castorix Jun 13 '19 at 12:25
  • 1
    This sounds like you are trying to retrieve the client area in screen coordinates. To do so, call `GetClientRect`, followed by `ClientToScreen`. – IInspectable Jun 13 '19 at 12:58

1 Answers1

3

As commented by Castorix, the horizontal shift can be retrieved.

#include <dwmapi.h>

#pragma comment(lib, "dwmapi.lib")

inline int get_horizontal_shift(const HWND window_handle)
{
    RECT window_rectangle, frame_rectangle;
    GetWindowRect(window_handle, &window_rectangle);
    DwmGetWindowAttribute(window_handle,
                         DWMWA_EXTENDED_FRAME_BOUNDS, &frame_rectangle, sizeof(RECT));

    return frame_rectangle.left - window_rectangle.left;
}

The code is based on this post. The return value is 7 on my machine.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185