2 votes

Coordonnées étranges dans `WM_MOUSEMOVE`.

MSDN décrit que lParam de WM_MOUSEMOVE est de 2 short est due au fait qu'elle doit être compatible avec les coordonnées virtuelles car elle agit comme un événement redirigé si la capture est activée, ce qui est clair. Cependant, les coordonnées négatives sont toujours reçues dans des circonstances normales lorsque l'on déplace la souris légèrement en dehors de la fenêtre, pour être exact un bonus de 5 pixels dans toutes les directions sauf vers le haut (qui est là où se trouve la légende, et elle irait à WM_NCMOUSEMOVE à la place).

J'ai d'abord pensé que cela était dû au fait que l'ombre portée faisait techniquement partie de la fenêtre (comme avec la sortie de AdjustWindowRectEx Il est possible de recevoir des événements dans une partie de l'ombre, mais les valeurs ne correspondent pas et le fait de fixer les valeurs à la taille de la zone client n'est pas voulu. D'où viennent les 5 pixels supplémentaires (sur mon système, Windows 10 Education 2004), surtout si l'on considère qu'ils ne devraient même pas faire partie de la zone client à ma connaissance, et existe-t-il un moyen propre/intuitif d'éviter les valeurs indésirables ?

J'ai vu des discussions sur le lien potentiel entre la zone que vous pouvez saisir pour redimensionner la fenêtre, mais ma fenêtre n'est pas redimensionnable (elle n'a pas de cadre épais).

Visualization

Edit : Après avoir bricolé, il semble que cela soit lié au style de la fenêtre. Voici un exemple reproductible (sur d'autres machines, j'espère) :

#include <Windows.h>
#include <stdio.h>

// Remove `^ WS_THICKFRAME` and the bug vanishes!
#define WINDOW_STYLE ((WS_OVERLAPPEDWINDOW | WS_VISIBLE) ^ WS_THICKFRAME)

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_MOUSEMOVE) {
        POINTS mouse = MAKEPOINTS(lParam);
        printf("WM_MOUSEMOVE @ x=%hd, y=%hd\n", mouse.x, mouse.y);
    } else if (message == WM_DESTROY) {
        PostQuitMessage(0);
    }
    return DefWindowProcW(hWnd, message, wParam, lParam);
}

int main(void) {
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = GetModuleHandle(NULL);
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"SO_Example";
    wcex.hIconSm = NULL;

    RECT windowRect = { 0, 0, 600, 600 };
    AdjustWindowRectEx(&windowRect, WINDOW_STYLE, FALSE, 0);

    ATOM windowClass = RegisterClassExW(&wcex);
    HWND hWnd = CreateWindowExW(
        0,
        (LPCWSTR)windowClass,
        L"hello stackoverflow!",
        WINDOW_STYLE,
        CW_USEDEFAULT, CW_USEDEFAULT,
        windowRect.right - windowRect.left,
        windowRect.bottom - windowRect.top,
        NULL,
        NULL,
        GetModuleHandle(NULL),
        NULL
    );

    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0) != 0) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    return 0;
}

Voici cet échantillon en action : https://i.imgur.com/LfCe9od.mp4

0voto

user15564038 Points 21

Il semble que 5 est la taille de la bordure (1) et le remplissage de la bordure (4) additionnés (c'est-à-dire la zone que l'utilisateur peut utiliser pour redimensionner la fenêtre), il est donc possible de rejeter les valeurs situées en dehors du rectangle du client, même s'il est un peu étrange que Win32 signale des événements dans cette zone.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X