我创建了一个带有以下标志的窗口来覆盖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);
}
感谢您提供任何帮助。
答案 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进行鼠标和键盘输入。否则,寻找加快绘图速度的方法。