using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Threading;
using System.Runtime.InteropServices;
namespace abPlayer
{
public partial class frmFileSelector : Form
{
// API calls
[DllImport("coredll.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("coredll.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
// treeview root name
private const String ROOT_NAME = "My Device";
// selected book & files are returned in these
public ArrayList BookFiles = null;
public String DefaultBookName = "";
public frmFileSelector()
{
InitializeComponent();
// selected book & files are returned in these
BookFiles = new ArrayList();
}
// override the showdialog so we can do some prep
// first time only - we scan the directories and build the treeview
// on subsequnt call we initialize view
public new DialogResult ShowDialog()
{
// reset book name & files
BookFiles.Clear();
DefaultBookName = "";
// clear files
lvw.Items.Clear();
// erase book count display
spl.Refresh();
chkRec.Checked = false;
// no treeview entries? - this is the first call - build treeview
if (tvw.Nodes.Count == 0)
{
// this may take time - show wait cursor
Cursor.Current = Cursors.WaitCursor;
tvw.BeginUpdate();
// create root node
TreeNode node = tvw.Nodes.Add(ROOT_NAME);
// add subdirs - this is a recursive function and is re-called
// for every directory found until all have been scanned
AddDirs(node);
tvw.EndUpdate();
// expand root
node.Expand();
// change cursor back to normal
Cursor.Current = Cursors.Default;
}
return base.ShowDialog();
}
// since we have a fictitios root we need to override the default
// fullpath function to return a legitimate path
String FullPath(TreeNode node)
{
return (node.Text == ROOT_NAME) ? "\\" : node.FullPath.Substring(ROOT_NAME.Length);
}
// recursive function that reads all the subdirectories of a given
// directory and adds them to the treeview. the node parameter is
// the directory/node to be scanned
private void AddDirs(TreeNode node)
{
// holds the directories we find
String[] dirs = new string[0];
// sub-node
TreeNode sNode = null;
// get subdirs
try
{
dirs = Directory.GetDirectories(FullPath(node));
}
catch { }
// sort them
Array.Sort(dirs);
foreach (String dir in dirs)
{
// use the file name of the path as treenode name
sNode = node.Nodes.Add(new FileInfo(dir).Name);
// image - directory
sNode.ImageIndex = 0;
sNode.SelectedImageIndex = 1;
// go do it now for the newly found dir
AddDirs(sNode);
}
}
// when a treenode is selected - we display the media files in it
// in the listview
private void tvw_AfterSelect(object sender, TreeViewEventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
lvw.BeginUpdate();
// clear all previous files
lvw.Items.Clear();
// clear result set
BookFiles.Clear();
// if a treenode is selected - go fetch the files
if(e.Node != null)
if (e.Node.IsSelected)
ShowFiles(FullPath(e.Node));
// show file count
spl.Refresh();
lvw.EndUpdate();
Cursor.Current = Cursors.Default;
}
// scan a directory (path) find media files and add to listview
// this is a recursive function that may be called for all
// subdirectories if relevant chekbox is checked
private void ShowFiles(String path)
{
// get files
String[] files = GetMediaFiles(path);
// sort
Array.Sort(files);
foreach (String file in files)
{
// extract file name from path
// add to listview
ListViewItem item = lvw.Items.Add(new ListViewItem(new FileInfo(file).Name));
// set image index
item.ImageIndex = 2;
// default state is checked (included)
item.Checked = true;
// add files to result set
BookFiles.Add(file);
}
// subdirs are to scanned:
if (chkRec.Checked)
{
// get subdirs
String[] dirs = Directory.GetDirectories(path);
// sort
Array.Sort(dirs);
// repeat scan for all found subdirs
foreach (String dir in dirs)
ShowFiles(dir);
}
}
public String[] GetMediaFiles(String path)
{
// audio files supported by WMP
String[] MEDIA_FILES = {"*.mp3", "*.wav", "*.snd", "*.wma", "*.mid"};
ArrayList files = new ArrayList();
foreach (String pattern in MEDIA_FILES)
{
try
{
files.AddRange(Directory.GetFiles(path, pattern));
}
catch (Exception e)
{
MessageBox.Show("File System Error : " + e.Message);
}
}
return (String[])files.ToArray(typeof(String));
}
// use splitter as a paint area to display file count
private void spl_Paint(object sender, PaintEventArgs e)
{
// erase the whole control face with its backcolor
e.Graphics.FillRectangle(new SolidBrush(spl.BackColor), 0, 0,
spl.Width, spl.Height);
// draw rectangle around it
e.Graphics.DrawRectangle(new Pen(Color.Silver, 1),
new Rectangle(0, 0, spl.Width - 2, spl.Height - 2));
// if no files are displayed - we are done
if (lvw.Items.Count <= 0) return;
// set display string
String txt = lvw.Items.Count.ToString() + " Files";
// get string sizes
SizeF strWH = e.Graphics.MeasureString(txt, this.Font);
// display string in mid horizontal and vertical point
e.Graphics.DrawString(txt, this.Font, new SolidBrush(Color.White),
(spl.Width / 2 - strWH.Width / 2),
(spl.Height / 2 - strWH.Height / 2));
}
// user hit OK
private void btnOK_Click(object sender, EventArgs e)
{
FlashControl((Control)sender);
// only if a directory is selected
if (tvw.SelectedNode != null)
{
// bookfiles already holds all files, however, user might have
// deselected some/all
// remove deselected files from result set
bool found = false;
for (int i = 0; i < lvw.Items.Count; i++)
{
if (lvw.Items[i].Checked)
{
found = true;
break;
}
}
if (!found)
return;
for (int i = lvw.Items.Count - 1; i >= 0; i--)
{
if (!lvw.Items[i].Checked)
BookFiles.RemoveAt(i);
}
// directory name is default book name
DefaultBookName = tvw.SelectedNode.Text;
// go back
DialogResult = DialogResult.OK;
}
}
// user hit cancel
private void btnCancel_Click(object sender, EventArgs e)
{
FlashControl((Control)sender);
// reset result set
DefaultBookName = "";
BookFiles.Clear();
// go back
DialogResult = DialogResult.Cancel;
}
// draw pic pitton if skin load failed
public void Pic_Paint(object sender, PaintEventArgs e)
{
PictureBox obj = (PictureBox)sender;
if (obj.Image == null)
{
String str = (String)obj.Tag;
e.Graphics.FillRectangle(new SolidBrush(Color.White),
1, 1, obj.Width - 2, obj.Height - 2);
if (str.Length > 0)
{
float size = Font.Size + 1;
Font font;
SizeF strWH;
do
{
size--;
font = new Font(Font.Name, size, FontStyle.Bold);
strWH = e.Graphics.MeasureString(str, font);
} while (strWH.Width > obj.Width);
e.Graphics.DrawString(str, font, new SolidBrush(Color.Black),
(obj.Width - strWH.Width) / 2,
(obj.Height - strWH.Height) / 2);
}
}
}
// function used by the frmPlayer and this form to provide visual
// confirmation that a button (actually a picture box) was pressed:
public void FlashControl(Control Wnd)
{
// create a graphics object from the control's dc
IntPtr hDC = GetDC(Wnd.Handle);
Graphics dc = Graphics.FromHdc(hDC);
// paint the whole control area black
dc.FillRectangle(new SolidBrush(Wnd.BackColor), 0, 0,
Wnd.Width, Wnd.Height);
// allow effect to take place
Application.DoEvents();
// go sleep for a while (60 milliseconds)
Thread.Sleep(60);
// release resources
ReleaseDC(Wnd.Handle, hDC);
dc.Dispose();
// have the control re-paint itself
Wnd.Refresh();
}
private void chkRec_CheckStateChanged(object sender, EventArgs e)
{
tvw_AfterSelect(tvw, new TreeViewEventArgs(tvw.SelectedNode, TreeViewAction.Unknown));
}
private void picNone_Click(object sender, EventArgs e)
{
CheckItems(sender, false);
}
private void picAll_Click(object sender, EventArgs e)
{
CheckItems(sender, true);
}
private void CheckItems(object sender, bool Value)
{
FlashControl((Control)sender);
foreach (ListViewItem item in lvw.Items)
item.Checked = Value;
}
}
}