Search code examples
c#winformstooltip

Weird behaviour of a form with WS_EX_COMPOSITED style


In my application I have a custom tooltip which is derived from the standard System.Windows.Forms.Form class. It has a WS_EX_COMPOSITED style set which prevents flickering. It can contain multiple lines of text and optionally some controls as well. Whenever its content changes, its size is recalculated so that it matches the bounds of the controls within it. However, I have noticed some weird behaviour - for example sometimes it fails to show up completely, sometimes it is cut.

I have created a simple application which demonstrates these issues. See the screenshot: Screenshot of the sample application

When you move the mouse over one of the displayed circles, the tooltip should be shown with N lines of text where N is the number drawn inside the circle. In the screenshot, you can see the tooltip was cut so that only "Item #1" is visible. The mouse was moved to the left from the "1" circle, the tooltip content was updated to contain 9 lines of text but its size remained the same. Unfortunately these issues seem to occur at random, so you'll have to "play" with the application for some time, moving the mouse between the circles.

So far I have made these observations:

  1. when I switch off the WS_EX_COMPOSITED style, the issues disappear
  2. when I force the size of the tooltip to actually change (even when moving to another circle with the same number), the issues disappear

This suggests that perhaps windows with WS_EX_COMPOSITED style somehow fail to update their size when going from hidden to visible state.

Does anyone know what's happening here? The complete sample project is available for download.


Solution

  • I managed to simplify the example to the point where I could draw a conclusion: A Form with the WS_EX_COMPOSITED style will very often be not drawn correctly if you hide it and then try to show it again without changing its size. So the easiest hack is to do just

    protected override void OnVisibleChanged( EventArgs e )
    {
        if( this.Visible )
        {
            this.Height++;
        }
    }