簡體   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