Question

Let me first decribe the symptoms of the problem. I'll then give additional facts and explain my question.

Symptoms

I have written a custom Windows control. The control paints itself in response to a WM_PAINT message. It also uses tracking tooltips (ie the tracking feature of the TOOLTIPS_CLASS common control).

When I drag the mouse over the control, the tooltip nicely follows the mouse. The problem is that it leaves a grey streak in its wake. This streak takes an observable amount of time to repaint -- as you can see from the attached image, I was able to hit PRNTSCRN and take a screenshot of it before the control had time to repaint itself.

Note the grey "trail" where the tooltip once was.

(What is even more peculiar is that the WM_PAINT handler doesn't appear to have run even once. But note that the code that causes the tooltip to track is in WM_MOUSEMOVE, and that is obviously being perfectly responsive.)

Facts

  • Please assume vanilla C using Win32 libraries.
  • The WM_PAINT handler is actually very fast. The control has a number of features that require repainting the entire client area, and this is imperceptible to the user.
    • Indeed, some features run animations that repaint the whole client area at 15-24fps.
    • It is also decently efficient and doesn't repaint much more than the update rectangle on any given repaint.
  • The WM_ERASEBKGND handler does nothing and simply returns 1.
    • I never erase the background, I simply paint over it.
  • The window has the following style bits set:
    • ws: WS_CHILD | WS_VISIBLE
    • ex: WS_EX_COMPOSITED
    • cs: CS_DBLCLKS
  • The parent window is a top-level window with the following style bits set:
    • ws: WS_TILEDWINDOW | WS_CLIPSIBLINGS | WS_VISIBLE
    • ex: WS_EX_WINDOWEDGE
    • cs: CS_REDRAW | CS_DBLCLKS
  • The control's window class background brush is GetStockObject(NULL_BRUSH).
  • The only other way I have found to cause the same kind of "trail" is by dragging another top-level window over my control. The area that is temporarily obscured by the dragged top-level window leaves the same trail.
  • Giving the control's window class the CS_SAVEBITS style doesn't seem to make any difference. I still get the same perceptible trail of slow repaints.

Questions

  1. Why am I getting the grey at all, especially if I set CS_SAVEBITS?
  2. What can I do to make the grey go away?
    • Should I call UpdateWindow() each time I move the tooltip?
      • But this doesn't solve the issue of other top-level windows being dragged over top of my control.
    • Help!
Was it helpful?

Solution

Adding the WS_CLIPCHILDREN style bit to the parent window made this issue go away.

For whatever reason, when a window is partly obscured and then revealed, the OS is very generous with the WM_ERASEBKGND messages and very stingy with the WM_PAINT messages. What was happening is that the parent's WM_ERASEBKGND handler was erasing over top of my control. Adding WS_CLIPCHILDREN causes the parent window to clip its erasing.

Funnily enough, this solution worked for my control, which simply ignores the WM_ERASEBKGND message, but didn't work for standard BUTTON controls with style BS_GROUPBOX style. I expect this is because of the same generous WM_ERASEBKGND policy. The standard button control probably dutifully erases its background in handling that message and then vainly waits around for a WM_PAINT message.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top