简体   繁体   中英

GetClientRect on WM_SIZING gives wrong size

I need to get correct size (width / height) of window's client area, when window is being resized. I tried to use GetClientRect , but it ALWAYS gives WRONG values (see details below).

User32.RECT clientRECT;
User32.GetClientRect(_handle, out clientRECT);

So I decided to store x- and y-delta, between window rect (with borders) and client rect, when window is created, and then sum up this delta values with window rect, received from lParam of WM_SIZING message.

var windowRECT = (User32.RECT)Marshal.PtrToStructure(lParam, typeof(User32.RECT));
var clientAreaWidth = ((windowRECT.right - windowRECT.left) + _xDelta);
var clientAreaHeight = ((windowRECT.bottom - windowRECT.top) + _yDelta);

This trick ALWAYS gives RIGHT size.

But why GetClientRect has such strange behavior? So I wrote this code to get more details about what is going on.

Debug.WriteLine("dX: " + (clientRECT.right - clientAreaWidth).ToString() + ", dY: " + (clientRECT.bottom - clientAreaHeight).ToString());

Then I started project and began dragging right-bottom corner of the window. Here's the output:

dX: 16, dY: 17 // fast dragging in NW-direction
dX: 21, dY: 16
dX: 34, dY: 25
dX: 92, dY: 62
dX: 110, dY: 75
dX: 94, dY: 65
dX: 60, dY: 48
dX: 22, dY: 19
...
dX: 0, dY: 1 // slow dragging in NW-direction
dX: 0, dY: 2
dX: 0, dY: 1
dX: 0, dY: 1
dX: 0, dY: 1
dX: 1, dY: 1
dX: 0, dY: 1
dX: 1, dY: 2
dX: 0, dY: 1
...
dX: -16, dY: -12 // fast dragging in SE-direction
dX: -68, dY: -65
dX: -77, dY: -75
dX: -53, dY: -43
dX: -22, dY: -17
dX: -5, dY: -4
...
dX: -1, dY: 0 // slow dragging in SE-direction
dX: -1, dY: 0
dX: -1, dY: 0
dX: -1, dY: -1
dX: -1, dY: 0
dX: -1, dY: -1
dX: -1, dY: 0
dX: 0, dY: -1
dX: -1, dY: 0
dX: 0, dY: -1

What cause this behavior?

如果要使用WM_SIZING ,则需要使用lParam携带的rect,而不是GetClientRect的结果

As the other answer correctly states, you should use the RECT* in lParam provided by WM_SIZING instead of doing extra calls that may return something out of date.

Since it provides the screen rectangle of the window, including the window border size, here's one way you can retrieve the client rectangle from it:

case WM_SIZING:
{
    // Get size of window border.
    // TODO: replace WS_OVERLAPPEDWINDOW with your window style.
    RECT pad{};
    check_bool(AdjustWindowRect(&pad, WS_OVERLAPPEDWINDOW, FALSE));

    // Subtract window border from screen rectangle to retrieve client rectangle.
    RECT* screenRect = (RECT*)lParam;
    RECT clientRect
    {
        screenRect->left - pad.left,
        screenRect->top - pad.top,
        screenRect->right - pad.right,
        screenRect->bottom - pad.bottom
    };

    // TODO: Use the client rectangle in your code.
    LONG clientWidth = clientRect.right - clientRect.left;
    LONG clientHeight = clientRect.bottom - clientRect.top;

    break;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM