ApplicationInterop.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / WinFormsIntegration / System / Windows / Integration / ApplicationInterop.cs / 1 / ApplicationInterop.cs

                            using System.Collections; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Interop; 
using MS.Win32;
 
using SWF = System.Windows.Forms; 
using SW = System.Windows;
using SWM = System.Windows.Media; 

namespace System.Windows.Forms.Integration
{
    internal static class ApplicationInterop 
    {
        [ThreadStatic] 
        private static WindowsFormsHostList _threadWindowsFormsHostList; 
        /// 
        /// Gets a list of all of the WindowsFormsHosts which were created on the current thread. 
        /// 
        internal static WindowsFormsHostList ThreadWindowsFormsHostList
        {
            get 
            {
                //No synchronization required (the field is ThreadStatic) 
                if (null == _threadWindowsFormsHostList) 
                {
                    _threadWindowsFormsHostList = new WindowsFormsHostList(); 
                }
                return _threadWindowsFormsHostList;
            }
        } 
        [ThreadStatic]
        private static bool _messageFilterInstalledOnThread; 
 
        /// 
        ///     Enables a System.Windows.Window to receive necessary keyboard 
        ///     messages when it is opened modelessly from a Windows.Forms.Application.
        /// 
        /// The System.Windows.Window which will be opened modelessly.
        public static void EnableModelessKeyboardInterop(SW.Window window) 
        {
            //Create and add IMessageFilter 
            ModelessWindowFilter filter = new ModelessWindowFilter(window); 
            WindowFilterList.FilterList.Add(filter);
            SWF.Application.AddMessageFilter(filter); 

            //Hook window Close event to remove IMessageFilter
            window.Closed += new EventHandler(WindowFilterList.ModelessWindowClosed);
        } 

        public static void EnableWindowsFormsInterop() 
        { 
            if (!_messageFilterInstalledOnThread)
            { 
                SW.Interop.ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ThreadMessageFilter);
                _messageFilterInstalledOnThread = true;
            }
        } 

