├── .gitignore ├── Controls ├── ComboBox.cs ├── ListView.cs └── TreeView.cs ├── EasyExplorer.Designer.cs ├── EasyExplorer.cs ├── EasyExplorer.csproj ├── EasyExplorer.resx ├── EasyExplorer.sln ├── Images ├── BrowseFolders.png ├── BrowserBack.png ├── BrowserForward.png └── BrowserUp.png ├── LICENSE ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx ├── README.md ├── Shell ├── Interfaces │ ├── IAdviseSink.cs │ ├── IContextMenu.cs │ ├── IDataObject.cs │ ├── IDragSourceHelper.cs │ ├── IDropSource.cs │ ├── IDropTarget.cs │ ├── IDropTargetHelper.cs │ ├── IEnumFORMATETC.cs │ ├── IEnumIDList.cs │ ├── IEnumSTATSTG.cs │ ├── IQueryInfo.cs │ ├── IShellExtInit.cs │ ├── IShellFolder.cs │ ├── IStorage.cs │ └── IStream.cs ├── PIDL.cs ├── ShellAPI.cs ├── ShellBrowser.cs ├── ShellBrowserUpdater.cs ├── ShellHelper.cs ├── ShellImageList.cs ├── ShellItem.cs └── StreamStorage.cs ├── Website ├── ee1.png └── ee2.png └── Wrappers ├── BrowserContextMenuWrappers.cs ├── BrowserDragWrappers.cs ├── BrowserDropWrappers.cs └── BrowserPluginWrapper.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /Controls/ComboBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using System.Collections; 6 | using System.Drawing; 7 | using System.Runtime.InteropServices; 8 | using ShellDll; 9 | using System.Drawing.Drawing2D; 10 | using System.Globalization; 11 | using System.ComponentModel; 12 | 13 | namespace EasyExplorer 14 | { 15 | #region ComboBox 16 | 17 | /// 18 | /// This is the ComboBox used in the navigationbar. It is extended to show the icons that go with the 19 | /// ShellItems. 20 | /// 21 | internal class ExplorerComboBox : ToolStripComboBox 22 | { 23 | #region Fields 24 | 25 | // The width of the indent of the ComboItems 26 | private int indentWidth = 10; 27 | 28 | // The item for the browser's current selected directory 29 | private ExplorerComboItem currentItem; 30 | 31 | // The class to draw the icon in the textbox area of the ComboBox 32 | private ComboEditWindow editWindow; 33 | 34 | #endregion 35 | 36 | public ExplorerComboBox() 37 | { 38 | ComboBox.DrawMode = DrawMode.OwnerDrawFixed; 39 | ComboBox.DrawItem += new DrawItemEventHandler(ComboBox_DrawItem); 40 | ComboBox.HandleCreated += new EventHandler(ComboBox_HandleCreated); 41 | 42 | ComboBox.MouseDown += new MouseEventHandler(ComboBox_MouseDown); 43 | ComboBox.MouseMove += new MouseEventHandler(ComboBox_MouseMove); 44 | ComboBox.MouseClick += new MouseEventHandler(ComboBox_MouseClick); 45 | 46 | ComboBox.DropDown += new EventHandler(ComboBox_DropDown); 47 | } 48 | 49 | #region Events 50 | 51 | /// 52 | /// This method will change the currentItem field once a new item is selected 53 | /// 54 | protected override void OnSelectedIndexChanged(EventArgs e) 55 | { 56 | base.OnSelectedIndexChanged(e); 57 | 58 | if (ComboBox.SelectedIndex > -1) 59 | currentItem = ComboBox.SelectedItem as ExplorerComboItem; 60 | } 61 | 62 | /// 63 | /// Once the handle has been created a new instance of ComboEditWindow is made to make sure 64 | /// the icons are drawn in the TextBox part of the ComboBox 65 | /// 66 | void ComboBox_HandleCreated(object sender, EventArgs e) 67 | { 68 | editWindow = new ComboEditWindow(this); 69 | } 70 | 71 | /// 72 | /// This method will draw the items of the DropDownList. It will draw the Icon and the text and 73 | /// with the indent that goes with the item 74 | /// 75 | void ComboBox_DrawItem(object sender, DrawItemEventArgs e) 76 | { 77 | if (e.Index == -1) 78 | return; 79 | else 80 | { 81 | ExplorerComboItem item = (ExplorerComboItem)Items[e.Index]; 82 | 83 | e.DrawBackground(); 84 | e.DrawFocusRectangle(); 85 | 86 | int indentOffset = indentWidth * item.Indent; 87 | 88 | int imageYOffset = (e.Bounds.Height - item.Image.Height) / 2; 89 | Point imagePoint = new Point( 90 | e.Bounds.Left + indentOffset + 2, 91 | e.Bounds.Top + imageYOffset); 92 | 93 | Size textSize = e.Graphics.MeasureString(item.Text, Font).ToSize(); 94 | int textYOffset = (e.Bounds.Height - textSize.Height) / 2; 95 | Point textPoint = new Point( 96 | e.Bounds.Left + item.Image.Width + indentOffset + 2, 97 | e.Bounds.Top + textYOffset); 98 | 99 | e.Graphics.DrawIcon(item.Image, imagePoint.X, imagePoint.Y); 100 | e.Graphics.DrawString(item.Text, e.Font, new SolidBrush(e.ForeColor), textPoint); 101 | } 102 | } 103 | 104 | /// 105 | /// If the mouse is moved over the icon of the ComboBox this method will change the cursor 106 | /// into an hand to indicate that the icon can be clicked 107 | /// 108 | void ComboBox_MouseMove(object sender, MouseEventArgs e) 109 | { 110 | if (editWindow.ImageRect.Contains(e.Location)) 111 | { 112 | Cursor.Current = Cursors.Hand; 113 | } 114 | else if (Cursor.Current == Cursors.Hand) 115 | { 116 | Cursor.Current = Cursors.Default; 117 | } 118 | } 119 | 120 | /// 121 | /// If the mouse is moved over the icon of the ComboBox this method will change the cursor 122 | /// into an hand to indicate that the icon can be clicked 123 | /// 124 | void ComboBox_MouseDown(object sender, MouseEventArgs e) 125 | { 126 | if (editWindow.ImageRect.Contains(e.Location)) 127 | Cursor.Current = Cursors.Hand; 128 | } 129 | 130 | /// 131 | /// If the icon of the ComboBox is clicked this method will select all text in the ComboBox 132 | /// 133 | void ComboBox_MouseClick(object sender, MouseEventArgs e) 134 | { 135 | if (editWindow.ImageRect.Contains(e.Location)) 136 | SelectAll(); 137 | } 138 | 139 | /// 140 | /// This method will make sure that when the ComboBox is dropped down, the width of the DropDownList 141 | /// will be sufficient to fit all items 142 | /// 143 | void ComboBox_DropDown(object sender, EventArgs e) 144 | { 145 | int width = 0; 146 | Graphics gfx = ComboBox.CreateGraphics(); 147 | foreach (ExplorerComboItem item in Items) 148 | { 149 | int itemWidth = 150 | gfx.MeasureString(item.Text, Font).ToSize().Width + 151 | item.Image.Width + 152 | indentWidth * item.Indent + 153 | (Items.Count > MaxDropDownItems ? SystemInformation.VerticalScrollBarWidth : 0); 154 | 155 | if (itemWidth > width) 156 | width = itemWidth; 157 | } 158 | 159 | if (width > this.Width) 160 | ComboBox.DropDownWidth = width; 161 | else 162 | ComboBox.DropDownWidth = this.Width; 163 | } 164 | 165 | #endregion 166 | 167 | #region Public 168 | 169 | [Browsable(false)] 170 | public ExplorerComboItem CurrentItem 171 | { 172 | get { return currentItem; } 173 | set { currentItem = value; } 174 | } 175 | 176 | #endregion 177 | 178 | #region ComboEditWindow 179 | 180 | class ComboEditWindow : NativeWindow 181 | { 182 | private const int LEFTMARGIN = 0x1; 183 | private ExplorerComboBox owner; 184 | private Rectangle imageRect; 185 | private int margin = 0; 186 | 187 | /// 188 | /// The native window's original handle is released 189 | /// and the handle of the TextBox is assigned to it. 190 | /// 191 | public ComboEditWindow(ExplorerComboBox owner) 192 | { 193 | this.owner = owner; 194 | 195 | ShellAPI.COMBOBOXINFO info = new ShellAPI.COMBOBOXINFO(); 196 | info.cbSize = Marshal.SizeOf(typeof(ShellAPI.COMBOBOXINFO)); 197 | ShellAPI.GetComboBoxInfo(owner.ComboBox.Handle, ref info); 198 | 199 | if (!this.Handle.Equals(IntPtr.Zero)) 200 | { 201 | this.ReleaseHandle(); 202 | } 203 | this.AssignHandle(info.hwndEdit); 204 | } 205 | 206 | public Rectangle ImageRect { get { return imageRect; } } 207 | 208 | /// 209 | /// Set the margin of the TextBox to make room for the icon 210 | /// 211 | /// The margin to set 212 | private void SetMargin(int margin) 213 | { 214 | if (this.margin != margin) 215 | { 216 | this.margin = margin; 217 | 218 | if (owner == null) 219 | return; 220 | 221 | ShellAPI.SendMessage( 222 | this.Handle, ShellAPI.WM.SETMARGINS, LEFTMARGIN, 223 | new IntPtr(margin)); 224 | } 225 | } 226 | 227 | /// 228 | /// Whenever the textbox is repainted, this method will draw the icon. 229 | /// 230 | private void DrawImage() 231 | { 232 | if (owner.CurrentItem != null) 233 | { 234 | SetMargin(owner.CurrentItem.Image.Width + 3); 235 | 236 | Icon icon = owner.CurrentItem.Image; 237 | Bitmap image = new Bitmap(icon.Width, icon.Height); 238 | 239 | Graphics imageGfx = Graphics.FromImage(image); 240 | imageRect = new Rectangle(new Point(0, 0), image.Size); 241 | imageGfx.FillRectangle(Brushes.White, imageRect); 242 | imageGfx.DrawIcon(icon, 0, 0); 243 | imageGfx.Flush(); 244 | 245 | // Gets a GDI drawing surface from the textbox. 246 | Graphics gfx = Graphics.FromHwnd(this.Handle); 247 | 248 | if (owner.RightToLeft == RightToLeft.Yes) 249 | { 250 | gfx.DrawImage(image, (int)gfx.VisibleClipBounds.Width - icon.Width, 0); 251 | } 252 | else if (owner.RightToLeft == RightToLeft.No) 253 | { 254 | gfx.DrawImage(image, 0, 0); 255 | } 256 | 257 | gfx.Flush(); 258 | gfx.Dispose(); 259 | } 260 | } 261 | 262 | // Override the WndProc method so that we can redraw the TextBox when the textbox is repainted. 263 | protected override void WndProc(ref Message m) 264 | { 265 | switch (m.Msg) 266 | { 267 | case (int)ShellAPI.WM.PAINT: 268 | base.WndProc(ref m); 269 | DrawImage(); 270 | break; 271 | case (int)ShellAPI.WM.LBUTTONDOWN: 272 | base.WndProc(ref m); 273 | DrawImage(); 274 | break; 275 | case (int)ShellAPI.WM.KEYDOWN: 276 | base.WndProc(ref m); 277 | DrawImage(); 278 | break; 279 | case (int)ShellAPI.WM.KEYUP: 280 | base.WndProc(ref m); 281 | DrawImage(); 282 | break; 283 | case (int)ShellAPI.WM.CHAR: 284 | base.WndProc(ref m); 285 | DrawImage(); 286 | break; 287 | case (int)ShellAPI.WM.GETTEXTLENGTH: 288 | base.WndProc(ref m); 289 | DrawImage(); 290 | break; 291 | case (int)ShellAPI.WM.GETTEXT: 292 | base.WndProc(ref m); 293 | DrawImage(); 294 | break; 295 | default: 296 | base.WndProc(ref m); 297 | break; 298 | } 299 | } 300 | } 301 | 302 | #endregion 303 | } 304 | 305 | /// 306 | /// This class represents the items that can be used for the ExplorerComboBox 307 | /// 308 | internal class ExplorerComboItem 309 | { 310 | // The ShellItem that goes with the ComboItem 311 | private ShellItem shellItem; 312 | 313 | // The indent that goes with the ComboItem 314 | private int indent; 315 | 316 | // The Icon that has to be drawn for this ComboItem 317 | private Icon image; 318 | 319 | public ExplorerComboItem(ShellItem shellItem, int indent) 320 | { 321 | this.shellItem = shellItem; 322 | this.indent = indent; 323 | this.image = ShellImageList.GetIcon(shellItem.ImageIndex, true); 324 | } 325 | 326 | #region Properties 327 | 328 | public ShellItem ShellItem { get { return shellItem; } } 329 | public int Indent { get { return indent; } } 330 | public Icon Image { get { return image; } } 331 | public string Text { get { return ShellItem.Text; } } 332 | 333 | #endregion 334 | 335 | public override string ToString() 336 | { 337 | return ShellItem.Path; 338 | } 339 | } 340 | 341 | #endregion 342 | } -------------------------------------------------------------------------------- /Controls/ListView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using System.Collections; 6 | using System.Drawing; 7 | using System.Runtime.InteropServices; 8 | using ShellDll; 9 | using System.Drawing.Drawing2D; 10 | using System.Globalization; 11 | using System.ComponentModel; 12 | 13 | namespace EasyExplorer 14 | { 15 | #region ListView 16 | 17 | /// 18 | /// This is the ListView used in the Browser control 19 | /// 20 | public class ExplorerListView : ListView 21 | { 22 | #region Fields 23 | 24 | // The arraylist to store the order by which ListViewItems has been selected 25 | private ArrayList selectedOrder; 26 | 27 | private ContextMenu columnHeaderContextMenu; 28 | private bool suspendHeaderContextMenu; 29 | private int columnHeight = 0; 30 | 31 | private ExplorerListSorter sorter; 32 | 33 | #endregion 34 | 35 | public ExplorerListView() 36 | { 37 | OwnerDraw = true; 38 | 39 | HandleCreated += new EventHandler(BrowserListView_HandleCreated); 40 | selectedOrder = new ArrayList(); 41 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 42 | SetStyle(ControlStyles.AllPaintingInWmPaint, true); 43 | 44 | DrawItem += new DrawListViewItemEventHandler(BrowserListView_DrawItem); 45 | DrawSubItem += new DrawListViewSubItemEventHandler(BrowserListView_DrawSubItem); 46 | DrawColumnHeader += new DrawListViewColumnHeaderEventHandler(BrowserListView_DrawColumnHeader); 47 | 48 | this.Alignment = ListViewAlignment.Left; 49 | sorter = new ExplorerListSorter(); 50 | } 51 | 52 | #region Owner Draw 53 | 54 | void BrowserListView_DrawItem(object sender, DrawListViewItemEventArgs e) 55 | { 56 | e.DrawDefault = true; 57 | } 58 | 59 | void BrowserListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e) 60 | { 61 | e.DrawDefault = true; 62 | } 63 | 64 | void BrowserListView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e) 65 | { 66 | e.DrawDefault = true; 67 | columnHeight = e.Bounds.Height; 68 | } 69 | 70 | #endregion 71 | 72 | #region Override 73 | 74 | public new View View 75 | { 76 | get 77 | { 78 | return base.View; 79 | } 80 | set 81 | { 82 | base.View = value; 83 | 84 | if (value == View.Details) 85 | { 86 | foreach (ColumnHeader col in Columns) 87 | if (col.Width == 0) 88 | col.Width = 120; 89 | } 90 | } 91 | } 92 | 93 | protected override void OnItemSelectionChanged(ListViewItemSelectionChangedEventArgs e) 94 | { 95 | if (e.IsSelected) 96 | selectedOrder.Insert(0, e.Item); 97 | else 98 | selectedOrder.Remove(e.Item); 99 | 100 | base.OnItemSelectionChanged(e); 101 | } 102 | 103 | protected override void WndProc(ref Message m) 104 | { 105 | if (this.View == View.Details && columnHeaderContextMenu != null && 106 | (int)m.Msg == (int)ShellAPI.WM.CONTEXTMENU) 107 | { 108 | if (suspendHeaderContextMenu) 109 | suspendHeaderContextMenu = false; 110 | else 111 | { 112 | int x = (int)ShellHelper.LoWord(m.LParam); 113 | int y = (int)ShellHelper.HiWord(m.LParam); 114 | Point clientPoint = PointToClient(new Point(x, y)); 115 | 116 | if (clientPoint.Y <= columnHeight) 117 | columnHeaderContextMenu.Show(this, clientPoint); 118 | } 119 | 120 | return; 121 | } 122 | 123 | base.WndProc(ref m); 124 | } 125 | 126 | #endregion 127 | 128 | #region Events 129 | 130 | /// 131 | /// Once the handle is created we can assign the image lists to the ListView 132 | /// 133 | void BrowserListView_HandleCreated(object sender, EventArgs e) 134 | { 135 | ShellImageList.SetSmallImageList(this); 136 | ShellImageList.SetLargeImageList(this); 137 | } 138 | 139 | #endregion 140 | 141 | #region Public 142 | 143 | [Browsable(false)] 144 | public ArrayList SelectedOrder 145 | { 146 | get { return selectedOrder; } 147 | } 148 | 149 | [Browsable(false)] 150 | public bool SuspendHeaderContextMenu 151 | { 152 | get { return suspendHeaderContextMenu; } 153 | set { suspendHeaderContextMenu = value; } 154 | } 155 | 156 | [Browsable(true)] 157 | public ContextMenu ColumnHeaderContextMenu 158 | { 159 | get { return columnHeaderContextMenu; } 160 | set { columnHeaderContextMenu = value; } 161 | } 162 | 163 | public void SetSorting(bool sorting) 164 | { 165 | if (sorting) 166 | this.ListViewItemSorter = sorter; 167 | else 168 | this.ListViewItemSorter = null; 169 | } 170 | 171 | public void ClearSelections() 172 | { 173 | selectedOrder.Clear(); 174 | selectedOrder.Capacity = 0; 175 | } 176 | 177 | public bool GetListItem(ShellItem shellItem, out ListViewItem listItem) 178 | { 179 | listItem = null; 180 | 181 | foreach (ListViewItem item in Items) 182 | { 183 | if (shellItem.Equals(item.Tag)) 184 | { 185 | listItem = item; 186 | return true; 187 | } 188 | } 189 | 190 | return false; 191 | } 192 | 193 | #endregion 194 | } 195 | 196 | /// 197 | /// This class is used to sort the ListViewItems in the BrowserListView 198 | /// 199 | internal class ExplorerListSorter : IComparer 200 | { 201 | #region IComparer Members 202 | 203 | /// 204 | /// This method will compare the ShellItems of the ListViewItems to determine the return value for 205 | /// comparing the ListViewItems. 206 | /// 207 | public int Compare(object x, object y) 208 | { 209 | ListViewItem itemX = x as ListViewItem; 210 | ListViewItem itemY = y as ListViewItem; 211 | 212 | if (itemX.Tag != null && itemY.Tag != null) 213 | return ((ShellItem)itemX.Tag).CompareTo(itemY.Tag); 214 | else if (itemX.Tag != null) 215 | return 1; 216 | else if (itemY.Tag != null) 217 | return -1; 218 | else 219 | return 0; 220 | } 221 | 222 | #endregion 223 | } 224 | 225 | #endregion 226 | } -------------------------------------------------------------------------------- /Controls/TreeView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using System.Collections; 6 | using System.Drawing; 7 | using System.Runtime.InteropServices; 8 | using ShellDll; 9 | using System.Drawing.Drawing2D; 10 | using System.Globalization; 11 | using System.ComponentModel; 12 | 13 | namespace EasyExplorer 14 | { 15 | #region TreeView 16 | 17 | /// 18 | /// This is the TreeView used in the Browser control 19 | /// 20 | public class ExplorerTreeView : TreeView 21 | { 22 | private ExplorerTreeSorter sorter; 23 | 24 | public ExplorerTreeView() 25 | { 26 | HandleCreated += new EventHandler(BrowserTreeView_HandleCreated); 27 | 28 | sorter = new ExplorerTreeSorter(); 29 | } 30 | 31 | #region Override 32 | 33 | #endregion 34 | 35 | #region Events 36 | 37 | /// 38 | /// Once the handle is created we can assign the image list to the TreeView 39 | /// 40 | void BrowserTreeView_HandleCreated(object sender, EventArgs e) 41 | { 42 | ShellImageList.SetSmallImageList(this); 43 | } 44 | 45 | #endregion 46 | 47 | #region Public 48 | 49 | public bool GetTreeNode(ShellItem shellItem, out TreeNode treeNode) 50 | { 51 | ArrayList pathList = new ArrayList(); 52 | 53 | while (shellItem.ParentItem != null) 54 | { 55 | pathList.Add(shellItem); 56 | shellItem = shellItem.ParentItem; 57 | } 58 | pathList.Add(shellItem); 59 | 60 | pathList.Reverse(); 61 | 62 | treeNode = Nodes[0]; 63 | for (int i = 1; i < pathList.Count; i++) 64 | { 65 | bool found = false; 66 | foreach (TreeNode node in treeNode.Nodes) 67 | { 68 | if (node.Tag != null && node.Tag.Equals(pathList[i])) 69 | { 70 | treeNode = node; 71 | found = true; 72 | break; 73 | } 74 | } 75 | 76 | if (!found) 77 | { 78 | treeNode = null; 79 | return false; 80 | } 81 | } 82 | 83 | return true; 84 | } 85 | 86 | /// 87 | /// This method will check whether a TreeNode is a parent of another TreeNode 88 | /// 89 | /// The parent TreeNode 90 | /// The child TreeNode 91 | /// true if the parent is a parent of the child, false otherwise 92 | public bool IsParentNode(TreeNode parent, TreeNode child) 93 | { 94 | TreeNode current = child; 95 | while (current.Parent != null) 96 | { 97 | if (current.Parent.Equals(parent)) 98 | return true; 99 | 100 | current = current.Parent; 101 | } 102 | return false; 103 | } 104 | 105 | /// 106 | /// This method will check whether a TreeNode is a parent of another TreeNode 107 | /// 108 | /// The parent TreeNode 109 | /// The child TreeNode 110 | /// If the parent is indeed a parent of the child, this will be a path of 111 | /// TreeNodes from the parent to the child including both parent and child 112 | /// true if the parent is a parent of the child, false otherwise 113 | public bool IsParentNode(TreeNode parent, TreeNode child, out TreeNode[] path) 114 | { 115 | ArrayList pathList = new ArrayList(); 116 | 117 | TreeNode current = child; 118 | while (current.Parent != null) 119 | { 120 | pathList.Add(current); 121 | if (current.Parent.Equals(parent)) 122 | { 123 | pathList.Add(parent); 124 | pathList.Reverse(); 125 | path = (TreeNode[])pathList.ToArray(typeof(TreeNode)); 126 | return true; 127 | } 128 | 129 | current = current.Parent; 130 | } 131 | 132 | path = null; 133 | return false; 134 | } 135 | 136 | public void SetSorting(bool sorting) 137 | { 138 | if (sorting) 139 | this.TreeViewNodeSorter = sorter; 140 | else 141 | this.TreeViewNodeSorter = null; 142 | } 143 | 144 | #endregion 145 | } 146 | 147 | /// 148 | /// This class is used to sort the TreeNodes in the BrowserTreeView 149 | /// 150 | internal class ExplorerTreeSorter : IComparer 151 | { 152 | #region IComparer Members 153 | 154 | /// 155 | /// This method will compare the ShellItems of the TreeNodes to determine the return value for 156 | /// comparing the TreeNodes. 157 | /// 158 | public int Compare(object x, object y) 159 | { 160 | TreeNode nodeX = x as TreeNode; 161 | TreeNode nodeY = y as TreeNode; 162 | 163 | if (nodeX.Tag != null && nodeY.Tag != null) 164 | return ((ShellItem)nodeX.Tag).CompareTo(nodeY.Tag); 165 | else if (nodeX.Tag != null) 166 | return 1; 167 | else if (nodeY.Tag != null) 168 | return -1; 169 | else 170 | return 0; 171 | } 172 | 173 | #endregion 174 | } 175 | 176 | #endregion 177 | } -------------------------------------------------------------------------------- /EasyExplorer.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace EasyExplorer 2 | { 3 | partial class Explorer 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Explorer)); 32 | this.browseSplitter = new System.Windows.Forms.SplitContainer(); 33 | this.folderView = new ExplorerTreeView(); 34 | this.viewSplitContainer = new System.Windows.Forms.SplitContainer(); 35 | this.fileView = new ExplorerListView(); 36 | this.browseToolStrip = new System.Windows.Forms.ToolStripContainer(); 37 | this.navigationBar = new System.Windows.Forms.ToolStrip(); 38 | this.navBackButton = new System.Windows.Forms.ToolStripSplitButton(); 39 | this.navForwardButton = new System.Windows.Forms.ToolStripSplitButton(); 40 | this.navUpButton = new System.Windows.Forms.ToolStripButton(); 41 | this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); 42 | this.navFoldersButton = new System.Windows.Forms.ToolStripButton(); 43 | this.navAddressLabel = new System.Windows.Forms.ToolStripLabel(); 44 | this.navAddressBox = new ExplorerComboBox(); 45 | this.browseSplitter.Panel1.SuspendLayout(); 46 | this.browseSplitter.Panel2.SuspendLayout(); 47 | this.browseSplitter.SuspendLayout(); 48 | this.viewSplitContainer.Panel2.SuspendLayout(); 49 | this.viewSplitContainer.SuspendLayout(); 50 | this.browseToolStrip.ContentPanel.SuspendLayout(); 51 | this.browseToolStrip.TopToolStripPanel.SuspendLayout(); 52 | this.browseToolStrip.SuspendLayout(); 53 | this.navigationBar.SuspendLayout(); 54 | this.SuspendLayout(); 55 | // 56 | // browseSplitter 57 | // 58 | this.browseSplitter.Dock = System.Windows.Forms.DockStyle.Fill; 59 | this.browseSplitter.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; 60 | this.browseSplitter.Location = new System.Drawing.Point(0, 0); 61 | this.browseSplitter.Name = "browseSplitter"; 62 | // 63 | // browseSplitter.Panel1 64 | // 65 | this.browseSplitter.Panel1.Controls.Add(this.folderView); 66 | // 67 | // browseSplitter.Panel2 68 | // 69 | this.browseSplitter.Panel2.Controls.Add(this.viewSplitContainer); 70 | this.browseSplitter.Size = new System.Drawing.Size(536, 408); 71 | this.browseSplitter.SplitterDistance = 162; 72 | this.browseSplitter.SplitterWidth = 3; 73 | this.browseSplitter.TabIndex = 0; 74 | this.browseSplitter.MouseDown += new System.Windows.Forms.MouseEventHandler(this.splitter_MouseDown); 75 | this.browseSplitter.MouseMove += new System.Windows.Forms.MouseEventHandler(this.splitter_MouseMove); 76 | this.browseSplitter.MouseUp += new System.Windows.Forms.MouseEventHandler(this.splitter_MouseUp); 77 | // 78 | // folderView 79 | // 80 | this.folderView.Dock = System.Windows.Forms.DockStyle.Fill; 81 | this.folderView.HideSelection = false; 82 | this.folderView.HotTracking = true; 83 | this.folderView.Location = new System.Drawing.Point(0, 0); 84 | this.folderView.Name = "folderView"; 85 | this.folderView.ShowLines = false; 86 | this.folderView.ShowRootLines = false; 87 | this.folderView.Size = new System.Drawing.Size(162, 408); 88 | this.folderView.TabIndex = 0; 89 | // 90 | // viewSplitContainer 91 | // 92 | this.viewSplitContainer.Dock = System.Windows.Forms.DockStyle.Fill; 93 | this.viewSplitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; 94 | this.viewSplitContainer.IsSplitterFixed = true; 95 | this.viewSplitContainer.Location = new System.Drawing.Point(0, 0); 96 | this.viewSplitContainer.Name = "viewSplitContainer"; 97 | this.viewSplitContainer.Orientation = System.Windows.Forms.Orientation.Horizontal; 98 | // 99 | // viewSplitContainer.Panel1 100 | // 101 | this.viewSplitContainer.Panel1.BackColor = System.Drawing.Color.White; 102 | this.viewSplitContainer.Panel1Collapsed = true; 103 | this.viewSplitContainer.Panel1MinSize = 0; 104 | // 105 | // viewSplitContainer.Panel2 106 | // 107 | this.viewSplitContainer.Panel2.Controls.Add(this.fileView); 108 | this.viewSplitContainer.Panel2MinSize = 0; 109 | this.viewSplitContainer.Size = new System.Drawing.Size(371, 408); 110 | this.viewSplitContainer.SplitterDistance = 300; 111 | this.viewSplitContainer.TabIndex = 1; 112 | this.viewSplitContainer.Resize += new System.EventHandler(this.viewSplitContainer_Resize); 113 | // 114 | // fileView 115 | // 116 | this.fileView.Alignment = System.Windows.Forms.ListViewAlignment.Left; 117 | this.fileView.AllowColumnReorder = true; 118 | this.fileView.ColumnHeaderContextMenu = null; 119 | this.fileView.Dock = System.Windows.Forms.DockStyle.Fill; 120 | this.fileView.HideSelection = false; 121 | this.fileView.Location = new System.Drawing.Point(0, 0); 122 | this.fileView.Name = "fileView"; 123 | this.fileView.OwnerDraw = true; 124 | this.fileView.Size = new System.Drawing.Size(371, 408); 125 | this.fileView.SuspendHeaderContextMenu = false; 126 | this.fileView.TabIndex = 0; 127 | this.fileView.UseCompatibleStateImageBehavior = false; 128 | this.fileView.View = System.Windows.Forms.View.List; 129 | this.fileView.Click += onClickFile; 130 | // 131 | // browseToolStrip 132 | // 133 | // 134 | // browseToolStrip.ContentPanel 135 | // 136 | this.browseToolStrip.ContentPanel.Controls.Add(this.browseSplitter); 137 | this.browseToolStrip.ContentPanel.Size = new System.Drawing.Size(536, 408); 138 | this.browseToolStrip.Dock = System.Windows.Forms.DockStyle.Fill; 139 | this.browseToolStrip.LeftToolStripPanelVisible = false; 140 | this.browseToolStrip.Location = new System.Drawing.Point(0, 0); 141 | this.browseToolStrip.Name = "browseToolStrip"; 142 | this.browseToolStrip.RightToolStripPanelVisible = false; 143 | this.browseToolStrip.Size = new System.Drawing.Size(536, 439); 144 | this.browseToolStrip.TabIndex = 1; 145 | this.browseToolStrip.Text = "browseToolStrip"; 146 | // 147 | // browseToolStrip.TopToolStripPanel 148 | // 149 | this.browseToolStrip.TopToolStripPanel.Controls.Add(this.navigationBar); 150 | // 151 | // navigationBar 152 | // 153 | this.navigationBar.CanOverflow = false; 154 | this.navigationBar.Dock = System.Windows.Forms.DockStyle.None; 155 | this.navigationBar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; 156 | this.navigationBar.ImageScalingSize = new System.Drawing.Size(24, 24); 157 | this.navigationBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 158 | this.navBackButton, 159 | this.navForwardButton, 160 | this.navUpButton, 161 | this.toolStripSeparator1, 162 | this.navFoldersButton, 163 | this.navAddressLabel, 164 | this.navAddressBox}); 165 | this.navigationBar.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow; 166 | this.navigationBar.Location = new System.Drawing.Point(0, 0); 167 | this.navigationBar.Name = "navigationBar"; 168 | this.navigationBar.Size = new System.Drawing.Size(536, 31); 169 | this.navigationBar.Stretch = true; 170 | this.navigationBar.TabIndex = 0; 171 | this.navigationBar.Resize += new System.EventHandler(this.navigationBar_Resize); 172 | // 173 | // navBackButton 174 | // 175 | this.navBackButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 176 | this.navBackButton.Enabled = false; 177 | this.navBackButton.Image = global::EasyExplorer.Properties.Resources.BrowserBack; 178 | this.navBackButton.ImageTransparentColor = System.Drawing.Color.Magenta; 179 | this.navBackButton.Name = "navBackButton"; 180 | this.navBackButton.Size = new System.Drawing.Size(40, 28); 181 | this.navBackButton.Text = "Back"; 182 | this.navBackButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; 183 | this.navBackButton.ButtonClick += new System.EventHandler(this.navBackForwardButton_ButtonClick); 184 | this.navBackButton.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.navBackForwardButton_DropDownItemClicked); 185 | // 186 | // navForwardButton 187 | // 188 | this.navForwardButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 189 | this.navForwardButton.Enabled = false; 190 | this.navForwardButton.Image = global::EasyExplorer.Properties.Resources.BrowserForward; 191 | this.navForwardButton.ImageTransparentColor = System.Drawing.Color.Magenta; 192 | this.navForwardButton.Name = "navForwardButton"; 193 | this.navForwardButton.Size = new System.Drawing.Size(40, 28); 194 | this.navForwardButton.Text = "Forward"; 195 | this.navForwardButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; 196 | this.navForwardButton.ButtonClick += new System.EventHandler(this.navBackForwardButton_ButtonClick); 197 | this.navForwardButton.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.navBackForwardButton_DropDownItemClicked); 198 | // 199 | // navUpButton 200 | // 201 | this.navUpButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 202 | this.navUpButton.Image = ((System.Drawing.Image)(resources.GetObject("navUpButton.Image"))); 203 | this.navUpButton.ImageTransparentColor = System.Drawing.Color.Magenta; 204 | this.navUpButton.Name = "navUpButton"; 205 | this.navUpButton.Size = new System.Drawing.Size(28, 28); 206 | this.navUpButton.Text = "Up"; 207 | this.navUpButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; 208 | this.navUpButton.Click += new System.EventHandler(this.navUpButton_Click); 209 | // 210 | // toolStripSeparator1 211 | // 212 | this.toolStripSeparator1.Name = "toolStripSeparator1"; 213 | this.toolStripSeparator1.Size = new System.Drawing.Size(6, 31); 214 | // 215 | // navFoldersButton 216 | // 217 | this.navFoldersButton.Checked = true; 218 | this.navFoldersButton.CheckOnClick = true; 219 | this.navFoldersButton.CheckState = System.Windows.Forms.CheckState.Checked; 220 | this.navFoldersButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 221 | this.navFoldersButton.Image = ((System.Drawing.Image)(resources.GetObject("navFoldersButton.Image"))); 222 | this.navFoldersButton.ImageTransparentColor = System.Drawing.Color.Magenta; 223 | this.navFoldersButton.Name = "navFoldersButton"; 224 | this.navFoldersButton.Size = new System.Drawing.Size(28, 28); 225 | this.navFoldersButton.Text = "Folders"; 226 | this.navFoldersButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText; 227 | this.navFoldersButton.CheckedChanged += new System.EventHandler(this.navFoldersButton_CheckedChanged); 228 | // 229 | // navAddressLabel 230 | // 231 | this.navAddressLabel.MergeIndex = 0; 232 | this.navAddressLabel.Name = "navAddressLabel"; 233 | this.navAddressLabel.Overflow = System.Windows.Forms.ToolStripItemOverflow.Never; 234 | this.navAddressLabel.Size = new System.Drawing.Size(46, 28); 235 | this.navAddressLabel.Text = "Address"; 236 | // 237 | // navAddressBox 238 | // 239 | this.navAddressBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Append; 240 | this.navAddressBox.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.FileSystemDirectories; 241 | this.navAddressBox.AutoSize = false; 242 | this.navAddressBox.CurrentItem = null; 243 | this.navAddressBox.MaxDropDownItems = 14; 244 | this.navAddressBox.MergeIndex = 0; 245 | this.navAddressBox.Name = "navAddressBox"; 246 | this.navAddressBox.Size = new System.Drawing.Size(200, 22); 247 | // 248 | // Browser 249 | // 250 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 251 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 252 | this.Controls.Add(this.browseToolStrip); 253 | this.Name = "Browser"; 254 | this.Size = new System.Drawing.Size(536, 439); 255 | this.browseSplitter.Panel1.ResumeLayout(false); 256 | this.browseSplitter.Panel2.ResumeLayout(false); 257 | this.browseSplitter.ResumeLayout(false); 258 | this.viewSplitContainer.Panel2.ResumeLayout(false); 259 | this.viewSplitContainer.ResumeLayout(false); 260 | this.browseToolStrip.ContentPanel.ResumeLayout(false); 261 | this.browseToolStrip.TopToolStripPanel.ResumeLayout(false); 262 | this.browseToolStrip.TopToolStripPanel.PerformLayout(); 263 | this.browseToolStrip.ResumeLayout(false); 264 | this.browseToolStrip.PerformLayout(); 265 | this.navigationBar.ResumeLayout(false); 266 | this.navigationBar.PerformLayout(); 267 | this.ResumeLayout(false); 268 | 269 | } 270 | 271 | #endregion 272 | 273 | private System.Windows.Forms.SplitContainer browseSplitter; 274 | public ExplorerTreeView folderView; 275 | public ExplorerListView fileView; 276 | private System.Windows.Forms.ToolStripContainer browseToolStrip; 277 | private System.Windows.Forms.ToolStrip navigationBar; 278 | private System.Windows.Forms.ToolStripLabel navAddressLabel; 279 | private ExplorerComboBox navAddressBox; 280 | private System.Windows.Forms.ToolStripButton navUpButton; 281 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; 282 | private System.Windows.Forms.ToolStripButton navFoldersButton; 283 | private System.Windows.Forms.ToolStripSplitButton navBackButton; 284 | private System.Windows.Forms.ToolStripSplitButton navForwardButton; 285 | private System.Windows.Forms.SplitContainer viewSplitContainer; 286 | 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /EasyExplorer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {FC8064DF-B0BC-4D03-B1AE-077F3387412C} 9 | Library 10 | Properties 11 | EasyExplorer 12 | EasyExplorer 13 | v2.0 14 | 15 | 16 | 17 | 18 | 2.0 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | false 33 | true 34 | 35 | 36 | 37 | true 38 | full 39 | false 40 | bin\Debug\ 41 | TRACE;DEBUG 42 | prompt 43 | 4 44 | false 45 | true 46 | 47 | 48 | none 49 | true 50 | bin\Release\ 51 | TRACE 52 | prompt 53 | 4 54 | false 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | Component 69 | 70 | 71 | Component 72 | 73 | 74 | Component 75 | 76 | 77 | UserControl 78 | 79 | 80 | EasyExplorer.cs 81 | 82 | 83 | 84 | 85 | Component 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | True 96 | True 97 | Resources.resx 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Component 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | Designer 120 | EasyExplorer.cs 121 | 122 | 123 | Designer 124 | ResXFileCodeGenerator 125 | Resources.Designer.cs 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | False 144 | .NET Framework 3.5 SP1 Client Profile 145 | false 146 | 147 | 148 | False 149 | .NET Framework 3.5 SP1 150 | true 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 165 | -------------------------------------------------------------------------------- /EasyExplorer.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 8, 19 122 | 123 | 124 | 125 | 126 | iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 127 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA1RJREFUSEvNlGtI 128 | U2EAhpNE1B9NWaVRo/JSVqYVGlHLckjQ/QJRVkRIkX+6X5AMamapkVhSlkUsTa0xymamdLGV4dbKWuq8 129 | nNo6udqGNTEnExbTt/N9tlLGnFZQB94/3znf87zfZRsx4n96ipXFCQG7ecylqgvr/novrVbrQ+ABl33h 130 | l+rdKswS3nqjezP2r4lW5C67GnjOD4IbPETLx2FawRgEH+HXZVSkJ/2xpOR5oYi0dsLnlk/A0qpwLH8Q 131 | jsjcIE3U8RkPq5uqp/yWiGVZX94BXvP466Nocyd8zZMIJL2Yg521MVh1NwJBR/2ZFOnh/cOWkK3h5/hT 132 | eJQ0GAmVIegPXykPV4Rm8hvGp/EavZK82hLzE3PcSgCtD3tXKO0fMomfEoiFWUKaiZkBP5snv4pF5FmB 133 | esitGVl0pYWRwGHXATBxqYXNogarTEFnZzus1nZMPuhNt4TA9zcvGp5AdztWDkcdB87/ld5H6HhXDH1p 134 | LI3kcSLiS8Io/NBb0fAE7+XzZegtGiggsl7pgDEiIPBjH1dQASnmjFlbKHK7ZX0ryIO7OLqzwd6bhQXX 135 | QihcbFqNmbkCWE0KGvK8zvfTuxUwsshKtHONLadcYtPvoXCH/TO3RREUfvrrRioA7DRW06PBBS3ScAUM 136 | ZwA2FR0vN1Bg/xA4cAsiTkDg2V2bMT0tlBsz0pD25Ca6XUFDsUCFFjFszzfBoNzHTbJwaeCi5vKEwp0C 137 | At/6LA7iktXcWD3s1vuDtydWTQG/DvUpMJRGcRMY18PmDpzcIrKC7K6tCDsRhA6dmPtOSeFms4c/v9qr 138 | /oz91V7oyxcDPU3At/MuCU0LwsWeHZidNxmSp1uATye5c7kJvWK72OMP7uWVkaxVtQNt9TlA9x2gK3tA 139 | SPv5kqkULpYt6XtnOEbbtxkUYR4F6kteRvODpbB3tgBfTrokPiMEgXv8UEqa/3hv1yZ73nunmQh08nmA 140 | rRH4kOoSSdlKGFTrYaqKAyObRMGaIoHK+K5sjsf25AMioLfHfANgDsLRuAsdNWthqIhFU0kwyPs66cz7 141 | OkXyUaPmwhqrsXb0kMD9V2CzaMCWxUBTwGsmQG2pUPq+5vBuc0uhaNA7PhQTAZK0qtO3fdHdiRnKnH/+ 142 | zXeqYBc+VexsyAAAAABJRU5ErkJggg== 143 | 144 | 145 | 146 | 147 | iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 148 | YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAz1JREFUSEvdlWtI 149 | U2EYx40kukBCgZYURVgRXcgQ+1DRhexDFxAiMuhmJIJCKUmgQWCZfqmkIEsNh3dXxkwJvOW8YOJlzul2 150 | tuX04JEds1bmgVGT6b/nPdq8Tlf4pQY/ztn7nvP8n/d5/u97vLz+mx9fdlA5E0C/bFEWaCzYUmdtvXdd 151 | bEuEzayAJKoxxCvBBBdNwPmjB0AZoSDSiRp85jJOc68C382HRwmYlFvVGK2cCMyCTzDaCMjQ3Jhq2rwk 152 | xoEJeyTASoTR164ADimZynNIxlKx34XTkep65o8EuMJNDZCyAOmhjEm5DQ7JTMFEgl3bYLc1Q6gLgWSJ 153 | gk13AXxlsLyCqbhdTVfBxiYMPAWsiXBYYmEsChgvy+9SsSv9H7Lky0iCEk57K+BsoXG1XL55y2XI829F 154 | bwolGwex4gCMhVtm94OJjCnnHqe5eQV0OX5aGO5TJSIhlgWBK9hM2aXNy2DneQi1IZOoQ7KFGbhKps1e 155 | qxszJGGk6RI45XYY8jcAtmS3sMBsr1DDiGHCBgh5gJ2n+xGZ7urLKS4BncLHMNKRIGfPNltX7nqAvyNj 156 | 74qAqD4Ky9sd4IoDZew2LQVhwdomMSeSHvUEX0i8BIL2WahLoCNrZbe9JQqm4l2QrOXozPEFum5AajwL 157 | Xh1Ojvo4niV6CT1RR7BNOQVzAgkwY3CwVIc+m3bMtKev6PleH4bBzlRIPU+gy14DaKIhqPbA6RDoJYXb 158 | 5rqcRgaBpKJkVLA03I6ZZllNpnefUBoMx7ARUmc4OhSr4WglAfVFco6OrPh8YUy3SCAXPe9PKAYGOnyn 159 | CbSlLe0Xaq8A3+plq2qzVuFrTai8IvwspebRdSG4WDhtj2EuD3s0a8M1v1hiZaeoUHUGXL4f2jOXg1ft 160 | pRWZqGcPPEN/k8xwOH9QUAfMKcBELB9ux4jGkiBNhncfX36Ssia3iOQONzj74iHpr0GsPw6uyB/6Nx4e 161 | 76xkcnk+5ZBx4l04uGgMtZyDUE7nUME6sKR0yt0VH2si7/brc47Nqr27w4m9yLxu10RgsOoI+JKd0Gb7 162 | GNk4y5K5xNpduu+vv3gsEEPz0seoLzuVyTcnXZ2zth59DP71h34BWgsbUN6O8WoAAAAASUVORK5CYII= 163 | 164 | 165 | -------------------------------------------------------------------------------- /EasyExplorer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyExplorer", "EasyExplorer.csproj", "{FC8064DF-B0BC-4D03-B1AE-077F3387412C}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {FC8064DF-B0BC-4D03-B1AE-077F3387412C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {FC8064DF-B0BC-4D03-B1AE-077F3387412C}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {FC8064DF-B0BC-4D03-B1AE-077F3387412C}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {FC8064DF-B0BC-4D03-B1AE-077F3387412C}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Images/BrowseFolders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Images/BrowseFolders.png -------------------------------------------------------------------------------- /Images/BrowserBack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Images/BrowserBack.png -------------------------------------------------------------------------------- /Images/BrowserForward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Images/BrowserForward.png -------------------------------------------------------------------------------- /Images/BrowserUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Images/BrowserUp.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Harsh Gupta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EasyExplorer")] 9 | [assembly: AssemblyDescription("A Windows Explorer component for .NET apps.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("EasyExplorer")] 12 | [assembly: AssemblyProduct("EasyExplorer")] 13 | [assembly: AssemblyCopyright("Copyright © EasyExplorer 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c5ff9b37-3f42-4058-81ec-2d490db59924")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.4.0.0")] 35 | [assembly: AssemblyFileVersion("1.4.0.0")] 36 | -------------------------------------------------------------------------------- /Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EasyExplorer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EasyExplorer.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap BrowseFolders { 67 | get { 68 | object obj = ResourceManager.GetObject("BrowseFolders", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap BrowserBack { 77 | get { 78 | object obj = ResourceManager.GetObject("BrowserBack", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap BrowserForward { 87 | get { 88 | object obj = ResourceManager.GetObject("BrowserForward", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap BrowserUp { 97 | get { 98 | object obj = ResourceManager.GetObject("BrowserUp", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Images\BrowseFolders.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Images\BrowserBack.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Images\BrowserForward.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Images\BrowserUp.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EasyExplorer 2 | EasyExplorer is the easiest way to integrate Windows Explorer functionality into your app. The component is configurable, and events are provided for all user actions such as navigating folders, opening files, etc. All credits go to [Steven Roebert](http://www.codeproject.com/Articles/15059/C-File-Browser) for building this component in 2006. 3 | 4 | ## Screenshots 5 | 6 | ### Folder View 7 | 8 | ![](https://github.com/hgupta9/EasyExplorer/raw/master/Website/ee2.png) 9 | 10 | ### Control Panel View 11 | 12 | ![](https://github.com/hgupta9/EasyExplorer/raw/master/Website/ee1.png) -------------------------------------------------------------------------------- /Shell/Interfaces/IAdviseSink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport] 9 | [Guid("0000010f-0000-0000-C000-000000000046")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IAdviseSink 12 | { 13 | // Advises that data has changed 14 | [PreserveSig] 15 | void OnDataChange( 16 | ref ShellAPI.FORMATETC pformatetcIn, 17 | ref ShellAPI.STGMEDIUM pmedium); 18 | 19 | // Advises that view of object has changed 20 | [PreserveSig] 21 | void OnViewChange( 22 | int dwAspect, 23 | int lindex); 24 | 25 | // Advises that name of object has changed 26 | [PreserveSig] 27 | void OnRename( 28 | IntPtr pmk); 29 | 30 | // Advises that object has been saved to disk 31 | [PreserveSig] 32 | void OnSave(); 33 | 34 | // Advises that object has been closed 35 | [PreserveSig] 36 | void OnClose(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Shell/Interfaces/IContextMenu.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport()] 9 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | [GuidAttribute("000214e4-0000-0000-c000-000000000046")] 11 | public interface IContextMenu 12 | { 13 | // Adds commands to a shortcut menu 14 | [PreserveSig()] 15 | Int32 QueryContextMenu( 16 | IntPtr hmenu, 17 | uint iMenu, 18 | uint idCmdFirst, 19 | uint idCmdLast, 20 | ShellAPI.CMF uFlags); 21 | 22 | // Carries out the command associated with a shortcut menu item 23 | [PreserveSig()] 24 | Int32 InvokeCommand( 25 | ref ShellAPI.CMINVOKECOMMANDINFOEX info); 26 | 27 | // Retrieves information about a shortcut menu command, 28 | // including the help string and the language-independent, 29 | // or canonical, name for the command 30 | [PreserveSig()] 31 | Int32 GetCommandString( 32 | uint idcmd, 33 | ShellAPI.GCS uflags, 34 | uint reserved, 35 | [MarshalAs(UnmanagedType.LPArray)] 36 | byte[] commandstring, 37 | int cch); 38 | } 39 | 40 | [ComImport, Guid("000214f4-0000-0000-c000-000000000046")] 41 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 42 | public interface IContextMenu2 43 | { 44 | // Adds commands to a shortcut menu 45 | [PreserveSig()] 46 | Int32 QueryContextMenu( 47 | IntPtr hmenu, 48 | uint iMenu, 49 | uint idCmdFirst, 50 | uint idCmdLast, 51 | ShellAPI.CMF uFlags); 52 | 53 | // Carries out the command associated with a shortcut menu item 54 | [PreserveSig()] 55 | Int32 InvokeCommand( 56 | ref ShellAPI.CMINVOKECOMMANDINFOEX info); 57 | 58 | // Retrieves information about a shortcut menu command, 59 | // including the help string and the language-independent, 60 | // or canonical, name for the command 61 | [PreserveSig()] 62 | Int32 GetCommandString( 63 | uint idcmd, 64 | ShellAPI.GCS uflags, 65 | uint reserved, 66 | [MarshalAs(UnmanagedType.LPWStr)] 67 | StringBuilder commandstring, 68 | int cch); 69 | 70 | // Allows client objects of the IContextMenu interface to 71 | // handle messages associated with owner-drawn menu items 72 | [PreserveSig] 73 | Int32 HandleMenuMsg( 74 | uint uMsg, 75 | IntPtr wParam, 76 | IntPtr lParam); 77 | } 78 | 79 | [ComImport, Guid("bcfce0a0-ec17-11d0-8d10-00a0c90f2719")] 80 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 81 | public interface IContextMenu3 82 | { 83 | // Adds commands to a shortcut menu 84 | [PreserveSig()] 85 | Int32 QueryContextMenu( 86 | IntPtr hmenu, 87 | uint iMenu, 88 | uint idCmdFirst, 89 | uint idCmdLast, 90 | ShellAPI.CMF uFlags); 91 | 92 | // Carries out the command associated with a shortcut menu item 93 | [PreserveSig()] 94 | Int32 InvokeCommand( 95 | ref ShellAPI.CMINVOKECOMMANDINFOEX info); 96 | 97 | // Retrieves information about a shortcut menu command, 98 | // including the help string and the language-independent, 99 | // or canonical, name for the command 100 | [PreserveSig()] 101 | Int32 GetCommandString( 102 | uint idcmd, 103 | ShellAPI.GCS uflags, 104 | uint reserved, 105 | [MarshalAs(UnmanagedType.LPWStr)] 106 | StringBuilder commandstring, 107 | int cch); 108 | 109 | // Allows client objects of the IContextMenu interface to 110 | // handle messages associated with owner-drawn menu items 111 | [PreserveSig] 112 | Int32 HandleMenuMsg( 113 | uint uMsg, 114 | IntPtr wParam, 115 | IntPtr lParam); 116 | 117 | // Allows client objects of the IContextMenu3 interface to 118 | // handle messages associated with owner-drawn menu items 119 | [PreserveSig] 120 | Int32 HandleMenuMsg2( 121 | uint uMsg, 122 | IntPtr wParam, 123 | IntPtr lParam, 124 | IntPtr plResult); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Shell/Interfaces/IDataObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport] 9 | [Guid("0000010e-0000-0000-C000-000000000046")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IDataObject 12 | { 13 | // Renders the data described in a FORMATETC structure 14 | // and transfers it through the STGMEDIUM structure 15 | [PreserveSig] 16 | Int32 GetData( 17 | ref ShellAPI.FORMATETC pformatetcIn, 18 | ref ShellAPI.STGMEDIUM pmedium); 19 | 20 | // Renders the data described in a FORMATETC structure 21 | // and transfers it through the STGMEDIUM structure allocated by the caller 22 | [PreserveSig] 23 | Int32 GetDataHere( 24 | ref ShellAPI.FORMATETC pformatetcIn, 25 | ref ShellAPI.STGMEDIUM pmedium); 26 | 27 | // Determines whether the data object is capable of 28 | // rendering the data described in the FORMATETC structure 29 | [PreserveSig] 30 | Int32 QueryGetData( 31 | ref ShellAPI.FORMATETC pformatetc); 32 | 33 | // Provides a potentially different but logically equivalent FORMATETC structure 34 | [PreserveSig] 35 | Int32 GetCanonicalFormatEtc( 36 | ref ShellAPI.FORMATETC pformatetc, 37 | ref ShellAPI.FORMATETC pformatetcout); 38 | 39 | // Provides the source data object with data described by a 40 | // FORMATETC structure and an STGMEDIUM structure 41 | [PreserveSig] 42 | Int32 SetData( 43 | ref ShellAPI.FORMATETC pformatetcIn, 44 | ref ShellAPI.STGMEDIUM pmedium, 45 | bool frelease); 46 | 47 | // Creates and returns a pointer to an object to enumerate the 48 | // FORMATETC supported by the data object 49 | [PreserveSig] 50 | Int32 EnumFormatEtc( 51 | int dwDirection, 52 | ref IEnumFORMATETC ppenumFormatEtc); 53 | 54 | // Creates a connection between a data object and an advise sink so 55 | // the advise sink can receive notifications of changes in the data object 56 | [PreserveSig] 57 | Int32 DAdvise( 58 | ref ShellAPI.FORMATETC pformatetc, 59 | ref ShellAPI.ADVF advf, 60 | ref IAdviseSink pAdvSink, 61 | ref int pdwConnection); 62 | 63 | // Destroys a notification previously set up with the DAdvise method 64 | [PreserveSig] 65 | Int32 DUnadvise( 66 | int dwConnection); 67 | 68 | // Creates and returns a pointer to an object to enumerate the current advisory connections 69 | [PreserveSig] 70 | Int32 EnumDAdvise( 71 | ref object ppenumAdvise); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Shell/Interfaces/IDragSourceHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport] 9 | [GuidAttribute("DE5BF786-477A-11d2-839D-00C04FD918D0")] 10 | [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IDragSourceHelper 12 | { 13 | // Initializes the drag-image manager for a windowless control 14 | [PreserveSig] 15 | Int32 InitializeFromBitmap( 16 | ref ShellAPI.SHDRAGIMAGE pshdi, 17 | IntPtr pDataObject); 18 | 19 | // Initializes the drag-image manager for a control with a window 20 | [PreserveSig] 21 | Int32 InitializeFromWindow( 22 | IntPtr hwnd, 23 | ref ShellAPI.POINT ppt, 24 | IntPtr pDataObject); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Shell/Interfaces/IDropSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | 7 | namespace ShellDll 8 | { 9 | [ComImport] 10 | [GuidAttribute("00000121-0000-0000-C000-000000000046")] 11 | [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 12 | public interface IDropSource 13 | { 14 | // Determines whether a drag-and-drop operation should continue 15 | [PreserveSig] 16 | Int32 QueryContinueDrag( 17 | bool fEscapePressed, 18 | ShellAPI.MK grfKeyState); 19 | 20 | // Gives visual feedback to an end user during a drag-and-drop operation 21 | [PreserveSig] 22 | Int32 GiveFeedback( 23 | DragDropEffects dwEffect); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Shell/Interfaces/IDropTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | 7 | namespace ShellDll 8 | { 9 | [ComImport] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | [Guid("00000122-0000-0000-C000-000000000046")] 12 | public interface IDropTarget 13 | { 14 | // Determines whether a drop can be accepted and its effect if it is accepted 15 | [PreserveSig] 16 | Int32 DragEnter( 17 | IntPtr pDataObj, 18 | ShellAPI.MK grfKeyState, 19 | ShellAPI.POINT pt, 20 | ref DragDropEffects pdwEffect); 21 | 22 | // Provides target feedback to the user through the DoDragDrop function 23 | [PreserveSig] 24 | Int32 DragOver( 25 | ShellAPI.MK grfKeyState, 26 | ShellAPI.POINT pt, 27 | ref DragDropEffects pdwEffect); 28 | 29 | // Causes the drop target to suspend its feedback actions 30 | [PreserveSig] 31 | Int32 DragLeave(); 32 | 33 | // Drops the data into the target window 34 | [PreserveSig] 35 | Int32 DragDrop( 36 | IntPtr pDataObj, 37 | ShellAPI.MK grfKeyState, 38 | ShellAPI.POINT pt, 39 | ref DragDropEffects pdwEffect); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Shell/Interfaces/IDropTargetHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | 7 | namespace ShellDll 8 | { 9 | [ComImport] 10 | [GuidAttribute("4657278B-411B-11d2-839A-00C04FD918D0")] 11 | [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 12 | public interface IDropTargetHelper 13 | { 14 | // Notifies the drag-image manager that the drop target's IDropTarget::DragEnter method has been called 15 | [PreserveSig] 16 | Int32 DragEnter( 17 | IntPtr hwndTarget, 18 | IntPtr pDataObject, 19 | ref ShellAPI.POINT ppt, 20 | DragDropEffects dwEffect); 21 | 22 | // Notifies the drag-image manager that the drop target's IDropTarget::DragLeave method has been called 23 | [PreserveSig] 24 | Int32 DragLeave(); 25 | 26 | // Notifies the drag-image manager that the drop target's IDropTarget::DragOver method has been called 27 | [PreserveSig] 28 | Int32 DragOver( 29 | ref ShellAPI.POINT ppt, 30 | DragDropEffects dwEffect); 31 | 32 | // Notifies the drag-image manager that the drop target's IDropTarget::Drop method has been called 33 | [PreserveSig] 34 | Int32 Drop( 35 | IntPtr pDataObject, 36 | ref ShellAPI.POINT ppt, 37 | DragDropEffects dwEffect); 38 | 39 | // Notifies the drag-image manager to show or hide the drag image 40 | [PreserveSig] 41 | Int32 Show( 42 | bool fShow); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Shell/Interfaces/IEnumFORMATETC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport] 9 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | [Guid("00000103-0000-0000-C000-000000000046")] 11 | public interface IEnumFORMATETC 12 | { 13 | // Retrieves the specified number of FORMATETC structures in the enumeration 14 | // sequence and advances the current position by the number of items retrieved 15 | [PreserveSig] 16 | int GetNext( 17 | int celt, 18 | ref ShellAPI.FORMATETC rgelt, 19 | ref int pceltFetched); 20 | 21 | // Skips over the specified number of elements in the enumeration sequence 22 | [PreserveSig] 23 | int Skip(int celt); 24 | 25 | // Returns to the beginning of the enumeration sequence 26 | [PreserveSig] 27 | int Reset(); 28 | 29 | // Creates a new item enumeration object with the same contents and state as the current one 30 | [PreserveSig] 31 | int Clone( 32 | ref IEnumFORMATETC ppenum); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Shell/Interfaces/IEnumIDList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace ShellDll 5 | { 6 | [ComImportAttribute()] 7 | [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 8 | [Guid("000214F2-0000-0000-C000-000000000046")] 9 | public interface IEnumIDList 10 | { 11 | // Retrieves the specified number of item identifiers in the enumeration 12 | // sequence and advances the current position by the number of items retrieved 13 | [PreserveSig()] 14 | Int32 Next( 15 | int celt, 16 | out IntPtr rgelt, 17 | out int pceltFetched); 18 | 19 | // Skips over the specified number of elements in the enumeration sequence 20 | [PreserveSig()] 21 | Int32 Skip( 22 | int celt); 23 | 24 | // Returns to the beginning of the enumeration sequence 25 | [PreserveSig()] 26 | Int32 Reset(); 27 | 28 | // Creates a new item enumeration object with the same contents and state as the current one 29 | [PreserveSig()] 30 | Int32 Clone( 31 | out IEnumIDList ppenum); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Shell/Interfaces/IEnumSTATSTG.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport] 9 | [Guid("0000000d-0000-0000-C000-000000000046")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IEnumSTATSTG 12 | { 13 | // The user needs to allocate an STATSTG array whose size is celt. 14 | [PreserveSig] 15 | uint Next( 16 | uint celt, 17 | [MarshalAs(UnmanagedType.LPArray)] 18 | out ShellAPI.STATSTG[] rgelt, 19 | out uint pceltFetched); 20 | 21 | [PreserveSig] 22 | void Skip(uint celt); 23 | 24 | [PreserveSig] 25 | void Reset(); 26 | 27 | [PreserveSig] 28 | IEnumSTATSTG Clone(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Shell/Interfaces/IQueryInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport()] 9 | [Guid("00021500-0000-0000-C000-000000000046")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IQueryInfo 12 | { 13 | [PreserveSig] 14 | Int32 GetInfoTip( 15 | ShellAPI.QITIPF dwFlags, 16 | [MarshalAs(UnmanagedType.LPWStr)] 17 | out string ppwszTip); 18 | 19 | [PreserveSig] 20 | Int32 GetInfoFlags( 21 | out IntPtr pdwFlags); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Shell/Interfaces/IShellExtInit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport()] 9 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 10 | [GuidAttribute("000214e8-0000-0000-c000-000000000046")] 11 | public interface IShellExtInit 12 | { 13 | [PreserveSig()] 14 | int Initialize( 15 | IntPtr pidlFolder, 16 | IntPtr lpdobj, 17 | uint hKeyProgID); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Shell/Interfaces/IShellFolder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace ShellDll 5 | { 6 | [ComImport] 7 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 8 | [Guid("000214E6-0000-0000-C000-000000000046")] 9 | public interface IShellFolder 10 | { 11 | // Translates a file object's or folder's display name into an item identifier list. 12 | // Return value: error code, if any 13 | [PreserveSig] 14 | Int32 ParseDisplayName( 15 | IntPtr hwnd, 16 | IntPtr pbc, 17 | [MarshalAs(UnmanagedType.LPWStr)] 18 | string pszDisplayName, 19 | ref uint pchEaten, 20 | out IntPtr ppidl, 21 | ref ShellAPI.SFGAO pdwAttributes); 22 | 23 | // Allows a client to determine the contents of a folder by creating an item 24 | // identifier enumeration object and returning its IEnumIDList interface. 25 | // Return value: error code, if any 26 | [PreserveSig] 27 | Int32 EnumObjects( 28 | IntPtr hwnd, 29 | ShellAPI.SHCONTF grfFlags, 30 | out IntPtr enumIDList); 31 | 32 | // Retrieves an IShellFolder object for a subfolder. 33 | // Return value: error code, if any 34 | [PreserveSig] 35 | Int32 BindToObject( 36 | IntPtr pidl, 37 | IntPtr pbc, 38 | ref Guid riid, 39 | out IntPtr ppv); 40 | 41 | // Requests a pointer to an object's storage interface. 42 | // Return value: error code, if any 43 | [PreserveSig] 44 | Int32 BindToStorage( 45 | IntPtr pidl, 46 | IntPtr pbc, 47 | ref Guid riid, 48 | out IntPtr ppv); 49 | 50 | // Determines the relative order of two file objects or folders, given their 51 | // item identifier lists. Return value: If this method is successful, the 52 | // CODE field of the HRESULT contains one of the following values (the code 53 | // can be retrived using the helper function GetHResultCode): Negative A 54 | // negative return value indicates that the first item should precede 55 | // the second (pidl1 < pidl2). 56 | 57 | // Positive A positive return value indicates that the first item should 58 | // follow the second (pidl1 > pidl2). Zero A return value of zero 59 | // indicates that the two items are the same (pidl1 = pidl2). 60 | [PreserveSig] 61 | Int32 CompareIDs( 62 | IntPtr lParam, 63 | IntPtr pidl1, 64 | IntPtr pidl2); 65 | 66 | // Requests an object that can be used to obtain information from or interact 67 | // with a folder object. 68 | // Return value: error code, if any 69 | [PreserveSig] 70 | Int32 CreateViewObject( 71 | IntPtr hwndOwner, 72 | Guid riid, 73 | out IntPtr ppv); 74 | 75 | // Retrieves the attributes of one or more file objects or subfolders. 76 | // Return value: error code, if any 77 | [PreserveSig] 78 | Int32 GetAttributesOf( 79 | uint cidl, 80 | [MarshalAs(UnmanagedType.LPArray)] 81 | IntPtr[] apidl, 82 | ref ShellAPI.SFGAO rgfInOut); 83 | 84 | // Retrieves an OLE interface that can be used to carry out actions on the 85 | // specified file objects or folders. 86 | // Return value: error code, if any 87 | [PreserveSig] 88 | Int32 GetUIObjectOf( 89 | IntPtr hwndOwner, 90 | uint cidl, 91 | [MarshalAs(UnmanagedType.LPArray)] 92 | IntPtr[] apidl, 93 | ref Guid riid, 94 | IntPtr rgfReserved, 95 | out IntPtr ppv); 96 | 97 | // Retrieves the display name for the specified file object or subfolder. 98 | // Return value: error code, if any 99 | [PreserveSig()] 100 | Int32 GetDisplayNameOf( 101 | IntPtr pidl, 102 | ShellAPI.SHGNO uFlags, 103 | IntPtr lpName); 104 | 105 | // Sets the display name of a file object or subfolder, changing the item 106 | // identifier in the process. 107 | // Return value: error code, if any 108 | [PreserveSig] 109 | Int32 SetNameOf( 110 | IntPtr hwnd, 111 | IntPtr pidl, 112 | [MarshalAs(UnmanagedType.LPWStr)] 113 | string pszName, 114 | ShellAPI.SHGNO uFlags, 115 | out IntPtr ppidlOut); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Shell/Interfaces/IStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace ShellDll 7 | { 8 | [ComImport] 9 | [Guid("0000000b-0000-0000-C000-000000000046")] 10 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 11 | public interface IStorage 12 | { 13 | [PreserveSig] 14 | Int32 CreateStream( 15 | [MarshalAs(UnmanagedType.LPWStr)] 16 | string pwcsName, 17 | ShellAPI.STGM grfMode, 18 | int reserved1, 19 | int reserved2, 20 | out IntPtr ppstm); 21 | 22 | [PreserveSig] 23 | Int32 OpenStream( 24 | [MarshalAs(UnmanagedType.LPWStr)] 25 | string pwcsName, 26 | IntPtr reserved1, 27 | ShellAPI.STGM grfMode, 28 | int reserved2, 29 | out IntPtr ppstm); 30 | 31 | [PreserveSig] 32 | Int32 CreateStorage( 33 | [MarshalAs(UnmanagedType.LPWStr)] 34 | string pwcsName, 35 | ShellAPI.STGM grfMode, 36 | int reserved1, 37 | int reserved2, 38 | out IntPtr ppstg); 39 | 40 | [PreserveSig] 41 | Int32 OpenStorage( 42 | [MarshalAs(UnmanagedType.LPWStr)] 43 | string pwcsName, 44 | IStorage pstgPriority, 45 | ShellAPI.STGM grfMode, 46 | IntPtr snbExclude, 47 | int reserved, 48 | out IntPtr ppstg); 49 | 50 | [PreserveSig] 51 | Int32 CopyTo( 52 | int ciidExclude, 53 | ref Guid rgiidExclude, 54 | IntPtr snbExclude, 55 | IStorage pstgDest); 56 | 57 | [PreserveSig] 58 | Int32 MoveElementTo( 59 | [MarshalAs(UnmanagedType.LPWStr)] 60 | string pwcsName, 61 | IStorage pstgDest, 62 | [MarshalAs(UnmanagedType.LPWStr)] 63 | string pwcsNewName, 64 | ShellAPI.STGMOVE grfFlags); 65 | 66 | [PreserveSig] 67 | Int32 Commit( 68 | ShellAPI.STGC grfCommitFlags); 69 | 70 | [PreserveSig] 71 | Int32 Revert(); 72 | 73 | [PreserveSig] 74 | Int32 EnumElements( 75 | int reserved1, 76 | IntPtr reserved2, 77 | int reserved3, 78 | out IntPtr ppenum); 79 | 80 | [PreserveSig] 81 | Int32 DestroyElement( 82 | [MarshalAs(UnmanagedType.LPWStr)] 83 | string pwcsName); 84 | 85 | [PreserveSig] 86 | Int32 RenameElement( 87 | [MarshalAs(UnmanagedType.LPWStr)] 88 | string pwcsOldName, 89 | [MarshalAs(UnmanagedType.LPWStr)] 90 | string pwcsNewName); 91 | 92 | [PreserveSig] 93 | Int32 SetElementTimes( 94 | [MarshalAs(UnmanagedType.LPWStr)] 95 | string pwcsName, 96 | ShellAPI.FILETIME pctime, 97 | ShellAPI.FILETIME patime, 98 | ShellAPI.FILETIME pmtime); 99 | 100 | [PreserveSig] 101 | Int32 SetClass( 102 | ref Guid clsid); 103 | 104 | [PreserveSig] 105 | Int32 SetStateBits( 106 | int grfStateBits, 107 | int grfMask); 108 | 109 | [PreserveSig] 110 | Int32 Stat( 111 | out ShellAPI.STATSTG pstatstg, 112 | ShellAPI.STATFLAG grfStatFlag); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Shell/Interfaces/IStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.IO; 6 | 7 | namespace ShellDll 8 | { 9 | [ComImport] 10 | [Guid("0000000c-0000-0000-C000-000000000046")] 11 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 12 | public interface IStream 13 | { 14 | // Reads a specified number of bytes from the stream object into memory 15 | // starting at the current seek pointer 16 | [PreserveSig] 17 | Int32 Read( 18 | [MarshalAs(UnmanagedType.LPArray)] 19 | byte[] pv, 20 | int cb, 21 | IntPtr pcbRead); 22 | 23 | // Writes a specified number of bytes into the stream object starting at 24 | // the current seek pointer 25 | [PreserveSig] 26 | Int32 Write( 27 | [MarshalAs(UnmanagedType.LPArray)] 28 | byte[] pv, 29 | int cb, 30 | IntPtr pcbWritten); 31 | 32 | // Changes the seek pointer to a new location relative to the beginning 33 | // of the stream, the end of the stream, or the current seek pointer 34 | [PreserveSig] 35 | Int32 Seek( 36 | long dlibMove, 37 | SeekOrigin dwOrigin, 38 | IntPtr plibNewPosition); 39 | 40 | // Changes the size of the stream object 41 | [PreserveSig] 42 | Int32 SetSize( 43 | long libNewSize); 44 | 45 | // Copies a specified number of bytes from the current seek pointer in 46 | // the stream to the current seek pointer in another stream 47 | [PreserveSig] 48 | Int32 CopyTo( 49 | IStream pstm, 50 | long cb, 51 | IntPtr pcbRead, 52 | IntPtr pcbWritten); 53 | 54 | // Ensures that any changes made to a stream object open in transacted 55 | // mode are reflected in the parent storage object 56 | [PreserveSig] 57 | Int32 Commit( 58 | ShellAPI.STGC grfCommitFlags); 59 | 60 | // Discards all changes that have been made to a transacted stream since 61 | // the last call to IStream::Commit 62 | [PreserveSig] 63 | Int32 Revert(); 64 | 65 | // Restricts access to a specified range of bytes in the stream. Supporting 66 | // this functionality is optional since some file systems do not provide it 67 | [PreserveSig] 68 | Int32 LockRegion( 69 | long libOffset, 70 | long cb, 71 | ShellAPI.LOCKTYPE dwLockType); 72 | 73 | // Removes the access restriction on a range of bytes previously restricted 74 | // with IStream::LockRegion 75 | [PreserveSig] 76 | Int32 UnlockRegion( 77 | long libOffset, 78 | long cb, 79 | ShellAPI.LOCKTYPE dwLockType); 80 | 81 | // Retrieves the STATSTG structure for this stream 82 | [PreserveSig] 83 | Int32 Stat( 84 | out ShellAPI.STATSTG pstatstg, 85 | ShellAPI.STATFLAG grfStatFlag); 86 | 87 | // Creates a new stream object that references the same bytes as the original 88 | // stream but provides a separate seek pointer to those bytes 89 | [PreserveSig] 90 | Int32 Clone( 91 | out IntPtr ppstm); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Shell/PIDL.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Collections; 6 | 7 | namespace ShellDll 8 | { 9 | internal class PIDL : IEnumerable 10 | { 11 | private IntPtr pidl = IntPtr.Zero; 12 | 13 | #region Constructors 14 | 15 | public PIDL(IntPtr pidl, bool clone) 16 | { 17 | if (clone) 18 | this.pidl = ILClone(pidl); 19 | else 20 | this.pidl = pidl; 21 | } 22 | 23 | public PIDL(PIDL pidl, bool clone) 24 | { 25 | if (clone) 26 | this.pidl = ILClone(pidl.Ptr); 27 | else 28 | this.pidl = pidl.Ptr; 29 | } 30 | 31 | #endregion 32 | 33 | #region Public 34 | 35 | public IntPtr Ptr { get { return pidl; } } 36 | 37 | public void Append(IntPtr appendPidl) 38 | { 39 | IntPtr newPidl = ILCombine(pidl, appendPidl); 40 | 41 | Marshal.FreeCoTaskMem(pidl); 42 | pidl = newPidl; 43 | } 44 | 45 | public void Insert(IntPtr insertPidl) 46 | { 47 | IntPtr newPidl = ILCombine(insertPidl, pidl); 48 | 49 | Marshal.FreeCoTaskMem(pidl); 50 | pidl = newPidl; 51 | } 52 | 53 | public static bool IsEmpty(IntPtr pidl) 54 | { 55 | if (pidl == IntPtr.Zero) 56 | return true; 57 | 58 | byte[] bytes = new byte[2]; 59 | Marshal.Copy(pidl, bytes, 0, 2); 60 | int size = bytes[0] + bytes[1] * 256; 61 | return (size <= 2); 62 | } 63 | 64 | public static bool SplitPidl(IntPtr pidl, out IntPtr parent, out IntPtr child) 65 | { 66 | parent = ILClone(pidl); 67 | child = ILClone(ILFindLastID(pidl)); 68 | 69 | if (!ILRemoveLastID(parent)) 70 | { 71 | Marshal.FreeCoTaskMem(parent); 72 | Marshal.FreeCoTaskMem(child); 73 | return false; 74 | } 75 | else 76 | { 77 | return true; 78 | } 79 | } 80 | 81 | public static void Write(IntPtr pidl) 82 | { 83 | StringBuilder path = new StringBuilder(256); 84 | ShellAPI.SHGetPathFromIDList(pidl, path); 85 | Console.Out.WriteLine("Pidl: {0}", path); 86 | } 87 | 88 | public static void WriteBytes(IntPtr pidl) 89 | { 90 | int size = Marshal.ReadByte(pidl, 0) + Marshal.ReadByte(pidl, 1) * 256 - 2; 91 | 92 | for (int i = 0; i < size; i++) 93 | { 94 | Console.Out.WriteLine(Marshal.ReadByte(pidl, i + 2)); 95 | } 96 | 97 | Console.Out.WriteLine(Marshal.ReadByte(pidl, size + 2)); 98 | Console.Out.WriteLine(Marshal.ReadByte(pidl, size + 3)); 99 | } 100 | 101 | public void Free() 102 | { 103 | if (pidl != IntPtr.Zero) 104 | { 105 | Marshal.FreeCoTaskMem(pidl); 106 | pidl = IntPtr.Zero; 107 | } 108 | } 109 | 110 | #endregion 111 | 112 | #region Shell 113 | 114 | private static int ItemIDSize(IntPtr pidl) 115 | { 116 | if (!pidl.Equals(IntPtr.Zero)) 117 | { 118 | byte[] buffer = new byte[2]; 119 | Marshal.Copy(pidl, buffer, 0, 2); 120 | return buffer[1] * 256 + buffer[0]; 121 | } 122 | else 123 | return 0; 124 | } 125 | 126 | private static int ItemIDListSize(IntPtr pidl) 127 | { 128 | if (pidl.Equals(IntPtr.Zero)) 129 | return 0; 130 | else 131 | { 132 | int size = ItemIDSize(pidl); 133 | int nextSize = Marshal.ReadByte(pidl, size) + (Marshal.ReadByte(pidl, size + 1) * 256); 134 | while (nextSize > 0) 135 | { 136 | size += nextSize; 137 | nextSize = Marshal.ReadByte(pidl, size) + (Marshal.ReadByte(pidl, size + 1) * 256); 138 | } 139 | 140 | return size; 141 | } 142 | } 143 | 144 | // Clones an ITEMIDLIST structure 145 | public static IntPtr ILClone(IntPtr pidl) 146 | { 147 | int size = ItemIDListSize(pidl); 148 | 149 | byte[] bytes = new byte[size + 2]; 150 | Marshal.Copy(pidl, bytes, 0, size); 151 | 152 | IntPtr newPidl = Marshal.AllocCoTaskMem(size + 2); 153 | Marshal.Copy(bytes, 0, newPidl, size + 2); 154 | 155 | return newPidl; 156 | } 157 | 158 | // Clones the first SHITEMID structure in an ITEMIDLIST structure 159 | public static IntPtr ILCloneFirst(IntPtr pidl) 160 | { 161 | int size = ItemIDSize(pidl); 162 | 163 | byte[] bytes = new byte[size + 2]; 164 | Marshal.Copy(pidl, bytes, 0, size); 165 | 166 | IntPtr newPidl = Marshal.AllocCoTaskMem(size + 2); 167 | Marshal.Copy(bytes, 0, newPidl, size + 2); 168 | 169 | return newPidl; 170 | } 171 | 172 | // Gets the next SHITEMID structure in an ITEMIDLIST structure 173 | public static IntPtr ILGetNext(IntPtr pidl) 174 | { 175 | int size = ItemIDSize(pidl); 176 | IntPtr nextPidl = new IntPtr((int)pidl + size); 177 | return nextPidl; 178 | } 179 | 180 | // Returns a pointer to the last SHITEMID structure in an ITEMIDLIST structure 181 | public static IntPtr ILFindLastID(IntPtr pidl) 182 | { 183 | IntPtr ptr1 = pidl; 184 | IntPtr ptr2 = ILGetNext(ptr1); 185 | 186 | while (ItemIDSize(ptr2) > 0) 187 | { 188 | ptr1 = ptr2; 189 | ptr2 = ILGetNext(ptr1); 190 | } 191 | 192 | return ptr1; 193 | } 194 | 195 | // Removes the last SHITEMID structure from an ITEMIDLIST structure 196 | public static bool ILRemoveLastID(IntPtr pidl) 197 | { 198 | IntPtr lastPidl = ILFindLastID(pidl); 199 | 200 | if (lastPidl != pidl) 201 | { 202 | int newSize = (int)lastPidl - (int)pidl + 2; 203 | Marshal.ReAllocCoTaskMem(pidl, newSize); 204 | Marshal.Copy(new byte[] { 0, 0 }, 0, new IntPtr((int)pidl + newSize - 2), 2); 205 | 206 | return true; 207 | } 208 | else 209 | return false; 210 | } 211 | 212 | // Combines two ITEMIDLIST structures 213 | public static IntPtr ILCombine(IntPtr pidl1, IntPtr pidl2) 214 | { 215 | int size1 = ItemIDListSize(pidl1); 216 | int size2 = ItemIDListSize(pidl2); 217 | 218 | IntPtr newPidl = Marshal.AllocCoTaskMem(size1 + size2 + 2); 219 | byte[] bytes = new byte[size1 + size2 + 2]; 220 | 221 | Marshal.Copy(pidl1, bytes, 0, size1); 222 | Marshal.Copy(pidl2, bytes, size1, size2); 223 | 224 | Marshal.Copy(bytes, 0, newPidl, bytes.Length); 225 | 226 | return newPidl; 227 | } 228 | 229 | #endregion 230 | 231 | #region IEnumerable Members 232 | 233 | public IEnumerator GetEnumerator() 234 | { 235 | return new PIDLEnumerator(pidl); 236 | } 237 | 238 | #endregion 239 | 240 | #region Override 241 | 242 | public override bool Equals(object obj) 243 | { 244 | try 245 | { 246 | if (obj is IntPtr) 247 | return ShellAPI.ILIsEqual(this.Ptr, (IntPtr)obj); 248 | if (obj is PIDL) 249 | return ShellAPI.ILIsEqual(this.Ptr, ((PIDL)obj).Ptr); 250 | else 251 | return false; 252 | } 253 | catch (Exception) 254 | { 255 | return false; 256 | } 257 | } 258 | 259 | public override int GetHashCode() 260 | { 261 | return pidl.GetHashCode(); 262 | } 263 | 264 | #endregion 265 | 266 | public class PIDLEnumerator : IEnumerator 267 | { 268 | private IntPtr pidl; 269 | private IntPtr currentPidl; 270 | private IntPtr clonePidl; 271 | private bool start; 272 | 273 | public PIDLEnumerator(IntPtr pidl) 274 | { 275 | start = true; 276 | this.pidl = pidl; 277 | currentPidl = pidl; 278 | clonePidl = IntPtr.Zero; 279 | } 280 | 281 | #region IEnumerator Members 282 | 283 | public object Current 284 | { 285 | get 286 | { 287 | if (clonePidl != IntPtr.Zero) 288 | { 289 | Marshal.FreeCoTaskMem(clonePidl); 290 | clonePidl = IntPtr.Zero; 291 | } 292 | 293 | clonePidl = PIDL.ILCloneFirst(currentPidl); 294 | return clonePidl; 295 | } 296 | } 297 | 298 | public bool MoveNext() 299 | { 300 | if (clonePidl != IntPtr.Zero) 301 | { 302 | Marshal.FreeCoTaskMem(clonePidl); 303 | clonePidl = IntPtr.Zero; 304 | } 305 | 306 | if (start) 307 | { 308 | start = false; 309 | return true; 310 | } 311 | else 312 | { 313 | IntPtr newPidl = ILGetNext(currentPidl); 314 | 315 | if (!PIDL.IsEmpty(newPidl)) 316 | { 317 | currentPidl = newPidl; 318 | return true; 319 | } 320 | else 321 | return false; 322 | } 323 | } 324 | 325 | public void Reset() 326 | { 327 | start = true; 328 | currentPidl = pidl; 329 | 330 | if (clonePidl != IntPtr.Zero) 331 | { 332 | Marshal.FreeCoTaskMem(clonePidl); 333 | clonePidl = IntPtr.Zero; 334 | } 335 | } 336 | 337 | #endregion 338 | } 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /Shell/ShellBrowser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Collections; 6 | using System.Threading; 7 | using System.ComponentModel; 8 | using EasyExplorer; 9 | 10 | namespace ShellDll { 11 | public class ShellBrowser : Component { 12 | public Explorer Browser; 13 | 14 | private ShellItem desktopItem; 15 | private string mydocsName, mycompName, sysfolderName, mydocsPath; 16 | 17 | private ShellBrowserUpdater updater; 18 | 19 | private ArrayList browsers; 20 | private ShellItemUpdateCondition updateCondition; 21 | 22 | internal event ShellItemUpdateEventHandler ShellItemUpdate; 23 | 24 | 25 | 26 | public ShellBrowser(Explorer browse) { 27 | Browser = browse; 28 | InitVars(); 29 | browsers = new ArrayList(); 30 | updateCondition = new ShellItemUpdateCondition(); 31 | updater = new ShellBrowserUpdater(this); 32 | } 33 | 34 | private void InitVars() { 35 | IntPtr tempPidl; 36 | ShellAPI.SHFILEINFO info; 37 | 38 | //My Computer 39 | info = new ShellAPI.SHFILEINFO(); 40 | tempPidl = IntPtr.Zero; 41 | ShellAPI.SHGetSpecialFolderLocation(IntPtr.Zero, ShellAPI.CSIDL.DRIVES, out tempPidl); 42 | 43 | ShellAPI.SHGetFileInfo(tempPidl, 0, ref info, ShellAPI.cbFileInfo, 44 | ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.DISPLAYNAME | ShellAPI.SHGFI.TYPENAME); 45 | 46 | sysfolderName = info.szTypeName; 47 | mycompName = info.szDisplayName; 48 | Marshal.FreeCoTaskMem(tempPidl); 49 | // 50 | 51 | //Dekstop 52 | tempPidl = IntPtr.Zero; 53 | ShellAPI.SHGetSpecialFolderLocation(IntPtr.Zero, ShellAPI.CSIDL.DESKTOP, out tempPidl); 54 | IntPtr desktopFolderPtr; 55 | ShellAPI.SHGetDesktopFolder(out desktopFolderPtr); 56 | desktopItem = new ShellItem(this, tempPidl, desktopFolderPtr); 57 | // 58 | 59 | //My Documents 60 | uint pchEaten = 0; 61 | ShellAPI.SFGAO pdwAttributes = 0; 62 | desktopItem.ShellFolder.ParseDisplayName( 63 | IntPtr.Zero, 64 | IntPtr.Zero, 65 | "::{450d8fba-ad25-11d0-98a8-0800361b1103}", 66 | ref pchEaten, 67 | out tempPidl, 68 | ref pdwAttributes); 69 | 70 | info = new ShellAPI.SHFILEINFO(); 71 | ShellAPI.SHGetFileInfo(tempPidl, 0, ref info, ShellAPI.cbFileInfo, 72 | ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.DISPLAYNAME); 73 | 74 | mydocsName = info.szDisplayName; 75 | Marshal.FreeCoTaskMem(tempPidl); 76 | 77 | StringBuilder path = new StringBuilder(ShellAPI.MAX_PATH); 78 | ShellAPI.SHGetFolderPath( 79 | IntPtr.Zero, ShellAPI.CSIDL.PERSONAL, 80 | IntPtr.Zero, ShellAPI.SHGFP.TYPE_CURRENT, path); 81 | mydocsPath = path.ToString(); 82 | // 83 | } 84 | 85 | #region ShellBrowser Update 86 | 87 | internal void OnShellItemUpdate(object sender, ShellItemUpdateEventArgs e) { 88 | if (ShellItemUpdate != null) { 89 | ShellItemUpdate(sender, e); 90 | } 91 | } 92 | 93 | #endregion 94 | 95 | #region Utility Methods 96 | 97 | internal ShellItem GetShellItem(PIDL pidlFull) { 98 | ShellItem current = DesktopItem; 99 | if (pidlFull.Ptr == IntPtr.Zero) 100 | return current; 101 | 102 | foreach (IntPtr pidlRel in pidlFull) { 103 | int index; 104 | if ((index = current.IndexOf(pidlRel)) > -1) { 105 | current = current[index]; 106 | } else { 107 | current = null; 108 | break; 109 | } 110 | } 111 | 112 | return current; 113 | } 114 | 115 | internal ShellItem[] GetPath(ShellItem item) { 116 | ArrayList pathList = new ArrayList(); 117 | 118 | ShellItem currentItem = item; 119 | while (currentItem.ParentItem != null) { 120 | pathList.Add(currentItem); 121 | currentItem = currentItem.ParentItem; 122 | } 123 | pathList.Add(currentItem); 124 | pathList.Reverse(); 125 | 126 | return (ShellItem[])pathList.ToArray(typeof(ShellItem)); 127 | } 128 | 129 | #endregion 130 | 131 | #region Properties 132 | 133 | internal ShellItem DesktopItem { get { return desktopItem; } } 134 | 135 | internal string MyDocumentsName { get { return mydocsName; } } 136 | internal string MyComputerName { get { return mycompName; } } 137 | internal string SystemFolderName { get { return sysfolderName; } } 138 | 139 | internal string MyDocumentsPath { get { return mydocsPath; } } 140 | 141 | internal ShellItemUpdateCondition UpdateCondition { get { return updateCondition; } } 142 | 143 | internal ArrayList Browsers { get { return browsers; } } 144 | 145 | #endregion 146 | } 147 | 148 | #region ShellItemUpdate 149 | 150 | internal delegate void ShellItemUpdateEventHandler(object sender, ShellItemUpdateEventArgs e); 151 | 152 | internal enum ShellItemUpdateType { 153 | Created, 154 | IconChange, 155 | Updated, 156 | Renamed, 157 | Deleted, 158 | MediaChange 159 | } 160 | 161 | internal class ShellItemUpdateEventArgs : EventArgs { 162 | ShellItem oldItem, newItem; 163 | ShellItemUpdateType type; 164 | 165 | public ShellItemUpdateEventArgs( 166 | ShellItem oldItem, 167 | ShellItem newItem, 168 | ShellItemUpdateType type) { 169 | this.oldItem = oldItem; 170 | this.newItem = newItem; 171 | this.type = type; 172 | } 173 | 174 | public ShellItem OldItem { get { return oldItem; } } 175 | public ShellItem NewItem { get { return newItem; } } 176 | public ShellItemUpdateType UpdateType { get { return type; } } 177 | } 178 | 179 | #endregion 180 | } -------------------------------------------------------------------------------- /Shell/ShellBrowserUpdater.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ShellDll 8 | { 9 | internal class ShellBrowserUpdater : NativeWindow 10 | { 11 | #region Fields 12 | 13 | private ShellBrowser br; 14 | private uint notifyId = 0; 15 | 16 | #endregion 17 | 18 | public ShellBrowserUpdater(ShellBrowser br) 19 | { 20 | this.br = br; 21 | CreateHandle(new CreateParams()); 22 | 23 | ShellAPI.SHChangeNotifyEntry entry = new ShellAPI.SHChangeNotifyEntry(); 24 | entry.pIdl = br.DesktopItem.PIDLRel.Ptr; 25 | entry.Recursively = true; 26 | 27 | notifyId = ShellAPI.SHChangeNotifyRegister( 28 | this.Handle, 29 | ShellAPI.SHCNRF.InterruptLevel | ShellAPI.SHCNRF.ShellLevel, 30 | ShellAPI.SHCNE.ALLEVENTS | ShellAPI.SHCNE.INTERRUPT, 31 | ShellAPI.WM.SH_NOTIFY, 32 | 1, 33 | new ShellAPI.SHChangeNotifyEntry[] { entry }); 34 | } 35 | 36 | ~ShellBrowserUpdater() 37 | { 38 | if (notifyId > 0) 39 | { 40 | ShellAPI.SHChangeNotifyDeregister(notifyId); 41 | GC.SuppressFinalize(this); 42 | } 43 | } 44 | 45 | protected override void WndProc(ref Message m) 46 | { 47 | if (m.Msg == (int)ShellAPI.WM.SH_NOTIFY) 48 | { 49 | ShellAPI.SHNOTIFYSTRUCT shNotify = 50 | (ShellAPI.SHNOTIFYSTRUCT)Marshal.PtrToStructure(m.WParam, typeof(ShellAPI.SHNOTIFYSTRUCT)); 51 | 52 | //Console.Out.WriteLine("Event: {0}", (ShellAPI.SHCNE)m.LParam); 53 | //if (shNotify.dwItem1 != IntPtr.Zero) 54 | //PIDL.Write(shNotify.dwItem1); 55 | //if (shNotify.dwItem2 != IntPtr.Zero) 56 | //PIDL.Write(shNotify.dwItem2); 57 | 58 | switch ((ShellAPI.SHCNE)m.LParam) 59 | { 60 | #region File Changes 61 | 62 | case ShellAPI.SHCNE.CREATE: 63 | #region Create Item 64 | { 65 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 66 | { 67 | IntPtr parent, child, relative; 68 | PIDL.SplitPidl(shNotify.dwItem1, out parent, out child); 69 | 70 | PIDL parentPIDL = new PIDL(parent, false); 71 | ShellItem parentItem = br.GetShellItem(parentPIDL); 72 | if (parentItem != null && parentItem.FilesExpanded && !parentItem.SubFiles.Contains(child)) 73 | { 74 | ShellAPI.SHGetRealIDL( 75 | parentItem.ShellFolder, 76 | child, 77 | out relative); 78 | parentItem.AddItem(new ShellItem(br, parentItem, relative)); 79 | } 80 | 81 | Marshal.FreeCoTaskMem(child); 82 | parentPIDL.Free(); 83 | } 84 | } 85 | #endregion 86 | break; 87 | 88 | case ShellAPI.SHCNE.RENAMEITEM: 89 | #region Rename Item 90 | { 91 | if (!PIDL.IsEmpty(shNotify.dwItem1) && !PIDL.IsEmpty(shNotify.dwItem2)) 92 | { 93 | ShellItem item = br.GetShellItem(new PIDL(shNotify.dwItem1, true)); 94 | if (item != null) 95 | item.Update(shNotify.dwItem2, ShellItemUpdateType.Renamed); 96 | } 97 | } 98 | #endregion 99 | break; 100 | 101 | case ShellAPI.SHCNE.DELETE: 102 | #region Delete Item 103 | { 104 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 105 | { 106 | IntPtr parent, child; 107 | PIDL.SplitPidl(shNotify.dwItem1, out parent, out child); 108 | 109 | PIDL parentPIDL = new PIDL(parent, false); 110 | ShellItem parentItem = br.GetShellItem(parentPIDL); 111 | if (parentItem != null && parentItem.SubFiles.Contains(child)) 112 | parentItem.RemoveItem(parentItem.SubFiles[child]); 113 | 114 | Marshal.FreeCoTaskMem(child); 115 | parentPIDL.Free(); 116 | } 117 | } 118 | #endregion 119 | break; 120 | 121 | case ShellAPI.SHCNE.UPDATEITEM: 122 | #region Update Item 123 | { 124 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 125 | { 126 | ShellItem item = br.GetShellItem(new PIDL(shNotify.dwItem1, true)); 127 | if (item != null) 128 | { 129 | Console.Out.WriteLine("Item: {0}", item); 130 | item.Update(IntPtr.Zero, ShellItemUpdateType.Updated); 131 | item.Update(IntPtr.Zero, ShellItemUpdateType.IconChange); 132 | } 133 | } 134 | } 135 | #endregion 136 | break; 137 | 138 | #endregion 139 | 140 | #region Folder Changes 141 | 142 | case ShellAPI.SHCNE.MKDIR: 143 | case ShellAPI.SHCNE.DRIVEADD: 144 | case ShellAPI.SHCNE.DRIVEADDGUI: 145 | #region Make Directory 146 | { 147 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 148 | { 149 | IntPtr parent, child, relative; 150 | PIDL.SplitPidl(shNotify.dwItem1, out parent, out child); 151 | 152 | PIDL parentPIDL = new PIDL(parent, false); 153 | ShellItem parentItem = br.GetShellItem(parentPIDL); 154 | if (parentItem != null && parentItem.FoldersExpanded && !parentItem.SubFolders.Contains(child)) 155 | { 156 | ShellAPI.SHGetRealIDL( 157 | parentItem.ShellFolder, 158 | child, 159 | out relative); 160 | 161 | IntPtr shellFolderPtr; 162 | if (parentItem.ShellFolder.BindToObject( 163 | relative, 164 | IntPtr.Zero, 165 | ref ShellAPI.IID_IShellFolder, 166 | out shellFolderPtr) == ShellAPI.S_OK) 167 | { 168 | parentItem.AddItem(new ShellItem(br, parentItem, relative, shellFolderPtr)); 169 | } 170 | else 171 | Marshal.FreeCoTaskMem(relative); 172 | } 173 | 174 | Marshal.FreeCoTaskMem(child); 175 | parentPIDL.Free(); 176 | } 177 | } 178 | #endregion 179 | break; 180 | 181 | case ShellAPI.SHCNE.RENAMEFOLDER: 182 | #region Rename Directory 183 | { 184 | if (!PIDL.IsEmpty(shNotify.dwItem1) && !PIDL.IsEmpty(shNotify.dwItem2)) 185 | { 186 | ShellItem item = br.GetShellItem(new PIDL(shNotify.dwItem1, false)); 187 | if (item != null) 188 | { 189 | //Console.Out.WriteLine("Update: {0}", item); 190 | item.Update(shNotify.dwItem2, ShellItemUpdateType.Renamed); 191 | } 192 | } 193 | } 194 | #endregion 195 | break; 196 | 197 | case ShellAPI.SHCNE.RMDIR: 198 | case ShellAPI.SHCNE.DRIVEREMOVED: 199 | #region Remove Directory 200 | { 201 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 202 | { 203 | IntPtr parent, child; 204 | PIDL.SplitPidl(shNotify.dwItem1, out parent, out child); 205 | 206 | PIDL parentPIDL = new PIDL(parent, false); 207 | ShellItem parentItem = br.GetShellItem(parentPIDL); 208 | if (parentItem != null && parentItem.SubFolders.Contains(child)) 209 | parentItem.RemoveItem(parentItem.SubFolders[child]); 210 | 211 | Marshal.FreeCoTaskMem(child); 212 | parentPIDL.Free(); 213 | } 214 | } 215 | #endregion 216 | break; 217 | 218 | case ShellAPI.SHCNE.UPDATEDIR: 219 | case ShellAPI.SHCNE.ATTRIBUTES: 220 | #region Update Directory 221 | { 222 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 223 | { 224 | ShellItem item = br.GetShellItem(new PIDL(shNotify.dwItem1, true)); 225 | if (item != null) 226 | { 227 | item.Update(IntPtr.Zero, ShellItemUpdateType.Updated); 228 | item.Update(IntPtr.Zero, ShellItemUpdateType.IconChange); 229 | } 230 | } 231 | } 232 | #endregion 233 | break; 234 | 235 | case ShellAPI.SHCNE.MEDIAINSERTED: 236 | case ShellAPI.SHCNE.MEDIAREMOVED: 237 | #region Media Change 238 | { 239 | if (!PIDL.IsEmpty(shNotify.dwItem1)) 240 | { 241 | ShellItem item = br.GetShellItem(new PIDL(shNotify.dwItem1, true)); 242 | if (item != null) 243 | item.Update(IntPtr.Zero, ShellItemUpdateType.MediaChange); 244 | } 245 | } 246 | #endregion 247 | break; 248 | 249 | #endregion 250 | 251 | #region Other Changes 252 | 253 | case ShellAPI.SHCNE.ASSOCCHANGED: 254 | #region Update Images 255 | { 256 | 257 | } 258 | #endregion 259 | break; 260 | 261 | case ShellAPI.SHCNE.NETSHARE: 262 | case ShellAPI.SHCNE.NETUNSHARE: 263 | break; 264 | 265 | case ShellAPI.SHCNE.UPDATEIMAGE: 266 | UpdateRecycleBin(); 267 | break; 268 | 269 | #endregion 270 | } 271 | } 272 | 273 | base.WndProc(ref m); 274 | } 275 | 276 | private void UpdateRecycleBin() 277 | { 278 | ShellItem recycleBin = br.DesktopItem["Recycle Bin"]; 279 | if (recycleBin != null) 280 | recycleBin.Update(IntPtr.Zero, ShellItemUpdateType.IconChange); 281 | } 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /Shell/ShellHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace ShellDll 8 | { 9 | internal static class ShellHelper 10 | { 11 | #region Low/High Word 12 | 13 | /// 14 | /// Retrieves the High Word of a WParam of a WindowMessage 15 | /// 16 | /// The pointer to the WParam 17 | /// The unsigned integer for the High Word 18 | public static uint HiWord(IntPtr ptr) 19 | { 20 | if (((uint)ptr & 0x80000000) == 0x80000000) 21 | return ((uint)ptr >> 16); 22 | else 23 | return ((uint)ptr >> 16) & 0xffff; 24 | } 25 | 26 | /// 27 | /// Retrieves the Low Word of a WParam of a WindowMessage 28 | /// 29 | /// The pointer to the WParam 30 | /// The unsigned integer for the Low Word 31 | public static uint LoWord(IntPtr ptr) 32 | { 33 | return (uint)ptr & 0xffff; 34 | } 35 | 36 | #endregion 37 | 38 | #region IStream/IStorage 39 | 40 | public static bool GetIStream(ShellItem item, out IntPtr streamPtr, out IStream stream) 41 | { 42 | if (item.ParentItem.ShellFolder.BindToStorage( 43 | item.PIDLRel.Ptr, 44 | IntPtr.Zero, 45 | ref ShellAPI.IID_IStream, 46 | out streamPtr) == ShellAPI.S_OK) 47 | { 48 | stream = (IStream)Marshal.GetTypedObjectForIUnknown(streamPtr, typeof(IStream)); 49 | return true; 50 | } 51 | else 52 | { 53 | stream = null; 54 | streamPtr = IntPtr.Zero; 55 | return false; 56 | } 57 | } 58 | 59 | public static bool GetIStorage(ShellItem item, out IntPtr storagePtr, out IStorage storage) 60 | { 61 | if (item.ParentItem.ShellFolder.BindToStorage( 62 | item.PIDLRel.Ptr, 63 | IntPtr.Zero, 64 | ref ShellAPI.IID_IStorage, 65 | out storagePtr) == ShellAPI.S_OK) 66 | { 67 | storage = (IStorage)Marshal.GetTypedObjectForIUnknown(storagePtr, typeof(IStorage)); 68 | return true; 69 | } 70 | else 71 | { 72 | storage = null; 73 | storagePtr = IntPtr.Zero; 74 | return false; 75 | } 76 | } 77 | 78 | #endregion 79 | 80 | #region Drag/Drop 81 | 82 | /// 83 | /// This method will use the GetUIObjectOf method of IShellFolder to obtain the IDataObject of a 84 | /// ShellItem. 85 | /// 86 | /// The item for which to obtain the IDataObject 87 | /// A pointer to the returned IDataObject 88 | /// the IDataObject the ShellItem 89 | public static IntPtr GetIDataObject(ShellItem[] items) 90 | { 91 | ShellItem parent = items[0].ParentItem != null ? items[0].ParentItem : items[0]; 92 | 93 | IntPtr[] pidls = new IntPtr[items.Length]; 94 | for (int i = 0; i < items.Length; i++) 95 | pidls[i] = items[i].PIDLRel.Ptr; 96 | 97 | IntPtr dataObjectPtr; 98 | if (parent.ShellFolder.GetUIObjectOf( 99 | IntPtr.Zero, 100 | (uint)pidls.Length, 101 | pidls, 102 | ref ShellAPI.IID_IDataObject, 103 | IntPtr.Zero, 104 | out dataObjectPtr) == ShellAPI.S_OK) 105 | { 106 | return dataObjectPtr; 107 | } 108 | else 109 | { 110 | return IntPtr.Zero; 111 | } 112 | } 113 | 114 | /// 115 | /// This method will use the GetUIObjectOf method of IShellFolder to obtain the IDropTarget of a 116 | /// ShellItem. 117 | /// 118 | /// The item for which to obtain the IDropTarget 119 | /// A pointer to the returned IDropTarget 120 | /// the IDropTarget from the ShellItem 121 | public static bool GetIDropTarget(ShellItem item, out IntPtr dropTargetPtr, out ShellDll.IDropTarget dropTarget) 122 | { 123 | ShellItem parent = item.ParentItem != null ? item.ParentItem : item; 124 | 125 | if (parent.ShellFolder.GetUIObjectOf( 126 | IntPtr.Zero, 127 | 1, 128 | new IntPtr[] { item.PIDLRel.Ptr }, 129 | ref ShellAPI.IID_IDropTarget, 130 | IntPtr.Zero, 131 | out dropTargetPtr) == ShellAPI.S_OK) 132 | { 133 | dropTarget = 134 | (ShellDll.IDropTarget)Marshal.GetTypedObjectForIUnknown(dropTargetPtr, typeof(ShellDll.IDropTarget)); 135 | 136 | return true; 137 | } 138 | else 139 | { 140 | dropTarget = null; 141 | dropTargetPtr = IntPtr.Zero; 142 | return false; 143 | } 144 | } 145 | 146 | public static bool GetIDropTargetHelper(out IntPtr helperPtr, out IDropTargetHelper dropHelper) 147 | { 148 | if (ShellAPI.CoCreateInstance( 149 | ref ShellAPI.CLSID_DragDropHelper, 150 | IntPtr.Zero, 151 | ShellAPI.CLSCTX.INPROC_SERVER, 152 | ref ShellAPI.IID_IDropTargetHelper, 153 | out helperPtr) == ShellAPI.S_OK) 154 | { 155 | dropHelper = 156 | (IDropTargetHelper)Marshal.GetTypedObjectForIUnknown(helperPtr, typeof(IDropTargetHelper)); 157 | 158 | return true; 159 | } 160 | else 161 | { 162 | dropHelper = null; 163 | helperPtr = IntPtr.Zero; 164 | return false; 165 | } 166 | } 167 | 168 | public static DragDropEffects CanDropClipboard(ShellItem item) 169 | { 170 | IntPtr dataObject; 171 | ShellAPI.OleGetClipboard(out dataObject); 172 | 173 | IntPtr targetPtr; 174 | ShellDll.IDropTarget target; 175 | 176 | DragDropEffects retVal = DragDropEffects.None; 177 | if (GetIDropTarget(item, out targetPtr, out target)) 178 | { 179 | #region Check Copy 180 | DragDropEffects effects = DragDropEffects.Copy; 181 | if (target.DragEnter( 182 | dataObject, 183 | ShellAPI.MK.CONTROL, 184 | new ShellAPI.POINT(0, 0), 185 | ref effects) == ShellAPI.S_OK) 186 | { 187 | if (effects == DragDropEffects.Copy) 188 | retVal |= DragDropEffects.Copy; 189 | 190 | target.DragLeave(); 191 | } 192 | #endregion 193 | 194 | #region Check Move 195 | effects = DragDropEffects.Move; 196 | if (target.DragEnter( 197 | dataObject, 198 | ShellAPI.MK.SHIFT, 199 | new ShellAPI.POINT(0, 0), 200 | ref effects) == ShellAPI.S_OK) 201 | { 202 | if (effects == DragDropEffects.Move) 203 | retVal |= DragDropEffects.Move; 204 | 205 | target.DragLeave(); 206 | } 207 | #endregion 208 | 209 | #region Check Lick 210 | effects = DragDropEffects.Link; 211 | if (target.DragEnter( 212 | dataObject, 213 | ShellAPI.MK.ALT, 214 | new ShellAPI.POINT(0, 0), 215 | ref effects) == ShellAPI.S_OK) 216 | { 217 | if (effects == DragDropEffects.Link) 218 | retVal |= DragDropEffects.Link; 219 | 220 | target.DragLeave(); 221 | } 222 | #endregion 223 | 224 | Marshal.ReleaseComObject(target); 225 | Marshal.Release(targetPtr); 226 | } 227 | 228 | return retVal; 229 | } 230 | 231 | #endregion 232 | 233 | #region QueryInfo 234 | 235 | public static bool GetIQueryInfo(ShellItem item, out IntPtr iQueryInfoPtr, out IQueryInfo iQueryInfo) 236 | { 237 | ShellItem parent = item.ParentItem != null ? item.ParentItem : item; 238 | 239 | if (parent.ShellFolder.GetUIObjectOf( 240 | IntPtr.Zero, 241 | 1, 242 | new IntPtr[] { item.PIDLRel.Ptr }, 243 | ref ShellAPI.IID_IQueryInfo, 244 | IntPtr.Zero, 245 | out iQueryInfoPtr) == ShellAPI.S_OK) 246 | { 247 | iQueryInfo = 248 | (IQueryInfo)Marshal.GetTypedObjectForIUnknown(iQueryInfoPtr, typeof(IQueryInfo)); 249 | 250 | return true; 251 | } 252 | else 253 | { 254 | iQueryInfo = null; 255 | iQueryInfoPtr = IntPtr.Zero; 256 | return false; 257 | } 258 | } 259 | 260 | #endregion 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /Shell/ShellImageList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.Windows.Forms; 4 | using System.Collections; 5 | using System.Threading; 6 | using System.Drawing; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace ShellDll 10 | { 11 | public static class ShellImageList 12 | { 13 | private static IntPtr smallImageListHandle, largeImageListHandle; 14 | private static Hashtable imageTable; 15 | 16 | private const int TVSIL_NORMAL = 0; 17 | private const int TVSIL_SMALL = 1; 18 | 19 | static ShellImageList() 20 | { 21 | imageTable = new Hashtable(); 22 | 23 | ShellAPI.SHGFI flag = ShellAPI.SHGFI.USEFILEATTRIBUTES | ShellAPI.SHGFI.SYSICONINDEX | ShellAPI.SHGFI.SMALLICON; 24 | ShellAPI.SHFILEINFO shfiSmall = new ShellAPI.SHFILEINFO(); 25 | smallImageListHandle = ShellAPI.SHGetFileInfo(".txt", ShellAPI.FILE_ATTRIBUTE.NORMAL, ref shfiSmall, ShellAPI.cbFileInfo, flag); 26 | 27 | flag = ShellAPI.SHGFI.USEFILEATTRIBUTES | ShellAPI.SHGFI.SYSICONINDEX | ShellAPI.SHGFI.LARGEICON; 28 | ShellAPI.SHFILEINFO shfiLarge = new ShellAPI.SHFILEINFO(); 29 | largeImageListHandle = ShellAPI.SHGetFileInfo(".txt", ShellAPI.FILE_ATTRIBUTE.NORMAL, ref shfiLarge, ShellAPI.cbFileInfo, flag); 30 | } 31 | 32 | internal static void SetIconIndex(ShellItem item, int index, bool SelectedIcon) 33 | { 34 | bool HasOverlay = false; //true if it's an overlay 35 | int rVal = 0; //The returned Index 36 | 37 | ShellAPI.SHGFI dwflag = ShellAPI.SHGFI.SYSICONINDEX | ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.ICON; 38 | ShellAPI.FILE_ATTRIBUTE dwAttr = 0; 39 | //build Key into HashTable for this Item 40 | int Key = index * 256; 41 | if (item.IsLink) 42 | { 43 | Key = Key | 1; 44 | dwflag = dwflag | ShellAPI.SHGFI.LINKOVERLAY; 45 | HasOverlay = true; 46 | } 47 | if (item.IsShared) 48 | { 49 | Key = Key | 2; 50 | dwflag = dwflag | ShellAPI.SHGFI.ADDOVERLAYS; 51 | HasOverlay = true; 52 | } 53 | if (SelectedIcon) 54 | { 55 | Key = Key | 4; 56 | dwflag = dwflag | ShellAPI.SHGFI.OPENICON; 57 | HasOverlay = true; //not really an overlay, but handled the same 58 | } 59 | 60 | if (imageTable.ContainsKey(Key)) 61 | { 62 | rVal = (int)imageTable[Key]; 63 | } 64 | else if (!HasOverlay && !item.IsHidden) //for non-overlay icons, we already have 65 | { 66 | rVal = (int)System.Math.Floor((double)Key / 256); // the right index -- put in table 67 | imageTable[Key] = rVal; 68 | } 69 | else //don't have iconindex for an overlay, get it. 70 | { 71 | if (item.IsFileSystem & !item.IsDisk & !item.IsFolder) 72 | { 73 | dwflag = dwflag | ShellAPI.SHGFI.USEFILEATTRIBUTES; 74 | dwAttr = dwAttr | ShellAPI.FILE_ATTRIBUTE.NORMAL; 75 | } 76 | 77 | PIDL pidlFull = item.PIDLFull; 78 | 79 | ShellAPI.SHFILEINFO shfiSmall = new ShellAPI.SHFILEINFO(); 80 | ShellAPI.SHGetFileInfo(pidlFull.Ptr, dwAttr, ref shfiSmall, ShellAPI.cbFileInfo, dwflag | ShellAPI.SHGFI.SMALLICON); 81 | 82 | ShellAPI.SHFILEINFO shfiLarge = new ShellAPI.SHFILEINFO(); 83 | ShellAPI.SHGetFileInfo(pidlFull.Ptr, dwAttr, ref shfiLarge, ShellAPI.cbFileInfo, dwflag | ShellAPI.SHGFI.LARGEICON); 84 | 85 | Marshal.FreeCoTaskMem(pidlFull.Ptr); 86 | 87 | lock (imageTable) 88 | { 89 | rVal = ShellAPI.ImageList_ReplaceIcon(smallImageListHandle, -1, shfiSmall.hIcon); 90 | ShellAPI.ImageList_ReplaceIcon(largeImageListHandle, -1, shfiLarge.hIcon); 91 | } 92 | 93 | ShellAPI.DestroyIcon(shfiSmall.hIcon); 94 | ShellAPI.DestroyIcon(shfiLarge.hIcon); 95 | imageTable[Key] = rVal; 96 | } 97 | 98 | if (SelectedIcon) 99 | item.SelectedImageIndex = rVal; 100 | else 101 | item.ImageIndex = rVal; 102 | } 103 | 104 | public static Icon GetIcon(int index, bool small) 105 | { 106 | IntPtr iconPtr; 107 | 108 | if (small) 109 | iconPtr = ShellAPI.ImageList_GetIcon(smallImageListHandle, index, ShellAPI.ILD.NORMAL); 110 | else 111 | iconPtr = ShellAPI.ImageList_GetIcon(largeImageListHandle, index, ShellAPI.ILD.NORMAL); 112 | 113 | if (iconPtr != IntPtr.Zero) 114 | { 115 | Icon icon = Icon.FromHandle(iconPtr); 116 | Icon retVal = (Icon)icon.Clone(); 117 | ShellAPI.DestroyIcon(iconPtr); 118 | return retVal; 119 | } 120 | else 121 | return null; 122 | } 123 | 124 | internal static IntPtr SmallImageList { get { return smallImageListHandle; } } 125 | internal static IntPtr LargeImageList { get { return largeImageListHandle; } } 126 | 127 | #region Set Small Handle 128 | 129 | internal static void SetSmallImageList(TreeView treeView) 130 | { 131 | ShellAPI.SendMessage(treeView.Handle, ShellAPI.WM.TVM_SETIMAGELIST, TVSIL_NORMAL, smallImageListHandle); 132 | } 133 | 134 | internal static void SetSmallImageList(ListView listView) 135 | { 136 | ShellAPI.SendMessage(listView.Handle, ShellAPI.WM.LVM_SETIMAGELIST, TVSIL_SMALL, smallImageListHandle); 137 | } 138 | 139 | #endregion 140 | 141 | #region Set Large Handle 142 | 143 | internal static void SetLargeImageList(ListView listView) 144 | { 145 | ShellAPI.SendMessage(listView.Handle, ShellAPI.WM.LVM_SETIMAGELIST, TVSIL_NORMAL, largeImageListHandle); 146 | } 147 | 148 | #endregion 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Shell/StreamStorage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using EasyExplorer; 5 | using System.IO; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace ShellDll 9 | { 10 | internal class StreamStorageProvider : IFileInfoProvider, IDirInfoProvider 11 | { 12 | #region Fields 13 | 14 | private ShellItem providerItem; 15 | private FileAccess fileAccess; 16 | 17 | #endregion 18 | 19 | public StreamStorageProvider(FileAccess fileAccess) 20 | { 21 | this.fileAccess = fileAccess; 22 | } 23 | 24 | #region Free 25 | 26 | internal void ReleaseStorage() 27 | { 28 | dirInfoRetrieved = false; 29 | } 30 | 31 | internal void ReleaseStream() 32 | { 33 | if (tempStreamReader != null) 34 | { 35 | tempStreamReader.CloseStream(); 36 | tempStreamReader = null; 37 | } 38 | 39 | if (tempParentStorage != null) 40 | { 41 | Marshal.ReleaseComObject(tempParentStorage); 42 | Marshal.Release(tempParentStoragePtr); 43 | tempParentStorage = null; 44 | } 45 | } 46 | 47 | #endregion 48 | 49 | #region IFileInfoProvider Members 50 | 51 | private ShellStreamReader tempStreamReader; 52 | private IStorage tempParentStorage; 53 | private IntPtr tempParentStoragePtr; 54 | 55 | public ShellAPI.STATSTG GetFileInfo() 56 | { 57 | if (tempStreamReader != null) 58 | return tempStreamReader.StreamInfo; 59 | else if (providerItem != null) 60 | { 61 | if (tempParentStorage == null) 62 | ShellHelper.GetIStorage(providerItem.ParentItem, out tempParentStoragePtr, out tempParentStorage); 63 | 64 | tempStreamReader = new ShellStreamReader(providerItem, tempParentStorage, fileAccess); 65 | return tempStreamReader.StreamInfo; 66 | } 67 | else 68 | throw new Exception("Not possible to retrieve the STATSTG."); 69 | } 70 | 71 | public Stream GetFileStream() 72 | { 73 | if (tempStreamReader != null) 74 | return tempStreamReader; 75 | else if (providerItem != null) 76 | { 77 | if (tempParentStorage == null) 78 | ShellHelper.GetIStorage(providerItem.ParentItem, out tempParentStoragePtr, out tempParentStorage); 79 | 80 | tempStreamReader = new ShellStreamReader(providerItem, tempParentStorage, fileAccess); 81 | return tempStreamReader; 82 | } 83 | else 84 | throw new Exception("Not possible to open a filestream."); 85 | } 86 | 87 | #endregion 88 | 89 | #region IDirInfoProvider Members 90 | 91 | private ShellAPI.STATSTG dirInfo; 92 | private bool dirInfoRetrieved = false; 93 | 94 | public ShellAPI.STATSTG GetDirInfo() 95 | { 96 | if (dirInfoRetrieved) 97 | return dirInfo; 98 | else if (providerItem != null) 99 | { 100 | IntPtr tempPtr; 101 | IStorage tempStorage; 102 | 103 | if (ShellHelper.GetIStorage(providerItem, out tempPtr, out tempStorage)) 104 | { 105 | tempStorage.Stat(out dirInfo, ShellAPI.STATFLAG.NONAME); 106 | Marshal.ReleaseComObject(tempStorage); 107 | Marshal.Release(tempPtr); 108 | } 109 | else 110 | throw new Exception("Not possible to retrieve the STATSTG."); 111 | 112 | dirInfoRetrieved = true; 113 | return dirInfo; 114 | } 115 | else 116 | throw new Exception("Not possible to retrieve the STATSTG."); 117 | } 118 | 119 | #endregion 120 | 121 | #region Properties 122 | 123 | public ShellItem ProviderItem 124 | { 125 | get { return providerItem; } 126 | set { providerItem = value; } 127 | } 128 | 129 | public FileAccess FileAccess 130 | { 131 | get { return fileAccess; } 132 | set { fileAccess = value; } 133 | } 134 | 135 | #endregion 136 | } 137 | 138 | public class ShellStreamReader : Stream, IDisposable 139 | { 140 | #region Fields 141 | 142 | private ShellItem shellItem; 143 | 144 | private IntPtr streamPtr; 145 | private IStream stream; 146 | 147 | private bool canRead, canWrite; 148 | 149 | private ShellAPI.STATSTG streamInfo; 150 | private bool streamInfoRead = false; 151 | 152 | private long currentPos; 153 | 154 | private bool disposed = false; 155 | 156 | #endregion 157 | 158 | internal ShellStreamReader(ShellItem shellItem, IStorage parentStorage, FileAccess access) 159 | { 160 | this.shellItem = shellItem; 161 | 162 | OpenStream(parentStorage, ref access); 163 | 164 | this.canRead = (access == FileAccess.Read || access == FileAccess.ReadWrite); 165 | this.canWrite = (access == FileAccess.Write || access == FileAccess.ReadWrite); 166 | currentPos = 0; 167 | } 168 | 169 | ~ShellStreamReader() 170 | { 171 | CloseStream(); 172 | } 173 | 174 | #region Stream Members 175 | 176 | public override bool CanRead 177 | { 178 | get { return canRead; } 179 | } 180 | 181 | public override bool CanSeek 182 | { 183 | get { return true; } 184 | } 185 | 186 | public override bool CanWrite 187 | { 188 | get { return canWrite; } 189 | } 190 | 191 | public override void Flush() 192 | { 193 | 194 | } 195 | 196 | public override long Length 197 | { 198 | get 199 | { 200 | if (CanRead) 201 | return StreamInfo.cbSize; 202 | else 203 | return 0; 204 | } 205 | } 206 | 207 | public override long Position 208 | { 209 | get 210 | { 211 | return currentPos; 212 | } 213 | set 214 | { 215 | Seek(value, SeekOrigin.Begin); 216 | } 217 | } 218 | 219 | public override int Read(byte[] buffer, int offset, int count) 220 | { 221 | if (CanRead) 222 | { 223 | byte[] readBytes = new byte[count]; 224 | 225 | IntPtr readNrPtr = Marshal.AllocCoTaskMem(32); 226 | stream.Read(readBytes, count, readNrPtr); 227 | 228 | int readNr = (int)Marshal.PtrToStructure(readNrPtr, typeof(Int32)); 229 | Marshal.FreeCoTaskMem(readNrPtr); 230 | 231 | Array.Copy(readBytes, 0, buffer, offset, readNr); 232 | currentPos += readNr; 233 | return readNr; 234 | } 235 | else 236 | return 0; 237 | } 238 | 239 | public override void SetLength(long value) 240 | { 241 | if (CanWrite) 242 | stream.SetSize(value); 243 | } 244 | 245 | public override void Write(byte[] buffer, int offset, int count) 246 | { 247 | if (CanWrite) 248 | { 249 | byte[] writeBytes = new byte[count]; 250 | Array.Copy(buffer, offset, writeBytes, 0, count); 251 | 252 | IntPtr writtenNrPtr = Marshal.AllocCoTaskMem(64); 253 | stream.Write(writeBytes, count, writtenNrPtr); 254 | 255 | long writtenNr = (long)Marshal.PtrToStructure(writtenNrPtr, typeof(Int64)); 256 | Marshal.FreeCoTaskMem(writtenNrPtr); 257 | 258 | currentPos += writtenNr; 259 | } 260 | } 261 | 262 | public override long Seek(long offset, SeekOrigin origin) 263 | { 264 | if (CanSeek) 265 | { 266 | IntPtr newPosPtr = Marshal.AllocCoTaskMem(64); 267 | stream.Seek(offset, origin, newPosPtr); 268 | 269 | long newPos = (long)Marshal.PtrToStructure(newPosPtr, typeof(Int64)); 270 | Marshal.FreeCoTaskMem(newPosPtr); 271 | 272 | return (currentPos = newPos); 273 | } 274 | else 275 | return -1; 276 | } 277 | 278 | #endregion 279 | 280 | #region IDisposable Members 281 | 282 | void IDisposable.Dispose() 283 | { 284 | if (!disposed) 285 | { 286 | disposed = true; 287 | 288 | if (stream != null) 289 | { 290 | Marshal.ReleaseComObject(stream); 291 | stream = null; 292 | } 293 | 294 | if (streamPtr != IntPtr.Zero) 295 | { 296 | Marshal.Release(streamPtr); 297 | streamPtr = IntPtr.Zero; 298 | } 299 | 300 | GC.SuppressFinalize(this); 301 | } 302 | } 303 | 304 | #endregion 305 | 306 | #region Open/Close Stream 307 | 308 | public override void Close() 309 | { 310 | 311 | } 312 | 313 | internal void CloseStream() 314 | { 315 | base.Close(); 316 | 317 | if (stream != null) 318 | { 319 | Marshal.ReleaseComObject(stream); 320 | Marshal.Release(streamPtr); 321 | } 322 | } 323 | 324 | internal ShellAPI.STATSTG StreamInfo 325 | { 326 | get 327 | { 328 | if (!streamInfoRead) 329 | { 330 | stream.Stat(out streamInfo, ShellAPI.STATFLAG.NONAME); 331 | streamInfoRead = true; 332 | } 333 | return streamInfo; 334 | } 335 | } 336 | 337 | private void OpenStream(IStorage parentStorage, ref FileAccess access) 338 | { 339 | ShellAPI.STGM grfmode = ShellAPI.STGM.SHARE_DENY_WRITE; 340 | 341 | switch (access) 342 | { 343 | case FileAccess.ReadWrite: 344 | grfmode |= ShellAPI.STGM.READWRITE; 345 | break; 346 | 347 | case FileAccess.Write: 348 | grfmode |= ShellAPI.STGM.WRITE; 349 | break; 350 | } 351 | 352 | if (parentStorage != null) 353 | { 354 | if (parentStorage.OpenStream( 355 | shellItem.Text + (shellItem.IsLink ? ".lnk" : string.Empty), 356 | IntPtr.Zero, 357 | grfmode, 358 | 0, 359 | out streamPtr) == ShellAPI.S_OK) 360 | { 361 | stream = (IStream)Marshal.GetTypedObjectForIUnknown(streamPtr, typeof(IStream)); 362 | } 363 | else if (access != FileAccess.Read) 364 | { 365 | if (parentStorage.OpenStream( 366 | shellItem.Text + (shellItem.IsLink ? ".lnk" : string.Empty), 367 | IntPtr.Zero, 368 | ShellAPI.STGM.SHARE_DENY_WRITE, 369 | 0, 370 | out streamPtr) == ShellAPI.S_OK) 371 | { 372 | access = FileAccess.Read; 373 | stream = (IStream)Marshal.GetTypedObjectForIUnknown(streamPtr, typeof(IStream)); 374 | } 375 | else 376 | throw new IOException(String.Format("Can't open stream: {0}", shellItem)); 377 | } 378 | else 379 | throw new IOException(String.Format("Can't open stream: {0}", shellItem)); 380 | } 381 | else 382 | { 383 | access = FileAccess.Read; 384 | 385 | if (!ShellHelper.GetIStream(shellItem, out streamPtr, out stream)) 386 | throw new IOException(String.Format("Can't open stream: {0}", shellItem)); 387 | } 388 | } 389 | 390 | #endregion 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /Website/ee1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Website/ee1.png -------------------------------------------------------------------------------- /Website/ee2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Website/ee2.png -------------------------------------------------------------------------------- /Wrappers/BrowserContextMenuWrappers.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robinrodricks/EasyExplorer/4b74fe2fc01b20a414cede7e8f776d4dcccc8ccd/Wrappers/BrowserContextMenuWrappers.cs -------------------------------------------------------------------------------- /Wrappers/BrowserDragWrappers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ShellDll; 5 | using System.Runtime.InteropServices; 6 | using System.Windows.Forms; 7 | using System.Drawing; 8 | 9 | namespace EasyExplorer 10 | { 11 | /// 12 | /// This class takes care of every drag operation in a BrowserTreeView 13 | /// 14 | internal class BrowserTVDragWrapper : IDropSource, IDisposable 15 | { 16 | #region Fields 17 | 18 | // The browser for which to do the drag work 19 | private Explorer br; 20 | 21 | // The pointer to the IDataObject being dragged 22 | private IntPtr dataObjectPtr; 23 | 24 | // The mouseButtons state when a drag starts 25 | private MouseButtons startButton; 26 | 27 | // A bool to indicate whether this class has been disposed 28 | private bool disposed = false; 29 | 30 | // The events that will be raised when a drag starts and when it ends 31 | public event DragEnterEventHandler DragStart; 32 | public event EventHandler DragEnd; 33 | 34 | #endregion 35 | 36 | /// 37 | /// Registers the TreeView.ItemDrag to receive the event when an item is being dragged 38 | /// 39 | /// The browser for which to support the drag 40 | public BrowserTVDragWrapper(Explorer br) 41 | { 42 | this.br = br; 43 | br.FolderView.ItemDrag += new ItemDragEventHandler(ItemDrag); 44 | } 45 | 46 | ~BrowserTVDragWrapper() 47 | { 48 | ((IDisposable)this).Dispose(); 49 | } 50 | 51 | #region Generated Events 52 | 53 | /// 54 | /// The event that is being raised when a drag starts 55 | /// 56 | /// the DragEnterEventArgs for the event 57 | private void OnDragStart(DragEnterEventArgs e) 58 | { 59 | if (DragStart != null) 60 | DragStart(this, e); 61 | } 62 | 63 | /// 64 | /// The event that is being raised when a drag ends 65 | /// 66 | /// the EventArgs for the event 67 | private void OnDragEnd(EventArgs e) 68 | { 69 | if (DragEnd != null) 70 | DragEnd(this, e); 71 | } 72 | 73 | #endregion 74 | 75 | #region IDropSource Members 76 | 77 | /// 78 | /// This method initialises the dragging of a TreeNode 79 | /// 80 | void ItemDrag(object sender, ItemDragEventArgs e) 81 | { 82 | ReleaseCom(); 83 | 84 | startButton = e.Button; 85 | ShellItem item = (ShellItem)((TreeNode)e.Item).Tag; 86 | dataObjectPtr = ShellHelper.GetIDataObject(new ShellItem[] { item }); 87 | 88 | if (dataObjectPtr != IntPtr.Zero) 89 | { 90 | DragDropEffects effects; 91 | OnDragStart(new DragEnterEventArgs((item.ParentItem != null ? item.ParentItem : item), br.FolderView)); 92 | ShellAPI.DoDragDrop(dataObjectPtr, this, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move, out effects); 93 | OnDragEnd(new EventArgs()); 94 | } 95 | } 96 | 97 | public int QueryContinueDrag(bool fEscapePressed, ShellAPI.MK grfKeyState) 98 | { 99 | if (fEscapePressed) 100 | return ShellAPI.DRAGDROP_S_CANCEL; 101 | else 102 | { 103 | if ((startButton & MouseButtons.Left) != 0 && (grfKeyState & ShellAPI.MK.LBUTTON) == 0) 104 | return ShellAPI.DRAGDROP_S_DROP; 105 | else if ((startButton & MouseButtons.Right) != 0 && (grfKeyState & ShellAPI.MK.RBUTTON) == 0) 106 | return ShellAPI.DRAGDROP_S_DROP; 107 | else 108 | return ShellAPI.S_OK; 109 | } 110 | } 111 | 112 | public int GiveFeedback(DragDropEffects dwEffect) 113 | { 114 | return ShellAPI.DRAGDROP_S_USEDEFAULTCURSORS; 115 | } 116 | 117 | #endregion 118 | 119 | #region IDisposable Members 120 | 121 | /// 122 | /// If not disposed, dispose the class 123 | /// 124 | public void Dispose() 125 | { 126 | if (!disposed) 127 | { 128 | ReleaseCom(); 129 | GC.SuppressFinalize(this); 130 | 131 | disposed = true; 132 | } 133 | } 134 | 135 | /// 136 | /// Release the IDataObject and free's the allocated memory 137 | /// 138 | private void ReleaseCom() 139 | { 140 | if (dataObjectPtr != IntPtr.Zero) 141 | { 142 | Marshal.Release(dataObjectPtr); 143 | dataObjectPtr = IntPtr.Zero; 144 | } 145 | } 146 | 147 | #endregion 148 | } 149 | 150 | /// 151 | /// This class takes care of every drag operation in a BrowserListView 152 | /// 153 | internal class BrowserLVDragWrapper : IDropSource, IDisposable 154 | { 155 | #region Fields 156 | 157 | // The browser for which to do the drag work 158 | private Explorer br; 159 | 160 | // The pointer to the IDataObject being dragged 161 | private IntPtr dataObjectPtr; 162 | 163 | // The mouseButtons state when a drag starts 164 | private MouseButtons startButton; 165 | 166 | // A bool to indicate whether this class has been disposed 167 | private bool disposed = false; 168 | 169 | // The events that will be raised when a drag starts and when it ends 170 | public event DragEnterEventHandler DragStart; 171 | public event EventHandler DragEnd; 172 | 173 | #endregion 174 | 175 | /// 176 | /// Registers the ListView.ItemDrag to receive the event when an item is being dragged 177 | /// 178 | /// The browser for which to support the drag 179 | public BrowserLVDragWrapper(Explorer br) 180 | { 181 | this.br = br; 182 | br.FileView.ItemDrag += new ItemDragEventHandler(ItemDrag); 183 | } 184 | 185 | ~BrowserLVDragWrapper() 186 | { 187 | ((IDisposable)this).Dispose(); 188 | } 189 | 190 | #region Generated Events 191 | 192 | /// 193 | /// The event that is being raised when a drag starts 194 | /// 195 | /// the DragEnterEventArgs for the event 196 | private void OnDragStart(DragEnterEventArgs e) 197 | { 198 | if (DragStart != null) 199 | DragStart(this, e); 200 | } 201 | 202 | /// 203 | /// The event that is being raised when a drag ends 204 | /// 205 | /// the EventArgs for the event 206 | private void OnDragEnd(EventArgs e) 207 | { 208 | if (DragEnd != null) 209 | DragEnd(this, e); 210 | } 211 | 212 | #endregion 213 | 214 | #region IDropSource Members 215 | 216 | /// 217 | /// This method initialises the dragging of a ListViewItem 218 | /// 219 | void ItemDrag(object sender, ItemDragEventArgs e) 220 | { 221 | ReleaseCom(); 222 | 223 | startButton = e.Button; 224 | 225 | ShellItem[] items = new ShellItem[br.FileView.SelectedItems.Count]; 226 | for (int i = 0; i < br.FileView.SelectedItems.Count; i++) 227 | { 228 | items[i] = (ShellItem)br.FileView.SelectedItems[i].Tag; 229 | } 230 | 231 | dataObjectPtr = ShellHelper.GetIDataObject(items); 232 | 233 | if (dataObjectPtr != IntPtr.Zero) 234 | { 235 | DragDropEffects effects; 236 | OnDragStart(new DragEnterEventArgs((items[0].ParentItem != null ? items[0].ParentItem : items[0]), br.FileView)); 237 | ShellAPI.DoDragDrop(dataObjectPtr, this, DragDropEffects.Copy | DragDropEffects.Link | DragDropEffects.Move, out effects); 238 | OnDragEnd(new EventArgs()); 239 | } 240 | } 241 | 242 | public int QueryContinueDrag(bool fEscapePressed, ShellAPI.MK grfKeyState) 243 | { 244 | if (fEscapePressed) 245 | return ShellAPI.DRAGDROP_S_CANCEL; 246 | else 247 | { 248 | if ((startButton & MouseButtons.Left) != 0 && (grfKeyState & ShellAPI.MK.LBUTTON) == 0) 249 | return ShellAPI.DRAGDROP_S_DROP; 250 | else if ((startButton & MouseButtons.Right) != 0 && (grfKeyState & ShellAPI.MK.RBUTTON) == 0) 251 | return ShellAPI.DRAGDROP_S_DROP; 252 | else 253 | return ShellAPI.S_OK; 254 | } 255 | } 256 | 257 | public int GiveFeedback(DragDropEffects dwEffect) 258 | { 259 | return ShellAPI.DRAGDROP_S_USEDEFAULTCURSORS; 260 | } 261 | 262 | #endregion 263 | 264 | #region IDisposable Members 265 | 266 | /// 267 | /// If not disposed, dispose the class 268 | /// 269 | public void Dispose() 270 | { 271 | if (!disposed) 272 | { 273 | ReleaseCom(); 274 | GC.SuppressFinalize(this); 275 | 276 | disposed = true; 277 | } 278 | } 279 | 280 | /// 281 | /// Release the IDataObject and free's the allocated memory 282 | /// 283 | private void ReleaseCom() 284 | { 285 | if (dataObjectPtr != IntPtr.Zero) 286 | { 287 | Marshal.Release(dataObjectPtr); 288 | dataObjectPtr = IntPtr.Zero; 289 | } 290 | } 291 | 292 | #endregion 293 | } 294 | 295 | #region Event Classes 296 | 297 | internal delegate void DragEnterEventHandler(object sender, DragEnterEventArgs e); 298 | 299 | internal class DragEnterEventArgs : EventArgs 300 | { 301 | private ShellItem parent; 302 | private Control dragStartControl; 303 | 304 | public DragEnterEventArgs(ShellItem parent, Control dragStartControl) 305 | { 306 | this.parent = parent; 307 | this.dragStartControl = dragStartControl; 308 | } 309 | 310 | public ShellItem Parent { get { return parent; } } 311 | public Control DragStartControl { get { return dragStartControl; } } 312 | } 313 | 314 | #endregion 315 | } 316 | -------------------------------------------------------------------------------- /Wrappers/BrowserDropWrappers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ShellDll; 5 | using System.Runtime.InteropServices; 6 | using System.Windows.Forms; 7 | using System.Drawing; 8 | 9 | namespace EasyExplorer 10 | { 11 | /// 12 | /// This class takes care of every drop operation in a BrowserTreeView 13 | /// 14 | internal class BrowserTVDropWrapper : ShellDll.IDropTarget, IDisposable 15 | { 16 | #region Fields 17 | 18 | // The browser for which to do the drop work 19 | private Explorer br; 20 | 21 | private IntPtr treeViewHandle; 22 | 23 | // The current IDropTarget the cursor is over and the pointers to the target and dataobject 24 | private ShellDll.IDropTarget dropTarget; 25 | private IntPtr dropTargetPtr; 26 | private IntPtr dropDataObject; 27 | 28 | private IDropTargetHelper dropHelper; 29 | private IntPtr dropHelperPtr; 30 | 31 | // The current node the cursor is over to drop on 32 | private TreeNode dropNode; 33 | 34 | // The last selected node from the browser 35 | // This is to remember which node to select after drop has completed 36 | private TreeNode lastSelectedNode; 37 | 38 | // The parent ShellItems of the drop- and dragitem 39 | private ShellItem parentDropItem, parentDragItem; 40 | 41 | // The mouse and keys state when a drag enter occurs 42 | private ShellAPI.MK mouseButtons; 43 | 44 | // A bool to indicate whether this class has been disposed 45 | private bool disposed = false; 46 | 47 | // The event for when a drop is occuring 48 | public event DropEventHandler Drop; 49 | 50 | #endregion 51 | 52 | /// 53 | /// Registers the TreeView for drag/drop operations and uses this class as the IDropTarget 54 | /// 55 | /// The browser for which to support the drop 56 | public BrowserTVDropWrapper(Explorer br) 57 | { 58 | this.br = br; 59 | 60 | treeViewHandle = br.FolderView.Handle; 61 | ShellAPI.RegisterDragDrop(treeViewHandle, this); 62 | 63 | br.FolderView.HandleCreated += new EventHandler(FolderView_HandleCreated); 64 | br.FolderView.HandleDestroyed += new EventHandler(FolderView_HandleDestroyed); 65 | 66 | ShellHelper.GetIDropTargetHelper(out dropHelperPtr, out dropHelper); 67 | } 68 | 69 | ~BrowserTVDropWrapper() 70 | { 71 | ((IDisposable)this).Dispose(); 72 | } 73 | 74 | #region Handle Changes 75 | 76 | void FolderView_HandleCreated(object sender, EventArgs e) 77 | { 78 | treeViewHandle = br.FolderView.Handle; 79 | ShellAPI.RegisterDragDrop(treeViewHandle, this); 80 | } 81 | 82 | void FolderView_HandleDestroyed(object sender, EventArgs e) 83 | { 84 | ShellAPI.RevokeDragDrop(br.FolderView.Handle); 85 | } 86 | 87 | #endregion 88 | 89 | #region Public 90 | 91 | /// 92 | /// This ShellItem is the parent item of the item being currently dragged. This field is used 93 | /// to check whether an item is being moved to it's original folder. If this is the case, we don't 94 | /// have to do anything, cause the item is allready there. 95 | /// 96 | public ShellItem ParentDragItem 97 | { 98 | get { return parentDragItem; } 99 | set { parentDragItem = value; } 100 | } 101 | 102 | #endregion 103 | 104 | #region Generated Events 105 | 106 | /// 107 | /// This event will be raised whenever a drop occurs on the TreeView. 108 | /// 109 | /// The DropEventArgs for the event 110 | private void OnDrop(DropEventArgs e) 111 | { 112 | if (Drop != null) 113 | Drop(this, e); 114 | } 115 | 116 | #endregion 117 | 118 | #region IDropTarget Members 119 | 120 | public int DragEnter(IntPtr pDataObj, ShellAPI.MK grfKeyState, ShellAPI.POINT pt, ref DragDropEffects pdwEffect) 121 | { 122 | mouseButtons = grfKeyState; 123 | 124 | br.FolderView.Focus(); 125 | br.SelectionChange = false; 126 | lastSelectedNode = br.FolderView.SelectedNode; 127 | 128 | ReleaseCom(); 129 | 130 | dropDataObject = pDataObj; 131 | 132 | #region Get DropItem 133 | 134 | Point point = br.FolderView.PointToClient(new Point(pt.x, pt.y)); 135 | TreeViewHitTestInfo hitTest = br.FolderView.HitTest(point); 136 | 137 | dropNode = hitTest.Node; 138 | br.FolderView.SelectedNode = dropNode; 139 | 140 | if (dropNode != null) 141 | { 142 | ShellItem item = (ShellItem)dropNode.Tag; 143 | parentDropItem = item; 144 | 145 | if (ShellHelper.GetIDropTarget(item, out dropTargetPtr, out dropTarget)) 146 | { 147 | dropTarget.DragEnter(pDataObj, grfKeyState, pt, ref pdwEffect); 148 | } 149 | } 150 | 151 | #endregion 152 | 153 | if (dropHelper != null) 154 | dropHelper.DragEnter(br.Handle, pDataObj, ref pt, pdwEffect); 155 | 156 | return ShellAPI.S_OK; 157 | } 158 | 159 | public int DragOver(ShellAPI.MK grfKeyState, ShellAPI.POINT pt, ref DragDropEffects pdwEffect) 160 | { 161 | bool reset = false; 162 | 163 | #region Get DropItem 164 | 165 | Point point = br.FolderView.PointToClient(new Point(pt.x, pt.y)); 166 | TreeViewHitTestInfo hitTest = br.FolderView.HitTest(point); 167 | if (!TreeNode.Equals(dropNode, hitTest.Node)) 168 | { 169 | if (dropTarget != null) 170 | dropTarget.DragLeave(); 171 | 172 | ReleaseCom(); 173 | 174 | dropNode = hitTest.Node; 175 | br.FolderView.SelectedNode = dropNode; 176 | 177 | if (dropNode == null) 178 | { 179 | pdwEffect = DragDropEffects.None; 180 | 181 | if (dropHelper != null) 182 | dropHelper.DragOver(ref pt, pdwEffect); 183 | 184 | return ShellAPI.S_OK; 185 | } 186 | else 187 | { 188 | ShellItem item = (ShellItem)dropNode.Tag; 189 | parentDropItem = item; 190 | 191 | ShellHelper.GetIDropTarget(item, out dropTargetPtr, out dropTarget); 192 | reset = true; 193 | } 194 | } 195 | else if (dropNode == null) 196 | { 197 | if (dropTarget != null) 198 | dropTarget.DragLeave(); 199 | 200 | ReleaseCom(); 201 | 202 | dropNode = null; 203 | br.SelectedNode = null; 204 | 205 | pdwEffect = DragDropEffects.None; 206 | 207 | if (dropHelper != null) 208 | dropHelper.DragOver(ref pt, pdwEffect); 209 | 210 | return ShellAPI.S_OK; 211 | } 212 | 213 | #endregion 214 | 215 | if (dropTarget != null) 216 | { 217 | if (reset) 218 | dropTarget.DragEnter(dropDataObject, grfKeyState, pt, ref pdwEffect); 219 | else 220 | dropTarget.DragOver(grfKeyState, pt, ref pdwEffect); 221 | } 222 | else 223 | pdwEffect = DragDropEffects.None; 224 | 225 | if (dropHelper != null) 226 | dropHelper.DragOver(ref pt, pdwEffect); 227 | 228 | return ShellAPI.S_OK; 229 | } 230 | 231 | public int DragLeave() 232 | { 233 | ResetDrop(); 234 | if (dropTarget != null) 235 | { 236 | dropTarget.DragLeave(); 237 | 238 | ReleaseCom(); 239 | dropDataObject = IntPtr.Zero; 240 | } 241 | 242 | if (dropHelper != null) 243 | dropHelper.DragLeave(); 244 | 245 | return ShellAPI.S_OK; 246 | } 247 | 248 | public int DragDrop(IntPtr pDataObj, ShellAPI.MK grfKeyState, ShellAPI.POINT pt, ref DragDropEffects pdwEffect) 249 | { 250 | OnDrop(new DropEventArgs(mouseButtons, br.FolderView)); 251 | 252 | if (!((mouseButtons & ShellAPI.MK.RBUTTON) != 0 || 253 | grfKeyState == ShellAPI.MK.CONTROL || 254 | grfKeyState == ShellAPI.MK.ALT || 255 | grfKeyState == (ShellAPI.MK.CONTROL | ShellAPI.MK.SHIFT)) && ShellItem.Equals(parentDragItem, parentDropItem)) 256 | { 257 | ResetDrop(); 258 | ReleaseCom(); 259 | pdwEffect = DragDropEffects.None; 260 | 261 | if (dropHelper != null) 262 | dropHelper.DragLeave(); 263 | 264 | return ShellAPI.S_OK; 265 | } 266 | 267 | ResetDrop(); 268 | if (dropTarget != null) 269 | { 270 | dropTarget.DragDrop(pDataObj, grfKeyState, pt, ref pdwEffect); 271 | 272 | ReleaseCom(); 273 | dropDataObject = IntPtr.Zero; 274 | } 275 | 276 | if (dropHelper != null) 277 | dropHelper.Drop(pDataObj, ref pt, pdwEffect); 278 | 279 | return ShellAPI.S_OK; 280 | } 281 | 282 | /// 283 | /// Reset all fields to the default values and release the IDropTarget 284 | /// 285 | private void ResetDrop() 286 | { 287 | if (dropNode != null) 288 | { 289 | dropNode = null; 290 | parentDropItem = null; 291 | } 292 | 293 | if (lastSelectedNode != null) 294 | br.FolderView.SelectedNode = lastSelectedNode; 295 | 296 | br.SelectionChange = true; 297 | } 298 | 299 | #endregion 300 | 301 | #region IDisposable Members 302 | 303 | /// 304 | /// If not disposed, dispose the class 305 | /// 306 | public void Dispose() 307 | { 308 | if (!disposed) 309 | { 310 | DisposeDropWrapper(); 311 | GC.SuppressFinalize(this); 312 | 313 | disposed = true; 314 | } 315 | } 316 | 317 | /// 318 | /// Revokes the TreeView from getting drop messages and releases the IDropTarget 319 | /// 320 | private void DisposeDropWrapper() 321 | { 322 | ReleaseCom(); 323 | 324 | if (dropHelper != null) 325 | { 326 | Marshal.ReleaseComObject(dropHelper); 327 | } 328 | } 329 | 330 | /// 331 | /// Release the IDropTarget and free's the allocated memory 332 | /// 333 | private void ReleaseCom() 334 | { 335 | if (dropTarget != null) 336 | { 337 | Marshal.ReleaseComObject(dropTarget); 338 | 339 | dropTarget = null; 340 | dropHelperPtr = IntPtr.Zero; 341 | } 342 | } 343 | 344 | #endregion 345 | } 346 | 347 | /// 348 | /// This class takes care of every drop operation in a BrowserListView 349 | /// 350 | internal class BrowserLVDropWrapper : ShellDll.IDropTarget, IDisposable 351 | { 352 | #region Fields 353 | 354 | // The browser for which to do the drop work 355 | private Explorer br; 356 | 357 | private IntPtr listViewHandle; 358 | 359 | // The current IDropTarget the cursor is over and the pointers to the target and dataobject 360 | private ShellDll.IDropTarget dropTarget; 361 | private IntPtr dropTargetPtr; 362 | private IntPtr dropDataObject; 363 | 364 | private IDropTargetHelper dropHelper; 365 | private IntPtr dropHelperPtr; 366 | 367 | // The current ListViewItem the cursor is over to drop on 368 | private ListViewItem dropListItem; 369 | 370 | // The selected state from the dropListItem before the cursor moved over it 371 | private bool wasSelected; 372 | 373 | // The parent ShellItems of the drop- and dragitem 374 | private ShellItem parentDropItem, parentDragItem; 375 | 376 | // The mouse and keys state and DragDropEffects when a drag enter occurs 377 | private ShellAPI.MK mouseButtons; 378 | private DragDropEffects startEffects; 379 | 380 | // A bool to indicate whether this class has been disposed 381 | private bool disposed = false; 382 | 383 | // The event for when a drop is occuring 384 | public event DropEventHandler Drop; 385 | 386 | #endregion 387 | 388 | /// 389 | /// Registers the ListView for drag/drop operations and uses this class as the IDropTarget 390 | /// 391 | /// The browser for which to support the drop 392 | public BrowserLVDropWrapper(Explorer br) 393 | { 394 | this.br = br; 395 | 396 | listViewHandle = br.FileView.Handle; 397 | ShellAPI.RegisterDragDrop(listViewHandle, this); 398 | 399 | br.FileView.HandleCreated += new EventHandler(FileView_HandleCreated); 400 | br.FileView.HandleDestroyed += new EventHandler(FileView_HandleDestroyed); 401 | 402 | ShellHelper.GetIDropTargetHelper(out dropHelperPtr, out dropHelper); 403 | } 404 | 405 | ~BrowserLVDropWrapper() 406 | { 407 | ((IDisposable)this).Dispose(); 408 | } 409 | 410 | #region Handle Changes 411 | 412 | void FileView_HandleCreated(object sender, EventArgs e) 413 | { 414 | listViewHandle = br.FileView.Handle; 415 | ShellAPI.RegisterDragDrop(listViewHandle, this); 416 | } 417 | 418 | void FileView_HandleDestroyed(object sender, EventArgs e) 419 | { 420 | ShellAPI.RevokeDragDrop(listViewHandle); 421 | } 422 | 423 | #endregion 424 | 425 | #region Public 426 | 427 | /// 428 | /// This ShellItem is the parent item of the item being currently dragged. This field is used 429 | /// to check whether an item is being moved to it's original folder. If this is the case, we don't 430 | /// have to do anything, cause the item is allready there. 431 | /// 432 | public ShellItem ParentDragItem 433 | { 434 | get { return parentDragItem; } 435 | set { parentDragItem = value; } 436 | } 437 | 438 | #endregion 439 | 440 | #region Generated Events 441 | 442 | /// 443 | /// This event will be raised whenever a drop occurs on the ListView. 444 | /// 445 | /// The DropEventArgs for the event 446 | private void OnDrop(DropEventArgs e) 447 | { 448 | if (Drop != null) 449 | Drop(this, e); 450 | } 451 | 452 | #endregion 453 | 454 | #region IDropTarget Members 455 | 456 | public int DragEnter(IntPtr pDataObj, ShellAPI.MK grfKeyState, ShellAPI.POINT pt, ref DragDropEffects pdwEffect) 457 | { 458 | mouseButtons = grfKeyState; 459 | startEffects = pdwEffect; 460 | 461 | br.FileView.Focus(); 462 | br.SelectionChange = false; 463 | ReleaseCom(); 464 | 465 | dropDataObject = pDataObj; 466 | 467 | #region Get DropItem 468 | Point point = br.FileView.PointToClient(new Point(pt.x, pt.y)); 469 | ListViewHitTestInfo hitTest = br.FileView.HitTest(point); 470 | if (hitTest.Item != null && 471 | (br.FileView.View != View.Details || hitTest.SubItem == null || hitTest.Item.Name == hitTest.SubItem.Name) && 472 | (hitTest.Location == ListViewHitTestLocations.Image || 473 | hitTest.Location == ListViewHitTestLocations.Label || 474 | hitTest.Location == ListViewHitTestLocations.StateImage)) 475 | { 476 | dropListItem = hitTest.Item; 477 | 478 | wasSelected = dropListItem.Selected; 479 | dropListItem.Selected = true; 480 | 481 | ShellItem item = (ShellItem)dropListItem.Tag; 482 | parentDropItem = item; 483 | 484 | ShellHelper.GetIDropTarget(item, out dropTargetPtr, out dropTarget); 485 | } 486 | else 487 | { 488 | dropListItem = null; 489 | parentDropItem = br.SelectedItem; 490 | ShellHelper.GetIDropTarget(br.SelectedItem, out dropTargetPtr, out dropTarget); 491 | } 492 | #endregion 493 | 494 | if (dropTarget != null) 495 | dropTarget.DragEnter(pDataObj, grfKeyState, pt, ref pdwEffect); 496 | 497 | if (dropHelper != null) 498 | dropHelper.DragEnter(br.Handle, pDataObj, ref pt, pdwEffect); 499 | 500 | return ShellAPI.S_OK; 501 | } 502 | 503 | public int DragOver(ShellAPI.MK grfKeyState, ShellAPI.POINT pt, ref DragDropEffects pdwEffect) 504 | { 505 | bool reset = false; 506 | 507 | #region Get DropItem 508 | 509 | Point point = br.FileView.PointToClient(new Point(pt.x, pt.y)); 510 | ListViewHitTestInfo hitTest = br.FileView.HitTest(point); 511 | if (hitTest.Item != null && 512 | (br.FileView.View != View.Details || hitTest.SubItem == null || hitTest.Item.Name == hitTest.SubItem.Name) && 513 | (hitTest.Location == ListViewHitTestLocations.Image || 514 | hitTest.Location == ListViewHitTestLocations.Label || 515 | hitTest.Location == ListViewHitTestLocations.StateImage)) 516 | { 517 | if (!hitTest.Item.Equals(dropListItem)) 518 | { 519 | if (dropTarget != null) 520 | dropTarget.DragLeave(); 521 | 522 | ReleaseCom(); 523 | 524 | if (dropListItem != null) 525 | dropListItem.Selected = wasSelected; 526 | 527 | dropListItem = hitTest.Item; 528 | wasSelected = dropListItem.Selected; 529 | dropListItem.Selected = true; 530 | 531 | ShellItem item = (ShellItem)dropListItem.Tag; 532 | parentDropItem = item; 533 | 534 | ShellHelper.GetIDropTarget(item, out dropTargetPtr, out dropTarget); 535 | reset = true; 536 | } 537 | } 538 | else 539 | { 540 | if (dropListItem != null) 541 | { 542 | if (dropTarget != null) 543 | dropTarget.DragLeave(); 544 | 545 | ReleaseCom(); 546 | 547 | dropListItem.Selected = wasSelected; 548 | 549 | dropListItem = null; 550 | parentDropItem = br.SelectedItem; 551 | 552 | ShellHelper.GetIDropTarget(br.SelectedItem, out dropTargetPtr, out dropTarget); 553 | reset = true; 554 | } 555 | } 556 | 557 | #endregion 558 | 559 | if (dropTarget != null) 560 | { 561 | if (reset) 562 | dropTarget.DragEnter(dropDataObject, grfKeyState, pt, ref pdwEffect); 563 | else 564 | dropTarget.DragOver(grfKeyState, pt, ref pdwEffect); 565 | } 566 | else 567 | pdwEffect = DragDropEffects.None; 568 | 569 | if (dropHelper != null) 570 | dropHelper.DragOver(ref pt, pdwEffect); 571 | 572 | return ShellAPI.S_OK; 573 | } 574 | 575 | public int DragLeave() 576 | { 577 | ResetDrop(); 578 | if (dropTarget != null) 579 | { 580 | dropTarget.DragLeave(); 581 | 582 | ReleaseCom(); 583 | dropDataObject = IntPtr.Zero; 584 | } 585 | 586 | if (dropHelper != null) 587 | dropHelper.DragLeave(); 588 | 589 | return ShellAPI.S_OK; 590 | } 591 | 592 | public int DragDrop(IntPtr pDataObj, ShellAPI.MK grfKeyState, ShellAPI.POINT pt, ref DragDropEffects pdwEffect) 593 | { 594 | OnDrop(new DropEventArgs(mouseButtons, br.FileView)); 595 | 596 | if (!((mouseButtons & ShellAPI.MK.RBUTTON) != 0 || 597 | grfKeyState == ShellAPI.MK.CONTROL || 598 | grfKeyState == ShellAPI.MK.ALT || 599 | grfKeyState == (ShellAPI.MK.CONTROL | ShellAPI.MK.SHIFT)) && ShellItem.Equals(parentDragItem, parentDropItem)) 600 | { 601 | ResetDrop(); 602 | ReleaseCom(); 603 | pdwEffect = DragDropEffects.None; 604 | 605 | if (dropHelper != null) 606 | dropHelper.Drop(pDataObj, ref pt, pdwEffect); 607 | 608 | return ShellAPI.S_OK; 609 | } 610 | 611 | ResetDrop(); 612 | if (dropTarget != null) 613 | { 614 | dropTarget.DragDrop(pDataObj, grfKeyState, pt, ref pdwEffect); 615 | 616 | ReleaseCom(); 617 | dropDataObject = IntPtr.Zero; 618 | } 619 | 620 | if (dropHelper != null) 621 | dropHelper.Drop(pDataObj, ref pt, pdwEffect); 622 | 623 | return ShellAPI.S_OK; 624 | } 625 | 626 | /// 627 | /// Reset all fields to the default values and release the IDropTarget 628 | /// 629 | private void ResetDrop() 630 | { 631 | if (dropListItem != null) 632 | { 633 | dropListItem.Selected = wasSelected; 634 | dropListItem = null; 635 | parentDropItem = null; 636 | } 637 | 638 | br.SelectionChange = true; 639 | } 640 | 641 | #endregion 642 | 643 | #region IDisposable Members 644 | 645 | /// 646 | /// If not disposed, dispose the class 647 | /// 648 | public void Dispose() 649 | { 650 | if (!disposed) 651 | { 652 | DisposeDropWrapper(); 653 | GC.SuppressFinalize(this); 654 | 655 | disposed = true; 656 | } 657 | } 658 | 659 | /// 660 | /// Revokes the ListView from getting drop messages and releases the IDropTarget 661 | /// 662 | private void DisposeDropWrapper() 663 | { 664 | ReleaseCom(); 665 | 666 | if (dropHelper != null) 667 | { 668 | Marshal.ReleaseComObject(dropHelper); 669 | } 670 | } 671 | 672 | /// 673 | /// Release the IDropTarget and free's the allocated memory 674 | /// 675 | private void ReleaseCom() 676 | { 677 | if (dropTarget != null) 678 | { 679 | Marshal.ReleaseComObject(dropTarget); 680 | 681 | dropTarget = null; 682 | dropHelperPtr = IntPtr.Zero; 683 | } 684 | } 685 | 686 | #endregion 687 | } 688 | 689 | #region Event Classes 690 | 691 | internal delegate void DropEventHandler(object sender, DropEventArgs e); 692 | 693 | internal class DropEventArgs : EventArgs 694 | { 695 | private ShellAPI.MK mouseButtons; 696 | private Control dragStartControl; 697 | 698 | public DropEventArgs(ShellAPI.MK mouseButtons, Control dragStartControl) 699 | { 700 | this.mouseButtons = mouseButtons; 701 | this.dragStartControl = dragStartControl; 702 | } 703 | 704 | public ShellAPI.MK MouseButtons { get { return mouseButtons; } } 705 | public Control DragStartControl { get { return dragStartControl; } } 706 | } 707 | 708 | #endregion 709 | } 710 | -------------------------------------------------------------------------------- /Wrappers/BrowserPluginWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Collections; 5 | using ShellDll; 6 | using System.Reflection; 7 | using System.Windows.Forms; 8 | using System.IO; 9 | using System.Globalization; 10 | using System.Security.Policy; 11 | using System.Drawing; 12 | using System.ComponentModel; 13 | 14 | namespace EasyExplorer 15 | { 16 | public class BrowserPluginWrapper : Component 17 | { 18 | #region Fields 19 | 20 | private ArrayList columnPlugins; 21 | private ArrayList viewPlugins; 22 | private ArrayList contextPlugins; 23 | 24 | #endregion 25 | 26 | public BrowserPluginWrapper() 27 | { 28 | columnPlugins = new ArrayList(); 29 | viewPlugins = new ArrayList(); 30 | contextPlugins = new ArrayList(); 31 | 32 | LoadPlugins(); 33 | } 34 | 35 | private void LoadPlugins() 36 | { 37 | string pluginPath = Application.StartupPath + @"\plugins"; 38 | 39 | if (Directory.Exists(pluginPath)) 40 | { 41 | string[] files = Directory.GetFiles(pluginPath, "*.dll"); 42 | 43 | foreach (string file in files) 44 | { 45 | try 46 | { 47 | Assembly plugin = Assembly.LoadFile(file); 48 | 49 | Type[] types = plugin.GetTypes(); 50 | 51 | foreach (Type type in types) 52 | { 53 | try 54 | { 55 | IBrowserPlugin browserPlugin = 56 | plugin.CreateInstance(type.ToString()) as IBrowserPlugin; 57 | 58 | if (browserPlugin != null) 59 | { 60 | if (browserPlugin is IColumnPlugin) 61 | columnPlugins.Add(browserPlugin); 62 | 63 | if (browserPlugin is IViewPlugin) 64 | viewPlugins.Add(browserPlugin); 65 | 66 | //if (browserPlugin is IContextPlugin) 67 | //contextPlugins.Add(browserPlugin); 68 | } 69 | } 70 | catch (Exception) { } 71 | } 72 | } 73 | catch (Exception) { } 74 | } 75 | } 76 | } 77 | 78 | #region Properties 79 | 80 | public ArrayList ColumnPlugins { get { return columnPlugins; } } 81 | public ArrayList ViewPlugins { get { return viewPlugins; } } 82 | public ArrayList ContextPlugins { get { return contextPlugins; } } 83 | 84 | #endregion 85 | } 86 | 87 | #region Plugins 88 | 89 | public interface IBrowserPlugin 90 | { 91 | string Name { get; } 92 | string Info { get; } 93 | } 94 | 95 | public interface IColumnPlugin : IBrowserPlugin 96 | { 97 | string[] ColumnNames { get; } 98 | 99 | HorizontalAlignment GetAlignment(string columnName); 100 | 101 | string GetFolderInfo(IDirInfoProvider provider, string columnName, ShellItem item); 102 | string GetFileInfo(IFileInfoProvider provider, string columnName, ShellItem item); 103 | } 104 | 105 | public interface IViewPlugin : IBrowserPlugin 106 | { 107 | string ViewName { get; } 108 | Control ViewControl { get; } 109 | 110 | void FolderSelected(IDirInfoProvider provider, ShellItem item); 111 | void FileSelected(IFileInfoProvider provider, ShellItem item); 112 | void Reset(); 113 | } 114 | 115 | /*public interface IContextPlugin : IBrowserPlugin 116 | { 117 | string MenuText { get; } 118 | Icon MenuIcon { get; } 119 | string MenuInfo { get; } 120 | 121 | string[] Extensions { get; } 122 | 123 | void MenuSelected(IFileInfoProvider2 streamProvider, IDirectoryInfoProvider2 storageProvider, ShellItem[] items); 124 | }*/ 125 | 126 | #region Provider Interfaces 127 | 128 | public interface IDirInfoProvider 129 | { 130 | ShellAPI.STATSTG GetDirInfo(); 131 | } 132 | 133 | public interface IFileInfoProvider 134 | { 135 | ShellAPI.STATSTG GetFileInfo(); 136 | Stream GetFileStream(); 137 | } 138 | 139 | public interface IDirectoryInfoProvider2 : IDirInfoProvider 140 | { 141 | IStorage GetDirInfo(ShellItem item); 142 | } 143 | 144 | public interface IFileInfoProvider2 : IFileInfoProvider 145 | { 146 | IStream GetFileInfo(ShellItem item); 147 | Stream GetFileStream(ShellItem item); 148 | } 149 | 150 | #endregion 151 | 152 | #endregion 153 | } 154 | --------------------------------------------------------------------------------