Почему я не получаю правильные координаты курсора с помощью функций Windows API?

Я пытаюсь захватить координаты курсора в приложении Windows. Хотя координата для позиции (0, 0) отображается корректно в левом верхнем углу, но чем дальше я от нее отхожу, тем больше искажаются координаты, так что вместо (600, 600) только (583, 560) отображается в правом нижнем углу. Вот код, который я использую


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

LRESULT MainWindowProcedure(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
    switch (Message)
    {
        case WM_MOUSEMOVE:
        {
            POINT Cursor;
            GetCursorPos(&Cursor);
            ScreenToClient(Window, &Cursor);

            char Buffer[256];
            snprintf(Buffer, sizeof(Buffer), "X: %d, Y: %d \n", Cursor.x, Cursor.y);
            OutputDebugStringA(Buffer);

        } break;
        case WM_DESTROY:
        {
            PostQuitMessage(0);
        } break;
        default:
        {
            return DefWindowProc(Window, Message, WParam, LParam);
        } break;
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
        WNDCLASSEXA WindowClass = {0};

        WindowClass.cbSize = sizeof(WNDCLASSEXA);
        WindowClass.style = CS_HREDRAW | CS_VREDRAW;
        WindowClass.lpfnWndProc = MainWindowProcedure;
        WindowClass.hInstance = hInstance;
        WindowClass.lpszClassName = "WindowClass";

        if (RegisterClassExA(&WindowClass) != 0)
        {
            HWND Window = CreateWindowExA(0, "WindowClass", "Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
                CW_USEDEFAULT, CW_USEDEFAULT, 600, 600, 0, 0, hInstance, 0);
            if (Window != 0)
            {

                int Running = 1;
                while (Running) {

                    MSG Message;

                    while (PeekMessageA(&Message, 0, 0, 0, PM_REMOVE))
                    {
                        if (Message.message == WM_QUIT)
                        {
                            Running = false;
                            break;
                        }

                        TranslateMessage(&Message);
                        DispatchMessageA(&Message);
                    }

                }
            }
        }
}

Я также попробовал GET_X_LPARAM и GET_Y_LPARAM из Windowsx.h. Точно такая же проблема. Кто-нибудь знает, в чем может быть проблема?

Не следует делать GetCursorPos() — извлеките координаты из аргумента LParam (так как вы говорите, что пробовали). Вы никогда не получите 600, 600 из окна с такими размерами, поскольку координаты соответствуют координатам клиентской области, которая меньше, чтобы вместить границы и тому подобное.

500 - Internal Server Error 24.05.2024 23:41

Возможно, вы захотите использовать AdjustWindowRect, если вам нужен определенный размер клиента. Он раздует прямоугольник до необходимого размера, необходимого для обработки границ, меню и т. д.

Retired Ninja 24.05.2024 23:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
94
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, все работает так, как задумано. Система точно сообщает координаты курсора, когда курсор мыши перемещается по клиентской области окна.

Проблема заключается в ошибочных ожиданиях. Аргументы nWidth и nHeight в вызове CreateWindowExA() описывают ширину и высоту окна, включая неклиентскую область (границы, строку заголовка и т. д.).

Запись документации о Windows приложения содержит следующую иллюстрацию, демонстрирующую, что клиентская область меньше прямоугольника окна:

window overview

Чтобы узнать, где находится курсор мыши относительно клиентской области окна, вы можете вызвать GetClientRect() , чтобы определить размеры клиентской области или создать окно с определенным размером клиентской области. AdjustWindowRectEx() вычисляет размер окна для заданного размера клиента.

Имейте в виду, что все это подлежит виртуализации DPI. Разработка настольных приложений с высоким разрешением для Windows раскрывает подробности.

Другие вопросы по теме