1

I Was working on a win32 project which uses the WM_MOVING message from WndProc to detect the new position where window is moved. but when i try to snap the window to left side the LPARAM gives wrong values for just a millisecond and gives the real value after that.

Please have a look into the output:

Left: 0, Right:683
Left: -205, Right:295
Left: 0, Right:683
Left: -205, Right:295
Left: 0, Right:683
Left: -205, Right:295

The real output is -205 but in between I get zero which cause the content of my window to flicker. In my case the position of the content is depend on the window position, so it causes flicker if I receive a wrong value.

Here is what i am trying to achieve : Manually creating acrylic effect

IMG Aero snap

When ever I move the window in this mode (just before the aero snap mode) the value will get changed to zero.

This is only affecting The Top and Left coordinates of the window and also flickers when aero snapping to any sides.

Here is a simple reproduceable example:

#ifndef UNICODE
#define UNICODE
#endif 

#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
RECT* hostRect;
char buffer[200];

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{

    const wchar_t CLASS_NAME[] = L"Sample Window Class";
    WNDCLASS wc = { };

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(0,CLASS_NAME,L"Learn to Program Windows",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL,hInstance,NULL);

    if (hwnd == NULL)
    {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    MSG msg = { };
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_MOVING:
    {
        hostRect = reinterpret_cast<RECT*>(lParam);
        sprintf_s(buffer, "Left: %d, Top:%d, Right:%d, Bottom:%d\n", hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
        OutputDebugStringA(buffer);
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
        EndPaint(hwnd, &ps);
    }
    return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Run this program and check the value in output while you move the window to any side for aero snap.

Note: In my case i will not be able to use GetWindowRect() in WM_MOVING, because calling GetWindowRect() slow down the render() function (just a directx painting) in my window.

trickymind
  • 557
  • 5
  • 21

1 Answers1

1

You can try to make temporary changes to the style of the window.

Here is an example:

#ifndef UNICODE
#define UNICODE
#endif 

#include <windows.h>
#include <stdio.h>
#define WM_RESTOREORIGINALSTYLE WM_USER + 1

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
RECT* hostRect;
char buffer[200];

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{

    const wchar_t CLASS_NAME[] = L"Sample Window Class";
    WNDCLASS wc = { };

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"Learn to Program Windows", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
    {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    MSG msg = { };
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_MOVING:
    {
        hostRect = reinterpret_cast<RECT*>(lParam);
        sprintf_s(buffer, "Left: %d, Top:%d, Right:%d, Bottom:%d\n", hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
        OutputDebugStringA(buffer);
        break;
    }

    case WM_SYSCOMMAND:
    {
        if (wParam == (SC_MOVE | 2)) wParam = SC_SIZE | 9;
        if ((wParam & 0xFFE0) == SC_SIZE && (wParam & 0x000F)) // handles MOVE and SIZE in one "if"
        {
            long int oldStyle = GetWindowLongW(hwnd, GWL_STYLE);
            PostMessageW(hwnd, WM_RESTOREORIGINALSTYLE, GWL_STYLE, oldStyle);
            SetWindowLongW(hwnd, GWL_STYLE, oldStyle & 0xFEFEFFFF); // disable WS_MAXIMIZE and WS_MAXIMIZEBOX
            DefWindowProcW(hwnd, WM_SYSCOMMAND, wParam, lParam);
            return 0;
        }
        return DefWindowProcW(hwnd, WM_SYSCOMMAND, wParam, lParam);
    }
    case WM_RESTOREORIGINALSTYLE:
    {
        if ((long int)wParam == GWL_STYLE)
            SetWindowLongW(hwnd, GWL_STYLE, lParam);
        return 0;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
        EndPaint(hwnd, &ps);
    }
    return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

More reference : Win32 prevent window “snap”

Zeus
  • 3,703
  • 3
  • 7
  • 20
  • Let me have a look – trickymind Jan 18 '21 at 09:44
  • but this one prevents me from using aero snap feature. i need aero snap feature – trickymind Jan 18 '21 at 09:48
  • is there any other alternative without loosing aero snapping – trickymind Jan 18 '21 at 09:48
  • @trickymind The reason that causes the window coordinates to change is because the window is captured by aviation. It seems that it is impossible to ensure that the position value is correct while capturing by aviation. – Zeus Jan 18 '21 at 09:50
  • This wrong values are becoming a problem only when i move window to corners. when maximized I can use the Desktop RECT – trickymind Jan 18 '21 at 09:56
  • When the window is moved to the corner, the window will be captured by aviation, and the coordinate value of the window will be displayed. Of course, you can do the processing according to the coordinate value captured by the aerial, and it will change the window size and position according to your resolution. – Zeus Jan 18 '21 at 09:59
  • How can i do that? – trickymind Jan 18 '21 at 10:01
  • Like `Left: 0, Right: 683`, it actually corresponds to half of your screen resolution. Triggering aerial capture will correspond to your entire screen resolution or half (according to the position you drag), if you don’t need this You can ignore the coordinates of several places.If you want to keep the aerial capture without triggering the flicker, this seems difficult to do. – Zeus Jan 19 '21 at 01:13
  • Yes it is difficult. Any changes I make will cause the flicker to come back – trickymind Jan 19 '21 at 01:31
  • I need to confirm why you need to do this, because the problem you raised has actually been solved, and the coordinates given are actually not wrong, just the position coordinates of the window after aerial capture. – Zeus Jan 19 '21 at 01:35
  • I am actually trying to recreate the acrylic blur effect of windows 10, i uses desktop background for ID2D1 Effect and when i move the window to a new position the input to effect should be having the same size as the window rect. – trickymind Jan 19 '21 at 04:22
  • It cannot prevent it from triggering the `WM_MOVING` message while retaining the aero snapping. You may be able to filter out the coordinate information you don't need because the coordinate changes obviously when the aerial capture is triggered, such as `Bottom` approaching the screen height or `Right` being the width of the whole or half screen. – Zeus Jan 19 '21 at 06:00