Esempio n. 1
0
        private object DispatcherCallbackOperation(object o)
        {
            DispatcherOperationCallbackParameter param = (DispatcherOperationCallbackParameter)o;

            param.handled = false;
            param.retVal  = IntPtr.Zero;
            if (_bond == Bond.Attached)
            {
                HwndWrapperHook hook = _hook.Target as HwndWrapperHook;

                if (hook != null)
                {
                    // make the call
                    param.retVal = hook(param.hwnd, param.msg, param.wParam, param.lParam, ref param.handled);
                }
            }

            return(param);
        }
Esempio n. 2
0
        /// <summary>
        ///     This is the WNDPROC that gets inserted into the window's
        ///     WNDPROC chain.  It responds to various conditions that
        ///     would cause this HwndSubclass object to unsubclass the window,
        ///     and then calls the delegate specified to the HwndSubclass
        ///     constructor to process the message.  If the delegate does not
        ///     handle the message, the message is then passed on down the
        ///     WNDPROC chain for further processing.
        /// </summary>
        /// <param name="hwnd">
        ///     The window that this message was sent or posted to.
        /// </param>
        /// <param name="msg">
        ///     The message that was sent or posted.
        /// </param>
        /// <param name="wParam">
        ///     A parameter for the message that was sent or posted.
        /// </param>
        /// <param name="lParam">
        ///     A parameter for the message that was sent or posted.
        /// </param>
        /// <returns>
        ///     The value that is the result of processing the message.
        /// </returns>
        internal IntPtr SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
        {
            IntPtr        retval  = IntPtr.Zero;
            bool          handled = false;
            WindowMessage message = (WindowMessage)msg;

            // If we are unattached and we receive a message, then we must have
            // been used as the original window proc.  In this case, we insert
            // ourselves as if the original window proc had been DefWindowProc.
            // We pass in DefWndProcStub as a workaround for a bug in UxTheme on
            // Windows XP. For details see the comment on the DefWndProcWrapper method.
            if (_bond == Bond.Unattached)
            {
                HookWindowProc(hwnd, new NativeMethods.WndProc(SubclassWndProc),
                               Marshal.GetFunctionPointerForDelegate(DefWndProcStub));
            }
            else if (_bond == Bond.Detached)
            {
                throw new InvalidOperationException();
            }

            IntPtr oldWndProc = _oldWndProc;    // in case we get detached during this method

            if (message == DetachMessage)
            {
                // We received our special message to detach.  Make sure it is intended
                // for us by matching the bridge.
                if (wParam == IntPtr.Zero || wParam == (IntPtr)_gcHandle)
                {
                    int  param = (int)lParam;   // 0 - normal, 1 - force, 2 - force and forward
                    bool force = (param > 0);

                    retval  = CriticalDetach(force) ? new IntPtr(1) : IntPtr.Zero;
                    handled = (param < 2);
                }
            }
            else
            {
                // Pass this message to our delegate function.  Do this under
                // the exception filter/handlers of the dispatcher for this thread.
                Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
                if (dispatcher != null && !dispatcher.HasShutdownFinished)
                {
                    if (_dispatcherOperationCallback == null)
                    {
                        _dispatcherOperationCallback = new DispatcherOperationCallback(this.DispatcherCallbackOperation);
                    }

                    // _paramDispatcherCallbackOperation is a thread static member which should be reused to avoid
                    // creating a new data structure every time we call DispatcherCallbackOperation
                    // Cache the param locally in case of reentrance and set _paramDispatcherCallbackOperation to null so reentrancy calls will create a new param
                    if (_paramDispatcherCallbackOperation == null)
                    {
                        _paramDispatcherCallbackOperation = new DispatcherOperationCallbackParameter();
                    }

                    DispatcherOperationCallbackParameter param = _paramDispatcherCallbackOperation;
                    _paramDispatcherCallbackOperation = null;
                    param.hwnd   = hwnd;
                    param.msg    = msg;
                    param.wParam = wParam;
                    param.lParam = lParam;
                    //synchronous call
                    object result = dispatcher.Invoke(
                        DispatcherPriority.Send,
                        _dispatcherOperationCallback,
                        param);


                    if (result != null)
                    {
                        handled = param.handled;
                        retval  = param.retVal;
                    }

                    // Restore _paramDispatcherCallbackOperation to the previous value so we will reuse it on the next call
                    _paramDispatcherCallbackOperation = param;
                }

                // Handle WM_NCDESTROY explicitly to forcibly clean up.
                if (message == WindowMessage.WM_NCDESTROY)
                {
                    // The fact that we received this message means that we are
                    // still in the call chain.  This is our last chance to clean
                    // up, and no other message should be received by this window
                    // proc again. It is OK to force a cleanup now.
                    CriticalDetach(true);

                    // Always pass the WM_NCDESTROY message down the chain!
                    handled = false;
                }
            }

            // If our window proc didn't handle this message, pass it on down the
            // chain.
            if (!handled)
            {
                retval = CallOldWindowProc(oldWndProc, hwnd, message, wParam, lParam);
            }

            return(retval);
        }
        internal IntPtr SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
        {
            IntPtr retval = IntPtr.Zero;
            bool handled = false;
            WindowMessage message = (WindowMessage)msg;

            // If we are unattached and we receive a message, then we must have
            // been used as the original window proc.  In this case, we insert
            // ourselves as if the original window proc had been DefWindowProc.
            // We pass in DefWndProcStub as a workaround for a bug in UxTheme on
            // Windows XP. For details see the comment on the DefWndProcWrapper method.
            if(_bond == Bond.Unattached)
            {
                HookWindowProc(hwnd, new NativeMethods.WndProc(SubclassWndProc),
                    Marshal.GetFunctionPointerForDelegate(DefWndProcStub));
            }
            else if(_bond == Bond.Detached)
            {
                throw new InvalidOperationException();
            }

            IntPtr oldWndProc = _oldWndProc;    // in case we get detached during this method

            if(message == DetachMessage)
            {
                // We received our special message to detach.  Make sure it is intended
                // for us by matching the bridge.
                if(wParam == IntPtr.Zero || wParam == (IntPtr)_gcHandle)
                {
                    int param = (int)lParam;    // 0 - normal, 1 - force, 2 - force and forward
                    bool force = (param > 0);

                    retval = CriticalDetach(force) ? new IntPtr(1) : IntPtr.Zero ;
                    handled = (param < 2);
                }
            }
            else
            {
                // Pass this message to our delegate function.  Do this under
                // the exception filter/handlers of the dispatcher for this thread.
                Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
                if(dispatcher != null && !dispatcher.HasShutdownFinished)
                {
                    if (_dispatcherOperationCallback == null)
                        _dispatcherOperationCallback = new DispatcherOperationCallback(this.DispatcherCallbackOperation);

                    // _paramDispatcherCallbackOperation is a thread static member which should be reused to avoid
                    // creating a new data structure every time we call DispatcherCallbackOperation
                    // Cache the param locally in case of reentrance and set _paramDispatcherCallbackOperation to null so reentrancy calls will create a new param
                    if (_paramDispatcherCallbackOperation == null)
                        _paramDispatcherCallbackOperation = new DispatcherOperationCallbackParameter();

                    DispatcherOperationCallbackParameter param = _paramDispatcherCallbackOperation;
                    _paramDispatcherCallbackOperation = null;
                    param.hwnd = hwnd;
                    param.msg = msg;
                    param.wParam = wParam;
                    param.lParam = lParam;
                    //synchronous call
                    object result = dispatcher.Invoke(
                             DispatcherPriority.Send,
                             _dispatcherOperationCallback,
                             param);


                    if (result != null)
                    {
                        handled = param.handled;
                        retval = param.retVal;
                    }

                    // Restore _paramDispatcherCallbackOperation to the previous value so we will reuse it on the next call
                    _paramDispatcherCallbackOperation = param;
                }

                // Handle WM_NCDESTROY explicitly to forcibly clean up.
                if(message == WindowMessage.WM_NCDESTROY)
                {
                    // The fact that we received this message means that we are
                    // still in the call chain.  This is our last chance to clean
                    // up, and no other message should be received by this window
                    // proc again. It is OK to force a cleanup now.
                    CriticalDetach(true);

                    // Always pass the WM_NCDESTROY message down the chain!
                    handled = false;
                }
            }

            // If our window proc didn't handle this message, pass it on down the
            // chain.
            if(!handled)
            {
                retval = CallOldWindowProc(oldWndProc, hwnd, message, wParam, lParam);
            }

            return retval;
        }