WM_LBUTTONDOWN 按下鼠标按钮时不立即发送
WM_LBUTTONDOWN not sent immediately when mouse button is down
我无法在 Windows 10 中使用 C++ 准确检测何时按下鼠标左键。
我尝试了两种方法:
捕获WM_LBUTTONDOWN
消息
直接使用GetKeyState(VK_LBUTTON)
每次,行为都是一样的:
如果我在一秒钟内按下左键,
WM_LBUTTONDOWN
在我按下后约 0.5 秒发送
左键
返回的GetKeyState(VK_LBUTTON)
值在发送WM_LBUTTONDOWN时完全改变,这意味着在我按下鼠标按钮后0.5秒
WM_LBUTTONDOWN
已发送:
- 如果我只用左键单击
- 如果我按下鼠标 同时移动鼠标
但是我还是不知道如何在我长按左键不移动鼠标的情况下立即检测左键按下。
有我不知道的活动吗?
Windows 是否迫使我们思考它的方式并使用它的 "CLICK" 和它的 "MOUSEDOWN" ?我的意思是,windows 是否无法准确检测鼠标按钮何时被按下?
如何在 windows 中使用 C++ 精确检测何时按下左键?
编辑:
感谢您的回答。
我制作了一个 Minimal Complete and Verifiable code 给你看。
以下程序使用 Visual C++ 2017 编译
它显示一个蓝色矩形,每次 GetMessage 收到消息时该矩形都会移动。
当检测到 WM_LBUTTONDOWN 时,矩形变为红色并向下平移。
正如我在第一个 post 中描述的那样:当您单击或在移动鼠标时按下鼠标按钮时,您会看到矩形变红,但变红大约需要 0.5 秒如果你按下左键不移动鼠标。
再次感谢您的帮助。
这是代码:
#include <Windows.h>
#include <GL/GL.h>
#include <math.h>
#pragma comment(lib, "opengl32.lib")
HDC hdc;
HGLRC hrc;
bool ButtonL;
void MyDisplay()
{
static float kk=0; kk+=0.04f;
glMatrixMode(GL_MODELVIEW); glLoadIdentity();glTranslated(0.5*sin(kk),0,0);
glMatrixMode(GL_PROJECTION); glLoadIdentity();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if ((GetKeyState(VK_LBUTTON) & 0x100) != 0) glColor3f(1,0,0); else glColor3f(0,0,1);
if (ButtonL) glTranslated(0,-0.5,0);
glBegin(GL_QUADS); glVertex2f(0,0); glVertex2f(0,1); glVertex2f(1,1); glVertex2f(1,0); glEnd();
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDOWN : ButtonL=true; break;
case WM_LBUTTONUP : ButtonL=false; break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int main(int argc, char** argv)
{
ButtonL=false;
WNDCLASS wc;
RECT WindowRect;
WindowRect.left =(long)0; WindowRect.right =(long)400;
WindowRect.top =(long)0; WindowRect.bottom =(long)300;
HINSTANCE hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
if (!RegisterClass(&wc)) return(0);
AdjustWindowRectEx(&WindowRect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
HWND hWnd=CreateWindowEx( WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,"OpenGL","Titre",WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0,
WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top,NULL,NULL,hInstance,NULL);
PIXELFORMATDESCRIPTOR pfd=
{ sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,PFD_TYPE_RGBA,32, 0, 0, 0, 0, 0, 0,
0,0,0,0, 0, 0, 0,16,0,0,PFD_MAIN_PLANE,0,0, 0, 0
};
hdc=GetDC(hWnd);
GLuint PixelFormat=ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,PixelFormat,&pfd);
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc , hrc);
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
MSG Msg;
while( GetMessage( &Msg, hWnd, 0, 0 ) != 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
MyDisplay();
SwapBuffers(hdc);
}
return 0;
}
你的程序在我的电脑上运行良好:按下按钮时我没有注意到任何延迟。
似乎 windows 消息在您的计算机上以非常低的级别被截获。
您是否使用像 "Sensiva" 或 "Just Gesture" 或 "Stroke it" 这样的鼠标识别引擎?
它可以解释你的问题。
我无法在 Windows 10 中使用 C++ 准确检测何时按下鼠标左键。
我尝试了两种方法:
捕获
WM_LBUTTONDOWN
消息直接使用
GetKeyState(VK_LBUTTON)
每次,行为都是一样的:
如果我在一秒钟内按下左键,
WM_LBUTTONDOWN
在我按下后约 0.5 秒发送 左键返回的
GetKeyState(VK_LBUTTON)
值在发送WM_LBUTTONDOWN时完全改变,这意味着在我按下鼠标按钮后0.5秒
WM_LBUTTONDOWN
已发送:
- 如果我只用左键单击
- 如果我按下鼠标 同时移动鼠标
但是我还是不知道如何在我长按左键不移动鼠标的情况下立即检测左键按下。 有我不知道的活动吗? Windows 是否迫使我们思考它的方式并使用它的 "CLICK" 和它的 "MOUSEDOWN" ?我的意思是,windows 是否无法准确检测鼠标按钮何时被按下? 如何在 windows 中使用 C++ 精确检测何时按下左键?
编辑:
感谢您的回答。 我制作了一个 Minimal Complete and Verifiable code 给你看。
以下程序使用 Visual C++ 2017 编译 它显示一个蓝色矩形,每次 GetMessage 收到消息时该矩形都会移动。 当检测到 WM_LBUTTONDOWN 时,矩形变为红色并向下平移。
正如我在第一个 post 中描述的那样:当您单击或在移动鼠标时按下鼠标按钮时,您会看到矩形变红,但变红大约需要 0.5 秒如果你按下左键不移动鼠标。
再次感谢您的帮助。
这是代码:
#include <Windows.h>
#include <GL/GL.h>
#include <math.h>
#pragma comment(lib, "opengl32.lib")
HDC hdc;
HGLRC hrc;
bool ButtonL;
void MyDisplay()
{
static float kk=0; kk+=0.04f;
glMatrixMode(GL_MODELVIEW); glLoadIdentity();glTranslated(0.5*sin(kk),0,0);
glMatrixMode(GL_PROJECTION); glLoadIdentity();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if ((GetKeyState(VK_LBUTTON) & 0x100) != 0) glColor3f(1,0,0); else glColor3f(0,0,1);
if (ButtonL) glTranslated(0,-0.5,0);
glBegin(GL_QUADS); glVertex2f(0,0); glVertex2f(0,1); glVertex2f(1,1); glVertex2f(1,0); glEnd();
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_LBUTTONDOWN : ButtonL=true; break;
case WM_LBUTTONUP : ButtonL=false; break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int main(int argc, char** argv)
{
ButtonL=false;
WNDCLASS wc;
RECT WindowRect;
WindowRect.left =(long)0; WindowRect.right =(long)400;
WindowRect.top =(long)0; WindowRect.bottom =(long)300;
HINSTANCE hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "OpenGL";
if (!RegisterClass(&wc)) return(0);
AdjustWindowRectEx(&WindowRect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
HWND hWnd=CreateWindowEx( WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,"OpenGL","Titre",WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0,
WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top,NULL,NULL,hInstance,NULL);
PIXELFORMATDESCRIPTOR pfd=
{ sizeof(PIXELFORMATDESCRIPTOR),1,PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,PFD_TYPE_RGBA,32, 0, 0, 0, 0, 0, 0,
0,0,0,0, 0, 0, 0,16,0,0,PFD_MAIN_PLANE,0,0, 0, 0
};
hdc=GetDC(hWnd);
GLuint PixelFormat=ChoosePixelFormat(hdc,&pfd);
SetPixelFormat(hdc,PixelFormat,&pfd);
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc , hrc);
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
MSG Msg;
while( GetMessage( &Msg, hWnd, 0, 0 ) != 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
MyDisplay();
SwapBuffers(hdc);
}
return 0;
}
你的程序在我的电脑上运行良好:按下按钮时我没有注意到任何延迟。 似乎 windows 消息在您的计算机上以非常低的级别被截获。 您是否使用像 "Sensiva" 或 "Just Gesture" 或 "Stroke it" 这样的鼠标识别引擎? 它可以解释你的问题。