/// <summary> /// Creates a WPF cursor from a win32 bitmap /// </summary> /// <param name="cursorBitmap"></param> /// <returns></returns> public static Cursor CreateCursor(Bitmap cursorBitmap) { var csh = new WPFCursorFromBitmap(cursorBitmap); return CursorInteropHelper.Create(csh); }
/// <summary> /// Changes the cursor for this control to show the coordinates /// </summary> /// <param name="uiElement"></param> private void SetCoordinatesOnCursor(FrameworkElement uiElement) { Point coordinate = locked ? lockPoint : lastCoordinate; Cursor newCursor = null; var cursorFont = new Font("Arial", 8f); try { // Lets get the string to be printed string coordinateText = coordinate.X.ToString(xFormat) + "," + coordinate.Y.ToString(yFormat); // Calculate the rectangle required to draw the string SizeF textSize = GetTextSize(coordinateText, cursorFont); // ok, so here's the minimum 1/4 size of the bitmap we need, as the // Hotspot for the cursor will be in the centre of the bitmap. int minWidth = 8 + (int)Math.Ceiling(textSize.Width); int minHeight = 8 + (int)Math.Ceiling(textSize.Height); // If the bitmap needs to be resized, then resize it, else just clear it if (cursorBitmap.Width < minWidth * 2 || cursorBitmap.Height < minHeight * 2) { Bitmap oldBitmap = cursorBitmap; cursorBitmap = new Bitmap(Math.Max(cursorBitmap.Width, minWidth * 2), Math.Max(cursorBitmap.Height, minHeight * 2)); oldBitmap.Dispose(); } // Get the centre of the bitmap which will be the Hotspot var centre = new System.Drawing.Point(cursorBitmap.Width / 2, cursorBitmap.Height / 2); /// Calculate the text rectangle var textRectangle = new Rectangle(centre.X + 8, centre.Y + 8, minWidth - 8, minHeight - 8); int diff = (int)cursorPosition.X + textRectangle.Right / 2 - 3 - (int)uiElement.ActualWidth; if (diff > 0) { textRectangle.Location = new System.Drawing.Point(textRectangle.Left - diff, textRectangle.Top); } // Draw the target symbol, and the coordinate text on the bitmap using (Graphics g = Graphics.FromImage(cursorBitmap)) { g.SmoothingMode = SmoothingMode.AntiAlias; // This line causes a crash on laptops when you render a string // g.CompositingMode = CompositingMode.SourceCopy; g.Clear(Color.Transparent); float targetX = centre.X; float targetY = centre.Y; float radius = 30; if (!locked) { var blackPen = new Pen(Color.FromArgb(255, 0, 0, 0), 1.4f); g.DrawEllipse(blackPen, targetX - radius * .5f, targetY - radius * .5f, radius, radius); g.DrawLine(blackPen, targetX - radius * .8f, targetY, targetX - 2f, targetY); g.DrawLine(blackPen, targetX + 2f, targetY, targetX + radius * .8f, targetY); g.DrawLine(blackPen, targetX, targetY - radius * .8f, targetX, targetY - 2f); g.DrawLine(blackPen, targetX, targetY + 2f, targetX, targetY + radius * .8f); } else { var blackPen = new Pen(Color.FromArgb(255, 0, 0, 0), 3f); var yellowPen = new Pen(Color.FromArgb(255, 255, 255, 0), 2f); g.DrawEllipse(blackPen, targetX - radius * .5f, targetY - radius * .5f, radius, radius); g.DrawEllipse(yellowPen, targetX - radius * .5f, targetY - radius * .5f, radius, radius); } if (!locked) { g.FillRectangle(new SolidBrush(Color.FromArgb(127, 255, 255, 255)), textRectangle); } else { g.FillRectangle(new SolidBrush(Color.FromArgb(170, 255, 255, 0)), textRectangle); } // Setup the text format for drawing the subnotes using (var stringFormat = new StringFormat()) { stringFormat.Trimming = StringTrimming.None; stringFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap; stringFormat.Alignment = StringAlignment.Near; // Draw the string left aligned g.DrawString( coordinateText, cursorFont, new SolidBrush(Color.Black), textRectangle, stringFormat); } } // Now copy the bitmap to the cursor newCursor = WPFCursorFromBitmap.CreateCursor(cursorBitmap); } catch { Trace.WriteLine("Error drawing on cursor"); } finally { // After the new cursor has been set, the unmanaged resources can be // cleaned up that were being used by the old cursor if (newCursor != null) { uiElement.Cursor = newCursor; } if (lastCursor != null) { lastCursor.Dispose(); } lastCursor = newCursor; // Save the new values for cleaning up on the next pass } }
/// <summary> /// Creates a WPF cursor from a win32 bitmap /// </summary> /// <param name="cursorBitmap"></param> /// <returns></returns> public static Cursor CreateCursor(Bitmap cursorBitmap) { var csh = new WPFCursorFromBitmap(cursorBitmap); return(CursorInteropHelper.Create(csh)); }