@@ -480,6 +480,108 @@ public WpfCursor CreateLineCursor(string colorHex)
480480 }
481481 }
482482
483+ /// <summary>
484+ /// Creates a cursor for the Circle tool with color indicator
485+ /// </summary>
486+ /// <param name="colorHex">Hex color for the circle (e.g., "#FF0000")</param>
487+ /// <returns>Custom cursor</returns>
488+ public WpfCursor CreateCircleCursor ( string colorHex )
489+ {
490+ lock ( _cursorLock )
491+ {
492+ if ( _disposed )
493+ {
494+ _logger . LogWarning ( "CreateCircleCursor called on disposed CursorHelper" ) ;
495+ return WpfCursors . Cross ;
496+ }
497+
498+ try
499+ {
500+ _logger . LogDebug ( "Creating circle cursor with color {Color}" , colorHex ) ;
501+
502+ // Destroy previous cursor handle to prevent leaks
503+ if ( _currentCursorHandle != nint . Zero )
504+ {
505+ try
506+ {
507+ DestroyCursor ( _currentCursorHandle ) ;
508+ _logger . LogDebug ( "Destroyed previous cursor handle" ) ;
509+ }
510+ catch ( Exception ex )
511+ {
512+ _logger . LogError ( ex , "Failed to destroy previous cursor handle" ) ;
513+ }
514+ _currentCursorHandle = nint . Zero ;
515+ }
516+
517+ // Create a bitmap for the cursor (32x32 pixels)
518+ int size = 32 ;
519+ using ( Bitmap bitmap = new Bitmap ( size , size ) )
520+ using ( Graphics g = Graphics . FromImage ( bitmap ) )
521+ {
522+ g . SmoothingMode = SmoothingMode . AntiAlias ;
523+ g . Clear ( Color . Transparent ) ;
524+
525+ // Parse the circle color
526+ Color circleColor = ColorTranslator . FromHtml ( colorHex ) ;
527+
528+ // Draw a small circle preview
529+ int circleRadius = 6 ;
530+ int circleLeft = 6 ;
531+ int circleTop = ( size - circleRadius * 2 ) / 2 ;
532+
533+ // Draw circle outline with the active color
534+ using ( Pen circlePen = new Pen ( circleColor , 2 ) )
535+ {
536+ g . DrawEllipse ( circlePen , circleLeft , circleTop , circleRadius * 2 , circleRadius * 2 ) ;
537+ }
538+
539+ // Draw corner markers (small filled squares at key points - top-left, top-right, bottom-left, bottom-right)
540+ int cornerSize = 3 ;
541+ using ( SolidBrush cornerBrush = new SolidBrush ( Color . White ) )
542+ {
543+ // Top-left (this is the hotspot - represents bounding box corner)
544+ g . FillRectangle ( cornerBrush , circleLeft - 1 , circleTop - 1 , cornerSize , cornerSize ) ;
545+ // Top-right
546+ g . FillRectangle ( cornerBrush , circleLeft + circleRadius * 2 - 1 , circleTop - 1 , cornerSize , cornerSize ) ;
547+ // Bottom-left
548+ g . FillRectangle ( cornerBrush , circleLeft - 1 , circleTop + circleRadius * 2 - 1 , cornerSize , cornerSize ) ;
549+ // Bottom-right
550+ g . FillRectangle ( cornerBrush , circleLeft + circleRadius * 2 - 1 , circleTop + circleRadius * 2 - 1 , cornerSize , cornerSize ) ;
551+ }
552+
553+ // Draw black outlines for corner markers
554+ using ( Pen cornerOutline = new Pen ( Color . Black , 1 ) )
555+ {
556+ g . DrawRectangle ( cornerOutline , circleLeft - 1 , circleTop - 1 , cornerSize , cornerSize ) ;
557+ g . DrawRectangle ( cornerOutline , circleLeft + circleRadius * 2 - 1 , circleTop - 1 , cornerSize , cornerSize ) ;
558+ g . DrawRectangle ( cornerOutline , circleLeft - 1 , circleTop + circleRadius * 2 - 1 , cornerSize , cornerSize ) ;
559+ g . DrawRectangle ( cornerOutline , circleLeft + circleRadius * 2 - 1 , circleTop + circleRadius * 2 - 1 , cornerSize , cornerSize ) ;
560+ }
561+
562+ // Convert bitmap to cursor with hotspot at top-left corner marker
563+ nint hCursor = CreateCursorFromBitmap ( bitmap , circleLeft , circleTop ) ;
564+
565+ if ( hCursor != nint . Zero )
566+ {
567+ _currentCursorHandle = hCursor ;
568+ _logger . LogDebug ( "Successfully created circle cursor (handle: {Handle})" , hCursor ) ;
569+
570+ return System . Windows . Interop . CursorInteropHelper . Create ( new SafeCursorHandle ( hCursor ) ) ;
571+ }
572+ }
573+
574+ _logger . LogWarning ( "Failed to create circle cursor, returning default" ) ;
575+ return WpfCursors . Cross ;
576+ }
577+ catch ( Exception ex )
578+ {
579+ _logger . LogError ( ex , "Error creating circle cursor, using default" ) ;
580+ return WpfCursors . Cross ;
581+ }
582+ }
583+ }
584+
483585 private nint CreateCursorFromBitmap ( Bitmap bitmap , int hotspotX , int hotspotY )
484586 {
485587 nint hIcon = nint . Zero ;
0 commit comments