        // CSS added for keyboard interop 
        // 
        //
 



 
        internal static void ThreadMessageFilter(ref MSG msg, ref bool outHandled)
        { 
            // Don’t do anything if already handled 
            if (outHandled)
            { 
                return;
            }

            Message m = Convert.ToSystemWindowsFormsMessage(msg); 

            // Process Winforms MessageFilters 
            if (Application.FilterMessage(ref m)) 
            {
                // Set the return value correctly. 
                outHandled = true;
                return;
            }
 
            bool handled = false;
 
            SWF.Control control = SWF.Control.FromChildHandle(m.HWnd); 
            if (control != null)
            { 
                //CSS The WM_SYSCHAR special case is a workaround for a bug VSWhidbey 575729, which
                //makes IsInputChar not get called with WM_SYSCHAR messages.
                if (m.Msg == NativeMethods.WM_SYSCHAR)
                { 
                    handled = control.PreProcessMessage(ref m);
                } 
                else 
                {
                    SWF.PreProcessControlState processedState = control.PreProcessControlMessage(ref m); 

                    if (processedState == SWF.PreProcessControlState.MessageNeeded)
                    {
                        // Control didn't process message but does want the message. 
                        UnsafeNativeMethods.TranslateMessage(ref msg);
                        UnsafeNativeMethods.DispatchMessage(ref msg); 
                        handled = true; 
                    }
                    else if (processedState == SWF.PreProcessControlState.MessageProcessed) 
                    {
                        // Control processed the mesage
                        handled = true;
                    } 
                    else
                    { 
                        // Control doesn't need message 
                        Debug.Assert(processedState == SWF.PreProcessControlState.MessageNotNeeded, "invalid state");
                        handled = false; 
                    }
                }
            }
            else if (msg.message != 0xc2a3) /* ControlFromHWnd == null */ 
            {
                // We are only letting the hosted control do preprocess message when it 
                // isn't active. All other WF controls will get PreProcessMessage at 
                // normal time (when focused).
                foreach (WindowsFormsHost wfh in ThreadWindowsFormsHostList.ActiveWindowList()) 
                {
                    if (wfh.HostContainerInternal.PreProcessMessage(ref m, false))
                    {
                        handled = true; 
                        break;
                    } 
                } 
            }
 
            // Set the return value correctly.
            outHandled = handled;
            return;
        } 

    } 
 

    ///  
    ///     This singleton is used to enable Avalon Modeless Windows when using
    ///     the WinForms application to handle events. It keeps track of all the Avalon windows.
    ///     See ElementHost.EnableModelessKeyboardInterop for more info.
    /// 
    ///     Since the filter information cannot be stored in the Avalon window
    ///     class itself, keep a list of all the Avalon windows and their filters. 
    ///     When an avalon window is closed, remove it from the list 
    /// 
    internal class WindowFilterList : WeakReferenceList 
    {
        //Singleton instance of the list
        private static WindowFilterList _filterList = new WindowFilterList();
        public static WindowFilterList FilterList 
        {
            get 
            { 
                return _filterList;
            } 
        }

        /// 
        ///     Seaches the filter list for an entry pointing to the current 
        ///     windows.
        ///  
        ///  
        /// 
        static ModelessWindowFilter FindFilter(SW.Window window) 
        {
            ModelessWindowFilter windowFilter = null;

            if (window == null) 
            {
                return null; 
            } 

            foreach (ModelessWindowFilter filter in _filterList.SnapshotListOfTargets) 
            {
                if (filter.Window == window)
                {
                    windowFilter = filter; 
                    break;
                } 
            } 
            Debug.Assert(windowFilter != null);
            return windowFilter; 
        }

        /// 
        ///     This callback is added to the avalon window so that its filter is removed 
        ///     when the window is closed.
        ///  
        ///  
        /// 
        public static void ModelessWindowClosed(object sender, EventArgs e) 
        {
            ModelessWindowFilter windowFilter = WindowFilterList.FindFilter(sender as SW.Window);
            if (windowFilter != null)
            { 
                SWF.Application.RemoveMessageFilter(windowFilter);
                WindowFilterList.FilterList.Remove(windowFilter); 
            } 
        }
    } 

    /// 
    ///     This message filter forwards messages to registered Avalon windows.
    ///     Use ElementHost.EnableModelessKeyboardInterop to setup 
    /// 
    internal class ModelessWindowFilter : SWF.IMessageFilter 
    { 
        private System.Windows.Window _window;
        public SW.Window Window 
        {
            get
            {
                return _window; 
            }
        } 
 
        public ModelessWindowFilter(System.Windows.Window window)
        { 
            _window = window;
        }

        //Need a recursion guard for PreFilterMessage: the same message can come back to us via the 
        //ComponentDispatcher.
        bool _inPreFilterMessage; 
        public bool PreFilterMessage(ref SWF.Message msg) 
        {
            if (_window == null || !_window.IsActive) 
            {
                return false;
            }
 
            switch (msg.Msg)
            { 
                case NativeMethods.WM_KEYDOWN:          //0x100 
                case NativeMethods.WM_KEYUP:            //0x101
                case NativeMethods.WM_CHAR:             //0x102 
                case NativeMethods.WM_DEADCHAR:         //0x103
                case NativeMethods.WM_SYSKEYDOWN:       //0x104
                case NativeMethods.WM_SYSKEYUP:         //0x105
                case NativeMethods.WM_SYSCHAR:          //0x106 
                case NativeMethods.WM_SYSDEADCHAR:      //0x107
                    if (!_inPreFilterMessage) 
                    { 
                        _inPreFilterMessage = true;
                        try 
                        {
                            SW.Interop.MSG msg2 = Convert.ToSystemWindowsInteropMSG(msg);
                            bool fReturn = SW.Interop.ComponentDispatcher.RaiseThreadMessage(ref msg2);
                            return fReturn; 
                        }
                        finally 
                        { 
                            _inPreFilterMessage = false;
                        } 
                    }
                    return false;

                default: 
                    return false;
            } 
        } 
    }
 
    /// 
    ///     This class make a strongly typed weak reference collection. Its enumerator
    ///     only returns references to live objects.
    ///     By not keeping a reference count on the objects in this list, they can be 
    ///     garbage collected normally.
    ///  
    internal class WeakReferenceList where T : class 
    {
        List _internalList; 
        object _syncRoot = new object();

        public WeakReferenceList()
            : base() 
        {
            _internalList = new List(); 
        } 

        ///  
        ///     This prunes object reference that no longer point to valid objects
        ///     from the list. This is called often in the current implementation,
        ///     but can be phased back if there are perf concerns.
        ///  
        protected void RemoveDeadReferencesFromList()
        { 
            for (int i = _internalList.Count - 1; i >= 0; i--) 
            {
                if (!_internalList[i].IsAlive) 
                {
                    _internalList.RemoveAt(i);
                }
            } 
        }
 
        public List SnapshotListOfTargets 
        {
            get 
            {
                List targets = new List();
                lock (_syncRoot)
                { 
                    RemoveDeadReferencesFromList();
                    foreach (WeakReference obj in _internalList) 
                    { 
                        //tempValue will be null if it's not alive
                        T tempValue = obj.Target as T; 
                        if (tempValue != null)
                        {
                            targets.Add(tempValue);
                        } 
                    }
                } 
                return targets; 
            }
        } 

        public void Add(T obj)
        {
            lock (_syncRoot) 
            {
                RemoveDeadReferencesFromList(); 
                WeakReference newItem = new WeakReference(obj, false); 
                _internalList.Add(newItem);
            } 
        }

        internal int IndexOf(T obj)
        { 
            {
                RemoveDeadReferencesFromList(); 
                for (int i = 0; i < _internalList.Count; i++) 
                {
                    if (_internalList[i].IsAlive) 
                    {
                        if (_internalList[i].Target as T == obj)
                        {
                            return i; 
                        }
                    } 
                } 
                return -1;
            } 
        }

        public bool Remove(T obj)
        { 
            lock (_syncRoot)
            { 
                int index = IndexOf(obj); 
                if (index >= 0)
                { 
                    _internalList.RemoveAt(index);
                    return true;
                }
                return false; 
            }
        } 
    } 

    internal class WindowsFormsHostList : WeakReferenceList 
    {
        public IEnumerable ActiveWindowList()
        {
            SW.Window rootWindow = null; 
            foreach (WindowsFormsHost wfh in this.SnapshotListOfTargets)
            { 
                rootWindow = FindRootVisual(wfh) as SW.Window; 
                if (rootWindow != null)
                { 
                    if (rootWindow.IsActive)
                    {
                        yield return wfh;
                    } 
                }
            } 
        } 

        private static SWM.Visual FindRootVisual(SWM.Visual x) 
        {
            return (PresentationSource.FromVisual(x) != null) ? (PresentationSource.FromVisual(x)).RootVisual : null;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System.Collections; 
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Interop; 
using MS.Win32;
 
using SWF = System.Windows.Forms; 
using SW = System.Windows;
using SWM = System.Windows.Media; 

namespace System.Windows.Forms.Integration
{
    internal static class ApplicationInterop 
    {
        [ThreadStatic] 
        private static WindowsFormsHostList _threadWindowsFormsHostList; 
        /// 
        /// Gets a list of all of the WindowsFormsHosts which were created on the current thread. 
        /// 
        internal static WindowsFormsHostList ThreadWindowsFormsHostList
        {
            get 
            {
                //No synchronization required (the field is ThreadStatic) 
                if (null == _threadWindowsFormsHostList) 
                {
                    _threadWindowsFormsHostList = new WindowsFormsHostList(); 
                }
                return _threadWindowsFormsHostList;
            }
        } 
        [ThreadStatic]
        private static bool _messageFilterInstalledOnThread; 
 
        /// 
        ///     Enables a System.Windows.Window to receive necessary keyboard 
        ///     messages when it is opened modelessly from a Windows.Forms.Application.
        /// 
        /// The System.Windows.Window which will be opened modelessly.
        public static void EnableModelessKeyboardInterop(SW.Window window) 
        {
            //Create and add IMessageFilter 
            ModelessWindowFilter filter = new ModelessWindowFilter(window); 
            WindowFilterList.FilterList.Add(filter);
            SWF.Application.AddMessageFilter(filter); 

            //Hook window Close event to remove IMessageFilter
            window.Closed += new EventHandler(WindowFilterList.ModelessWindowClosed);
        } 

        public static void EnableWindowsFormsInterop() 
        { 
            if (!_messageFilterInstalledOnThread)
            { 
                SW.Interop.ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ThreadMessageFilter);
                _messageFilterInstalledOnThread = true;
            }
        } 

        // CSS added for keyboard interop 
        // 
        //
 



 
        internal static void ThreadMessageFilter(ref MSG msg, ref bool outHandled)
        { 
            // Don’t do anything if already handled 
            if (outHandled)
            { 
                return;
            }

            Message m = Convert.ToSystemWindowsFormsMessage(msg); 

            // Process Winforms MessageFilters 
            if (Application.FilterMessage(ref m)) 
            {
                // Set the return value correctly. 
                outHandled = true;
                return;
            }
 
            bool handled = false;
 
            SWF.Control control = SWF.Control.FromChildHandle(m.HWnd); 
            if (control != null)
            { 
                //CSS The WM_SYSCHAR special case is a workaround for a bug VSWhidbey 575729, which
                //makes IsInputChar not get called with WM_SYSCHAR messages.
                if (m.Msg == NativeMethods.WM_SYSCHAR)
                { 
                    handled = control.PreProcessMessage(ref m);
                } 
                else 
                {
                    SWF.PreProcessControlState processedState = control.PreProcessControlMessage(ref m); 

                    if (processedState == SWF.PreProcessControlState.MessageNeeded)
                    {
                        // Control didn't process message but does want the message. 
                        UnsafeNativeMethods.TranslateMessage(ref msg);
                        UnsafeNativeMethods.DispatchMessage(ref msg); 
                        handled = true; 
                    }
                    else if (processedState == SWF.PreProcessControlState.MessageProcessed) 
                    {
                        // Control processed the mesage
                        handled = true;
                    } 
                    else
                    { 
                        // Control doesn't need message 
                        Debug.Assert(processedState == SWF.PreProcessControlState.MessageNotNeeded, "invalid state");
                        handled = false; 
                    }
                }
            }
            else if (msg.message != 0xc2a3) /* ControlFromHWnd == null */ 
            {
                // We are only letting the hosted control do preprocess message when it 
                // isn't active. All other WF controls will get PreProcessMessage at 
                // normal time (when focused).
                foreach (WindowsFormsHost wfh in ThreadWindowsFormsHostList.ActiveWindowList()) 
                {
                    if (wfh.HostContainerInternal.PreProcessMessage(ref m, false))
                    {
                        handled = true; 
                        break;
                    } 
                } 
            }
 
            // Set the return value correctly.
            outHandled = handled;
            return;
        } 

    } 
 

    ///  
    ///     This singleton is used to enable Avalon Modeless Windows when using
    ///     the WinForms application to handle events. It keeps track of all the Avalon windows.
    ///     See ElementHost.EnableModelessKeyboardInterop for more info.
    /// 
    ///     Since the filter information cannot be stored in the Avalon window
    ///     class itself, keep a list of all the Avalon windows and their filters. 
    ///     When an avalon window is closed, remove it from the list 
    /// 
    internal class WindowFilterList : WeakReferenceList 
    {
        //Singleton instance of the list
        private static WindowFilterList _filterList = new WindowFilterList();
        public static WindowFilterList FilterList 
        {
            get 
            { 
                return _filterList;
            } 
        }

        /// 
        ///     Seaches the filter list for an entry pointing to the current 
        ///     windows.
        ///  
        ///  
        /// 
        static ModelessWindowFilter FindFilter(SW.Window window) 
        {
            ModelessWindowFilter windowFilter = null;

            if (window == null) 
            {
                return null; 
            } 

            foreach (ModelessWindowFilter filter in _filterList.SnapshotListOfTargets) 
            {
                if (filter.Window == window)
                {
                    windowFilter = filter; 
                    break;
                } 
            } 
            Debug.Assert(windowFilter != null);
            return windowFilter; 
        }

        /// 
        ///     This callback is added to the avalon window so that its filter is removed 
        ///     when the window is closed.
        ///  
        ///  
        /// 
        public static void ModelessWindowClosed(object sender, EventArgs e) 
        {
            ModelessWindowFilter windowFilter = WindowFilterList.FindFilter(sender as SW.Window);
            if (windowFilter != null)
            { 
                SWF.Application.RemoveMessageFilter(windowFilter);
                WindowFilterList.FilterList.Remove(windowFilter); 
            } 
        }
    } 

    /// 
    ///     This message filter forwards messages to registered Avalon windows.
    ///     Use ElementHost.EnableModelessKeyboardInterop to setup 
    /// 
    internal class ModelessWindowFilter : SWF.IMessageFilter 
    { 
        private System.Windows.Window _window;
        public SW.Window Window 
        {
            get
            {
                return _window; 
            }
        } 
 
        public ModelessWindowFilter(System.Windows.Window window)
        { 
            _window = window;
        }

        //Need a recursion guard for PreFilterMessage: the same message can come back to us via the 
        //ComponentDispatcher.
        bool _inPreFilterMessage; 
        public bool PreFilterMessage(ref SWF.Message msg) 
        {
            if (_window == null || !_window.IsActive) 
            {
                return false;
            }
 
            switch (msg.Msg)
            { 
                case NativeMethods.WM_KEYDOWN:          //0x100 
                case NativeMethods.WM_KEYUP:            //0x101
                case NativeMethods.WM_CHAR:             //0x102 
                case NativeMethods.WM_DEADCHAR:         //0x103
                case NativeMethods.WM_SYSKEYDOWN:       //0x104
                case NativeMethods.WM_SYSKEYUP:         //0x105
                case NativeMethods.WM_SYSCHAR:          //0x106 
                case NativeMethods.WM_SYSDEADCHAR:      //0x107
                    if (!_inPreFilterMessage) 
                    { 
                        _inPreFilterMessage = true;
                        try 
                        {
                            SW.Interop.MSG msg2 = Convert.ToSystemWindowsInteropMSG(msg);
                            bool fReturn = SW.Interop.ComponentDispatcher.RaiseThreadMessage(ref msg2);
                            return fReturn; 
                        }
                        finally 
                        { 
                            _inPreFilterMessage = false;
                        } 
                    }
                    return false;

                default: 
                    return false;
            } 
        } 
    }
 
    /// 
    ///     This class make a strongly typed weak reference collection. Its enumerator
    ///     only returns references to live objects.
    ///     By not keeping a reference count on the objects in this list, they can be 
    ///     garbage collected normally.
    ///  
    internal class WeakReferenceList where T : class 
    {
        List _internalList; 
        object _syncRoot = new object();

        public WeakReferenceList()
            : base() 
        {
            _internalList = new List(); 
        } 

        ///  
        ///     This prunes object reference that no longer point to valid objects
        ///     from the list. This is called often in the current implementation,
        ///     but can be phased back if there are perf concerns.
        ///  
        protected void RemoveDeadReferencesFromList()
        { 
            for (int i = _internalList.Count - 1; i >= 0; i--) 
            {
                if (!_internalList[i].IsAlive) 
                {
                    _internalList.RemoveAt(i);
                }
            } 
        }
 
        public List SnapshotListOfTargets 
        {
            get 
            {
                List targets = new List();
                lock (_syncRoot)
                { 
                    RemoveDeadReferencesFromList();
                    foreach (WeakReference obj in _internalList) 
                    { 
                        //tempValue will be null if it's not alive
                        T tempValue = obj.Target as T; 
                        if (tempValue != null)
                        {
                            targets.Add(tempValue);
                        } 
                    }
                } 
                return targets; 
            }
        } 

        public void Add(T obj)
        {
            lock (_syncRoot) 
            {
                RemoveDeadReferencesFromList(); 
                WeakReference newItem = new WeakReference(obj, false); 
                _internalList.Add(newItem);
            } 
        }

        internal int IndexOf(T obj)
        { 
            {
                RemoveDeadReferencesFromList(); 
                for (int i = 0; i < _internalList.Count; i++) 
                {
                    if (_internalList[i].IsAlive) 
                    {
                        if (_internalList[i].Target as T == obj)
                        {
                            return i; 
                        }
                    } 
                } 
                return -1;
            } 
        }

        public bool Remove(T obj)
        { 
            lock (_syncRoot)
            { 
                int index = IndexOf(obj); 
                if (index >= 0)
                { 
                    _internalList.RemoveAt(index);
                    return true;
                }
                return false; 
            }
        } 
    } 

    internal class WindowsFormsHostList : WeakReferenceList 
    {
        public IEnumerable ActiveWindowList()
        {
            SW.Window rootWindow = null; 
            foreach (WindowsFormsHost wfh in this.SnapshotListOfTargets)
            { 
                rootWindow = FindRootVisual(wfh) as SW.Window; 
                if (rootWindow != null)
                { 
                    if (rootWindow.IsActive)
                    {
                        yield return wfh;
                    } 
                }
            } 
        } 

        private static SWM.Visual FindRootVisual(SWM.Visual x) 
        {
            return (PresentationSource.FromVisual(x) != null) ? (PresentationSource.FromVisual(x)).RootVisual : null;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK