繁体   English   中英

WM_MOVING,LPARAM 在气动快照上给出错误的值

[英]WM_MOVING, LPARAM Gives Wrong values on aero snap

我正在开发一个 win32 项目,该项目使用来自WndProcWM_MOVING消息来检测新的 position,其中 window 被移动。 但是当我尝试将 window 捕捉到左侧时,LPARAM 仅在一毫秒内给出错误值,然后给出实际值。

请查看 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

真正的 output 是 -205 但在两者之间我得到零,这导致我的 window 的内容闪烁。 在我的情况下,内容的 position 取决于 window position,因此如果我收到错误的值,它会导致闪烁。

这是我想要实现的目标:手动创建丙烯酸效果

IMG 航空按扣

每当我在此模式下(就在航空快照模式之前)移动 window 时,该值将变为零。

这仅影响 window 的TopLeft坐标,并且在气动捕捉到任何侧面时也会闪烁。

这是一个简单的可复制示例:

#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);
}

运行此程序并检查 output 中的值,同时将 window 移动到任何一侧以进行气动捕捉。

注意:在我的情况下,我将无法在WM_MOVING中使用GetWindowRect() ,因为调用GetWindowRect()会减慢我的 window 中的 render() function(只是一个 directx 绘画)。

您可以尝试对 window 的样式进行临时更改。

这是一个例子:

#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);
}

更多参考: Win32 防止 window “snap”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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