December 2, 2007

Pattern for Detecting Object Leaks

A simple method
// Add these to the class
private static int instanceId = 1;
private int instance = 1;

// Call this within the contructor
public SetObjectInstance(...)
{
    instance = instanceId;
    instanceId++;
    Debug.WriteLine("XXX instance \'" +
        instance.ToString() + "\' constructed");
}

// Within the finalizer OR if the object does not have a Finalizer add one
~XXX()
{
    Debug.WriteLine("XXX instance \'" + instance.ToString() + 
     "\' finalized");
}

Deploying Unmanaged DLLs

Found this neat trick here Nice idea. Tried it and it works. Heres my version of the resource extractor:
public static class ResourceExtractor
{
    public static void ExtractResourceToFile(
      string resourceName, 
      string filename)
    {
        if (System.IO.File.Exists(filename))
        {
            System.IO.File.Delete(filename);
        }
        if (!System.IO.File.Exists(filename))
        {
            using (System.IO.Stream s = System.Reflection.Assembly.
               GetExecutingAssembly().GetManifestResourceStream(resourceName))
            {
                using (System.IO.FileStream fs = new System.IO.
                            FileStream(filename, System.IO.FileMode.Create))
                {
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, b.Length);
                    fs.Write(b, 0, b.Length);
                }
            }
        }
    }
}

November 25, 2007

Using HelpRequested

The following will get help related to the control which has the mouse over it by pressing the F1 button

this.HelpRequested += new HelpEventHandler(this.XXXDialog_HelpHandler);
...
private void XXXDialog_HelpHandler(
  object sender, HelpEventArgs helpEvent)
{
  if (helpEventHandler != null)
  {
    Point pt = this.PointToControl(e.MousePos);
    Control control = this.GetChildAtPoint(pt);
    
    GetHelpOn(control);

    helpEvent.Handled = true;
  }
}

c# Printing

See this link C# Printing

CultureInfo, DateSeparator and TimeSeparator

CultureInfo ci = new CultureInfo("de-DE");
string dateSep = CultureInfo.CurrentCulture.DateTimeFormat.DateSeparator;
string timeSep = CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator;

Using the Params keyword

string[] ReplaceInStrings(char oldchar, char newchar, params string[] src)
{
    string[] res = new string[src.Length];
    int ix = 0;
    foreach (string targ in src)
    {
        res[ix++] = targ.Replace(oldchar, newchar);
    }
    return res;
}
The nice thing about the use of the 'params' keyword is that it can take an array parameter directly or a series of the specified type. It can even work with no parameters of the specified type. The following code demonstrates this behaviour
private void ParamsTest()
{
    string[] res;
    string[] strings = new string[] { "Some_string", "Another_string"};
    // Pass an array directly
    res = ReplaceInStrings('_', ' ', strings); 
    // Pass a series of objects of the specified type, this is automatically
    // converted to an array
    res = ReplaceInStrings('_', ' ', "This_string", "That_string", "Unchanged"); 
    // Pass a single object of the specified type
    res = ReplaceInStrings('_', ' ', "A_Single_string"); 
    // Pass NO objects of the specified type!
    // This still works an empty array is passed into the routine
    res = ReplaceInStrings('_', ' '); 

}
can it be used on a remoting interface?

Flags Based Enumerated Types

An extension class that extends a flag based enumerated type with set/group theory type operations. See FileAttributesExtender for a usage of this class.
public partial class EnumFlagsForm : Form
{
    [Flags]
    public enum EnumFlags
    {
        None = 0,
        Emergency_Stop = 0x1,
        Greasey = 0x2,
        Spot_Spot = 0x4,
        Doughnuts = 0x8,
        Lift_Moving = 0x10,
        Doors_Open = 0x20,
        Forbidden = 0x40
    }

//SourceTypes sourceTypes;
public static class EnumFlagsExtender
{
 // Return lhs flags plus rhs flags
 public static EnumFlags Union(this EnumFlags lhs, EnumFlags rhs)
 {
  return lhs | rhs;
 }

 // Return flags common to lhs and rhs
 public static EnumFlags Intersection(this EnumFlags lhs, EnumFlags rhs)
 {
  return lhs & rhs;
 }

 // Return lhs flags minus rhs flags
 public static EnumFlags Subtract(this EnumFlags lhs, EnumFlags rhs)
 {
  EnumFlags common = lhs & rhs;
  int res = (int)lhs - (int)common;
  return (EnumFlags)(res);
 }

 // Return true if lhs contains all the flags within rhs
 public static bool Contains(this EnumFlags lhs, EnumFlags rhs)
 {
  EnumFlags common = lhs & rhs;
  return (common == rhs);
 }

 // Return true if lhs contains one of the flags within rhs
 public static bool ContainsOneOf(this EnumFlags lhs, EnumFlags rhs)
 {
  EnumFlags common = lhs & rhs;
  return ((int)common > 0);
 }

 
 // NON-extension methods here

 public static EnumFlags FromString(string source)
 {
  EnumFlags res = (EnumFlags)Enum.Parse(typeof(EnumFlags), source, true);
  return res;
 }

    }

    public void Test1()
    {
      EnumFlags test = EnumFlags.Lift_Moving |
          EnumFlags.Doors_Open | EnumFlags.Doughnuts;
      string str = test.ToString();
      //str = str.Replace('_', ' ');
      Debug.WriteLine(str);
      EnumFlags newtest = EnumFlagsExtender.FromString(str);
      Debug.Assert(newtest == test);      
    }

public void EnumFlagsSubtractTest()
{
    EnumFlags test1 = EnumFlags.Lift_Moving | EnumFlags.Doors_Open |
        EnumFlags.Doughnuts | EnumFlags.Emergency_Stop;
    EnumFlags test2 = EnumFlags.Lift_Moving | EnumFlags.Forbidden |
        EnumFlags.Emergency_Stop;
    EnumFlags expected = EnumFlags.Doors_Open | EnumFlags.Doughnuts;
    EnumFlags outcome = test1.Subtract(test2);
    Debug.Assert(outcome == expected);

    expected = EnumFlags.Doors_Open | EnumFlags.Doughnuts | EnumFlags.Greasey;
    outcome = outcome.Union(EnumFlags.Greasey);
    Debug.Assert(outcome == expected);

    EnumFlags test3 = EnumFlags.Doughnuts | EnumFlags.Greasey;
    bool res = outcome.Contains(test3);
    Debug.Assert(res);
    
    res = outcome.Contains(EnumFlags.Lift_Moving | EnumFlags.Forbidden);
    Debug.Assert(!res);
}


