BOOL IMsoComponentManager.FSetTrackingComponent(UIntPtr dwComponentID, BOOL fTrack)
            {
                if (!OleComponents.TryGetValue(dwComponentID, out ComponentHashtableEntry entry) ||
                    !((entry.component == _trackingComponent) ^ fTrack.IsTrue()))
                {
                    return(BOOL.FALSE);
                }

                _trackingComponent = fTrack.IsTrue() ? entry.component : null;

                return(BOOL.TRUE);
            }
Ejemplo n.º 2
0
        /// <summary>
        ///  Here is where we handle IVsPerPropertyBrowsing.GetLocalizedPropertyInfo and IVsPerPropertyBrowsing.   HideProperty
        ///  such as IPerPropertyBrowsing, IProvidePropertyBuilder, etc.
        /// </summary>
        private unsafe void OnGetDynamicAttributes(Com2PropertyDescriptor sender, GetAttributesEvent attrEvent)
        {
            if (sender.TargetObject is VSSDK.IVsPerPropertyBrowsing vsObj)
            {
                HRESULT hr = HRESULT.S_OK;

                // we want to avoid allowing clients to force a bad property to be browsable,
                // so we don't allow things that are marked as non browsable to become browsable,
                // only the other way around.
                if (sender.CanShow)
                {
                    // should we hide this?
                    BOOL pfHide = sender.Attributes[typeof(BrowsableAttribute)] is Attribute browsableAttribute &&
                                  browsableAttribute.Equals(BrowsableAttribute.No) ? BOOL.TRUE : BOOL.FALSE;
                    hr = vsObj.HideProperty(sender.DISPID, &pfHide);
                    if (hr == HRESULT.S_OK)
                    {
                        attrEvent.Add(pfHide.IsTrue() ? BrowsableAttribute.No : BrowsableAttribute.Yes);
                    }
                }

                // should we show this
                if (typeof(Oleaut32.IDispatch).IsAssignableFrom(sender.PropertyType) && sender.CanShow)
                {
                    BOOL pfDisplay = BOOL.FALSE;
                    hr = vsObj.DisplayChildProperties(sender.DISPID, &pfDisplay);
                    if (hr == HRESULT.S_OK && pfDisplay.IsTrue())
                    {
                        attrEvent.Add(BrowsableAttribute.Yes);
                    }
                }
            }

            Debug.Assert(sender.TargetObject is null || sender.TargetObject is VSSDK.IVsPerPropertyBrowsing, "Object is not " + Interface.Name + "!");
        }
Ejemplo n.º 3
0
        private LinkClickedEventArgs ExecuteClickOnLink(int characterIndex)
        {
            Point previousPosition = new Point();
            BOOL  setOldCursorPos  = GetPhysicalCursorPos(ref previousPosition);

            LinkClickedEventArgs    result  = null;
            LinkClickedEventHandler handler = (sender, e) => result = e;

            _control.LinkClicked += handler;

            try
            {
                Point pt = _control.PointToScreen(_control.GetPositionFromCharIndex(characterIndex));

                // Adjust point a bit to make sure we are clicking inside the character cell instead of on its edge.
                MouseHelper.SendClick(pt.X + 2, pt.Y + 2);

                // Let the event queue drain after clicking, before moving the cursor back to the old position.
                Application.DoEvents();
            }
            finally
            {
                _control.LinkClicked -= handler;

                if (setOldCursorPos.IsTrue())
                {
                    // Move cursor to old position
                    MouseHelper.ChangeMousePosition(previousPosition.X, previousPosition.Y);
                    Application.DoEvents();
                }
            }

            return(result);
        }
