|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionI seem to spend a fair bit of time managing files on my PC and don't find Windows Explorer the easiest tool to use. The best file manager I have ever used came with a DOS program called Brooklyn Bridge, which sold me completely on the concept of dual panes. The files I want to copy/move are on the left, the place I want to move them to is on the right. Mark the files, press the right keys (no menus in those days) and job done. Unfortunately it is not Y2K compliant and I haven't been able to find an alternative that I can get on with. I also like to keep notes about files, so I can remind myself what they are, and I also want the ability to search those notes for a file I “know” that I have somewhere. Although this is possible in Explorer, I prefer those notes to be in my database so I can back it up and re-use it after a re-install. Having tried several file managers, none seemed to do what I wanted so I took the plunge and wrote my own. This project is the result, it is not the first attempt, it's probably not the one hundredth attempt, but it's the one that works and doesn't (seem to) leak memory. NET and Files/FoldersThere are several classes in .NET relating to file/folder handling, and the Application StructureAt the top level, there is a Windows Form - In turn, the Speed of ApplicationI was anxious to ensure the program ran at a reasonable speed. The first obvious bottleneck was getting the drive information which is used three times in each of the The second bottleneck was setting the When you close the AcknowledgementsProgramming is a hobby for me. I have had a lot of help from various people over the years, generously and freely given, for which I am grateful. I have acknowledged specific contributions in the source code. Using the CodeI have tried to document the code as completely as possible, as it stands this is a complete application but there may be useful bits that can be pulled out and used in other projects. Class ExampleThis is the using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace JFileManager
{
/// <summary>
/// Provides additional information about drives
/// </summary>
public class cJDriveInfo
{
public string DisplayName = "";
public string Path = "";
public ObjectType ObjectType = ObjectType.DRIVE;
public DriveType DriveType = DriveType.Unknown;
public string TypeName = "";
public int IconIndex = 0;
public int SelectedIconIndex = 0;
public long TotalSize = 0L;
public long AvailableFreeSpace = 0L;
public Image Image = null;
public bool IsReady = false;
public int Mask;
public int StateMask;
public int State;
public bool HasChildren = false;
public string VolumeLabel = "";
public int Index;
public cJDriveInfo(string strPath)
: this(new DriveInfo(strPath))
{
}
public cJDriveInfo(DriveInfo drivInfo)
{
this.Path = drivInfo.RootDirectory.ToString();
this.DriveType = drivInfo.DriveType;
this.IsReady = drivInfo.IsReady;
this.GetSHFileInfo();
// We won't get this info if drive is not ready
try
{
this.TotalSize = drivInfo.TotalSize;
this.AvailableFreeSpace = drivInfo.AvailableFreeSpace;
// Display Name
this.VolumeLabel = drivInfo.VolumeLabel;
string strDrive = drivInfo.RootDirectory.ToString().Replace("\\", "");
this.DisplayName = this.VolumeLabel + " (" + strDrive + ")";
}
catch
{
this.TotalSize = 0L;
this.AvailableFreeSpace = 0L;
}
// Image Masks
cCommon.GetLVImageMask(this.Path, out this.Mask, out this.StateMask,
out this.State);
// Sub-folders
this.HasChildren = (cCommon.DirectorySubFolderCount(this.Path) > 0);
}
private void GetSHFileInfo()
{
SHFILEINFO shfi = new SHFILEINFO();
UInt32 uFlags = (UInt32)(SHGFI.SHGFI_ICON | SHGFI.SHGFI_SMALLICON |
SHGFI.SHGFI_TYPENAME | SHGFI.SHGFI_ADDOVERLAYS |
SHGFI.SHGFI_SYSICONINDEX | SHGFI.SHGFI_DISPLAYNAME);
IntPtr ipTemp = cCommon.SHGetFileInfo(this.Path, 0, out shfi,
Marshal.SizeOf(shfi), uFlags);
// Check result
if (ipTemp != IntPtr.Zero)
{
this.DisplayName = shfi.szDisplayName;
this.TypeName = shfi.szTypeName;
this.IconIndex = shfi.iIcon;
this.Image = cCommon.ImageFromIcon(shfi.hIcon);
}
if (shfi.hIcon != IntPtr.Zero)
cCommon.DestroyIcon(shfi.hIcon);
// Selected Icon
uFlags = (uint)(SHGFI.SHGFI_ICON | SHGFI.SHGFI_SMALLICON |
SHGFI.SHGFI_ADDOVERLAYS | SHGFI.SHGFI_SYSICONINDEX |
SHGFI.SHGFI_OPENICON);
ipTemp = cCommon.SHGetFileInfo(this.Path, 0, out shfi,
Marshal.SizeOf(shfi), uFlags);
if (ipTemp != IntPtr.Zero)
{
this.SelectedIconIndex = shfi.iIcon;
}
if (shfi.hIcon != IntPtr.Zero)
cCommon.DestroyIcon(shfi.hIcon);
}
}
}
As you can see, its properties are obtained partly from the inbuilt Memory LeaksUsing the API means moving out of the shelter of .NET’s memory management. I learnt (not quickly I have to confess) to read the help that comes with Visual Studio, especially when using the API! If Whoops! My fault, I really should read the help more closely. I hope that I have picked up all the memory issues now. History
|
||||||||||||||||||||||