    public EnumFlagsForm()
    {
        InitializeComponent();
        lbSourceTypes.Items.AddRange(
UnderscoresToSpaces(
Enum.GetNames(typeof(EnumFlags))));
        OnSelectedValueChanged(this, null);
    }

    string[] UnderscoresToSpaces(string[] src)
    {
        return ReplaceInStrings('_', ' ', src);
    }

    string[] SpacesToUnderscores(string[] src)
    {
        return ReplaceInStrings('_', ' ', src);
    }

    string SpacesToUnderscores(string src)
    {
        return src.Replace(' ', '_');
    }

    string[] ReplaceInStrings(char oldchar, char newchar, params string[] src)
    {
        string[] res = new string[src.Length];
        int ix = 0;
        foreach (string targ in src)
        {
            res[ix++] = targ.Replace(oldchar, newchar);
        }
        return res;
    }


    private void OnSelectedValueChanged(object sender, EventArgs e)
    {
        EnumFlags test = EnumFlags.None;
        foreach (string type in lbSourceTypes.SelectedItems)
        {
            test = EnumFlagsHelper.Add(test, 
EnumFlagsHelper.FromString(SpacesToUnderscores(type)));
        }
        tbSelected.Text = test.ToString();
        lblIsAudioAndVideo.Text = "WoopsTest() == " + 
(EnumFlagsHelper.WoopsTest(test)).ToString();
    }

    private void butTest_Click(object sender, EventArgs e)
    {
        Test1();
 
        EnumFlagsSubtractTest();
    }

}
Here is a visual studio code snippet for the enum extender
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
     <CodeSnippet Format="1.0.0">
          <Header><Title>Flags Enum Extender pattern</Title>
               <Description>Implement an extender for a 'Flags' type Enum. The extender adds set type methods to the enumertaion type</Description>
               <Keywords>
                   <Keyword>Enum</Keyword>
              </Keywords>
              <Author>Roger Bovill</Author>
         </Header>
         <Snippet>
         <Declarations> 
              <Literal Editable="true">
          <ID>EnumName</ID>
          <ToolTip>Name of the '[Flags]' based enumerated type</ToolTip>
    <Default>MyEnumType</Default>  
                <Function></Function>
             </Literal>
        </Declarations>
        <Code Language="CSharp">
            <![CDATA[

#region $EnumName$Extender

    public static class $EnumName$Extender
    {
        // Return lhs flags plus rhs flags
        public static $EnumName$ Union(this $EnumName$ lhs, $EnumName$ rhs)
        {
            return lhs | rhs;
        }

        // Return flags common to lhs and rhs
        public static $EnumName$ Intersection(this $EnumName$ lhs, $EnumName$ rhs)
        {
            return lhs & rhs;
        }

        // Return lhs flags minus rhs flags
        public static $EnumName$ Subtract(this $EnumName$ lhs, $EnumName$ rhs)
        {
            $EnumName$ common = lhs & rhs;
            int res = (int)lhs - (int)common;
            return ($EnumName$)(res);
        }

        // Return true if lhs contains all the flags within rhs
        public static bool Contains(this $EnumName$ lhs, $EnumName$ rhs)
        {
            $EnumName$ common = lhs & rhs;
            return (common == rhs);
        }

        // Return true if lhs contains one of the flags within rhs
        public static bool ContainsAnyOf(this $EnumName$ lhs, $EnumName$ rhs)
        {
            $EnumName$ common = lhs & rhs;
            return ((int)common > 0);
        }

        // NON-extension methods here

        public static $EnumName$ FromString(string source)
        {
            $EnumName$ res = ($EnumName$)Enum.Parse(typeof($EnumName$), source, true);
            return res;
        }

    }

#endregion $EnumName$Extender

            ]]>
        </Code>
       </Snippet>
    </CodeSnippet>
</CodeSnippets>

November 13, 2007

Web Colors

Web Colors

DateTime

Here are some links regarding DateTime string formatting and parsing: Truncating Milliseconds
private static DateTime TruncateMilliSeconds(DateTime dt)
{
  DateTime trunc = new DateTime(dt.Ticks - (10000*dt.Millisecond));
  Debug.Assert(trunc.Millisecond == 0);
  return trunc;
}
Parsing a date from a non standard form
DateTime.TryParseExact(dateStart, "yyyyMMdd",
  System.Globalization.CultureInfo.CurrentCulture,
  System.Globalization.DateTimeStyles.AssumeLocal, out m_StartDate);
Here is another example that will parse this string "Sun, 30 Jun 2013 14:14:01 +0100"
DateTime when = DateTime.MinValue;
string form = @"ddd, dd MMM yyyy HH':'mm':'ss K";
DateTime.TryParseExact(this.rawDateTime, form, 
  System.Globalization.CultureInfo.CurrentCulture,
  System.Globalization.DateTimeStyles.AssumeLocal, 
  out when);
Converting a date to a non standard string form
string datTimeStr = DateTime.UtcNow.ToString("yyyyMMdd"); 
where
M=month digit, y=year digit, d=day digit
h=hour digit, m=minute digit, s=second digit

Here is an example of this from renaming photos extracted from a digital camera
public class PhotoBackupOptions
{
    private string m_fileDateFormatStr = "yyyy_MMdd_HHmm";
    private string m_filenamePrefix = "Photo_";

    public string FileNameDateFormatStr
    {
        get { return m_fileDateFormatStr; }
    }

    public string FileNamePrefix
    {
        get { return m_filenamePrefix; }
    }

