Windows Forms and Win32

by Richard Grimes





Listing One



class IndentListView : ListView

{

   public int InsertIndented(ListViewItem lvi, int indentLevel);

   protected int InsertItem(ListViewItem lvi, int indentLevel, int id);

   protected void SetItemText(int itemIndex, int subItemIndex, string text);

   class LVIData{};

   private ArrayList operations = null;

   protected override void OnHandleCreated(EventArgs e);

}





Listing Two



[DllImport("user32")]

static extern int SendMessage(IntPtr hWnd, int msg,

   int wParam, ref LVITEM lParam);

[StructLayout(LayoutKind.Sequential)]

struct LVITEM

{

   public const int LVIF_TEXT   = 0x0001;

   public const int LVIF_IMAGE  = 0x0002;

   public const int LVIF_PARAM  = 0x0004;

   public const int LVIF_INDENT = 0x0010;

   public const int LVM_INSERTITEM = 0x1007;

   public const int LVM_SETITEMTEXT = 0x102d;



   public uint mask;

   public int iItem;

   public int iSubItem;

   public uint state;

   public uint stateMask;

   public string pszText;

   public int cchTextMax;

   public int iImage;

   public IntPtr lParam;

   public int iIndent;

   public int iGroupId;

   public uint cColumns;

   public uint puColumns;

}





Listing Three



protected int InsertItem(ListViewItem lvi, int indentLevel, int id)

{

   int dispIdx = GetCount() + 1;

   LVITEM lvitem = new LVITEM();

   lvitem.mask = LVITEM.LVIF_TEXT | LVITEM.LVIF_PARAM

      | LVITEM.LVIF_IMAGE | LVITEM.LVIF_INDENT;

   lvitem.iItem = dispIdx;

   lvitem.pszText = lvi.Text;

   lvitem.iImage = lvi.ImageIndex;

   lvitem.iIndent = indentLevel;

   lvitem.lParam = (IntPtr)id;



   AddToItemsTable(lvi, id);

   dispIdx = SendMessage(this.Handle, LVITEM.LVM_INSERTITEM, 0, ref lvitem);

   UpdateItem(lvi, id, dispIdx);



   for (int idx = 0; (idx < lvi.SubItems.Count); ++idx)

   {

      SetItemText(id, idx, lvi.SubItems[idx].Text);

   }

   return lvi.Index;

}

protected void SetItemText(int itemIndex, int subItemIndex, string text)

{

   LVITEM lvitem = new LVITEM();

   lvitem.mask = LVITEM.LVIF_TEXT;

   lvitem.iItem = itemIndex;

   lvitem.iSubItem = subItemIndex;

   lvitem.pszText = text;

   SendMessage(this.Handle, LVITEM.LVM_SETITEMTEXT, itemIndex, ref lvitem);

}

private int GenerateNextID()

{

   Type type = typeof(ListView);

   MethodInfo mi = type.GetMethod("GenerateUniqueID",

      BindingFlags.NonPublic | BindingFlags.Instance);

   return (int)mi.Invoke(this, null);

}

private void AddToItemsTable(ListViewItem lvi, int id)

{

   Type type = typeof(ListView);

   FieldInfo fi = type.GetField("listItemsTable",

      BindingFlags.NonPublic | BindingFlags.Instance);

   Hashtable listItemsTable = (Hashtable)fi.GetValue(this);

   listItemsTable.Add(id, lvi);

   fi = type.GetField("itemCount",

      BindingFlags.NonPublic | BindingFlags.Instance);

   int count = (int)fi.GetValue(this);

   fi.SetValue(this, ++count);

}

private void UpdateItem(ListViewItem lvi, int id, int dispIdx)

{

   Type type = typeof(ListViewItem);

   MethodInfo mi = type.GetMethod("Host",

      BindingFlags.NonPublic | BindingFlags.Instance);

   object[] args = new object[]{this, id, dispIdx};

   mi.Invoke(lvi, args);

}





Listing Four



class LVIData

{

   public ListViewItem lvi;

   public int IndexLevel;

   public int ID;

}

public int InsertIndented(ListViewItem lvi, int indentLevel)

{

   if (this.Handle == IntPtr.Zero)

   {

      if (operations == null)

         operations = new ArrayList();

      LVIData data = new LVIData();

      data.lvi = lvi;

      data.IndexLevel = indentLevel;

      data.ID = GenerateNextID();

      operations.Add(data);

      return data.ID;

   }

   return InsertItem(lvi, indentLevel, GenerateNextID());

}

protected override void OnHandleCreated(EventArgs e)

{

   if (operations != null)

   {

      for (int idx = 0; idx < operations.Count; ++idx)

      {

         LVIData data = operations[idx] as LVIData;

         InsertItem(data.lvi, data.IndexLevel, data.ID);

      }

      operations = null;

   }

   base.OnHandleCreated(e);

}





Listing Five



public class MainForm : Form

{

   private IndentListView lv;

   public MainForm()

   {

      this.lv = new IndentListView();

      this.lv.Dock = DockStyle.Fill;

      this.lv.View = View.Details;

      ImageList il = new ImageList();

      Icon ic = LoadIconFromResources("first_icon");

      il.Images.Add(ic);

      lv.SmallImageList = il;



      ColumnHeader header;

      header = new ColumnHeader();

      this.lv.Columns.Add(header);

      header.Text = "Data";

      header.Width = 200;

      this.Controls.Add(this.lv);



      ListViewItem lvi = new ListViewItem("one", 0);

      lv.InsertIndented(lvi, 0);

      lvi = new ListViewItem("two", 0);

      lv.InsertIndented(lvi, 1);

      lvi = new ListViewItem("three", 0);

      lv.InsertIndented(lvi, 0);

   }

   static void Main()

   {

      Application.Run(new MainForm());

   }

}





Listing Six



class MainForm : Form

{

   MainForm()

   {

      this.Closed += new EventHandler(ClosedForm);

   }

   void ClosedForm(object sender, EventArgs e)

   {

      Application.ExitThread();

   }

   static void Main()

   {

      MainForm form = new MainForm();

      form.Visible = true;

      Application.Run();

   }

}







