(Windows API)WM_PAINT鼠标问题

时间:2010-02-20 04:49:37

标签: windows window gdi overlay createwindow

我创建了一个带有以下标志的窗口来覆盖d3d应用程序: WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TRANSPARENT | WS_EX_LAYERED 我继续对窗口进行颜色调整,以便顺利进行,一切运作良好。 然而,一旦我开始使用GDI进行绘制,就会发生无法预料的问题:

出于某种原因,当WM_PAINT正在进行时,鼠标事件(尤其是移动)没有正确地通过窗口传递,因此看起来好像鼠标和键盘的延迟。 FPS很好,这是一些API问题,我怀疑由于某些原因,键盘/鼠标消息在WM_PAINT正在进行时没有得到处理,因为定时器被设置为较少的抖动。“ / p>

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);
}

感谢您提供任何帮助。

2 个答案:

答案 0 :(得分:1)

WM_PAINT消息永远不会传递到您的窗口,除非有人调用UpdateWindow或输入队列中没有键盘或鼠标消息。

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

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

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

如果您希望鼠标消息通过您的窗口,更可靠的方法是处理WM_NCHITTEST消息并返回您希望鼠标通过的HTTRANSPARENT。
这基本上就是WS_EX_TRANSPARENT样式的工作方式。像这样

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

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

答案 1 :(得分:0)

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