    public string GetPhotoFileName(FileInfo fsi)
    {
        Debug.Assert((fsi != null) && fsi.Exists);
        string res = fsi.Name;
        if (FileNameDateFormatStr.Length > 0)
        {
            DateTime dt = fsi.CreationTime;
            res = FileNamePrefix + 
                  dt.ToString(FileNameDateFormatStr) +
                  fsi.Extension;
        }
        return res;
    }
}
Here is a static method to load a date from a photo using WPF
// Retrieve the datetime from an image WITHOUT loading the whole thing
public static bool GetDateTakenFromImage(FileInfo fi, out DateTime dateTaken)
{
    dateTaken = DateTime.MinValue;
    bool found = false;
    try
    {
        using (FileStream fs = new FileStream(fi.FullName, 
            FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            BitmapMetadata md = (BitmapMetadata)BitmapFrame.Create(fs).Metadata;              
            found = DateTime.TryParse(md.DateTaken, out dateTaken);
        }
    }
    catch (Exception)
    {
        Trace.WriteLine("Could not get DateTaken from the image: \'" + fi.FullName + "\'");
    }
    return found;
}

C# SQL Update Key Value Type Table

// Updates a table called databaseTableName with columns 
// 'Key' and 'Value'. Its untested!
public void UpdateSettingValueEntry(
  string databaseTableName, string key, string value)
{
  private const string updateCommand = 
   "UPDATE {0} SET Value = @value WHERE Key = '{1}'"
  using (SqlConnection databaseConnection = 
         new SqlConnection(DatabaseConnectionString))
  {
    try
    {
      databaseConnection.Open();

      using (SqlCommand command = new SqlCommand())
      {
        command.Connection = databaseConnection;
        command.CommandText = string.format(updateCommand, 
              databaseTableName, key);
        command.Parameters.AddWithValue("@value", value);
        Debug.Trace("SQL({0})", command.CommandText);
        int rows = command.ExecuteNonQuery();
        if (rows == 1)
        {
           Debug.WriteLine("Updated key \'" + key + 
              "\' to value of \'" +
               value + "\'");
        }
        else
        {
          HandleError("Updated key \'" + key + 
           "\' to value of \'" + value + 
           "\' returned unexpected row count of \'" +
           rows + "\'");
        }
        if (rows < 1)
        {
          HandleUpdateError(xxx);
        }
      }
    }
    catch (SqlException se)
    {
      HandleException(se);
    }
  }
}

C# SQL Update, Insert, Read, Delete

public void UpdateXXXs(XXX[] xxxs)
{
    using (SqlConnection databaseConnection = 
       new SqlConnection(DatabaseConnectionString))
    {
        try
        {
            databaseConnection.Open();
            SqlTransaction trans = 
              databaseConnection.BeginTransaction();

            // One strategy is to delete the whole table 
            // and then recreate with the new rows
            // it depends on how big the table is. This is 
            // not practical with a very large table
            DeleteXXXTable(databaseConnection, trans);
            foreach (XXX xxx in xxxs)
            {
                InsertXXX(databaseConnection, trans, xxx);
            }
            trans.Commit();
        }
        catch (SqlException se)
        {
            trans.Rollback();
            HandleException(se);
        }
    }
}


private void InsertXXX(SqlConnection databaseConnection,
    SqlTransaction trans, XXX xxx)
{
    try
    {
      using (SqlCommand sqlCommand = databaseConnection.CreateCommand())
      {
        command.Connection = databaseConnection;
        command.Transaction = trans;
        command.CommandText = "INSERT INTO [XXXTable] " + 
            "([field1], [field2]) VALUES " + 
            "(@field1, @field2)";
        command.Parameters.AddWithValue("@field1", xxx.field1);
        command.Parameters.AddWithValue("@field2", xxx.field2);
        Debug.Trace("SQL({0})", command.CommandText);
        int rows = command.ExecuteNonQuery();
        if (rows < 1)
        {
            trans.Rollback();
            HandleInsertError(xxx);
        }
      }
    }
    catch (SqlException se)
    {
        trans.Rollback();
        HandleException(se);
    }
}

public XXX[] ReadSomeDatabaseTable()
{
  List xxxList = new List();

  using (SqlConnection databaseConnection = 
    new SqlConnection(SomeConnectionString))
  {
    try
    {
      databaseConnection.Open();

      using (SqlCommand command = new SqlCommand())
      {
        command.Connection = databaseConnection;
        command.CommandText = "SELECT * FROM [XXXTable] ";

        using (SqlDataReader reader = command.ExecuteReader())
        {
          if (reader != null)
          {
            while (reader.HasRows && reader.Read())
            {
              string field1 = reader.GetString(0).Trim();
              string field2 = reader.GetString(1).Trim();
              XXX xxx = new XXX(field1, field2);
              xxxList.Add(xxx);
            }
          }
        }
      }
    }
    catch (SqlException se)
    {
        HandleException(se);
    }
  }
  return xxxList.ToArray();
}

private void DeleteXXXTable(SqlConnection databaseConnection,
    SqlTransaction trans)
{
    try
    {
      using (SqlCommand command = databaseConnection.CreateCommand())
      {
        command.Connection = databaseConnection;
        command.Transaction = trans;
        command.CommandText = "DELETE FROM [XXXTable];";
        command.ExecuteNonQuery();
      }  
    }
    catch (SqlException se)
    {
        trans.Rollback();
        HandleException(se);
    }
}

November 4, 2007

Using KeyDown Event On A Grid/List Control

This code adds keyboard handling to a grid or list control. The Delete Key performs a Delete, the Insert Key performs an Insert, the Return Key performs a an edit when a single row is selected

private void xxxxxxxxxxxxx_KeyDown(object sender, KeyEventArgs e)
{
   switch (e.KeyCode)
   {
       // Delete with one or more rows selected 
       // performs a Remove on those rows
       case Keys.Delete: 
         e.Handled = true;
         DeleteSelectedRows();
           break;
       case Keys.Insert: // Insert performs an Add
         e.Handled = true;
         AddRow();
           break;
       // RETURN When a single row is selected 
       // perform an Edit, editing the currently 
       // selected row
       case Keys.Return: 
           
         e.Handled = true;
         EditSelectedRow());
           break;
       default:
           break;
   }
}

September 23, 2007

Test String Padding Functions

private static void TestPadding()
{
int ix = 0;
string result = string.Empty;
result = ix.ToString("X");
result = result.PadLeft(8, '0');
System.Diagnostics.Debug.Assert(result.Length == 8);
ix = 1;
result = ix.ToString("X");
result = result.PadLeft(8, '0');
System.Diagnostics.Debug.Assert(result.Length == 8);
ix = 9999;
result = ix.ToString("X");
result = result.PadLeft(8, '0');
System.Diagnostics.Debug.Assert(result.Length == 8);
ix = 99999999;
result = ix.ToString("X");
result = result.PadLeft(8, '0');
System.Diagnostics.Debug.Assert(result.Length == 8);
ix = int.MaxValue;
result = ix.ToString("X");
result = result.PadLeft(8, '0');
System.Diagnostics.Debug.Assert(result.Length == 8);
ix = int.MinValue;
result = ix.ToString("X");
result = result.PadLeft(8, '0');
System.Diagnostics.Debug.Assert(result.Length == 8);
}

Using The IComparer and IComparable Interfaces

Sorting and the IComparer and IComparable Interfaces
private class XXXComparer : IComparer
{
    public XXXComparer()
    {
    }

    #region IComparer Members

    public int Compare(IXXX x, IXXX y)
    {
        return x.SomeProperty.CompareTo(y.SomeProperty);
    }

    #endregion
}

Say you have a list of IXXX, you can sort it with this
m_XXX_List.Sort(new XXXComparer());

private class SomeObjectComparer : IComparer
{
 #region IComparer Members

 public int Compare(object x, object y)
 {
  IXXX xi = x as IXXX;
  IXXX yi = y as IXXX;

         return xi.SomeProperty.CompareTo(yi.SomeProperty);
 }

 #endregion
}


private class XXX : IComparable
{
    #region IComparable Members

    public int CompareTo(XXX other)
    {
        return this.SomeProperty.CompareTo(other.SomeProperty);
    }

    #endregion
}

Say you have a list of XXX, you can sort it with this
m_XXX_List.Sort();

// Simplest Enumerator. Can enumerate the objects without 
// exposing the underlying list
public IEnumerable Processes()
{
    foreach (IProcess process in m_Processes)
    {
       yield return process;
    }
}

Enable/Disable Form Close

This disables the system menu file close
        private const int SC_CLOSE = 0xF060;
        private const int MF_ENABLED = 0x0;
        private const int MF_DISABLED = 0x1;

        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        private static extern int EnableMenuItem(IntPtr hMenu, int wIDEnableItem, int wEnable);

        private void DisableFormClose()
        {
            EnableMenuItem(GetSystemMenu(this.Handle, false), SC_CLOSE, MF_DISABLED);
        }

        private void EnableFormClose()
        {
            EnableMenuItem(GetSystemMenu(this.Handle, false), SC_CLOSE, MF_ENABLED);
        }
Need to add something that disables the File Close menu

Iterating Over Dictionary Entries

Dictionary<string, XXX> m_MyDictionary = new Dictionary<string, XXX>()
foreach (KeyValuePair kvp in m_MyDictionary)
{
 DoSomething(kvp.Key);
 DoSomethingElse(kvp.Value);
}

How To: Hash Data with Salt

Sample is here

Using PInvoke

Check out the PInvoke website. Greate Site for finding PInvoke syntax for c# Calls to the WIN 32 API.

A Winforms CheckList

  • Check the StartPosition property is CenterParent
  • Check the Text property (the Title) is set to something sensible
  • IF it is a child window set the 'ShowInTaskbar' property to 'False'
  • Check FormBorderStyle property is set to 'FixedDialog' on the Form if it is non-resizable.
  • Check MaximiseBox property is set to 'True' on the Form if you want it
  • Check MinimiseBox property is set to 'True' on the Form if you want it
  • Check AcceptButton property is set on the Form to the 'default' accept/OK button
  • Check CancelButton property is set on the Form to the 'default' cancel changes button
  • IF you want the OK and cancel buttons to work automatically then set the DialogResult property of the button to Accept or Cancel etc.
  • Check the TAB order is set.
OR put these in the xxxForm.designer.cs file, in InitializeComponent() just before ResumeLayout(false);
    this.AcceptButton = this.NAME_OF_ACCEPT_OK_BUTTON;
    this.CancelButton = this.NAME_OF_CANCEL_BUTTON;
    this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
    this.MaximizeBox = false;
    this.MinimizeBox = false;
    this.ShowIcon = false;
    this.ShowInTaskbar = false;
    this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
    this.Text = "FORM TITLE";

C# Lists And Arrays

C# Arrays Comprehensive
C# Lists

Modal/Modeless Dialogs

Modal Dialog
    SomeForm sf = new SomeForm();
    DialogResult res = sf.ShowDialog(this);
To close a form
... // within the form class itself
    DialogResult = DialogResult.OK;
    Close();
...
Set the AcceptButton and CancelButton to the correct buttons if required Modeless Dialog
    // Declare the modeless dialog
    private MagnifyingGlassForm m_MagFrm = null;


    // Creating and showing the modeless dialog
    if (m_MagFrm == null)
    {
      m_MagFrm = new MagnifyingGlassForm();
      m_MagFrm.Owner = this; // IMPORTANT Set the owner of the modeless dialog 
      m_MagFrm.Show(); // Show the modeless dialog
    }

    ...

    // To just hide the modeless dialog use Hide() method
    m_MagFrm.Hide()

    ...

    // Terminating the Modeless Dialog
    if (m_MagFrm != null)
    {
      m_MagFrm.Close();
      m_MagFrm.Dispose();
      m_MagFrm = null;
    }

May 9, 2007

Using DataTables, DataSets and DataAdaptors

Why use a Dataset? Using summary ADO.NET Tutorial
// Use Visual Studio to generate the data set classes. Use 'Typed' datasets
//XXXDataSet m_XXXDataSet = new XXXDataSet();
// Create the data table and data adaptors
XXXDataSet.XXXDataTable m_XXXDataTable;
XXXDataAdapter m_XXXDataAdaptor = new XXXDataAdapter();

// Filling the dataset/datatable
m_XXXDataTable = m_XXXDataAdaptor.GetData();
//m_DataAdaptor.Fill(m_XXXDataSet.XXX);


//Dont forget to Dispose()
//m_XXXDataSet.Dispose();
m_XXXDataTable.Dispose();
m_XXXDataAdaptor.Dispose();


// Finding a record
//XXXDataSet.XXXRow lir = m_XXXDataSet.XXX.FindByName(requestor.ToLower());
XXXDataSet.XXXRow lir = m_XXXDataTable.FindByName(requestor.ToLower());

// ADD
//m_XXXDataSet.XXX.AddXXXRow(userName, password);
m_XXXDataTable.AddXXXRow(userName, password);
m_Dirty = true;

// DELETE
//m_XXXDataSet.XXX.RemoveXXXRow(lir);
m_XXXDataTable.RemoveXXXRow(lir);
lir.Delete();

// UPDATING the database
m_DataAdaptor.Update(m_XXXDataTable);
//m_DataAdaptor.Update(m_XXXDataSet);

Double Buffering in C# .Net

Double Buffering in Dot Net 2.0
More Double Buffering in Dot Net 2.0 - Check this out as well
bool m_Dirty = true;
Bitmap m_Bitmap;

~XXXCtrl()
{
    Dispose(false);
}

public void ChangeSomething(int xmin, int xmax)
{
    ...
    Dirty = true; // Regenerate the bitmap (during the paint cycle)
    Invalidate(); // Repaint
}


protected override void OnResize(EventArgs e)
{
    _DisposeBitmap();
    if ((ClientSize.Width > 0) && (ClientSize.Height > 0))
    {
        m_Bitmap = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
    }
    else
    {
        m_Bitmap = null;
    }
    Dirty = true;
    base.OnResize(e);
    Invalidate();
}


protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    Graphics gfx = e.Graphics;
    if (Dirty) 
    { // Only regenerate the bitmap when something has changed
        _RenderToBitmap();
        Dirty = false;
    }
    // Option 1:  Redraw entire bitmap
    //gfx.DrawRectangle(Pens.Red, e.ClipRectangle);
    //_DisplayBitmap(gfx, BitmapRect()); //
    // OR 
    // Option 2:  Redraw just the area that has changed           
    //Debug.WriteLine("Paint: e.ClipRectangle=" +
e.ClipRectangle.ToString());
    _DisplayBitmap(gfx, e.ClipRectangle); 
}


private void _DisplayBitmap(Graphics gfx, Rectangle clipRectangle)
{
    gfx.DrawImage(m_Bitmap, clipRectangle, clipRectangle, GraphicsUnit.Pixel);
}

// Draw the graphics onto a bitmap
private void _RenderToBitmap()
{
    using (Graphics gs = Graphics.FromImage(m_Bitmap))
    {
      _Render(gs, BitmapRect());
    }
}

private Rectangle BitmapRect()
{
    return new Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height);
}

// Here is the main graphics routine
private void _Render(Graphics ds, Rectangle area)
{
    // Draw rectangle around client rectangle and text in centre
    Rectangle rect = area;
    rect.Height -= 1;
    rect.Width -= 1;
    using (Brush brush = new SolidBrush(this.BackColor))
    {
        ds.FillRectangle(brush, rect);
    }
    ds.DrawRectangle(Pens.Black, rect);

    if ((area.Width > 25) && (area.Height > 10))
    {
        int xpos = 0;
        // Draw axis
        int x1 = area.Left + 20;
        int x2 = area.Right - 20;
        int ymid = (area.Height/2);
        ds.DrawLine(Pens.Black, new Point(x1, ymid), new Point(x2, ymid));

        ...        
    }
}

private bool Dirty
{
    get { return m_Dirty; }
    set { m_Dirty = value; }
}

private void _DisposeBitmap()
{
    if (m_Bitmap != null)
    {
        m_Bitmap.Dispose();
    }
}

and in the designer class

protected override void Dispose(bool disposing)
{
  if (disposing && (components != null))
  {
     components.Dispose();
  }

  _DisposeBitmap();

  base.Dispose(disposing);
}

April 13, 2007

Finding a Machine SID in C#

public static class MachineSidHelper
{

    private static SecurityIdentifier GetAccountSid(string localAdminAccount)
    {
        NTAccount name = new NTAccount(localAdminAccount);
        SecurityIdentifier sid = (SecurityIdentifier)name.Translate(typeof(SecurityIdentifier));
        return sid;
    }


    // Get the Machine Sid for the PC the code is currently executing on
    public static string MachineSid
    {
        get
        {
            string machineSid = string.Empty;
            string domain;
            short accounttype;
            try
            {
                LookupAccountName(Environment.MachineName, 
                   Environment.MachineName, out machineSid, 
                   out domain, out accounttype);
                System.Diagnostics.Debug.WriteLine("From LookupAccountName
(\'" + Environment.MachineName + "\',  \'" +
                    Environment.MachineName + "\', ...): " + machineSid);
            }
            catch (Exception)
            {
                System.Diagnostics.Trace.WriteLine(
"Can not get the Machine Identifier using \'LookupAccountName\'");
            }
            if (machineSid.Length < 1)
            {

                string account = Environment.MachineName + @"\Administrator";
                try
                {
                    SecurityIdentifier sid = GetAccountSid(account);
                    machineSid = sid.AccountDomainSid.ToString();
                    System.Diagnostics.Debug.WriteLine("From GetAccountSid(\'" + account +
                        "\'): " + machineSid);
                }
                catch (Exception)
                {
                    System.Diagnostics.Trace.WriteLine(
"Can not get the Machine Identifier using \'Administrator Sid\'");
                }
            }
            return machineSid;
        }
    }

    internal static bool LookupAccountName(string strServer, 
        string strAccountName, out string accountSid, 
        out string strDomainName, out short AccountType)
    {
        bool bRet = false;
        int lSidSize = 256;
        int lDomainNameSize = 256;

        accountSid = "";
        strDomainName = "";
        AccountType = 0;
        StringBuilder strName;
        lSidSize = 0;
        IntPtr Sid = IntPtr.Zero;

        // First get the required buffer sizes for SID and domain name.
        int nRet = Win32API.LookupAccountName(
                            strServer,
                            strAccountName,
                            Sid,
                            ref lSidSize,
                            null,
                            ref lDomainNameSize,
                            ref AccountType);
        bRet = (0 != nRet);
        if (!bRet)
        {
            int nErr = Marshal.GetLastWin32Error();
            if (122 == nErr) // Buffer too small
            {
                // Allocate the buffers with actual sizes that are required
                // for SID and domain name.
                strName = new StringBuilder(lDomainNameSize);
                Sid = Marshal.AllocHGlobal(lSidSize);
                nRet = Win32API.LookupAccountName(
                    strServer,
                    strAccountName,
                    Sid,
                    ref lSidSize,
                    strName,
                    ref lDomainNameSize,
                    ref AccountType);
                bRet = (0 != nRet);
                if (bRet)
                {
                    byte[] sidArray = new byte[lSidSize];
                    strDomainName = strName.ToString();
                    Marshal.Copy(Sid, sidArray, 0, lSidSize);
                    SecurityIdentifier sid = new SecurityIdentifier(sidArray, 0);
                    accountSid = sid.ToString();
                }
            }
            else
            {
                System.Diagnostics.Debug.WriteLine(nErr);
            }
        }
        Marshal.FreeHGlobal(Sid);
        return bRet;
    }


    private class Win32API
    {
        #region Win32 API Interfaces

        [DllImport("Advapi32.dll", SetLastError = true)]
        public static extern int LookupAccountName(
            string ServerName,
            string AccountName,
            IntPtr Sid,
            ref int SidSize,
            StringBuilder DomainName,
            ref int DomainNameSize,
            ref short SidUse);


        #endregion
    }
 
} 

Simple C# IEnumerable Samples

This example shows how the iterator can be exposed to allow an object to be iteratied in different ways, In this case a matrix type object can be iterated row by row or column by column. The advantage of the iterator is that it only gets a value when asked.

// Iterate column by column starting with Pin 1,1
public IEnumerable<Thing> ColumnByColum()
{
    Thing rcl = new Thing();
    for (int col = 0; col < Cols; col++)
    {
        for (int row = 0; row < Rows; row++)
        {
            rcl.Row = row + 1;
            rcl.Column = col + 1;
            yield return rcl;
        }
    }
}

// Iterate row by row starting with Pin 1,1
public IEnumerable<Thing> RowByRow()
{
    Thing rcl = new Thing();
    for (int row = 0; row < Rows; row++)
    {
        for (int col = 0; col < Cols; col++)
        {
            rcl.Row = row + 1;
            rcl.Column = col + 1;
            yield return rcl;
        }
    }
}


foreach (Thing thing in matrixThingey.ColumnByColum)
{
}
There are 2 yield statements:
  • "yield return XXX" returns an item.
  • "yield break" ends the iterator without returning any item. You can think of yield break as return statement which does not return a value.

Discarding Pending Mouse Or Keyboard Messages in C#

public static class Win32Helper
{

/// Window messages
private enum WindowMessage : uint
{
    // Keyboard messages
    KeyboardFirst = 0x0100,
    KeyboardLast = 0x0108,

    // Mouse messages
    //MouseMove = 0x0200,
    MouseFirst = 0x0201, // Skip mouse move, it happens 
                         //a lot and there is another message for that
    MouseLast = 0x020d,
}

public static void DiscardMousebMessages(IntPtr hWnd)
{
    Message msg;
    while (PeekMessage(out msg, hWnd, (uint)WindowMessage.MouseFirst,
        (uint)WindowMessage.MouseLast, (uint)PeekMessageFlags.PM_REMOVE)) ;
}

public static void DiscardKeyboardMessages(IntPtr hWnd)
{
    Message msg;
    while (PeekMessage(out msg, hWnd, (uint)WindowMessage.KeyboardFirst,
        (uint)WindowMessage.KeyboardLast, (uint)PeekMessageFlags.PM_REMOVE)) ;
}

[StructLayout(LayoutKind.Sequential)]
private struct Message
{
    public IntPtr hWnd;
    public WindowMessage msg;
    public IntPtr wParam;
    public IntPtr lParam;
    public uint time;
    public System.Drawing.Point p;
}

[System.Security.SuppressUnmanagedCodeSecurity] 
[DllImport("User32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage(
    out Message msg, IntPtr hWnd, 
    uint messageFilterMin, uint messageFilterMax, 
    uint flags);

}

January 29, 2007

C# SQL

SQL Dos and Donts
SQLDataAdapter without using SQLCommandBuilder. - Useful SQL sample
Data Access Strategies Using ADO.NET and SQL
Lesson 03: The SqlCommand Object - Simplest example possible to start using SqlCOnnection and SqlCommand

Here is some code to save to an SQL database:
using (SqlConnection connection = new SqlConnection(MYDATABASECONFIGURATION.ConnectionString))
{
    connection.Open();
    SqlTransaction sqlTransaction = connection.BeginTransaction();
    try
    {

        int outcome = SqlStoreSomething(connection, sqlTransaction, thingToStore);
        if (outcome == 1)
        {
            SqlStoreSomethingElse(connection, sqlTransaction, otherThingy);
        }
        else
        {
            throw new ApplicationException(msg);
        }
    }
    catch (Exception ex)
    {
        sqlTransaction.Rollback();
        throw ex;
    }
    sqlTransaction.Commit();
    sqlTransaction.Dispose();
    connection.Close();
}

private int SqlStoreThingey(
        SqlConnection connection,
        SqlTransaction sqlTransaction,
        SomeThingey thingey)
{
    int returnValue = 0;
    if ((thingey.Id == Guid.Empty))
    {
        throw new System.ArgumentOutOfRangeException("Id: " + thingey.Id.ToString());
    }
    if ((thingey.SomeRef == null))
    {
        throw new System.ArgumentNullException("SomeRef");
    }

    using (SqlCommand sqlCmd = new SqlCommand())
    {
        sqlCmd.Connection = connection;
        sqlCmd.Transaction = sqlTransaction;
        sqlCmd.CommandText =
            @"INSERT INTO [dbo].[MasterThingeyTable] ([Id], [SomeRef], [Date] " +
            @") VALUES (@Id, @SomeRef, @Date, )";
        sqlCmd.CommandType = System.Data.CommandType.Text;
        sqlCmd.Parameters.Add(new SqlParameter("@Id", System.Data.SqlDbType.UniqueIdentifier, 0, 

System.Data.ParameterDirection.Input, 0, 0, "Id", System.Data.DataRowVersion.Current, false, null, "", "", ""));
        sqlCmd.Parameters.Add(new SqlParameter("@SomeRef", System.Data.SqlDbType.NVarChar, 0, 

System.Data.ParameterDirection.Input, 0, 0, "SomeRef", System.Data.DataRowVersion.Current, false, null, "", "", ""));
        sqlCmd.Parameters.Add(new SqlParameter("@Date", System.Data.SqlDbType.DateTime, 0, 

System.Data.ParameterDirection.Input, 0, 0, "Date", System.Data.DataRowVersion.Current, false, null, "", "", ""));

        sqlCmd.Parameters[0].Value = ((System.Guid)(thingey.Id));
        sqlCmd.Parameters[1].Value = ((string)(thingey.SomeRef));
        sqlCmd.Parameters[2].Value = ((System.DateTime)(thingey.Date));

        returnValue = sqlCmd.ExecuteNonQuery();
    }
    return returnValue;
}

January 26, 2007

Simple Wizard Form

The SimpleWizardForm.designer.cs contenst are not here. Put 3 buttons on the Wizard form, 'butCancel', 'butPrevious' and 'butNext'. Use a 2 pixel high label control to get a bevel.

public partial class SimpleWizardForm : Form
{
    protected readonly string NEXT_BUT = @"&Next >";
    protected readonly string FINISH_BUT = @"Fi&nish";

    private Control[] panels;
    private readonly Size MaxPanelSize = new Size(590, 462);
    private readonly Point PanelOffset = new Point(0, 56);

    private int m_pos = 0;

    public SimpleWizardForm(Image img)
    {
        InitializeComponent();
        InitWizardImage(img);
    }

    private void InitWizardImage(Image img)
    {
        
    }

    // Takes an array or list or whatever of that are to 
    // be shown in the Wizard form. They are shown in the 
    // order that they are defined in the list.
    protected void Initialise(IList argPanels)
    {
        panels = new Control[argPanels.Count];
        int ix = 0;
        foreach (Control ctrl in argPanels)
        {
            panels[ix++] = ctrl;// Add the control to the wizard array
            System.Diagnostics.Debug.Assert(
                (ctrl.Size.Width < MaxPanelSize.Width) && 
                (ctrl.Size.Height < MaxPanelSize.Height),
                "Passed a control to the WizardForm which is larger in size (= " +
                ctrl.Size.ToString() + ") than the area available (=" +
                MaxPanelSize.ToString() + ") for showing panels!");                    
            this.Controls.Add(ctrl);
            ctrl.Location = new Point(
                PanelOffset.X + (MaxPanelSize.Width-ctrl.Width) / 2, 
                PanelOffset.Y + (MaxPanelSize.Height-ctrl.Height) / 2);
            ctrl.Visible = false; // All panels are invisible
        }

        m_pos = 0; 
        // Make first panel visible
        panels[m_pos].Visible = true;
        UpdatePrevNextButts();
    }

