开发者

How can I stop window rendering and later resume?

I'd like to prevent my window from being updated until I finish receiving data from the server and render it. Can I hook on the WM_PAINT event, or better still call some Win32API method to prevent the window from being updated and unfreeze it later?

More info: In the context of an MMC snapin written in C#, our application suffers from annoying flickering and double sorting behaviour: We use MMC's listViews, but since we subscribe to the sort event. MMC does it's own magic and sorts the page being displayed (and we can't override tha开发者_如何转开发t), and when we receive a reply from our server we change the listView again. each row change is done sequentially, there's no beginUpdate etc. (AFAIK).


Normally hooking into WM_PAINT is the way to go, but make sure you also ignore all WM_ERASEBKGND notifcations, otherwise you'll still get flicker, because Windows erases the Windows area for you. (Return non-zero to prevent Windows from doing that)

One other possibility is to use the LockWindowUpdate function, but it has some drawbacks:

  • Only one window can be locked
  • Upon unlock the whole desktop and all sub-windows (i.e. everything) is repainted, resulting in short flash of the whole desktop. (It's worse on XP than on Vista)


Some controls have BeginUpdate and EndUpdate APIs for this purpose.

If you do something (e.g. hook and ignore paint events) do disable painting, then a way to force a repaint later is to call the Invalidate method.


OK, after all searching and checking I've found that LockUpdateWindow is bad idea - see for example articles of Raimond Chen OldNewThing. But even to implement the idea of SetRedrawWindow wasn't so simple - because what I had was only received from IConsole2* pConsole->GetMainWindow() HWND handler of main window. By setting it to SetRedraw = FALSE it was disappeared in very strange manner. Though to make the procedure run only for the TreeView and not for the whole application (ours left panel) I ran

EnumChildWindows(hWnd, SetChildRedraw, FALSE); //stopping redraw
//... here you do your operations
EnumChildWindows(hWnd, SetChildRedraw, TRUE); //restarting redraw

where SetChildRedraw callback was defined in next way:

#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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