Esempio n. 1
0
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            /// <summary>
            /// Initializes a new instance of the Oceanside.Win32.Native.WindowHookManager.Message class.
            /// </summary>
            ///
            /// <param name="hWnd">     The h window. </param>
            /// <param name="msg">      The message. </param>
            /// <param name="wparam">   The w parameter. </param>
            /// <param name="lparam">   The l parameter. </param>
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            public HookMessage(IntPtr hWnd, HookMsgType msg, IntPtr wparam, IntPtr lparam)
            {
                HWnd        = hWnd;
                HookMsgType = msg;
                WParam      = wparam;
                LParam      = lparam;
                Result      = IntPtr.Zero;
            }
Esempio n. 2
0
 public Win32HookMsgEventArgs(IntPtr hIEWnd, HookMsgType msgType)
 {
     this.hWnd = hIEWnd;
     this.type = msgType;
 }
Esempio n. 3
0
 public Win32HookMsgEventArgs(IntPtr hIEWnd, HookMsgType msgType)
 {
     this.hWnd = hIEWnd;
     this.type = msgType;
 }
Esempio n. 4
0
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            /// <summary>   Returns the fully qualified type name of this instance. </summary>
            ///
            /// <returns>   The fully qualified type name. </returns>
            ///
            /// <seealso cref="System.ValueType.ToString()"/>
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            public override string ToString()
            {
                return(HookMsgType.ToString());
            }
            ////////////////////////////////////////////////////////////////////////////////////////////////////
            /// <summary>   Custom window procedure. </summary>
            ///
            /// <param name="hWnd">     The window. </param>
            /// <param name="msg">      The message. </param>
            /// <param name="wParam">   The parameter. </param>
            /// <param name="lParam">   The parameter. </param>
            ///
            /// <returns>   An IntPtr. </returns>
            ////////////////////////////////////////////////////////////////////////////////////////////////////

            private IntPtr CustomWndProc(IntPtr hWnd, HookMsgType msg, IntPtr wParam, IntPtr lParam)
            {
                var m = new HookMessage(hWnd, msg, wParam, lParam);

                //Deactivated means there are zero callbacks and destroyed means that the WM_DESTROY message
                // has already been processed and there is no need to call our custom logic.  I think there
                // are a few messages that can still come in after WM_DESTROY, such as WM_NCDESTROY that is
                // sent after all child Windows have been destroyed.  Note that we try to unhook our custom
                // logic upon a WM_DESTROY by replacing it with the original WndProc but race conditions
                // could affect that timing.
                if (_isDeActivated || _isDestroyed)
                {
                    return(CallWindowProc(_originalWndProc, m.HWnd, (uint)m.HookMsgType, m.WParam, m.LParam));
                }

                //Grab a copy of the callbacks so we do not remain inside the lock while we are looping through
                // and calling back into unknown code that could (but hopefully not) be lengthy.  In rare race
                // conditions this could cause a slight delay in the amount of time it takes to "UnRegister"
                // a callback if code desired to do so.
                //
                // TODO Window Procedure Performance Evaluation
                // Note that the performance of this design should be considered carefully.  Although it makes
                // it flexible to be able to add callbacks to a Window throughout the application, the fact
                // that I am locking inside of a hot function is cause for careful thought.  Atop of locking,
                // I am copying the current callbacks into another local variable.  Since Window procedures
                // can cause recursion by design, that could lead to a stack overflow if the Size of
                // the RegisteredWndProcCallbacks grew.  If an application only intended to attach one
                // callback at any given time, this could be simplified greatly.
                WndProcCallback[]? callbacksCopy = null;
                lock (_callbacksLocker)
                {
                    callbacksCopy = RegisteredWndProcCallbacks.ToArray();
                }

                if (callbacksCopy != null)
                {
                    //Loop through all callbacks until one callback handles the message or we exhaust all
                    // items in the loop.  If a callback handles the message we can return the result so
                    // long as it is not a DESTROY message, then we need to unhook.
                    foreach (var callback in callbacksCopy)
                    {
                        if (!callback(ref m))
                        {
                            continue;
                        }

                        if (msg != HookMsgType.DESTROY)
                        {
                            return(m.Result);
                        }

                        break;
                    }
                }

                //This one makes me nervous, keep an eye on it.  Of the many examples I happened upon, they
                // were re-hooking the WndProc with the original loop and for that reason I will do the
                // same.  If you are seeing exceptions, this could be a race condition of some sort.
                if (msg == HookMsgType.DESTROY)
                {
                    Destroy();
                }

                //Note that this is still called after we call Destroy to unhook this routine because
                // it needs to receive the DESTROY message or else the window will not close.  Also
                // notice that we are sending the values inside  of the local HookMessage rather than
                // the ones that came into this CustomWndProc.  This lets other callbacks change the
                // parameter values if needed.
                return(CallWindowProc(_originalWndProc, m.HWnd, (uint)m.HookMsgType, m.WParam, m.LParam));
            }