    private void butNext_Click(object sender, EventArgs e)
    {
        NextPanel();
        UpdatePrevNextButts();
    }

    private void butPrev_Click(object sender, EventArgs e)
    {
        PreviousPanel();
        UpdatePrevNextButts();
    }

    private void NextPanel()
    {
        // If this is the last panel
        if (m_pos == (panels.Length - 1))
        {
            // Close the dialog with a successful outcome
            this.DialogResult = DialogResult.OK;
            Close();
        }
        else
        {
            // Show the next panel
            panels[m_pos].Visible = false;
            m_pos = (m_pos + 1) % panels.Length;
            panels[m_pos].Visible = true;
        }
    }

    private void PreviousPanel()
    {
        panels[m_pos].Visible = false;
        m_pos = (m_pos + 1 + panels.Length) % panels.Length;
        panels[m_pos].Visible = true;
    }

    private void UpdatePrevNextButts()
    {
        if (IsLastPanel())
        {
            butNext.Text = FINISH_BUT; 
        }
        else
        {
            butNext.Text = NEXT_BUT; 
        }
        butPrev.Enabled = (!IsFirstPanel());
    }

    private bool IsLastPanel()
    {
        return m_pos == (panels.Length - 1);
    }

    private bool IsFirstPanel()
    {
        return (m_pos == 0);
    }

    private void butCancel_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.Cancel;
        Close();
    }
}
And the corresponding WizardForm.Designer.cs
partial class WizardForm
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; 

otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.bevelControl1 = new System.Windows.Forms.Label();
        this.butPrev = new System.Windows.Forms.Button();
        this.butNext = new System.Windows.Forms.Button();
        this.butCancel = new System.Windows.Forms.Button();
        
        this.SuspendLayout();
        // 
        // bevelControl1
        // 
        this.bevelControl1.Anchor = 

((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom 

| System.Windows.Forms.AnchorStyles.Left)
                    | System.Windows.Forms.AnchorStyles.Right)));
        this.bevelControl1.Location = new System.Drawing.Point(-26, 524);
        this.bevelControl1.Name = "bevelControl1";
        this.bevelControl1.Size = new System.Drawing.Size(645, 2);
        this.bevelControl1.TabIndex = 59;
        // 
        // butPrev
        // 
        this.butPrev.Anchor = 

((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | 

System.Windows.Forms.AnchorStyles.Left)));
        this.butPrev.Location = new System.Drawing.Point(299, 534);
        this.butPrev.Name = "butPrev";
        this.butPrev.Size = new System.Drawing.Size(75, 23);
        this.butPrev.TabIndex = 57;
        this.butPrev.Text = "< &Previous";
        this.butPrev.UseVisualStyleBackColor = true;
        this.butPrev.Click += new System.EventHandler(this.butPrev_Click);
        // 
        // butNext
        // 
        this.butNext.Anchor = 

((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | 

System.Windows.Forms.AnchorStyles.Left)));
        this.butNext.Location = new System.Drawing.Point(390, 534);
        this.butNext.Name = "butNext";
        this.butNext.Size = new System.Drawing.Size(75, 23);
        this.butNext.TabIndex = 56;
        this.butNext.Text = "&Next >";
        this.butNext.UseVisualStyleBackColor = true;
        this.butNext.Click += new System.EventHandler(this.butNext_Click);
        // 
        // butCancel
        // 
        this.butCancel.Anchor = 

((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | 

System.Windows.Forms.AnchorStyles.Left)));
        this.butCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
        this.butCancel.Location = new System.Drawing.Point(127, 534);
        this.butCancel.Name = "butCancel";
        this.butCancel.Size = new System.Drawing.Size(75, 23);
        this.butCancel.TabIndex = 58;
        this.butCancel.Text = "&Cancel";
        this.butCancel.UseVisualStyleBackColor = true;
        this.butCancel.Click += new System.EventHandler(this.butCancel_Click);
        // 
        // WizardForm
        // 
        this.AcceptButton = this.butNext;
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.CancelButton = this.butCancel;
        this.ClientSize = new System.Drawing.Size(593, 565);
        this.Controls.Add(this.panelBrandHeader);
        this.Controls.Add(this.bevelControl1);
        this.Controls.Add(this.butPrev);
        this.Controls.Add(this.butNext);
        this.Controls.Add(this.butCancel);
        this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
        this.MaximizeBox = false;
        this.MinimizeBox = false;
        this.Name = "XXXWizardForm";
        this.StartPosition = 

System.Windows.Forms.FormStartPosition.CenterParent;
        this.Text = "XXX Wizard Form";
        this.ResumeLayout(false);
        this.PerformLayout();

    }

    #endregion

    
    private System.Windows.Forms.Label bevelControl1;
    private System.Windows.Forms.Button butPrev;
    private System.Windows.Forms.Button butNext;
    private System.Windows.Forms.Button butCancel;
}

January 8, 2007

Simple Usage of OpenFileDialog and SaveFileDialog

OpenFileDialog
using (OpenFileDialog of = new OpenFileDialog())
{
  of.Title = "Open the XXX file";
  of.Filter = "XXX files (*.xxx)|*.xxx";
  // Optional: Set the initial directory to look in
  // if (Directory.Exists(someDir))
  //   of.InitialDirectory = someDir;
  // Optional: Set the initial filename
  // of.FileName = "???.exe";
  if (of.ShowDialog() == DialogResult.OK)
  {
    if (File.Exists(of.FileName))
    {
      DoReadFile(of.FileName); 
      // eg string someString = File.ReadAllText(of.FileName);
    }
  }
}
SaveFileDialog
private string GetSaveFileName()
{
  string fileName = string.Empty;
  
  // Create new SaveFileDialog object
  using (SaveFileDialog saveFileDlg = new SaveFileDialog())
  {

    saveFileDlg.SupportMultiDottedExtensions = true;

    // Default file extension
    saveFileDlg.DefaultExt = ".zip";

    // Set initial filename (file only NOT directory/path)
    saveFileDlg.FileName = "Changes." + DateTime.UtcNow.ToString("yyyyMMdd");

    // Available file extensions
    saveFileDlg.Filter = "Batch file (*.zip)|*.zip|All files (*.*)|*.*";

    // Adds a extension if the user does not
    saveFileDlg.AddExtension = true;

    // Restores the selected directory, next time
    //saveFileDlg.RestoreDirectory = true;

    // Dialog title
    saveFileDlg.Title = "Where do you want to save the 'zip' file?";

    // Startup directory
    //saveFileDlg.InitialDirectory = @"C:/";

    // Show the dialog and process the result
    if (saveFileDlg.ShowDialog() == DialogResult.OK)
    {
      if (File.Exists(saveFileDlg.FileName))
      {
         File.Delete(saveFileDlg.FileName);
      }
      fileName = saveFileDlg.FileName;
    }
  }
  return fileName;
}
SaveFileDialog Snippet
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Keywords>
        <Keyword>SaveFileDialog</Keyword>
      </Keywords>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
      <Title>SnippetFile1</Title>
      <Author>Roger</Author>
      <Description>SaveFileDialog</Description>
      <HelpUrl>
      </HelpUrl>
      <Shortcut>SaveFileDialog</Shortcut>
    </Header>
    <Snippet>
      <Declarations>
        <Literal Editable="true">
          <ID>bat</ID>
          <ToolTip>default file extension</ToolTip>
          <Default>txt</Default>
          <Function>
          </Function>
        </Literal>
      </Declarations>
      <Code Language="csharp"><![CDATA[        
private void SaveFileDialog(string text)
{
  // Create new SaveFileDialog object
  using (SaveFileDialog saveFileDlg = new SaveFileDialog())
  {

    saveFileDlg.SupportMultiDottedExtensions = true;

    // Default file extension
    saveFileDlg.DefaultExt = "$bat$";

    // Available file extensions
    saveFileDlg.Filter = "Batch file (*.$bat$)|*.$bat$|All files (*.*)|*.*";

    // Adds a extension if the user does not
    saveFileDlg.AddExtension = true;

    // Restores the selected directory, next time
    //saveFileDlg.RestoreDirectory = true;

    // Dialog title
    saveFileDlg.Title = "Where do you want to save the 'batch' file?";

    // Startup directory
    //saveFileDlg.InitialDirectory = @"C:/";

    // Show the dialog and process the result
    if (saveFileDlg.ShowDialog() == DialogResult.OK)
    {
      //SaveFileImplement(sf.FileName);
      if (!File.Exists(saveFileDlg.FileName))
      {
        File.WriteAllText(saveFileDlg.FileName, text);
      }
    }
  }
}
  ]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

Making a form a fixed sized dialog box without a Minimise or Maximise buttons

this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;

January 2, 2007

Creating A Temp File In The Temporary directory

Use a specific file name in the temporary directory:
private readonly string testPath = 
    Path.Combine(Path.GetTempPath(), "TestSerializer.xml");
Create a temporary file name in the temporary directory but with a specified extension:
public static class PathClassExtender
{
  public static string GetTempFileName(string newExtension)
  {
    string res = Path.ChangeExtension(Path.GetTempFileName(), newExtension);
    return res;
  }
}
Sample usage:
string filename = PathClassExtender.GetTempFileName(".bat");
filename will get set to something like
"C:\Users\RB\AppData\Local\Temp\tmp517F.bat"

Controlling TextBox Character Input

Good set opf samples
/// <summary>
/// Ensure only alpha numeric characters and
/// backspace are acceptable characters for the Thingey
/// </summary>
/// <param name="sender"></param>
/// <param name="kpea"></param>
private void OnSomeTextBox_KeyPressEvent(object sender, 
    KeyPressEventArgs kpea)
{
    const char BACKSPACE = '\b';
    const char FULLSTOP = '.';
    if (textBox.Text.Length > 0) // AFter first character
    {
        if ( !Char.IsLetterOrDigit(kpea.KeyChar) && 
            (kpea.KeyChar != BACKSPACE) && 
            (kpea.KeyChar != FULLSTOP))
        { // input is not passed on to the control(TextBox)
            kpea.Handled = true; 
        }
    } // First character must be an alphabetic character
    else if (!Char.IsLetter(kpea.KeyChar)) 
    {
 // input is not passed on to the control(TextBox)
        kpea.Handled = true; 
    }
}

// Another example
    switch(kpea.KeyChar) 
    {  
        case 'a': 
        case 'b': 
        case 'c': 
        case '#': 
        case '*': 
        case '1': 
            e.Handled=true; //event is handled.
            this.errorProvider.SetError(this.textboxChars, 
               "not allowed chars: 'a','b','c','#','*','1'");
            this.statusBar.Text="not allowed char..."+e.KeyChar;
            break; 
       default:
            //clear error
            this.errorProvider.SetError(this.textboxChars, "");
            break;
    } //switch 


    private static class FilterCharacters
    {
        public static void FilterSample(TextBox tb, 
     KeyPressEventArgs kpea)
        {
            const char BACKSPACE = '\b';
            const char FULLSTOP = '.';
            const char HYPHEN = '-';
            const char UNDERSCORE = '_';
            if (tb.Text.Length > 0)
            {
                if (!Char.IsLetterOrDigit(kpea.KeyChar) && 
                    (kpea.KeyChar != BACKSPACE) && 
                    (kpea.KeyChar != FULLSTOP) &&
                    (kpea.KeyChar != HYPHEN) &&
                    (kpea.KeyChar != UNDERSCORE) )
                { // input is not passed on to the control(TextBox)
                    kpea.Handled = true; 
                }
            }// First character must be an alphabetic character
            else if (!Char.IsLetter(kpea.KeyChar)) 
            {// input is not passed on to the control(TextBox)
                kpea.Handled = true; 
            }
        }

        public static void NumericOnlyFilter(TextBox tb,
      KeyPressEventArgs kpea)
        {
            const char BACKSPACE = '\b';
            //const char FULLSTOP = '.';
            if (!Char.IsDigit(kpea.KeyChar) && 
                // If you want decimal numbers
                //(kpea.KeyChar != FULLSTOP) && 
                (kpea.KeyChar != BACKSPACE) ) 
            {
               kpea.Handled = true; 
            }
        }
    }

Creating A Hash Of A String

// A quick and simple implementation
public string HashString(string target)
{
    if ((target == null) || (target.Length == 0))
        return string.Empty;

    byte[] targetAsBytes = Encoding.UTF8.GetBytes(target);
    SHA1 sha1 = SHA1.Create();
    byte[] hash = sha1.ComputeHash(targetAsBytes);
    return Convert.ToBase64String(hash);
}