我想阻止我的窗口更新,直到我从服务器接收数据并呈现它。我可以挂钩WM_PAINT事件,或者更好的是仍然调用一些Win32API方法来防止窗口被更新并在以后解冻它?
更多信息: 在用C#编写的MMC管理单元的上下文中,我们的应用程序遭受恼人的闪烁和双重排序行为: 我们使用MMC的listViews,但是因为我们订阅了sort事件。 MMC做了它自己的魔术并对正在显示的页面进行排序(我们无法覆盖它),当我们从服务器收到回复时,我们再次更改listView。 每行更改按顺序完成,没有beginUpdate等。(AFAIK)。
答案 0 :(得分:1)
通常情况下挂钩WM_PAINT
是可行的方法,但请确保您也忽略所有WM_ERASEBKGND
通知,否则您仍然会闪烁,因为Windows会为您删除Windows区域。 (返回非零以防止Windows执行此操作)
另一种可能性是使用LockWindowUpdate
函数,但它有一些缺点:
答案 1 :(得分:1)
有些控件有BeginUpdate
和EndUpdate
API用于此目的。
如果您执行了某些操作(例如,挂钩和忽略绘制事件),请禁用绘画,那么稍后强制重新绘制的方法是调用Invalidate
方法。
答案 2 :(得分:0)
好的,在所有搜索和检查之后我发现LockUpdateWindow是个坏主意 - 例如参见Raimond Chen OldNewThing的文章。但即使实现SetRedrawWindow的想法也不是那么简单 - 因为我所拥有的只是从主窗口的IConsole2 * pConsole-> GetMainWindow()HWND处理程序中获得的。通过将其设置为SetRedraw = FALSE,它以非常奇怪的方式消失了。虽然为了使程序只运行TreeView而不是整个应用程序(我们的左侧面板),我运行
EnumChildWindows(hWnd, SetChildRedraw, FALSE); //stopping redraw
//... here you do your operations
EnumChildWindows(hWnd, SetChildRedraw, TRUE); //restarting redraw
其中SetChildRedraw回调是以下一种方式定义的:
#define DECLARE_STRING(str) TCHAR str[MAX_PATH]; ZeroMemory(str, sizeof(str));
BOOL CALLBACK SetChildRedraw(HWND hwndChild, LPARAM lParam)
{
RECT rcChildRect; ZeroMemory(&rcChildRect, sizeof(rcChildRect));
DECLARE_STRING(sText)
GetClassName(hwndChild, sText, MAX_PATH);
if (wcsstr(sText, L"SysTreeView32") != NULL)
{
SetWindowRedraw(hwndChild, lParam);
if (lParam == TRUE)
{
GetWindowRect(hwndChild, &rcChildRect);
InvalidateRect(hwndChild, &rcChildRect, TRUE);
}
}
return TRUE;
}