HotDog's Blog

Hotdog (Robert Verpalen) about C# and vb.net

This blog hosted by:
http://blogs.vbcity.com      
  Home :: Syndication  :: Login

JunJuly 2008Aug
SMTWTFS
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

Articles

Archives

Topics

CONTACT

Fun but useful linkies

General

VS 2005

Wolfenstein ET

The .net framework of course has the openfiledialog and savefiledialog components build in which do all the rough work. Also the AutoComplete source in .net 2.0 makes it very easy to use the file system as an auto complete source.
However, manually assigning those each time, adding a button to browse, etc. got a bit tiresome. Hence time for a little control.
The class below is a simple control that uses autocompletion and/or a browsebutton to get input for a file (with the option to switch between save mode or open mode).

Update 16-3 : drop functionality. Dropping from explorer and the likes was easy enough. The framework has good implementations for that, but outlook attachments was a bit harder: http://blogs.vbcity.com/hotdog/archive/2006/03/16/5896.aspx

Update 18-3: icon is shown as well.

Code listing:
NB: as the comments in top of the code mention you need the 2 other classes to have this function right. Those blocks are build up, so you only have to copy and paste them underneath (or above) this class and you're good to go. Sorry for the inconvenience, but if I would have added them here, it would have been too difficult in maintenance :-/  The classes are
http://blogs.vbcity.com/hotdog/archive/2006/03/16/5896.aspx and http://blogs.vbcity.com/hotdog/archive/2006/03/07/5873.aspx

Code CopyHideScrollFull

