Erkan Demirci
Erkan Demirci

Reputation: 21

GetCursorPos doesn't work when mouse stops with GetMessage-based Window

I'm making a UI-based DirectX 11 application. I had no problem until I found out that PeekMessage() uses high CPU usage (it triples the usage when the window is minimized), so I decided to use GetMessage(), but now inputs are being weird and I don't know how to explain that, when the mouse stops it doesn't give me the cursor position.

Here is the function that gives me the cursor position:

Vector2f* InputSystem::GetMousePosition(Window* window, bool normalized) {
    POINT p;
    GetCursorPos(&p);
    RECT r;
    GetClientRect(window->hWnd, &r);
    ScreenToClient(window->hWnd, &p);
    lastMousePos = Vector2i(p.x - (r.right - r.left) / 2.0f, p.y - (r.bottom - r.top) / 2.0f);
    lastMousePos.y *= -1.0f;
    lastMousePos *= 2.0f;
    if (normalized) { lastMousePos /= Vector2f(window->GetClientSize().x, window->GetClientSize().y); }
    return &lastMousePos;
}

And the loop:

while (mainWindow.IsRunning()) {
    mainWindow.Broadcast();
    mainWindow.PhaseUpdate();
    mainWindow.Loop();
}

Window::Broadcast():

void Window::Broadcast() {
    if (GetMessageA(&msg, hWnd, NULL, NULL)) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }
}

Upvotes: 0

Views: 88

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597036

GetMessage() blocks the calling thread until a message arrives. PeekMessage() does not block. You want something like PeekMessage() in a game loop rather than GetMessage(). Despite your claim, using PeekMessage() will not increase your CPU load unless you misuse it. For instance, rather than calling it only once per loop iteration, try calling it in a 2nd loop until the message queue is drained, eg:

void Window::Broadcast() {
    while (PeekMessageA(&msg, hWnd, 0, 0, PM_REMOVE)) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }
}

Also, see The dangers of filtering window messages

Upvotes: 3

Related Questions