我目前正试图以外部插件的形式将我的一些动画绘图代码集成到第三方应用程序中。
在我的基础应用程序中,我是世界之王,我控制应用程序消息泵,以便尽可能地进行绘图。像这样:
for (;;)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
do
{
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
}
draw();
}
现在我不再是世界之王,我必须好好处理应用程序消息,这样它才能保持响应。据我所知,由于我是一个插件,我无法劫持整个应用程序消息泵;所以我尝试了各种各样的事情,在里面画画
WM_PAINT
消息处理程序:
使用
WM_TIMER
,这不起作用:我事先不知道我需要哪个时间步长(通常不是固定的),时间也不准确。
呼叫
InvalidateRect
一旦我完成绘图,它就不起作用了:完全阻止了应用程序的其余部分响应并自行刷新。
无效Rect
there
).
到目前为止,我的最后一次尝试是更好的,有时效果很好。
DWORD WINAPI PaintCommandThreadProc(LPVOID lpParameter)
{
Plugin* plugin = static_cast<Plugin*>(lpParameter);
HANDLE updateEvent = plugin->updateEvent();
while (updateEvent == plugin->updateEvent())
{
::WaitForSingleObject(updateEvent, 100);
::Sleep(0);
if (updateEvent == plugin->updateEvent())
{
::PostMessage(plugin->hwnd(), WM_USER+0x10, 0, 0);
}
}
return 0;
}
...
LRESULT CALLBACK PluginWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
bool processDefault = true;
LRESULT result = 0;
Plugin* plugin = reinterpret_cast<Plugin*>( GetWindowLong(hWnd, GWL_USERDATA) );
switch (msg) {
...
case WM_GL_MESSAGE:
{
::InvalidateRect( hWnd, NULL, FALSE );
processDefault = false;
result = TRUE;
}
break;
case WM_PAINT:
{
draw(hWnd);
::SetEvent( plugin->updateEvent() );
processDefault = false;
result = TRUE;
}
break;
...
}
if (processDefault && plugin && plugin->m_wndOldProc)
result = ::CallWindowProc(plugin->m_wndOldProc, hWnd, msg, wParam, lParam);
return result;
}
对于这种尽可能频繁的动画重绘问题,是否有任何“行业标准”的解决方案?