1- using System ;
1+ using System ;
22using System . Drawing ;
33using System . Drawing . Drawing2D ;
44using System . Drawing . Imaging ;
@@ -15,7 +15,7 @@ public static class Logger
1515 private static readonly object _lock = new object ( ) ;
1616 public static bool DebugEnabled = false ;
1717 public static string LogFilePath = "FinalShotDebug.log" ;
18- public static long MaxLogFileSize = 5 * 1024 * 1024 ; // 5 MB
18+ public static long MaxLogFileSize = 5 * 1024 * 1024 ;
1919
2020 public static void Log ( string message )
2121 {
@@ -30,7 +30,7 @@ public static void Log(string message)
3030 File . AppendAllText ( LogFilePath , logMessage ) ;
3131 }
3232 }
33- catch { /* swallow */ }
33+ catch { }
3434 }
3535
3636 private static void RotateIfNeeded ( )
@@ -50,7 +50,7 @@ private static void RotateIfNeeded()
5050 }
5151 }
5252 }
53- catch { /* ignore */ }
53+ catch { }
5454 }
5555 }
5656
@@ -93,31 +93,49 @@ public static class ScreenshotManager
9393
9494 [ DllImport ( "user32.dll" ) ]
9595 private static extern bool GetCursorInfo ( out CURSORINFO pci ) ;
96+
9697 [ DllImport ( "user32.dll" ) ]
9798 private static extern bool DrawIcon ( IntPtr hDC , int X , int Y , IntPtr hIcon ) ;
9899
100+ [ DllImport ( "user32.dll" , SetLastError = true ) ]
101+ private static extern bool GetIconInfo ( IntPtr hIcon , out ICONINFO pIconInfo ) ;
102+
99103 [ StructLayout ( LayoutKind . Sequential ) ]
100104 private struct POINT { public int x , y ; }
105+
101106 [ StructLayout ( LayoutKind . Sequential ) ]
102107 private struct CURSORINFO
103108 {
104109 public int cbSize , flags ;
105110 public IntPtr hCursor ;
106111 public POINT ptScreenPos ;
107112 }
113+
114+ [ StructLayout ( LayoutKind . Sequential ) ]
115+ private struct ICONINFO
116+ {
117+ public bool fIcon ;
118+ public int xHotspot ;
119+ public int yHotspot ;
120+ public IntPtr hbmMask ;
121+ public IntPtr hbmColor ;
122+ }
123+
108124 private const int CURSOR_SHOWING = 0x00000001 ;
109125
110126 public static void DrawCursor ( Graphics g , Rectangle bounds )
111127 {
112128 var ci = new CURSORINFO { cbSize = Marshal . SizeOf ( typeof ( CURSORINFO ) ) } ;
113129 if ( GetCursorInfo ( out ci ) && ci . flags == CURSOR_SHOWING )
114130 {
115- IntPtr hdc = g . GetHdc ( ) ;
116- DrawIcon ( hdc ,
117- ci . ptScreenPos . x - bounds . Left ,
118- ci . ptScreenPos . y - bounds . Top ,
119- ci . hCursor ) ;
120- g . ReleaseHdc ( ) ;
131+ if ( GetIconInfo ( ci . hCursor , out ICONINFO iconInfo ) )
132+ {
133+ IntPtr hdc = g . GetHdc ( ) ;
134+ int x = ci . ptScreenPos . x - bounds . Left - iconInfo . xHotspot ;
135+ int y = ci . ptScreenPos . y - bounds . Top - iconInfo . yHotspot ;
136+ DrawIcon ( hdc , x , y , ci . hCursor ) ;
137+ g . ReleaseHdc ( ) ;
138+ }
121139 }
122140 }
123141
@@ -171,19 +189,33 @@ public static void TakePredefined(Settings settings)
171189
172190 public static void TakeCustom ( Settings settings , Action finishCallback )
173191 {
174- if ( string . IsNullOrEmpty ( settings . SavePath ) ) return ;
192+ Logger . Log ( $ "TakeCustom() called. SavePath='{ settings . SavePath } ' ShowCursor={ settings . ShowCursor } ") ;
193+ if ( string . IsNullOrWhiteSpace ( settings . SavePath ) )
194+ {
195+ Logger . Log ( "TakeCustom: SavePath is empty, aborting custom capture." ) ;
196+ return ;
197+ }
175198 Application . Run ( new CustomScreenshotForm ( settings , finishCallback ) ) ;
176199 }
177200
201+
178202 public static void CompositeCapture ( Rectangle rect , Settings settings )
179203 {
204+ // ←—— Guard against missing SavePath
205+ if ( settings == null || string . IsNullOrWhiteSpace ( settings . SavePath ) )
206+ {
207+ Logger . Log ( "CompositeCapture: no SavePath, skipping." ) ;
208+ return ;
209+ }
210+
180211 using ( var finalBmp = new Bitmap ( rect . Width , rect . Height ) )
181212 using ( var finalG = Graphics . FromImage ( finalBmp ) )
182213 {
183214 foreach ( var scr in Screen . AllScreens )
184215 {
185216 var inter = Rectangle . Intersect ( rect , scr . Bounds ) ;
186- if ( inter . Width <= 0 || inter . Height <= 0 ) continue ;
217+ if ( inter . Width <= 0 || inter . Height <= 0 )
218+ continue ;
187219
188220 using ( var part = new Bitmap ( inter . Width , inter . Height ) )
189221 using ( var g = Graphics . FromImage ( part ) )
@@ -192,51 +224,67 @@ public static void CompositeCapture(Rectangle rect, Settings settings)
192224 if ( settings . ShowCursor )
193225 DrawCursor ( g , new Rectangle ( Point . Empty , inter . Size ) ) ;
194226 finalG . DrawImage ( part ,
195- inter . Left - rect . Left ,
196- inter . Top - rect . Top ) ;
227+ inter . Left - rect . Left ,
228+ inter . Top - rect . Top ) ;
197229 }
198230 }
231+
199232 SaveImageSafely ( finalBmp , settings ) ;
200233 }
201234 }
202235
236+
203237 private static void SaveImageSafely ( Bitmap source , Settings settings )
204238 {
205239 try
206240 {
241+ if ( source == null ) { Logger . Log ( "SaveImageSafely: source bitmap is null" ) ; return ; }
242+ if ( settings == null ) { Logger . Log ( "SaveImageSafely: settings is null" ) ; return ; }
243+
244+ string path = settings . SavePath ;
245+ if ( string . IsNullOrWhiteSpace ( path ) )
246+ {
247+ Logger . Log ( "SaveImageSafely: SavePath is null or empty" ) ;
248+ return ;
249+ }
250+ string dir = Path . GetDirectoryName ( path ) ;
251+ if ( ! string . IsNullOrEmpty ( dir ) && ! Directory . Exists ( dir ) )
252+ Directory . CreateDirectory ( dir ) ;
253+
207254 using ( var clone = new Bitmap ( source . Width , source . Height , source . PixelFormat ) )
208255 using ( var g = Graphics . FromImage ( clone ) )
209256 {
210257 g . DrawImageUnscaled ( source , 0 , 0 ) ;
211258
212- var fmt = GetImageFormat ( settings . SavePath ) ;
213- using ( var fs = new FileStream (
214- settings . SavePath ,
215- FileMode . Create ,
216- FileAccess . Write ,
217- FileShare . None ) )
259+ var fmt = GetImageFormat ( path ) ;
260+ using var fs = new FileStream ( path , FileMode . Create , FileAccess . Write , FileShare . None ) ;
261+
262+ if ( fmt . Guid == ImageFormat . Jpeg . Guid )
218263 {
219- if ( fmt . Guid == ImageFormat . Jpeg . Guid )
264+ var enc = ImageCodecInfo
265+ . GetImageEncoders ( )
266+ . FirstOrDefault ( e => e . FormatID == ImageFormat . Jpeg . Guid ) ;
267+ if ( enc == null )
220268 {
221- var enc = ImageCodecInfo
222- . GetImageEncoders ( )
223- . First ( e => e . FormatID == ImageFormat . Jpeg . Guid ) ;
224- var pars = new EncoderParameters ( 1 ) ;
225- pars . Param [ 0 ] = new EncoderParameter (
226- Encoder . Quality ,
227- settings . JpegQuality ) ;
228- clone . Save ( fs , enc , pars ) ;
269+ Logger . Log ( "SaveImageSafely: JPEG encoder not found, falling back to PNG" ) ;
270+ clone . Save ( fs , ImageFormat . Png ) ;
229271 }
230272 else
231273 {
232- clone . Save ( fs , fmt ) ;
274+ var pars = new EncoderParameters ( 1 ) ;
275+ pars . Param [ 0 ] = new EncoderParameter ( Encoder . Quality , settings . JpegQuality ) ;
276+ clone . Save ( fs , enc , pars ) ;
233277 }
234278 }
279+ else
280+ {
281+ clone . Save ( fs , fmt ) ;
282+ }
235283 }
236284 }
237285 catch ( Exception ex )
238286 {
239- Logger . Log ( "Error saving screenshot: " + ex . Message ) ;
287+ Logger . Log ( "Error saving screenshot: " + ex . ToString ( ) ) ;
240288 }
241289 }
242290
@@ -249,7 +297,7 @@ private static ImageFormat GetImageFormat(string path)
249297 return ImageFormat . Png ;
250298 }
251299
252- private static void ExecuteFinishAction ( Settings settings )
300+ public static void ExecuteFinishAction ( Settings settings )
253301 {
254302 if ( string . IsNullOrEmpty ( settings . FinishAction ) ) return ;
255303 try
@@ -317,8 +365,10 @@ private void OnMouseMove(object s, MouseEventArgs e)
317365 private void OnMouseUp ( object s , MouseEventArgs e )
318366 {
319367 _dragging = false ;
368+ Logger . Log ( $ "CustomScreenshotForm: user dropped selection { _selection } ") ;
320369 if ( _selection . Width < 1 || _selection . Height < 1 )
321370 {
371+ Logger . Log ( "CustomScreenshotForm: selection too small, closing." ) ;
322372 Close ( ) ;
323373 return ;
324374 }
@@ -394,7 +444,11 @@ public static void ExecuteBang(IntPtr data, IntPtr args)
394444 }
395445 else if ( string . Equals ( cmd , "-cs" , StringComparison . OrdinalIgnoreCase ) )
396446 {
397- ScreenshotManager . TakeCustom ( settings , ( ) => { } ) ;
447+ ScreenshotManager . TakeCustom ( settings , ( ) =>
448+ {
449+ Logger . Log ( "Custom capture done, calling FinishAction." ) ;
450+ ScreenshotManager . ExecuteFinishAction ( settings ) ;
451+ } ) ;
398452 }
399453 else if ( cmd . StartsWith ( "ExecuteBatch " , StringComparison . OrdinalIgnoreCase ) )
400454 {
0 commit comments