Ejemplo n.º 4
0
        private bool IsHoveredWithMouse(TabControl tabControl, int mousePositionX, int mousePositionY)
        {
            Point previousPosition     = new Point();
            BOOL  setOldCursorPosition = User32.GetPhysicalCursorPos(ref previousPosition);

            try
            {
                // Offset the mouse cursor relative to the test app window
                Point pt = tabControl.PointToScreen(new Point(mousePositionX, mousePositionY));
                MouseHelper.ChangeMousePosition(pt.X, pt.Y);

                bool resultOfPage1 = ((IKeyboardToolTip)tabControl.TabPages[0]).IsHoveredWithMouse();
                bool resultOfPage2 = ((IKeyboardToolTip)tabControl.TabPages[1]).IsHoveredWithMouse();

                return(resultOfPage1 && resultOfPage2);
            }
            finally
            {
                if (setOldCursorPosition.IsTrue())
                {
                    // Move cursor to old position
                    MouseHelper.ChangeMousePosition(previousPosition.X, previousPosition.Y);
                    Application.DoEvents();
                }
            }
        }
        public unsafe bool Contains(string name)
        {
            BOOL    contains = BOOL.FALSE;
            HRESULT hr       = _headers.Contains(name, &contains);

            Debug.Assert(hr == HRESULT.S_OK);
            return(contains.IsTrue());
        }
        public unsafe static bool SystemParametersInfoW(SPI uiAction, ref bool value)
        {
            BOOL nativeBool = value ? BOOL.TRUE : BOOL.FALSE;
            bool result     = SystemParametersInfoW(uiAction, 0, &nativeBool, 0);

            value = nativeBool.IsTrue();
            return(result);
        }
Ejemplo n.º 7
0
        /// <summary>
        ///  [See win32 equivalent.]
        /// </summary>
        public bool GetBoolean(BooleanProperty prop)
        {
            SourceGenerated.EnumValidator.Validate(prop, nameof(prop));

            BOOL val = BOOL.FALSE;

            _lastHResult = GetThemeBool(this, Part, State, (int)prop, ref val);
            return(val.IsTrue());
        }
Ejemplo n.º 8
0
        public bool GetBoolean(BooleanProperty prop)
        {
            if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)BooleanProperty.Transparent, (int)BooleanProperty.SourceShrink))
            {
                throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(BooleanProperty));
            }

            BOOL val = BOOL.FALSE;

            lastHResult = UxTheme.GetThemeBool(this, part, state, (int)prop, ref val);
            return(val.IsTrue());
        }
        public unsafe override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            IntPtr parentHandle = (IntPtr)User32.GetFocus();

            IUIService uiSvc = (IUIService)provider.GetService(typeof(IUIService));

            if (uiSvc != null)
            {
                IWin32Window parent = uiSvc.GetDialogOwnerWindow();
                if (parent != null)
                {
                    parentHandle = parent.Handle;
                }
            }

            BOOL   useValue = BOOL.FALSE;
            object pValue   = value;

            try
            {
                object obj = propDesc.TargetObject;
                if (obj is ICustomTypeDescriptor)
                {
                    obj = ((ICustomTypeDescriptor)obj).GetPropertyOwner(propDesc);
                }

                Debug.Assert(obj is VSSDK.IProvidePropertyBuilder, "object is not IProvidePropertyBuilder");
                VSSDK.IProvidePropertyBuilder propBuilder = (VSSDK.IProvidePropertyBuilder)obj;

                if (!propBuilder.ExecuteBuilder(
                        propDesc.DISPID,
                        guidString,
                        null,
                        parentHandle,
                        ref pValue,
                        &useValue).Succeeded())
                {
                    useValue = BOOL.FALSE;
                }
            }
            catch (ExternalException ex)
            {
                Debug.Fail("Failed to show property frame: " + ex.ErrorCode.ToString(CultureInfo.InvariantCulture));
            }

            if (useValue.IsTrue() && (bldrType & VSSDK.CTLBLDTYPE.FEDITSOBJIDRECTLY) == 0)
            {
                return(pValue);
            }

            return(value);
        }
Ejemplo n.º 10
0
 /// <summary>
 ///  Here is where we handle IVsPerPropertyBrowsing.IsPropertyReadOnly
 /// </summary>
 private unsafe void OnGetIsReadOnly(Com2PropertyDescriptor sender, GetBoolValueEvent gbvevent)
 {
     if (sender.TargetObject is VSSDK.IVsPerPropertyBrowsing vsObj)
     {
         // should we make this read only?
         BOOL    pfResult = BOOL.FALSE;
         HRESULT hr       = vsObj.IsPropertyReadOnly(sender.DISPID, &pfResult);
         if (hr == HRESULT.S_OK)
         {
             gbvevent.Value = pfResult.IsTrue();
         }
     }
 }