namespace
Subro.Controls
{
/*
* For complete functionality, you need these 2 components (if not added allready)
* the OutlookDropCatcher: http://blogs.vbcity.com/hotdog/archive/2006/03/16/5896.aspx
* the fileextension class: http://blogs.vbcity.com/hotdog/archive/2006/03/07/5873.aspx
*
*/

using
System;
using
System.Text;
using
System.Windows.Forms;
using
System.ComponentModel;
using
System.IO;
using
Subro.IO;
using
System.Drawing;
using
Subro.Outlook;
///
///
Control to quickly select files
///

[DefaultProperty("FileName")]
[DefaultEvent("FileNameChanged")]
public
class FileSelect : UserControl, INotifyPropertyChanged
{
#region Constructor
///
Source : http://blogs.vbcity.com/hotdog/archive/2006/03/03/5861.aspx
///

private
FileBox txtFile;
private
BrowseButton btn = new BrowseButton();
public
FileSelect()
{
CreateTextBox();
btn.Bounds = new Rectangle(Width - btn.Width - pad, pad, btn.Width, Height - 2 * pad-1);
btn.Anchor = AnchorStyles.Right | AnchorStyles.Top;
Controls.Add(btn);
btn.Click += new EventHandler(btn_Click);
base
.AllowDrop = true;
file.FileChanged += new EventHandler(file_FileChanged);
}
#endregion
#region textbox
const
int pad = 2;
void
CreateTextBox()
{
txtFile = new FileBox(this);
SetControl(txtFile);
}
class
FileBox : TextBox
{
readonly FileSelect owner;
public
FileBox(FileSelect Owner)
{
this.owner = Owner;
AutoCompleteMode = AutoCompleteMode.SuggestAppend;
AutoCompleteSource = AutoCompleteSource.FileSystem;
AutoSize = false;                
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
UserPaint = true;
}
protected
override void OnValidated(EventArgs e)
{
owner.EndEditCurrentFile();
base
.OnValidated(e);
}
protected
override void OnPaint(PaintEventArgs e)
{
owner.file.DrawFile(e.Graphics, DisplayRectangle, Font,true);
base
.OnPaint(e);
}
   
protected override void OnDoubleClick(EventArgs e)
{
SelectAll();
base
.OnDoubleClick(e);
}
bool
UserPaint
{
set
{
SetStyle(ControlStyles.UserPaint, value);
}
}
protected
override void OnEnter(EventArgs e)
{
base.OnEnter(e);
SelectAll();
UserPaint = false;
}
protected
override void OnLeave(EventArgs e)
{
UserPaint = true;
base
.OnLeave(e);
}           
}
#endregion
#region ListView (used for detailed and MultiSelect view)
FileList list;
class
FileList : ListBox
{
public FileList(FileSelect owner)
{
this.DrawMode = DrawMode.OwnerDrawFixed;
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
FileData data = Items[e.Index] as FileData;
if
(data == null)
{
Font f = new Font(Font, FontStyle.Italic | FontStyle.Underline);
e.Graphics.DrawString("New", f, Brushes.Blue, 0, 0);
}
else
data.DrawFile(e.Graphics, e.Bounds, e.Font, true);
base.OnDrawItem(e);
}
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
}
}
#endregion
#region Keys
protected
override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.F3)
{
Browse();
return
true;
}
if
(keyData == Keys.Enter)
{
EndEditCurrentFile();
}
return
base.ProcessCmdKey(ref msg, keyData);
}
#endregion
#region properties
private
FileData file = new FileData();
[Description("The current file name")]
[SettingsBindable(true)]
[DefaultValue(null)]
public
string FileName
{
get { return file.FileName; }
set

{
file.FileName = value;
}
}
void file_FileChanged(object sender, EventArgs e)
{
txtFile.Text = file.FileName;
OnPropertyChanged("FileName", FileNameChanged);
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public
FileData Info
{
get { return file; }
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public
string Folder
{
get { return file.Folder; }
set

{
file.Folder = value;
}
}
public
event EventHandler FileNameChanged;

void EndEditCurrentFile()
{
FileName = txtFile.Text;
}

///
///
Returns if the selected file exists
///

public
bool IsValid
{
get
{
return file.IsValid;
}
}
[DefaultValue(true)]
[Description("If true (Default) the user can type in files manually. If false, only the dialog (browse button) can be used")]
public
bool AllowTextEdit
{
get { return !txtFile.ReadOnly; }
set

{
if (value == AllowTextEdit) return;
txtFile.ReadOnly = !value;
txtFile.BackColor = value ? Color.Empty : Color.White;
OnPropertyChanged("AllowTextEdit", null);
}
}
private
bool savemode;
[DefaultValue(false)]
[Description("The mode the file dialog is used. If this value is true, a savedialog is used, if false (default) an open dialog is used")]
public
bool SaveMode
{
get { return savemode; }
set

{
if (savemode == value) return;
savemode = value;
fd = null;
OnPropertyChanged("SaveMode", null);
}
}
string
filter;
[DefaultValue(null)]
public
string Filter
{
get
{
return filter;
}
set

{
if (value != null && value.Trim().Length == 0)
value = null;
filter = value;
}
}
#endregion
#region Dialog
FileDialog
fd;
///

///
Gets the underlying .
///
The type of dialog depends on the setting
///

public
FileDialog FileDialog
{
get
{
if (fd == null)
fd = savemode ? (FileDialog)new SaveFileDialog() : new OpenFileDialog();
return fd;
}
}
///

///
Opens the browse dialog
///

public
void Browse()
{
if (file != null)
{
FileDialog.InitialDirectory = Folder;
if
(file.IsValid)
FileDialog.FileName = file.Info.Name;
}
fd.Filter = filter;
if
(fd.ShowDialog(this) == DialogResult.OK)
{
FileName = fd.FileName;
}
}
#endregion
#region Drag/drop
[DefaultValue(true)]
public
override bool AllowDrop
{
get
{
return base.AllowDrop;
}
set

{
base.AllowDrop = value;
}
}
protected
override void OnDragEnter(DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Link;
else if (e.Data.GetDataPresent(OutlookAttachmentDropCatcher.GroupIdentifier))
e.Effect = DragDropEffects.Copy;
base.OnDragEnter(e);
}


protected override void OnDragDrop(DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
AddFiles(
(string[])e.Data.GetData(DataFormats.FileDrop));
else if (e.Data.GetDataPresent(OutlookAttachmentDropCatcher.GroupIdentifier))
{
AddFiles(OutlookAttachmentDropCatcher.GetFiles(e));
}
base
.OnDragDrop(e);
}
#endregion
#region Selected files
public const int
DefaultHeightSingle = 20,
DefaultHeightMulti = 60;
///
///
more than 1?....
///
Not supported yet...
///

[DefaultValue(false)]
bool
MultiSelect
{
get
{
return list != null;
}
set

{
if (value == MultiSelect) return;
txtFile.Visible = !value;
if
(value)
{
list = new FileList(this);
SetControl(list);
if
(FileName != null)
list.Items.Add(file);
list.Items.Add("New");
}
else

{
list.Dispose();
list = null;
}
if
(DesignMode)
Height = value ? DefaultHeightMulti : DefaultHeightSingle;
}
}
void AddFiles(params string[] files)
{
if (files == null || files.Length == 0)
return;//FileName = null;
else if (MultiSelect)
{
list.Items.RemoveAt(list.Items.Count - 1);
foreach
(string s in files)
{
list.Items.Add(new FileData(s));
}
list.Items.Add("New");
}
else
FileName = files[0];
}
#endregion
#region Browse button
void
btn_Click(object sender, EventArgs e)
{
Browse();
txtFile.SelectAll();
txtFile.Focus();
}
class
BrowseButton : Button
{
public BrowseButton()
{
FlatStyle = FlatStyle.Flat;
TabStop = false;
BackColor = Color.LightGray;
}
protected
override Size DefaultSize
{
get
{
return new Size(18, 18);
}
}
protected
override void OnPaint(PaintEventArgs pevent)
{
base.OnPaint(pevent);
pevent.Graphics.DrawString("...", Font, Brushes.Black, 2, 0);
}
}
#endregion
#region Appearance
protected
override Size DefaultSize
{
get
{
return new Size(200, DefaultHeightSingle);
}
}
void SetControl(Control c)
{
if(c is TextBox)
(c as TextBox).BorderStyle = System.Windows.Forms.BorderStyle.None;
else
(c as ListBox).BorderStyle = System.Windows.Forms.BorderStyle.None;
//no docking used because the displayrectangle property uses the Padding property as well
c.Bounds = new Rectangle(pad, pad, Width - btn.Width - pad * 2 - 1, Height - pad * 2);
c.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
Controls.Add(c);
}
protected
override void OnPaint(PaintEventArgs e)
{
Rectangle r = DisplayRectangle;
ControlPaint
.DrawBorder3D(e.Graphics, r, bstyle);
}
static
Border3DStyle defaultBorderStyle = Border3DStyle.Etched;
Border3DStyle
bstyle = defaultBorderStyle;
public
new Border3DStyle BorderStyle
{
get { return bstyle; }
set

{
bstyle = value;
Invalidate();
}
}
bool
ShouldSerializeBorderStyle()
{
return BorderStyle != defaultBorderStyle;
}
[Browsable(false)]
public
override Color BackColor
{
get
{
return Color.White;
}
set
{ }
}
bool
ShouldSerializeBackColor()
{
return false;
}
#endregion
#region INotifyPropertyChanged Members
public
event PropertyChangedEventHandler PropertyChanged;
void
OnPropertyChanged(string Name, EventHandler ChangedHandler)
{
if (ChangedHandler != null)
ChangedHandler(this, EventArgs.Empty);
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(Name));
}
#endregion
}

}
. . .
posted on Friday, March 03, 2006 2:38 AM