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;
}