1- using System . Text ;
1+ using Microsoft . VisualBasic . FileIO ;
2+ using System ;
3+ using System . Collections . ObjectModel ;
4+ using System . Diagnostics ;
5+ using System . IO ;
6+ using System . Linq ;
7+ using System . Runtime . InteropServices ;
28using System . Windows ;
3- using System . Windows . Controls ;
4- using System . Windows . Data ;
5- using System . Windows . Documents ;
69using System . Windows . Input ;
10+ using System . Windows . Interop ;
711using System . Windows . Media ;
812using System . Windows . Media . Imaging ;
9- using System . Windows . Navigation ;
10- using System . Windows . Shapes ;
1113
1214namespace GarbageCollector
1315{
14- /// <summary>
15- /// Interaction logic for MainWindow.xaml
16- /// </summary>
1716 public partial class MainWindow : Window
1817 {
18+ private readonly string desktopPath = Environment . GetFolderPath ( Environment . SpecialFolder . Desktop ) ;
19+ public ObservableCollection < FileItem > Files { get ; set ; } = new ObservableCollection < FileItem > ( ) ;
20+
1921 public MainWindow ( )
2022 {
2123 InitializeComponent ( ) ;
24+ LoadFiles ( ) ;
25+ }
26+
27+ private void LoadFiles ( )
28+ {
29+ Files . Clear ( ) ;
30+
31+ // Add folders
32+ foreach ( var dir in Directory . GetDirectories ( desktopPath ) )
33+ {
34+ Files . Add ( new FileItem
35+ {
36+ Name = Path . GetFileName ( dir ) ,
37+ FullPath = dir ,
38+ Icon = IconHelper . GetIcon ( dir , true ) ,
39+ IsFolder = true
40+ } ) ;
41+ }
42+
43+ // Add files
44+ foreach ( var file in Directory . GetFiles ( desktopPath ) )
45+ {
46+ Files . Add ( new FileItem
47+ {
48+ Name = Path . GetFileName ( file ) ,
49+ FullPath = file ,
50+ Icon = IconHelper . GetIcon ( file , false ) ,
51+ IsFolder = false
52+ } ) ;
53+ }
54+
55+ FileList . ItemsSource = Files ;
56+ }
57+
58+ private void DeleteSelected_Click ( object sender , RoutedEventArgs e )
59+ {
60+ var selected = Files . Where ( f => f . IsChecked ) . ToList ( ) ;
61+ if ( ! selected . Any ( ) )
62+ {
63+ MessageBox . Show ( "No items selected." , "GarbageCollector" , MessageBoxButton . OK , MessageBoxImage . Information ) ;
64+ return ;
65+ }
66+
67+ // CONFIRMATION
68+ var result = MessageBox . Show (
69+ $ "Are you sure you want to delete { selected . Count } selected item(s)? They will be sent to the Recycle Bin.",
70+ "Confirm Delete" ,
71+ MessageBoxButton . YesNo ,
72+ MessageBoxImage . Warning ) ;
73+
74+ if ( result != MessageBoxResult . Yes ) return ;
75+
76+ foreach ( var f in selected )
77+ {
78+ try
79+ {
80+ if ( f . IsFolder )
81+ {
82+ Microsoft . VisualBasic . FileIO . FileSystem . DeleteDirectory ( f . FullPath ,
83+ Microsoft . VisualBasic . FileIO . UIOption . OnlyErrorDialogs ,
84+ Microsoft . VisualBasic . FileIO . RecycleOption . SendToRecycleBin ) ;
85+ }
86+ else
87+ {
88+ Microsoft . VisualBasic . FileIO . FileSystem . DeleteFile ( f . FullPath ,
89+ Microsoft . VisualBasic . FileIO . UIOption . OnlyErrorDialogs ,
90+ Microsoft . VisualBasic . FileIO . RecycleOption . SendToRecycleBin ) ;
91+ }
92+ }
93+ catch ( Exception ex )
94+ {
95+ MessageBox . Show ( $ "Error deleting { f . Name } : { ex . Message } ", "Error" , MessageBoxButton . OK , MessageBoxImage . Error ) ;
96+ }
97+ }
98+
99+ LoadFiles ( ) ;
100+ }
101+
102+
103+ private void OrganizeByType_Click ( object sender , RoutedEventArgs e )
104+ {
105+ // CONFIRMATION
106+ var result = MessageBox . Show (
107+ "Are you sure you want to organize your desktop files into folders by type?" ,
108+ "Confirm Organize" ,
109+ MessageBoxButton . YesNo ,
110+ MessageBoxImage . Question ) ;
111+
112+ if ( result != MessageBoxResult . Yes ) return ;
113+
114+ foreach ( var file in Directory . GetFiles ( desktopPath ) )
115+ {
116+ string ext = Path . GetExtension ( file ) . Trim ( '.' ) . ToUpper ( ) ;
117+ if ( string . IsNullOrEmpty ( ext ) ) ext = "OTHERS" ;
118+
119+ string folder = Path . Combine ( desktopPath , ext ) ;
120+ Directory . CreateDirectory ( folder ) ;
121+
122+ string destPath = Path . Combine ( folder , Path . GetFileName ( file ) ) ;
123+ try
124+ {
125+ if ( ! File . Exists ( destPath ) )
126+ File . Move ( file , destPath ) ;
127+ }
128+ catch ( Exception ex )
129+ {
130+ MessageBox . Show ( $ "Error moving { file } : { ex . Message } ") ;
131+ }
132+ }
133+ LoadFiles ( ) ;
134+ }
135+
136+
137+ private void Refresh_Click ( object sender , RoutedEventArgs e ) => LoadFiles ( ) ;
138+
139+ private void FileList_MouseDoubleClick ( object sender , MouseButtonEventArgs e )
140+ {
141+ if ( FileList . SelectedItem is FileItem item )
142+ {
143+ try
144+ {
145+ var psi = new ProcessStartInfo
146+ {
147+ FileName = item . FullPath ,
148+ UseShellExecute = true
149+ } ;
150+ Process . Start ( psi ) ;
151+ }
152+ catch ( Exception ex )
153+ {
154+ MessageBox . Show ( $ "Cannot open { item . Name } : { ex . Message } ") ;
155+ }
156+ }
157+ }
158+ }
159+
160+ // ========== FileItem ==========
161+ public class FileItem
162+ {
163+ public string Name { get ; set ; }
164+ public string FullPath { get ; set ; }
165+ public bool IsFolder { get ; set ; }
166+ public bool IsChecked { get ; set ; }
167+ public ImageSource Icon { get ; set ; }
168+ }
169+
170+ // ========== IconHelper ==========
171+ internal static class IconHelper
172+ {
173+ private const uint SHGFI_ICON = 0x000000100 ;
174+ private const uint SHGFI_SMALLICON = 0x000000001 ;
175+ private const uint FILE_ATTRIBUTE_DIRECTORY = 0x10 ;
176+ private const uint FILE_ATTRIBUTE_NORMAL = 0x80 ;
177+
178+ [ StructLayout ( LayoutKind . Sequential , CharSet = CharSet . Auto ) ]
179+ private struct SHFILEINFO
180+ {
181+ public IntPtr hIcon ;
182+ public int iIcon ;
183+ public uint dwAttributes ;
184+ [ MarshalAs ( UnmanagedType . ByValTStr , SizeConst = 260 ) ]
185+ public string szDisplayName ;
186+ [ MarshalAs ( UnmanagedType . ByValTStr , SizeConst = 80 ) ]
187+ public string szTypeName ;
188+ }
189+
190+ [ DllImport ( "shell32.dll" , CharSet = CharSet . Auto ) ]
191+ private static extern IntPtr SHGetFileInfo ( string pszPath , uint dwFileAttributes , ref SHFILEINFO psfi , uint cbFileInfo , uint uFlags ) ;
192+
193+ [ DllImport ( "user32.dll" , SetLastError = true ) ]
194+ private static extern bool DestroyIcon ( IntPtr hIcon ) ;
195+
196+ public static ImageSource GetIcon ( string path , bool isFolder )
197+ {
198+ try
199+ {
200+ SHFILEINFO shinfo = new SHFILEINFO ( ) ;
201+ uint flags = SHGFI_ICON | SHGFI_SMALLICON ;
202+ uint attrs = isFolder ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL ;
203+
204+ SHGetFileInfo ( path , attrs , ref shinfo , ( uint ) Marshal . SizeOf ( shinfo ) , flags ) ;
205+ if ( shinfo . hIcon != IntPtr . Zero )
206+ {
207+ var img = Imaging . CreateBitmapSourceFromHIcon (
208+ shinfo . hIcon ,
209+ Int32Rect . Empty ,
210+ BitmapSizeOptions . FromWidthAndHeight ( 16 , 16 ) ) ;
211+ img . Freeze ( ) ;
212+ DestroyIcon ( shinfo . hIcon ) ;
213+ return img ;
214+ }
215+ }
216+ catch
217+ {
218+ // fallback: no icon
219+ }
220+ return null ;
22221 }
23222 }
24- }
223+ }
0 commit comments