Ejemplo n.º 11
0
        public unsafe static bool AllowChildProperties(Com2PropertyDescriptor propDesc)
        {
            if (propDesc.TargetObject is VSSDK.IVsPerPropertyBrowsing)
            {
                BOOL    pfHide = BOOL.FALSE;
                HRESULT hr     = ((VSSDK.IVsPerPropertyBrowsing)propDesc.TargetObject).DisplayChildProperties(propDesc.DISPID, &pfHide);
                if (hr == HRESULT.S_OK)
                {
                    return(pfHide.IsTrue());
                }
            }

            return(false);
        }
Ejemplo n.º 12
0
        private unsafe void OnCanResetPropertyValue(Com2PropertyDescriptor sender, GetBoolValueEvent boolEvent)
        {
            if (sender.TargetObject is VSSDK.IVsPerPropertyBrowsing target)
            {
                BOOL    canReset = boolEvent.Value ? BOOL.TRUE : BOOL.FALSE;
                HRESULT hr       = target.CanResetPropertyValue(sender.DISPID, &canReset);
                if (hr.Succeeded())
                {
                    boolEvent.Value = canReset.IsTrue();
                }
            }

            Debug.Assert(sender.TargetObject is null || sender.TargetObject is VSSDK.IVsPerPropertyBrowsing, "Object is not " + Interface.Name + "!");
        }
Ejemplo n.º 13
0
            private void RaiseMouseClick(int x, int y)
            {
                Point previousPosition = new();
                BOOL  setOldCursorPos  = User32.GetPhysicalCursorPos(ref previousPosition);

                bool mouseSwapped = User32.GetSystemMetrics(User32.SystemMetric.SM_SWAPBUTTON) != 0;

                SendMouseInput(x, y, User32.MOUSEEVENTF.MOVE | User32.MOUSEEVENTF.ABSOLUTE);
                SendMouseInput(0, 0, mouseSwapped ? User32.MOUSEEVENTF.RIGHTDOWN : User32.MOUSEEVENTF.LEFTDOWN);
                SendMouseInput(0, 0, mouseSwapped ? User32.MOUSEEVENTF.RIGHTUP : User32.MOUSEEVENTF.LEFTUP);

                Threading.Thread.Sleep(50);

                // Set back the mouse position where it was.
                if (setOldCursorPos.IsTrue())
                {
                    SendMouseInput(previousPosition.X, previousPosition.Y, User32.MOUSEEVENTF.MOVE | User32.MOUSEEVENTF.ABSOLUTE);
                }
            }
Ejemplo n.º 14
0
        public static void SendClick(int x, int y)
        {
            var  previousPosition = new Point();
            BOOL setOldCursorPos  = GetPhysicalCursorPos(ref previousPosition);

            bool mouseSwapped = GetSystemMetrics(SystemMetric.SM_SWAPBUTTON) != 0;

            SendMouseInput(x, y, MOUSEEVENTF.MOVE | MOUSEEVENTF.ABSOLUTE);
            SendMouseInput(x: 0, y: 0, mouseSwapped ? MOUSEEVENTF.RIGHTDOWN : MOUSEEVENTF.LEFTDOWN);
            SendMouseInput(x: 0, y: 0, mouseSwapped ? MOUSEEVENTF.RIGHTUP : MOUSEEVENTF.LEFTUP);

            Thread.Sleep(50);

            // Set back the mouse position where it was.
            if (setOldCursorPos.IsTrue())
            {
                SendMouseInput(previousPosition.X, previousPosition.Y, MOUSEEVENTF.MOVE | MOUSEEVENTF.ABSOLUTE);
            }
        }
        private unsafe bool GetBuilderGuidString(VSSDK.IProvidePropertyBuilder target, Ole32.DispatchID dispid, ref string strGuidBldr, VSSDK.CTLBLDTYPE *bldrType)
        {
            BOOL valid     = BOOL.FALSE;
            var  pGuidBldr = new string[1];

            if (!target.MapPropertyToBuilder(dispid, bldrType, pGuidBldr, &valid).Succeeded())
            {
                return(false);
            }

            if (valid.IsTrue() && (*bldrType & VSSDK.CTLBLDTYPE.FINTERNALBUILDER) == 0)
            {
                Debug.Fail("Property Browser doesn't support standard builders -- NYI");
                return(false);
            }

            strGuidBldr = pGuidBldr[0] ?? Guid.Empty.ToString();
            return(true);
        }
