Я пытаюсь захватить координаты курсора в приложении 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. Точно такая же проблема. Кто-нибудь знает, в чем может быть проблема?
Возможно, вы захотите использовать AdjustWindowRect, если вам нужен определенный размер клиента. Он раздует прямоугольник до необходимого размера, необходимого для обработки границ, меню и т. д.
Кажется, все работает так, как задумано. Система точно сообщает координаты курсора, когда курсор мыши перемещается по клиентской области окна.
Проблема заключается в ошибочных ожиданиях. Аргументы nWidth
и nHeight
в вызове CreateWindowExA() описывают ширину и высоту окна, включая неклиентскую область (границы, строку заголовка и т. д.).
Запись документации о Windows приложения содержит следующую иллюстрацию, демонстрирующую, что клиентская область меньше прямоугольника окна:
Чтобы узнать, где находится курсор мыши относительно клиентской области окна, вы можете вызвать GetClientRect() , чтобы определить размеры клиентской области или создать окно с определенным размером клиентской области. AdjustWindowRectEx() вычисляет размер окна для заданного размера клиента.
Имейте в виду, что все это подлежит виртуализации DPI. Разработка настольных приложений с высоким разрешением для Windows раскрывает подробности.
Не следует делать
GetCursorPos()
— извлеките координаты из аргументаLParam
(так как вы говорите, что пробовали). Вы никогда не получите 600, 600 из окна с такими размерами, поскольку координаты соответствуют координатам клиентской области, которая меньше, чтобы вместить границы и тому подобное.