Current filter:
                                You should refresh the page.
                                  • I've implemented the drag-and-drop functionality in my layout view. However, when a user is dragging a card, a standard cursor is shown. However, I want to show my custom cursor, which represents a miniature copy of the dragged card. How can I implement this?

                                1 Solution

                                Creation Date Importance Sort by

                                NOTE: This approach doesn't work starting with v14.1. We will update it as soon as we make improvement in our API - LayoutView - Make the LayoutViewPainter.DrawCardCore method public.
                                As a temporary workaround, use the approach described in the ObjectPainter.DrawObject raises 'Object reference not set to an instance of an object.' exception in DX 14.1 thread.


                                <para>To learn how to implement the drag-and-drop functionality, please see the following Knowledge Base articles:

                                A1418
                                A1444
                                A1445
                                AK14896

                                This article describes how to obtain a dragged card as an image. The main idea is to use the View's painter, but draw the card not onto the View's canvas, but onto a bitmap.

                                First, you should obtain the clicked card using the CalcHitInfo method:

                                [C#]
                                private void layoutView1_MouseDown(object sender, MouseEventArgs e) { LayoutView view = sender as LayoutView; downHitInfo = null; LayoutViewHitInfo hitInfo = view.CalcHitInfo(new Point(e.X, e.Y)); if (Control.ModifierKeys != Keys.None) return; if (e.Button == MouseButtons.Left & hitInfo.InCard) downHitInfo = hitInfo; GetPicture(); }

                                 

                                [VB.NET]
                                Private Sub layoutView1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Dim view As LayoutView = TryCast(sender, LayoutView) downHitInfo = Nothing Dim hitInfo As LayoutViewHitInfo = view.CalcHitInfo(New Point(e.X, e.Y)) If Control.ModifierKeys <> Keys.None Then Return End If If e.Button = MouseButtons.Left AndAlso hitInfo.InCard Then downHitInfo = hitInfo End If End Sub

                                Then, use the ILayoutControl interface to obtain the Painter, and draw the card onto a temporary bitmap:

                                [C#]
                                private Bitmap GetPicture() { ... using (Bitmap bmp = new Bitmap(r.Width, r.Height, PixelFormat.Format32bppArgb)) { using (Graphics imgGraphics = Graphics.FromImage(bmp)) { using (XtraBufferedGraphics bufferedGraphics = XtraBufferedGraphicsManager.Current.Allocate(imgGraphics, r)) { ObjectPainter cardPainter = (layoutView1 as ILayoutControl).PaintStyle.GetPainter(layoutCard); bufferedGraphics.Graphics.Clear(Color.White); layoutCard.ViewInfo.Cache = new GraphicsCache(new DXPaintEventArgs(bufferedGraphics.Graphics, r)); cardPainter.DrawObject(layoutCard.ViewInfo); layoutCard.ViewInfo.Cache = null; bufferedGraphics.Render(); } return newImage; } } }

                                 

                                [VB.NET]
                                Using bmp As New Bitmap(r.Width, r.Height, PixelFormat.Format32bppArgb) Using imgGraphics As Graphics = Graphics.FromImage(bmp) Using bufferedGraphics As XtraBufferedGraphics = XtraBufferedGraphicsManager.Current.Allocate(imgGraphics, r) Dim cardPainter As ObjectPainter = (TryCast(layoutView1, ILayoutControl)).PaintStyle.GetPainter(layoutCard) bufferedGraphics.Graphics.Clear(Color.White) layoutCard.ViewInfo.Cache = New GraphicsCache(New DXPaintEventArgs(bufferedGraphics.Graphics, r)) cardPainter.DrawObject(layoutCard.ViewInfo) layoutCard.ViewInfo.Cache = Nothing bufferedGraphics.Render() End Using Dim newImage As Bitmap = Copy(bmp, layoutCard.Bounds) Return newImage End Using End Using

                                Finally, you need to create a cursor from the resulting image, and assign it to the Cursor.Current property. To create a custom cursor, it's necessary to import GetIconInfo and CreateIconIndirect functions from the system user32.dll library:

                                [C#]
                                [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo); [DllImport("user32.dll")] public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

                                 

                                [VB.NET]
                                <DllImport("user32.dll")> _ Public Shared Function GetIconInfo(ByVal hIcon As IntPtr, ByRef pIconInfo As IconInfo) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport("user32.dll")> _ Public Shared Function CreateIconIndirect(ByRef icon As IconInfo) As IntPtr End Function

                                Here is the CreateCursor function's implementation:

                                 

                                [C#]
                                public static Cursor CreateCursor(Bitmap bmp) { if (bmp == null) return Cursors.Default; bmp = (Bitmap)bmp.GetThumbnailImage(<width>, <height>, null, IntPtr.Zero); IntPtr ptr = bmp.GetHicon(); IconInfo tmp = new IconInfo(); GetIconInfo(ptr, ref tmp); tmp.fIcon = false; ptr = CreateIconIndirect(ref tmp); return new Cursor(ptr); }

                                 

                                [VB.NET]
                                Public Shared Function CreateCursor(ByVal bmp As Bitmap) As Cursor If bmp Is Nothing Then Return Cursors.Default End If bmp = CType(bmp.GetThumbnailImage(<width>, <height>, Nothing, IntPtr.Zero), Bitmap) Dim ptr As IntPtr = bmp.GetHicon() Dim tmp As New IconInfo() GetIconInfo(ptr, tmp) tmp.fIcon = False ptr = CreateIconIndirect(tmp) Return New Cursor(ptr) End Function

                                Finally, it's necessary to handle the GridControl's GiveFeedback event to provide your custom cursor:

                                 

                                [C#]
                                private void gridControl1_GiveFeedback(object sender, GiveFeedbackEventArgs e) { e.UseDefaultCursors = false; Cursor.Current = CreateCursor(GetPicture()); }


                                <code lang="vb">          Private Sub gridControl1_GiveFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs) Handles gridControl1.GiveFeedback
                                            e.UseDefaultCursors = False
                                            Cursor.Current = CreateCursor(GetPicture())
                                          End Sub

                                 See also:
                                How to replace the cursor with a thumbnail image while dragging a row in GridView