2017-11-18 162 views
-3

在Windows 10中,当使用C++按下鼠标左键时,无法准确检测到鼠标按键。WM_LBUTTONDOWN在鼠标按键关闭时不会立即发送

我尝试2种方式:

  1. 醒目WM_LBUTTONDOWN消息

  2. 直接使用GetKeyState(VK_LBUTTON)

每一次,行为是相同的:
如果我按左按钮,在一秒钟内,

  1. WM_LBUTTONDOWN后我按下 左键

  2. GetKeyState(VK_LBUTTON)返回值的变化恰好当WM_LBUTTONDOWN被发送,这意味着0.5秒后我按下鼠标按钮被发送约0.5秒

WM_LBUTTONDOWN发送:

  1. 如果我只点击用左键
  2. 如果我按鼠标按下同时移动鼠标

但我仍然不知道如何立即检测当左键向下长时间按下左按钮而不移动鼠标的情况。 有没有我不知道的事件? Windows是否迫使我们思考它的方式并使用其“CLICK”及其“MOUSEDOWN”?我的意思是,有没有办法用windows来检测鼠标按键被按下的时间? 如何准确检测在Windows中用C++按下左按钮的时间?


编辑:

谢谢您的解答。 我做了一个最小完整和可验证的代码来展示给你。

下面的程序使用Visual C++编译2017 它显示了一个蓝色的矩形,每次GetMessage都会收到一条消息。 当检测到WM_LBUTTONDOWN时,该矩形变为红色并向下翻译。

正如我在第一篇文章中所描述的那样:当您单击鼠标或当您移动鼠标时按下鼠标按钮时,您会看到矩形变为红色,但如果按下左键并不要移动鼠标。

再次感谢您的帮助。

下面是代码:

#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; 
} 
+2

它没有发送,它被张贴。它立即被添加到消息队列中。当你的程序读取它是不可预知的,这取决于你做了什么。就像处理之前的消息一样。是的,GetKeyState()与您的GetMessage()调用同步。考虑使用MSG.time成员,默认情况下精度大约为16毫秒。 –

+1

半秒钟听起来不对。你的程序可能有些问题。只有你可以看到它。 –

+0

发布相关代码 – Asesh

回答

2

你的程序工作正常,我的电脑上:当我按下按钮时,我没有注意到任何延迟。 看起来Windows消息在您的计算机上处​​于非常低的级别。 您是否使用“Sensiva”或“Just Gesture”或“Stroke it”等鼠标识别引擎? 它可以解释你的问题。

+0

就像看起来那样令人难以置信,那就是解决方案!事实上,我使用“Just Gesture”,如果我禁用这个程序,0.5秒的延迟消失! 我不明白这样的程序如何拦截Windows消息并惹恼我的C++程序,但这是另一个问题。 – Xhilbert

+0

推测“Just Gesture”不会为您计算机上运行的其他程序产生任何问题,但它确实会为您的程序带来问题。你的程序和其他程序有什么区别?消息循环中的明显错误是可疑的。 –