(Windows API) WM_PAINT Проблемы с мышью
Я создал окно со следующими флагами для наложения 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);
}
Спасибо за любую помощь, которую вы можете оказать.
2 ответа
Сообщения 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.
WndProc() не всегда повторный. Я думаю, что с основным насосом сообщений сообщения мыши и клавиатуры ставятся в очередь и ждут, пока вы закончите предыдущее сообщение WM_PAINT. И наоборот, если вы вызываете SendMessage() из WndProc(), то вы смотрите на повторный захват. Другой случай - PostMessage(), который добавил бы сообщение в очередь. Может быть, посмотрите на использование DirectInput для ввода с клавиатуры и мыши, если это проблема. В противном случае ищите способы ускорить ваш рисунок.