(Windows API)WM_PAINT鼠标问题 [英] (Windows API) WM_PAINT Mouse problems

查看:141
本文介绍了(Windows API)WM_PAINT鼠标问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个带有以下标志的窗口以覆盖d3d应用程序: WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TRANSPARENT | WS_EX_LAYERED 我继续用颜色标记了透明性的窗口,并且一切正常. 但是,一旦我开始使用GDI进行绘图,就会发生无法预料的问题:

I created a window with the following flags to overlay a d3d application: WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TRANSPARENT | WS_EX_LAYERED I proceeded with colorkeying the window for transperacy and all worked well. However once I began drawing on it using GDI an unforeseen problem occurred:

由于某些原因,在进行WM_PAINT时,鼠标事件(尤其是移动)没有正确地通过窗口传递,因此看起来与此有关的鼠标和键盘滞后了. FPS很好,这是一些API问题,我怀疑由于某些原因,在WM_PAINT进行过程中,键盘/鼠标消息没有得到应有的处理,因为计时器设置得越慢,抖动就越少. /p>

For some reason the mouse events (especially movement) are not passed correctly through the window when WM_PAINT is in progress, and so it appears as though the mouse and the keyboard for that matter lag. the FPS is fine, this is some API problem, I suspect that for some reason the keyboard/mouse messages are not handled as they should while the WM_PAINT is in progress, because the slower the timer is set to the less jerking there is.

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

感谢您可能提供的帮助.

Thank you for any help you may be able to give.

推荐答案

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

WM_PAINT messages are never delivered to your window unless someone calls UpdateWindow or there are no keyboard or mouse messages in your input queue.

一旦您开始处理WM_PAINT,如果收到键盘或鼠标消息,它将一直排在您的队列中,直到您完成WM_PAINT.因此,您要描述的内容是不可能的.

Once you begin processing WM_PAINT, if a keyboard or mouse message arrives, it just sits in your queue until you are done with WM_PAINT. So What you are describing isn't possible.

如果您的WM_PAINT代码执行时间很长,则可能会导致混乱,但是您说这不是问题,所以也许是您对WM_ERASEBKGND的处理?我没有看到该代码,但确实看到了,当您InvalidateRect时,您将TRUE作为最后一个参数传递,这意味着您希望擦除背景.

If your WM_PAINT code takes a long time to execute, that could cause jerkiness, but you say that's not a problem so perhaps it's your handling of WM_ERASEBKGND? I don't see that code, but I do see that when you InvalidateRect, you are passing TRUE as the last parameter which means that you want the background to be erased.

如果您不处理WM_ERASEBKGND,则DefWindowProc会执行此操作,以便您使用窗口类中的画笔擦除整个窗口.这可能导致窗口认为窗口的任何部分都不透明.

If you don't handle WM_ERASEBKGND, then DefWindowProc will do it for you erasing your entire window with the brush from from your window class. This could result in windows thinking that no part of your window is transparent.

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

If you want mouse messages to pass through your window, a more reliable way is to handle the WM_NCHITTEST message and return HTTRANSPARENT where you want the mouse to pass through.
This is basically what how the WS_EX_TRANSPARENT style works. like this

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

如果您的窗口没有非工作区,则可以跳过对DefWindowProc的调用.

If your window has no non-client area, then you can skip the call to DefWindowProc.

这篇关于(Windows API)WM_PAINT鼠标问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