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); }
/// <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 + "!"); }
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); }
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); }
/// <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()); }
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); }
/// <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(); } } }
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); }
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 + "!"); }
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); } }
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); }
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(); } } }
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); }
/// <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 + "!"); }
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); }); }
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); }