Ejemplo n.º 16
0
        private void ExecuteDoubleClickOnItem(ListViewItem listViewItem)
        {
            Point previousPosition = new Point();
            BOOL  setOldCursorPos  = GetPhysicalCursorPos(ref previousPosition);

            try
            {
                Rectangle pt = _listView.RectangleToScreen(listViewItem.Bounds);

                // We shouldn't move the cursor to the old position immediately after double-clicking,
                // because the ListView uses the cursor position to get data about the item that was double-clicked.
                MouseHelper.SendDoubleClick(pt.X, pt.Y);
                Application.DoEvents();
            }
            finally
            {
                if (setOldCursorPos.IsTrue())
                {
                    // Move cursor to old position
                    MouseHelper.ChangeMousePosition(previousPosition.X, previousPosition.Y);
                    Application.DoEvents();
                }
            }
        }
Ejemplo n.º 17
0
        public async Task RichTextBox_Click_On_Friendly_Name_Link_Provides_Hidden_Link_SpanAsync()
        {
            await RunTestAsync(async (form, richTextBox) =>
            {
                richTextBox.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang4105{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
{\*\generator Riched20 10.0.17134}\viewkind4\uc1 
{\field{\*\fldinst { HYPERLINK ""http://www.google.com"" }}{\fldrslt {Click link #1}}}
\pard\sa200\sl276\slmult1\f0\fs22\lang9  for more information.\par
{\field{\*\fldinst { HYPERLINK ""http://www.google.com"" }}{\fldrslt {Click link #2}}}
\pard\sa200\sl276\slmult1\f0\fs22\lang9  for more information.\par
{\field{\*\fldinst { HYPERLINK ""http://www.google.com"" }}{\fldrslt {Click link #3}}}
\pard\sa200\sl276\slmult1\f0\fs22\lang9  for more information.\par
}";

                Point previousPosition = new();
                BOOL setOldCursorPos   = GetPhysicalCursorPos(ref previousPosition);

                LinkClickedEventArgs?result     = null;
                LinkClickedEventHandler handler = (sender, e) => result = e;
                richTextBox.LinkClicked        += handler;
                try
                {
                    Point pt = richTextBox.PointToScreen(richTextBox.GetPositionFromCharIndex(richTextBox.Text.IndexOf("Click link #2")));

                    // Adjust point a bit to make sure we are clicking inside the character cell instead of on its edge.
                    pt.X += 2;
                    pt.Y += 2;
                    await MoveMouseAsync(form, pt);
                    await InputSimulator.SendAsync(
                        form,
                        inputSimulator => inputSimulator.Mouse.LeftButtonClick());
                    if (setOldCursorPos.IsTrue())
                    {
                        await MoveMouseAsync(form, previousPosition);
                    }

                    // Let the event queue drain after clicking, before moving the cursor back to the old position.
                    Application.DoEvents();
                }
                finally
                {
                    richTextBox.LinkClicked -= handler;

                    if (setOldCursorPos.IsTrue())
                    {
                        // Move cursor to the old position.
                        await InputSimulator.SendAsync(
                            form,
                            inputSimulator => inputSimulator.Mouse.MoveMouseTo(previousPosition.X, previousPosition.Y));
                        Application.DoEvents();
                    }
                }

                Assert.NotNull(result);

                Assert.True(result !.LinkStart + result.LinkLength <= richTextBox.Text.Length);
                Assert.Equal(result.LinkText, richTextBox.Text.Substring(result.LinkStart, result.LinkLength));

                // This assumes the input span is the hidden text of a "friendly name" URL,
                // which is what the native control will pass to the LinkClicked event instead
                // of the actual span of the clicked display text.
                var displayText = GetTextFromRange(richTextBox, result.LinkStart, result.LinkLength, range =>
                {
                    // Move the cursor to the end of the hidden area we are currently located in.
                    range.EndOf(TomHidden, 0);

                    // Extend the cursor to the end of the display text of the link.
                    range.EndOf(TomLink, 1);
                });

                Assert.Equal("Click link #2", displayText);
            });
        }
            BOOL IMsoComponentManager.FPushMessageLoop(
                UIntPtr dwComponentID,
                msoloop uReason,
                void *pvLoopData)
            {
                // Hold onto old state to allow restore before we exit...
                msocstate currentLoopState = _currentState;
                BOOL      continueLoop     = BOOL.TRUE;

                if (!OleComponents.TryGetValue(dwComponentID, out ComponentHashtableEntry entry))
                {
                    return(BOOL.FALSE);
                }

                IMsoComponent prevActive = _activeComponent;

                try
                {
                    User32.MSG    msg = new User32.MSG();
                    IMsoComponent requestingComponent = entry.component;
                    _activeComponent = requestingComponent;

                    Debug.WriteLineIf(
                        CompModSwitches.MSOComponentManager.TraceInfo,
                        $"ComponentManager : Pushing message loop {uReason}");
                    Debug.Indent();

                    while (continueLoop.IsTrue())
                    {
                        // Determine the component to route the message to
                        IMsoComponent component = _trackingComponent ?? _activeComponent ?? requestingComponent;

                        bool useAnsi = false;
                        BOOL peeked  = User32.PeekMessageW(ref msg);

                        if (peeked.IsTrue())
                        {
                            useAnsi = msg.hwnd != IntPtr.Zero && User32.IsWindowUnicode(msg.hwnd).IsFalse();
                            if (useAnsi)
                            {
                                peeked = User32.PeekMessageA(ref msg);
                            }
                        }

                        if (peeked.IsTrue())
                        {
                            continueLoop = component.FContinueMessageLoop(uReason, pvLoopData, &msg);

                            // If the component wants us to process the message, do it.
                            if (continueLoop.IsTrue())
                            {
                                if (useAnsi)
                                {
                                    User32.GetMessageA(ref msg);
                                    Debug.Assert(User32.IsWindowUnicode(msg.hwnd).IsFalse());
                                }
                                else
                                {
                                    User32.GetMessageW(ref msg);
                                    Debug.Assert(msg.hwnd == IntPtr.Zero || User32.IsWindowUnicode(msg.hwnd).IsTrue());
                                }

                                if (msg.message == User32.WM.QUIT)
                                {
                                    Debug.WriteLineIf(
                                        CompModSwitches.MSOComponentManager.TraceInfo,
                                        "ComponentManager : Normal message loop termination");

                                    ThreadContext.FromCurrent().DisposeThreadWindows();

                                    if (uReason != msoloop.Main)
                                    {
                                        User32.PostQuitMessage((int)msg.wParam);
                                    }

                                    continueLoop = BOOL.FALSE;
                                    break;
                                }

                                // Now translate and dispatch the message.
                                //
                                // Reading through the rather sparse documentation,
                                // it seems we should only call FPreTranslateMessage
                                // on the active component.
                                if (component.FPreTranslateMessage(&msg).IsFalse())
                                {
                                    User32.TranslateMessage(ref msg);
                                    if (useAnsi)
                                    {
                                        User32.DispatchMessageA(ref msg);
                                    }
                                    else
                                    {
                                        User32.DispatchMessageW(ref msg);
                                    }
                                }
                            }
                        }
                        else
                        {
                            // If this is a DoEvents loop, then get out. There's nothing left for us to do.
                            if (uReason == msoloop.DoEvents || uReason == msoloop.DoEventsModal)
                            {
                                break;
                            }

                            // Nothing is on the message queue. Perform idle processing and then do a WaitMessage.
                            bool continueIdle = false;

                            if (OleComponents != null)
                            {
                                IEnumerator enumerator = OleComponents.Values.GetEnumerator();

                                while (enumerator.MoveNext())
                                {
                                    ComponentHashtableEntry idleEntry = (ComponentHashtableEntry)enumerator.Current;
                                    continueIdle |= idleEntry.component.FDoIdle(msoidlef.All).IsTrue();
                                }
                            }

                            // Give the component one more chance to terminate the message loop.
                            continueLoop = component.FContinueMessageLoop(uReason, pvLoopData, null);

                            if (continueLoop.IsTrue())
                            {
                                if (continueIdle)
                                {
                                    // If someone has asked for idle time, give it to them.  However,
                                    // don't cycle immediately; wait up to 100ms.  Why?  Because we don't
                                    // want someone to attach to idle, forget to detach, and then cause
                                    // CPU to end up in race condition.  For Windows Forms this generally isn't an issue because
                                    // our component always returns false from its idle request
                                    User32.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, User32.QS.ALLINPUT, User32.MWMO.INPUTAVAILABLE);
                                }
                                else
                                {
                                    // We should call GetMessage here, but we cannot because
                                    // the component manager requires that we notify the
                                    // active component before we pull the message off the
                                    // queue.  This is a bit of a problem, because WaitMessage
                                    // waits for a NEW message to appear on the queue.  If a
                                    // message appeared between processing and now WaitMessage
                                    // would wait for the next message.  We minimize this here
                                    // by calling PeekMessage.
                                    if (User32.PeekMessageW(ref msg, IntPtr.Zero, 0, 0, User32.PM.NOREMOVE).IsFalse())
                                    {
                                        User32.WaitMessage();
                                    }
                                }
                            }
                        }
                    }

                    Debug.Unindent();
                    Debug.WriteLineIf(CompModSwitches.MSOComponentManager.TraceInfo, $"ComponentManager : message loop {uReason} complete.");
                }
                finally
                {
                    _currentState    = currentLoopState;
                    _activeComponent = prevActive;
                }

                return(continueLoop.IsFalse() ? BOOL.TRUE : BOOL.FALSE);
            }
Ejemplo n.º 19
0
        /// <summary>
        ///  Here is where we handle IVsPerPropertyBrowsing.DisplayChildProperties
        /// </summary>
        private unsafe void OnGetTypeConverterAndTypeEditor(Com2PropertyDescriptor sender, GetTypeConverterAndTypeEditorEvent gveevent)
        {
            if (sender.TargetObject is VSSDK.IVsPerPropertyBrowsing)
            {
                // we only do this for IDispatch types
                if (sender.CanShow && typeof(Oleaut32.IDispatch).IsAssignableFrom(sender.PropertyType))
                {
                    VSSDK.IVsPerPropertyBrowsing vsObj = (VSSDK.IVsPerPropertyBrowsing)sender.TargetObject;

                    // should we make this read only?
                    BOOL    pfResult = BOOL.FALSE;
                    HRESULT hr       = vsObj.DisplayChildProperties(sender.DISPID, &pfResult);
                    if (gveevent.TypeConverter is Com2IDispatchConverter)
                    {
                        gveevent.TypeConverter = new Com2IDispatchConverter(sender, hr == HRESULT.S_OK && pfResult.IsTrue());
                    }
                    else
                    {
                        gveevent.TypeConverter = new Com2IDispatchConverter(hr == HRESULT.S_OK && pfResult.IsTrue(), gveevent.TypeConverter);
                    }
                }
            }

            Debug.Assert(sender.TargetObject is null || sender.TargetObject is VSSDK.IVsPerPropertyBrowsing, "Object is not " + Interface.Name + "!");
        }
Ejemplo n.º 20
0
        public async Task RichTextBox_Click_On_Custom_Link_Preceeded_By_Hidden_Text_Provides_Displayed_Link_SpanAsync()
        {
            await RunTestAsync(async (form, richTextBox) =>
            {
                richTextBox.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang4105{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
{\*\generator Riched20 10.0.17134}\viewkind4\uc1\pard\sa200\sl276\slmult1\f0\fs22\lang9
This is hidden text preceeding a \v #link1#\v0 custom link.\par
This is hidden text preceeding a \v #link2#\v0 custom link.\par
This is hidden text preceeding a \v #link3#\v0 custom link.\par
}";

                MakeLink(richTextBox, "#link1#custom link");
                MakeLink(richTextBox, "#link2#custom link");
                MakeLink(richTextBox, "#link3#custom link");

                Point previousPosition = new();
                BOOL setOldCursorPos   = GetPhysicalCursorPos(ref previousPosition);

                LinkClickedEventArgs?result     = null;
                LinkClickedEventHandler handler = (sender, e) => result = e;
                richTextBox.LinkClicked        += handler;
                try
                {
                    Point pt = richTextBox.PointToScreen(richTextBox.GetPositionFromCharIndex(richTextBox.Text.IndexOf("#link2#custom link")));

                    // Adjust point a bit to make sure we are clicking inside the character cell instead of on its edge.
                    pt.X += 2;
                    pt.Y += 2;
                    await MoveMouseAsync(form, pt);
                    await InputSimulator.SendAsync(
                        form,
                        inputSimulator => inputSimulator.Mouse.LeftButtonClick());
                    if (setOldCursorPos.IsTrue())
                    {
                        await MoveMouseAsync(form, previousPosition);
                    }

                    // Let the event queue drain after clicking, before moving the cursor back to the old position.
                    Application.DoEvents();
                }
                finally
                {
                    richTextBox.LinkClicked -= handler;

                    if (setOldCursorPos.IsTrue())
                    {
                        // Move cursor to the old position.
                        await InputSimulator.SendAsync(
                            form,
                            inputSimulator => inputSimulator.Mouse.MoveMouseTo(previousPosition.X, previousPosition.Y));
                        Application.DoEvents();
                    }
                }

                Assert.NotNull(result);

                Assert.True(result !.LinkStart + result.LinkLength <= richTextBox.Text.Length);
                Assert.Equal(result.LinkText, richTextBox.Text.Substring(result.LinkStart, result.LinkLength));

                // This assumes the input span is a custom link preceeded by hidden text.
                var hiddenText = GetTextFromRange(richTextBox, result.LinkStart, result.LinkLength, range =>
                {
                    // Move the cursor to the start of the link we are currently located in.
                    range.StartOf(TomLink, 0);

                    // Extend the cursor to the start of the hidden area preceeding the link.
                    range.StartOf(TomHidden, 1);
                });

                Assert.Equal("#link2#", hiddenText);
            });
        }
Ejemplo n.º 21
0
            public unsafe HRESULT GetDragDropEffect(BOOL fDrag, User32.MK grfKeyState, Ole32.DROPEFFECT *pdwEffect)
            {
                if (pdwEffect is null)
                {
                    return(HRESULT.E_POINTER);
                }

                Debug.WriteLineIf(RichTextDbg.TraceVerbose, "IRichEditOleCallback::GetDragDropEffect");

                if (owner.AllowDrop || owner.EnableAutoDragDrop)
                {
                    if (fDrag.IsTrue() && grfKeyState == (User32.MK) 0)
                    {
                        // This is the very first call we receive in a Drag-Drop operation,
                        // so we will let the control know what we support.

                        // Note that we haven't gotten any data yet, so we will let QueryAcceptData
                        // do the OnDragEnter. Note too, that grfKeyState does not yet reflect the
                        // current keystate
                        if (owner.EnableAutoDragDrop)
                        {
                            lastEffect = (DragDropEffects.All | DragDropEffects.None);
                        }
                        else
                        {
                            lastEffect = DragDropEffects.None;
                        }
                    }
                    else
                    {
                        // We are either dragging over or dropping

                        // The below is the complete reverse of what the docs on MSDN suggest,
                        // but if we follow the docs, we would be firing OnDragDrop all the
                        // time instead of OnDragOver (see

                        // drag - fDrag = false, grfKeyState != 0
                        // drop - fDrag = false, grfKeyState = 0
                        // We only care about the drag.
                        //
                        // When we drop, lastEffect will have the right state
                        if (fDrag.IsFalse() && lastDataObject is not null && grfKeyState != (User32.MK) 0)
                        {
                            DragEventArgs e = new DragEventArgs(lastDataObject,
                                                                (int)grfKeyState,
                                                                Control.MousePosition.X,
                                                                Control.MousePosition.Y,
                                                                DragDropEffects.All,
                                                                lastEffect);

                            // Now tell which of the allowable effects we want to use, but only if we are not already none
                            if (lastEffect != DragDropEffects.None)
                            {
                                e.Effect = ((grfKeyState & User32.MK.CONTROL) == User32.MK.CONTROL) ? DragDropEffects.Copy : DragDropEffects.Move;
                            }

                            owner.OnDragOver(e);
                            lastEffect = e.Effect;
                        }
                    }

                    *pdwEffect = (Ole32.DROPEFFECT)lastEffect;
                }
                else
                {
                    *pdwEffect = Ole32.DROPEFFECT.NONE;
                }

                return(HRESULT.S_OK);
            }