(Windows API)WM_PAINT鼠标问题

我创build了一个包含以下标志的窗口覆盖一个d3d应用程序:WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TRANSPARENT | WS_EX_LAYERED我继续着色转换的窗口,一切运作良好。 但是一旦我开始使用GDI进行绘图,就会出现一个无法预料的问题:

出于某种原因,当WM_PAINT正在进行时,鼠标事件(特别是运动)不能正确地通过窗口传递,所以看起来好像鼠标和键盘相对滞后。 FPS是好的,这是一些API的问题,我怀疑由于某种原因,键盘/鼠标消息没有处理,因为他们应该在WM_PAINT正在进行,因为计时器设置得越慢,那就是。

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: { KillTimer(hwnd, ID_TIMER); PostQuitMessage(0); break; } case WM_CREATE: { SetTimer(hwnd, ID_TIMER, 10, NULL); break; } case WM_TIMER: { InvalidateRect(hwnd, 0, 1); break; } case WM_PAINT: { paint(hwnd); break; } } return DefWindowProc(hwnd, msg, wParam, lParam); } 

 void paint (HWND hwnd) { PAINTSTRUCT Ps; HDC hdc = BeginPaint(hwnd, &Ps); SetBkColor(hdc, RGB(0,0,0)); SetBkMode(hdc, TRANSPARENT); LOGBRUSH log_brush; log_brush.lbStyle = BS_NULL; HBRUSH handle_brush = CreateBrushIndirect(&log_brush); SelectObject(hdc, handle_brush); .......................................... DeleteObject(font); DeleteObject(pen); DeleteObject(handle_brush); EndPaint(hwnd, &Ps); } 

感谢您提供的任何帮助。

除非有人调用UpdateWindow或者在输入队列中没有键盘或鼠标消息,否则WM_PAINT消息不会传递到窗口。

一旦开始处理WM_PAINT,如果键盘或鼠标消息到达,它只是在您的队列中,直到完成WM_PAINT。 所以你所描述的是不可能的。

如果你的WM_PAINT代码需要很长时间才能执行,那可能会造成不稳定,但是你说这不是问题,所以也许是你对WM_ERASEBKGND的处理? 我没有看到这个代码,但是我确实看到,当你InvalidateRect ,你传递TRUE作为最后一个参数,这意味着你想要背景被删除。

如果你不处理WM_ERASEBKGND,那么DefWindowProc将会用你的窗口类中的笔刷来擦除整个窗口。 这可能会导致Windows认为窗口的任何部分都不透明。

如果你想鼠标消息通过你的窗口,更可靠的方法是处理WM_NCHITTEST消息,并返回HTTRANSPARENT你想要鼠标通过。
这基本上是WS_EX_TRANSPARENT风格的工作原理。 喜欢这个

 case WM_NCHITTEST: { lRet = DefWindowProc(hwnd, uMsg, wParam, lParam); if (HTCLIENT == lRet) lRet = HTTRANSPARENT; } 

如果你的窗口没有非客户区域,那么你可以跳过对DefWindowProc的调用。

WndProc()并不总是可重入的。 我相信随着主消息泵,鼠标和键盘消息排队等待您完成以前的WM_PAINT消息。 相反,如果您要从WndProc()调用SendMessage(),那么您正在查看re-entrace。 另一种情况是PostMessage()会将消息添加到队列中。 如果这是一个问题,也许看看使用DirectInput进行鼠标和键盘输入。 否则,寻找加快绘图的方法。