@@ -108,12 +108,7 @@ private void CropForm_KeyDown(object? sender, KeyEventArgs e)
108108 {
109109 if ( moveWhole )
110110 {
111- // We move one handle, then make the other handle match.
112- // Compared to moving both handles independently, this ensures the overall crop size doesn't change once
113- // we hit the end of the image.
114- float sum = _cropB + _cropT ;
115- MoveCropTop ( - d ) ;
116- _cropB = sum - _cropT ;
111+ MoveWholeArea ( 0 , - d ) ;
117112 }
118113 else if ( moveOtherHandle )
119114 {
@@ -128,9 +123,7 @@ private void CropForm_KeyDown(object? sender, KeyEventArgs e)
128123 {
129124 if ( moveWhole )
130125 {
131- float sum = _cropB + _cropT ;
132- MoveCropBottom ( d ) ;
133- _cropT = sum - _cropB ;
126+ MoveWholeArea ( 0 , d ) ;
134127 }
135128 else if ( moveOtherHandle )
136129 {
@@ -145,9 +138,7 @@ private void CropForm_KeyDown(object? sender, KeyEventArgs e)
145138 {
146139 if ( moveWhole )
147140 {
148- float sum = _cropR + _cropL ;
149- MoveCropLeft ( - d ) ;
150- _cropR = sum - _cropL ;
141+ MoveWholeArea ( - d , 0 ) ;
151142 }
152143 else if ( moveOtherHandle )
153144 {
@@ -162,9 +153,7 @@ private void CropForm_KeyDown(object? sender, KeyEventArgs e)
162153 {
163154 if ( moveWhole )
164155 {
165- float sum = _cropR + _cropL ;
166- MoveCropRight ( d ) ;
167- _cropL = sum - _cropR ;
156+ MoveWholeArea ( d , 0 ) ;
168157 }
169158 else if ( moveOtherHandle )
170159 {
@@ -223,6 +212,7 @@ private Handle GetHandleUnderMouse(MouseEventArgs e)
223212 if ( dyM == dyMin && dxL == dxMin ) return Handle . Left ;
224213 if ( dyB == dyMin && dxM == dxMin ) return Handle . Bottom ;
225214 if ( dyM == dyMin && dxR == dxMin ) return Handle . Right ;
215+ if ( dyM == dyMin && dxM == dxMin ) return Handle . Middle ;
226216 }
227217 return Handle . None ;
228218 }
@@ -290,6 +280,38 @@ private void UpdateCrop(PointF mousePos)
290280 {
291281 MoveCropLeft ( delta . X ) ;
292282 }
283+ if ( _activeHandle . HasFlag ( Handle . Middle ) )
284+ {
285+ MoveWholeArea ( delta . X , delta . Y ) ;
286+ }
287+ }
288+ }
289+
290+ private void MoveWholeArea ( float deltaX , float deltaY )
291+ {
292+ // We move one handle, then make the other handle match.
293+ // Compared to moving both handles independently, this ensures the overall crop size doesn't change once
294+ // we hit the end of the image.
295+ float ySum = _cropB + _cropT ;
296+ float xSum = _cropL + _cropR ;
297+ if ( deltaY < 0 )
298+ {
299+ MoveCropTop ( deltaY ) ;
300+ _cropB = ySum - _cropT ;
301+ }
302+ else if ( deltaY > 0 )
303+ {
304+ MoveCropBottom ( deltaY ) ;
305+ _cropT = ySum - _cropB ;
306+ }
307+ if ( deltaX < 0 )
308+ {
309+ MoveCropLeft ( deltaX ) ;
310+ _cropR = xSum - _cropL ;
311+ } else if ( deltaX > 0 )
312+ {
313+ MoveCropRight ( deltaX ) ;
314+ _cropL = xSum - _cropR ;
293315 }
294316 }
295317
@@ -368,6 +390,7 @@ protected override void PaintOverlay(object? sender, PaintEventArgs e)
368390 // For a small crop selection, we shrink the handles so they don't overlap
369391 var xHandleLen = Math . Min ( HandleLength , ( x2 - x1 ) / 5 ) ;
370392 var yHandleLen = Math . Min ( HandleLength , ( y2 - y1 ) / 5 ) ;
393+ var midHandleLen = Math . Min ( xHandleLen , yHandleLen ) / 3 ;
371394
372395 if ( _freeformActive )
373396 {
@@ -399,6 +422,10 @@ protected override void PaintOverlay(object? sender, PaintEventArgs e)
399422 e . Graphics . DrawLine ( handlePen , x2 , yMid - yHandleLen / 2f , x2 , yMid + yHandleLen / 2f ) ;
400423 e . Graphics . DrawLine ( handlePen , xMid - xHandleLen / 2f , y1 , xMid + xHandleLen / 2f , y1 ) ;
401424 e . Graphics . DrawLine ( handlePen , xMid - xHandleLen / 2f , y2 , xMid + xHandleLen / 2f , y2 ) ;
425+
426+ // Draw middle handle
427+ e . Graphics . DrawLine ( handlePen , xMid , yMid - midHandleLen / 2f , xMid , yMid + midHandleLen / 2f ) ;
428+ e . Graphics . DrawLine ( handlePen , xMid - midHandleLen / 2f , yMid , xMid + midHandleLen / 2f , yMid ) ;
402429 }
403430 }
404431
@@ -410,6 +437,7 @@ private enum Handle
410437 Right = 2 ,
411438 Top = 4 ,
412439 Bottom = 8 ,
440+ Middle = 16 ,
413441 TopLeft = Top | Left ,
414442 TopRight = Top | Right ,
415443 BottomLeft = Bottom | Left ,
0 commit comments