Dia
Dia

Reputation: 947

Modify the win32 window dragging/moving behavior

I have a child window in a parent window. I want the child window not go out of the parent border when I drag and move the child window.

Here is my current working code in child's callback:

case WM_MOVE:
    RECT rect = getLocalCoordinates(hWnd);
    RECT rectFather;
    GetWindowRect(hWndFather, &rectFather);
    if (rect.left < 0)
        rect.left = 0;
    if (rect.top < 0)
        rect.top = 0;
    if (rect.bottom > rectFather.bottom - rectFather.top - 60)
        rect.top = rectFather.bottom - rectFather.top - 341;
    if (rect.right > rectFather.right - rectFather.left - 35)
        rect.left = rectFather.right - rectFather.left - 110;
    SetWindowPos(hWnd, NULL,rect.left, rect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    break;

The only thing I miss is that when dragging my child window over the parent border, the child window keeps blinking.

It is because the child window first moved out of border, than the WM_MOVE message triggers my SetWindowPos.

My question is: how could I prevent this, maybe by overriding the mouse drag event?

Upvotes: 2

Views: 2882

Answers (3)

ewu11
ewu11

Reputation: 65

From what I understand, the better and simpler solution for this would be when you are creating the child window, which is when calling the "CreateWindow()" method.

Under "dwStyle" parameter, you can set the child's style to WS_CHILD | WS_OVERLAPPEDWINDOW | WS_VISIBLE

Example: CreateWindow(lpClassName, lpWindowName, WS_CHILD | WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);

where:

lpClassName = child's window class name,
lpWindowName = child's window name,
x = child window x position,
y = child window y position,
nWidth = child window width,
nHeight = child window height,
hWndParent = parent window of the child's window,
hMenu = nullptr | identifier of the child window,
hInstance = nullptr,
pParam = nullptr.

Upvotes: 0

IInspectable
IInspectable

Reputation: 51355

While handling the WM_WINDOWPOSCHANGING it is possible to confine window movement, it has the unpleasant effect to break the visual connection between the mouse cursor and the dragged window, once you move the mouse outside the allowed area.

Another solution to the problem is to confine the cursor movement, by calling ClipCursor, passing in an appropriately sized bounding rectangle. This ensures that the cursor will always be in the same location relative to the dragged window.

Upvotes: 3

Dia
Dia

Reputation: 947

Thanks to RbMm, WM_WINDOWPOSCHANGING message is what I need. The new working code:

case WM_WINDOWPOSCHANGING: 
    WINDOWPOS *pos = (WINDOWPOS *)lParam;
    RECT rectFather;
    GetWindowRect(hWndFather, &rectFather);

    if (pos->x < 0)
        pos->x = 0;
    if (pos->y < 0)
        pos->y = 0;
    if (pos->y > rectFather.bottom - rectFather.top - 341)
        pos->y = rectFather.bottom - rectFather.top - 341;
    if (pos->x > rectFather.right - rectFather.left - 110)
        pos->x = rectFather.right - rectFather.left - 110;

    break;

Upvotes: 3

Related Questions