How to stop flickering on Video by turning off AllowsTransparency

If you need to put a Win32 video control, say a webcam, in WPF program, and you also need to put WPF controls over it, your only possiblity is to use Popup as the container for these controls, because Win32 controls always on the top of all the WPF controls(including adorners), regardless the Z order. The reason why Popup can “stay” over Win32 controls is that it actually spawn another independ window.

However, under the circumstance of current version of WPF, if you do not use popup carefully, it will always cause very annoying flicker over the video. This is because you probably set the AllowsTransparency property of Popup to true. Dr.WPF gave his understanding of this issue. Then I do not repeate again.

Turning off AllowsTransparency of Popup is easy. How about MenuItem, ComboBox, ContextMenu and Tooltip? They all have internal popup which has AllowsTransparency set to true by default, but in different ways.

For MenuItem and ComboBox, you need to retemplate them with custom control template within which you explicitly set AllowsTransparency of Popup to false.

For ContextMenu and Tooltip, it will be more difficult becaue you cannot find popup in their templates. Therefore, you neend another method to deal with it. You Zhong provides a mothed to traverse the visual tree to get the popup instance. Although in his post, he did not directly address this issue, the method he came up with can certainly help. Here I quoted the two methods which are most important.

 private static void SetAllowsTransparencyInternal(Control element, Object value)
    {
        ToolTip tooTip = element as ToolTip;
        ContextMenu contextMenu = element as ContextMenu;

        // Set the IsOpen property to true to let the ToolTip/ContextMenu create Popup instance early, since
        // we are only interesting in Popup.AllowsTransparency property rather than
        // opening the ToolTip/ContextMenu, set its Visibility to Collapsed.
        element.Visibility = Visibility.Collapsed;
        if (tooTip != null)
        {
            tooTip.IsOpen = true;
        }
        else if (contextMenu != null)
        {
            contextMenu.IsOpen = true;
        }

        //Find the Popup logical element root.
        Popup popup = GetPopupFromVisualChild(element);
        if (popup != null) popup.SetValue(Popup.AllowsTransparencyProperty, value);

        //Set properties back to what it is initially.
        if (tooTip != null)
        {
            tooTip.ClearValue(ToolTip.IsOpenProperty);
        }
        else if (contextMenu != null)
        {
            contextMenu.ClearValue(ToolTip.IsOpenProperty);
        }
        element.ClearValue(FrameworkElement.VisibilityProperty);
    }

    private static Popup GetPopupFromVisualChild(Visual child)
    {
        Visual parent = child;
        FrameworkElement visualRoot = null;

        //Traverse the visual tree up to find the PopupRoot instance.
        while (parent != null)
        {
            visualRoot = parent as FrameworkElement;
            parent = VisualTreeHelper.GetParent(parent) as Visual;
        }

        Popup popup = null;

        // Examine the PopupRoot's logical parent to get the Popup instance.
        // This might break in the future since it relies on the internal implementation of Popup's element tree.
        if (visualRoot != null)
        {
            popup = visualRoot.Parent as Popup;
        }

        return popup;
    }
Advertisements

~ by Martin on November 9, 2008.

One Response to “How to stop flickering on Video by turning off AllowsTransparency”

  1. Harbans Lal Gera – I know this is off topic but need help with Vista

    Thanks,
    Harbans Lal Gera

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: