A period of time before the project to implement a mouse to drag an element onto another element and the function of the assignment, because to run on surface, drag when the finger will block the system's default drag icon, causing users to realize that they are not dragging things, so to solve the problem.
Initial ideas
At first, the idea is that when you drag a new element to drag at the beginning, and then set the secondary element to follow the mouse movement, the problem here is that when you use the DoDragDrop event, you cannot capture the mouse's coordinate changes so that the newly created element cannot follow the move. To implement the function must abandon the DoDragDrop event, but at that time many of the functions have been written around the event, do not want to change, so began to explore new ways, although the beginning of a waste of time, but the benefits are not no, such as the discovery of givefeedback events, So I thought of the second option.
Since there is no implementation of the method, so this is not on the code.
Second scenario
Buttondown trigger, add MouseMove event to element, when MouseMove trigger, get to current element and generate image into cursor format, in givefeedback to change mouse style, Add the GiveFeedback event and start Dodrapdrop.
Public voidViewelemenmouseleftbuttondown (Objectsender, MouseButtonEventArgs e) { varViewelement = Sender asviewelement; if(Viewelemen = =NULL)return; Viewelemen.mousemove+=Viewelemenonpreviewmousemove; } Private voidPatienttitleonpreviewmousemove (Objectsender, MouseEventArgs MouseEventArgs) { varViewelement = Sender asviewelement; if(Viewelement = =NULL)return; Holocursor=formutility.createcursor (viewelement); Viewelemen.rockstart (); Viewelemen.givefeedback+=Dragsource_givefeedback; Dragdrop.dodragdrop (Viewelemen, Model, dragdropeffects.copy); Viewelemen.mousemove-=Viewelemenonpreviewmousemove; Viewelemen.givefeedback-=Dragsource_givefeedback; Mouse.setcursor (Cursors.arrow); } voidDragsource_givefeedback (Objectsender, GiveFeedbackEventArgs e) { varViewelement = Sender asviewelement; if(Viewelemen = =NULL)return; Mouse.setcursor (Holocursor); E.usedefaultcursors=false; E.handled=true; }
The reason why this trouble is because, the mouse click event to have other business operations, so can only be added to the MouseMove inside.
Generate mouse Formutility.createcursor based on elements:
Public StaticCursor createcursor (UIElement Element) {element. Measure (NewSize (Double. PositiveInfinity,Double. PositiveInfinity)); Element. Arrange (NewRect (NewPoint (), element. DesiredSize)); varRTB =NewRenderTargetBitmap ((int) element. Desiredsize.width, (int) element. Desiredsize.height, the, the, PIXELFORMATS.PBGRA32); Rtb. Render (Element); varEncoder =NewPngbitmapencoder (); Encoder. Frames.add (Bitmapframe.create (RTB)); using(varms =NewMemoryStream ()) {Encoder. Save (MS); using(varBMP =NewSystem.Drawing.Bitmap (MS)) { returninternalcreatecursor (BMP); } } }
Private StaticCursor internalcreatecursor (System.Drawing.Bitmap bmp) {varIconinfo =NewNativemethods.iconinfo (); Nativemethods.geticoninfo (BMP. Gethicon (),reficoninfo); Iconinfo.xhotspot= the; Iconinfo.yhotspot= $; Iconinfo.ficon=false; Safeiconhandle Cursorhandle= Nativemethods.createiconindirect (reficoninfo); returncursorinterophelper.create (Cursorhandle); }
[SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode = true )] private class
Safeiconhandle:safehandlezeroorminusoneisinvalid { public Safeiconhandle (): base (true override protected bool ReleaseHandle () { return Nativemethods.destroyicon (handle); } }
Private Static classNativeMethods { Public structIconinfo { Public BOOLFIcon; Public intXhotspot; Public intYhotspot; PublicIntPtr hbmmask; PublicIntPtr Hbmcolor; } [DllImport ("user32.dll")] Public Static externSafeiconhandle Createiconindirect (reficoninfo icon); [DllImport ("user32.dll")] Public Static extern BOOLDestroyIcon (IntPtr hicon); [DllImport ("user32.dll")] [return: MarshalAs (unmanagedtype.bool)] Public Static extern BOOLGeticoninfo (IntPtr Hicon,reficoninfo piconinfo); }
Rockstart is an element effect, that is, when you start dragging, the element shakes left and right, giving the user a clearer idea of which element to drag.
PrivateStoryboard _SB =NewStoryboard () {Fillbehavior =Fillbehavior.stop}; Publicviewelement () {InitializeComponent (); _SB. AutoReverse=true; varDbAscending1 =NewDoubleAnimation (0,3,NewDuration (Timespan.frommilliseconds ( -))); _SB. Children.add (DBASCENDING1); Storyboard.settarget (DbAscending1, Border); Storyboard.settargetproperty (DbAscending1,NewPropertyPath ("(Rectangle.rendertransform). (Rotatetransform.angle)")); varDbAscending2 =NewDoubleAnimation (3, -3,NewDuration (Timespan.frommilliseconds ( $))); _SB. Children.add (DBASCENDING2); Storyboard.settarget (DbAscending2, Border); Storyboard.settargetproperty (DbAscending2,NewPropertyPath ("(Rectangle.rendertransform). (Rotatetransform.angle)")); } Public voidRockstart () {Dispatcher.invokeasync ()=_SB. Begin (), dispatcherpriority.background); }
At this point, the function is complete.
WPF DragDrop Event Element following