Click here to Skip to main content
15,895,142 members
Articles / Programming Languages / Visual Basic
Article

TreeView Rearrange

Rate me:
Please Sign up or sign in to vote.
4.87/5 (57 votes)
6 Jun 2005Public Domain4 min read 247.4K   4.7K   132   80
How to do a TreeView rearrange.

Introduction

While merrily programming a top secret (snicker) application I was developing - I ran into a major roadblock that set me back a few days. My application was based around a treeview but I wanted to give users the ability to rearrange the node/folder structure of the treeview using drag and drop. Upon a bit of research, I found the treeview does have some sort of drag & drop support, but as far as I could tell, this just turned on the event handlers for when a user starts dragging a node. "Hmmm", I thought, "this is gonna require some custom coding."... Let's delve into my series of failures and successes leading us to a workable extension of the treeview control.

How is it going to work?

In my first attempt, I wanted all the visual goodies. I wanted the dragged node to be placed into the "slots" in between nodes as I moved over them. This, unfortunately, led me to some problems. When the node moves into a slot - the treeview structure changes and the node your mouse is currently over changes entirely, this introduced some (only slightly entertaining) node dances. I then decided to remove the node being dragged, to prevent the node dance - and it worked! My next problem was that I wanted to be able to drag the node into a "folder" node but what if the folder node is closed? I'm sure you guessed it, use Expand()! But guess what!? The dreaded node dance returned! :(

I gave up for the night and went to bed without any hope and (like many a times) woke up with an answer. Mimic the "Windows" (tm) way and implement a placeholder letting the user know where the item will be dropped. With a bit of work and a few cases of RC cola, I had the functionality I wanted.

Moving on to the code

Most of the functionality is handled within the "DragOver" event of the treeview control, however there are two other events that needed to be handled to give you the cursor effect you need.

C#
private void treeView1_ItemDrag(object sender, 
  System.Windows.Forms.ItemDragEventArgs e)
{
    DoDragDrop(e.Item, DragDropEffects.Move);
}


private void treeView1_DragEnter(object sender, 
  System.Windows.Forms.DragEventArgs e)
{
    e.Effect = DragDropEffects.Move;
}

Now into the DragOver event. The point to remember here is that we're dealing with two types of nodes: those that can accept children and those that can't. For nodes that can accept children, we need to have three vertical regions we have to watch for:

  • Top (placeholder above)
  • Bottom (placeholder below)
  • Middle (expand the folder and allow users to drop nodes onto it)

The non-folder nodes are divided into two vertical regions. For brevity, I will only go into the code for the "top" of the "non-folder" node. This code is divided into four main parts:

  • Paradox prevention, we should never be allowed to drag a folder into a child folder.
  • Store the current placeholder into a global string called NodeMap, basically a pipe delimited set of indexes. If the new NodeMap matches the global NodeMap then method returns to minimize flickering.
  • Refresh the screen to remove old placeholders.
  • Draw the placeholders.
C#
#region If NodeOver is a child then cancel
TreeNode tnParadox = NodeOver;
while(tnParadox.Parent != null)
{
    if(tnParadox.Parent == NodeMoving)
    {
        this.NodeMap = "";
        return;
    }
    
    tnParadox = tnParadox.Parent;
}
#endregion
#region Store the placeholder info into a pipe delimited string
TreeNode tnPlaceholderInfo = NodeOver;
string NewNodeMap = ((int)NodeOver.Index).ToString();
while(tnPlaceholderInfo.Parent != null)
{
    tnPlaceholderInfo = tnPlaceholderInfo.Parent;
     NewNodeMap = tnPlaceholderInfo.Index + "|" + NewNodeMap;
}
if(NewNodeMap == this.NodeMap)
    return;
else
    this.NodeMap = NewNodeMap;
#endregion
#region Clear placeholders above and below
this.Refresh();
#endregion
#region Draw the placeholders
int LeftPos, RightPos;
LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth;
RightPos = this.treeView1.Width - 4;
Point[] LeftTriangle = new Point[5]{
    new Point(LeftPos, NodeOver.Bounds.Top - 4), 
    new Point(LeftPos, NodeOver.Bounds.Top + 4), 
    new Point(LeftPos + 4, NodeOver.Bounds.Y), 
    new Point(LeftPos + 4, NodeOver.Bounds.Top - 1), 
    new Point(LeftPos, NodeOver.Bounds.Top - 5)};

Point[] RightTriangle = new Point[5]{
    new Point(RightPos, NodeOver.Bounds.Top - 4),
    new Point(RightPos, NodeOver.Bounds.Top + 4),
    new Point(RightPos - 4, NodeOver.Bounds.Y),
    new Point(RightPos - 4, NodeOver.Bounds.Top - 1),
    new Point(RightPos, NodeOver.Bounds.Top - 5)};

g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle);
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle);
g.DrawLine(new System.Drawing.Pen(Color.Black, 2), 
  new Point(LeftPos, NodeOver.Bounds.Top), 
  new Point(RightPos, NodeOver.Bounds.Top));
#endregion

The placeholders are drawn with three graphics calls to create the black line and two triangles.

The final piece to the puzzle is actually moving the dragged node. This is handled in the drag_drop event. It basically traverses the nodemap, adds the new node and removes the old one.

C#
private void treeView1_DragDrop(object sender, 
  System.Windows.Forms.DragEventArgs e)

{
    if(e.Data.GetDataPresent("System.Windows.Forms.TreeNode",
      false) && this.NodeMap != "")
    { 
        TreeNode MovingNode = (TreeNode)e.Data.GetData(
          "System.Windows.Forms.TreeNode");
        string[] NodeIndexes = this.NodeMap.Split('|');
        TreeNodeCollection InsertCollection = this.treeView1.Nodes;
        for(int i = 0; i < NodeIndexes.Length - 1; i++)
        {
            InsertCollection = InsertCollection[Int32.Parse(
               NodeIndexes[i])].Nodes;
        }
        if(InsertCollection != null)
        {
            InsertCollection.Insert(Int32.Parse(NodeIndexes[
             NodeIndexes.Length - 1]), (TreeNode)MovingNode.Clone());
            this.treeView1.SelectedNode = InsertCollection[
             Int32.Parse(NodeIndexes[NodeIndexes.Length - 1])];
            MovingNode.Remove();
        }
    } 

}

Remarks

While not a completely comprehensive solution, I believe this article will be a good stepping stone for those wanting to add better drag and drop support to their applications. The code is divided clearly into regions and commented fairly well.

I look forward to your comments and suggestions. CodeProject is a great site, and I'm glad to contribute.

History

  • February 11, 2004: (Version 1.0) code and article submitted.
  • March 7, 2004: (Version 1.1) minor bug where the last subfolder could be dragged onto itself fixed.
  • June, 5, 2005 (Version 1.2) utilized code by creatio, needed some minor tweaks but got it working. Also made an attempt to convert the code into VB.NET - there is a problem with the code - see comment that says "Error!". Not sure what is going on because I'm not a very competent VB.NET developer - advice appreciated.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralRe: Aquire the target node Pin
Gabe Anguiano5-Jun-05 10:46
Gabe Anguiano5-Jun-05 10:46 
GeneralVisual Basic Pin
Member 19069964-May-05 22:19
Member 19069964-May-05 22:19 
GeneralRe: Visual Basic Pin
Gabe Anguiano5-Jun-05 12:48
Gabe Anguiano5-Jun-05 12:48 
GeneralRe: Visual Basic Pin
Member 19069965-Jun-05 12:52
Member 19069965-Jun-05 12:52 
GeneralThanks Pin
prog329-Mar-05 4:27
prog329-Mar-05 4:27 
GeneralRe: Thanks Pin
Gabe Anguiano11-Mar-05 7:50
Gabe Anguiano11-Mar-05 7:50 
QuestionNice .. Possible in VB? Pin
MightyMart4-Nov-04 14:35
MightyMart4-Nov-04 14:35 
AnswerYes - here is a conversion to VB Pin
Member 151841125-Nov-04 8:19
Member 151841125-Nov-04 8:19 
Here is a conversion of this code to VB.Net. It works well but there still may be some bugs in it.

When I get a little more time, I want to compare it line by line with the c# source and make sure there are no errors.

Private Sub TreeViewItemDrag(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemDragEventArgs) Handles TreeView1.ItemDrag
'DoDragDrop(e.Item, DragDropEffects.Move)

' Move the dragged node when the left mouse button is used.
If e.Button = MouseButtons.Left Then
DoDragDrop(e.Item, DragDropEffects.Move)

' Copy the dragged node when the right mouse button is used.
ElseIf e.Button = MouseButtons.Right Then
DoDragDrop(e.Item, DragDropEffects.Copy)
End If
End Sub

Private Sub TreeViewDragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles TreeView1.DragEnter
e.Effect = DragDropEffects.Move
'e.Effect = e.AllowedEffect
End Sub

Private Sub TreeViewDragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles TreeView1.DragDrop

If (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", False) AndAlso Not Nodemap = "") Then
Dim MovingNode As TreeNode = e.Data.GetData("System.Windows.Forms.TreeNode")
Dim NodeIndexes() As String = Nodemap.Split("|")
Dim InsertCollection As TreeNodeCollection = TreeView1.Nodes

Dim i As Integer
For i = 0 To NodeIndexes.Length - 2
InsertCollection = InsertCollection(Int32.Parse(NodeIndexes(i))).Nodes
Next

If Not InsertCollection Is Nothing Then
InsertCollection.Insert(Int32.Parse(NodeIndexes(NodeIndexes.Length - 1)), MovingNode.Clone())
TreeView1.SelectedNode = InsertCollection(Int32.Parse(NodeIndexes(NodeIndexes.Length - 1)))
MovingNode.Remove()
End If
End If
End Sub

Private Sub TreeView1_DragOver(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles TreeView1.DragOver
Dim NodeOver As TreeNode = Me.TreeView1.GetNodeAt(Me.TreeView1.PointToClient(System.Windows.Forms.Cursor.Position))
Dim NodeMoving As TreeNode = e.Data.GetData("System.Windows.Forms.TreeNode")

'A bit long, but to summarize, process the following coe only if the nodeover is null
'and either the nodeover is not the same thing as nodemoving UNLESSS nodeover happens
'to be the last node in the branch (so we can allow drag & drop below a parent branch)
' true true false
If (Not NodeOver Is Nothing AndAlso (Not NodeOver Is NodeMoving OrElse (Not NodeOver.Parent Is Nothing AndAlso (NodeOver.Index = NodeOver.Parent.Nodes.Count - 1)))) Then
Dim OffsetY As Int32 = Me.TreeView1.PointToClient(System.Windows.Forms.Cursor.Position).Y - NodeOver.Bounds.Top
Dim NodeOverImageWidth As Integer = Me.TreeView1.ImageList.Images(NodeOver.ImageIndex).Size.Width + 8
Dim g As Graphics = Me.TreeView1.CreateGraphics()

'Image index of 1 is the non-folder icon
If NodeOver.ImageIndex = 1 Then
'Standard Node
If (OffsetY < (NodeOver.Bounds.Height / 2)) Then
'this.lblDebug.Text = "top"

'If NodeOver is a child then cancel
Dim tnParadox As TreeNode = NodeOver
While Not tnParadox.Parent Is Nothing
If tnParadox.Parent Is NodeMoving Then
NodeMap = ""
Return
End If
tnParadox = tnParadox.Parent
End While

'Store the placeholder info into a pipe delimited string
Dim tnPlaceholderInfo As TreeNode = NodeOver
Dim NewNodeMap As String = NodeOver.Index.ToString()
While Not tnPlaceholderInfo.Parent Is Nothing
tnPlaceholderInfo = tnPlaceholderInfo.Parent
NewNodeMap = tnPlaceholderInfo.Index.ToString + "|" + NewNodeMap
End While
If NewNodeMap Is NodeMap Then
Return
Else
NodeMap = NewNodeMap
End If
'Clear placeholders above and below
Me.Refresh()

'Draw the placeholders
Dim LeftPos As Int32, RightPos As Int32
LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth
RightPos = TreeView1.Width - 4

Dim LeftTriangle() As Point = { _
New Point(LeftPos, NodeOver.Bounds.Top - 4), _
New Point(LeftPos, NodeOver.Bounds.Top + 4), _
New Point(LeftPos + 4, NodeOver.Bounds.Y), _
New Point(LeftPos + 4, NodeOver.Bounds.Top - 1), _
New Point(LeftPos, NodeOver.Bounds.Top - 5)}

Dim RightTriangle() As Point = { _
New Point(RightPos, NodeOver.Bounds.Top - 4), _
New Point(RightPos, NodeOver.Bounds.Top + 4), _
New Point(RightPos - 4, NodeOver.Bounds.Y), _
New Point(RightPos - 4, NodeOver.Bounds.Top - 1), _
New Point(RightPos, NodeOver.Bounds.Top - 5)}

g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle)
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle)
g.DrawLine(New System.Drawing.Pen(Color.Black, 2), New Point(LeftPos, NodeOver.Bounds.Top), New Point(RightPos, NodeOver.Bounds.Top))

Else

'lblDebug.Text = "bottom"

'If NodeOver is a child then cancel
Dim tnParadox As TreeNode = NodeOver
While Not tnParadox.Parent Is Nothing
If tnParadox.Parent Is NodeMoving Then
NodeMap = ""
Return
End If
tnParadox = tnParadox.Parent
End While
'Allow drag drop to parent branches
Dim ParentDragDrop As TreeNode = Nothing
'If the node the mouse is over is the last node of the branch we should allow
'the ability to drop the "nodemoving" node BELOW the parent node
If Not NodeOver.Parent Is Nothing AndAlso NodeOver.Index = NodeOver.Parent.Nodes.Count - 1 Then
Dim XPos As Integer = Me.TreeView1.PointToClient(System.Windows.Forms.Cursor.Position).X
If (XPos < NodeOver.Bounds.Left) Then
ParentDragDrop = NodeOver.Parent
While (True)
If (XPos > (ParentDragDrop.Bounds.Left - TreeView1.ImageList.Images(ParentDragDrop.ImageIndex).Size.Width)) Then
Exit Sub 'break()
End If
If Not ParentDragDrop.Parent Is Nothing Then
ParentDragDrop = ParentDragDrop.Parent
Else
Exit Sub 'break()
End If
End While
End If
End If

'Store the placeholder info into a pipe delimited string
'Since we are in a special case here, use the ParentDragDrop node as the current "nodeover"
Dim tnPlaceholderInfo As TreeNode
If Not ParentDragDrop Is Nothing Then
tnPlaceholderInfo = ParentDragDrop
Else
tnPlaceholderInfo = NodeOver
End If

Dim NewNodeMap As String = (tnPlaceholderInfo.Index + 1).ToString()
While Not tnPlaceholderInfo.Parent Is Nothing
tnPlaceholderInfo = tnPlaceholderInfo.Parent
NewNodeMap = tnPlaceholderInfo.Index.ToString + "|" + NewNodeMap
End While
If NewNodeMap = NodeMap Then
Return
Else
NodeMap = NewNodeMap
End If

'Clear placeholders above and below
Me.Refresh()

'Draw the placeholders
'Once again, we are not dragging to node over, draw the placeholder using the ParentDragDrop bounds
Dim LeftPos As Int32, RightPos As Int32
If Not ParentDragDrop Is Nothing Then
LeftPos = ParentDragDrop.Bounds.Left - (TreeView1.ImageList.Images(ParentDragDrop.ImageIndex).Size.Width + 8)
Else
LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth
End If

RightPos = Me.TreeView1.Width - 4
Dim LeftTriangle() As Point = { _
New Point(LeftPos, NodeOver.Bounds.Bottom - 4), _
New Point(LeftPos, NodeOver.Bounds.Bottom + 4), _
New Point(LeftPos + 4, NodeOver.Bounds.Bottom), _
New Point(LeftPos + 4, NodeOver.Bounds.Bottom - 1), _
New Point(LeftPos, NodeOver.Bounds.Bottom - 5)}

Dim RightTriangle() As Point = { _
New Point(RightPos, NodeOver.Bounds.Bottom - 4), _
New Point(RightPos, NodeOver.Bounds.Bottom + 4), _
New Point(RightPos - 4, NodeOver.Bounds.Bottom), _
New Point(RightPos - 4, NodeOver.Bounds.Bottom - 1), _
New Point(RightPos, NodeOver.Bounds.Bottom - 5)}

g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle)
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle)
g.DrawLine(New System.Drawing.Pen(Color.Black, 2), New Point(LeftPos, NodeOver.Bounds.Bottom), New Point(RightPos, NodeOver.Bounds.Bottom))
End If
Else 'must be a folder icon

'Folder Node
If (OffsetY < (NodeOver.Bounds.Height / 3)) Then
'this.lblDebug.Text = "folder top"

'If NodeOver is a child then cancel
Dim tnParadox As TreeNode = NodeOver
While Not tnParadox.Parent Is Nothing
If tnParadox.Parent Is NodeMoving Then
NodeMap = ""
Return
End If
tnParadox = tnParadox.Parent
End While

'Store the placeholder info into a pipe delimited string
Dim tnPlaceholderInfo As TreeNode = NodeOver
Dim NewNodeMap As String = NodeOver.Index.ToString()
While Not tnPlaceholderInfo.Parent Is Nothing
tnPlaceholderInfo = tnPlaceholderInfo.Parent
NewNodeMap = tnPlaceholderInfo.Index.ToString + "|" + NewNodeMap
End While
If NewNodeMap = NodeMap Then
Return
Else
NodeMap = NewNodeMap
End If

'Clear placeholders above and below
Me.Refresh()

'Draw the placeholders
Dim LeftPos As Int32, RightPos As Int32
LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth
RightPos = TreeView1.Width - 4

Dim LeftTriangle() As Point = { _
New Point(LeftPos, NodeOver.Bounds.Top - 4), _
New Point(LeftPos, NodeOver.Bounds.Top + 4), _
New Point(LeftPos + 4, NodeOver.Bounds.Y), _
New Point(LeftPos + 4, NodeOver.Bounds.Top - 1), _
New Point(LeftPos, NodeOver.Bounds.Top - 5)}

Dim RightTriangle() As Point = { _
New Point(RightPos, NodeOver.Bounds.Top - 4), _
New Point(RightPos, NodeOver.Bounds.Top + 4), _
New Point(RightPos - 4, NodeOver.Bounds.Y), _
New Point(RightPos - 4, NodeOver.Bounds.Top - 1), _
New Point(RightPos, NodeOver.Bounds.Top - 5)}

g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle)
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle)
g.DrawLine(New System.Drawing.Pen(Color.Black, 2), New Point(LeftPos, NodeOver.Bounds.Top), New Point(RightPos, NodeOver.Bounds.Top))
ElseIf Not NodeOver.Parent Is Nothing AndAlso NodeOver.Index = 0 AndAlso (OffsetY > (NodeOver.Bounds.Height - (NodeOver.Bounds.Height / 3))) Then

'Me.lblDebug.Text = "folder bottom"

'If NodeOver is a child then cancel
Dim tnParadox As TreeNode = NodeOver
While Not tnParadox.Parent Is Nothing
If tnParadox.Parent Is NodeMoving Then
Nodemap = ""
Return
End If
tnParadox = tnParadox.Parent
End While

'Store the placeholder info into a pipe delimited string
Dim tnPlaceholderInfo As TreeNode = NodeOver
Dim NewNodeMap As String = NodeOver.Index + 1.ToString()
While Not tnPlaceholderInfo.Parent Is Nothing
tnPlaceholderInfo = tnPlaceholderInfo.Parent
NewNodeMap = tnPlaceholderInfo.Index.ToString + "|" + NewNodeMap
End While
If NewNodeMap = Nodemap Then
Return
Else
Nodemap = NewNodeMap
End If

'Clear placeholders above and below
Me.Refresh()

'Draw the placeholders
Dim LeftPos As Int32, RightPos As Int32
LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth
RightPos = Me.TreeView1.Width - 4
Dim LeftTriangle() As Point = { _
New Point(LeftPos, NodeOver.Bounds.Bottom - 4), _
New Point(LeftPos, NodeOver.Bounds.Bottom + 4), _
New Point(LeftPos + 4, NodeOver.Bounds.Bottom), _
New Point(LeftPos + 4, NodeOver.Bounds.Bottom - 1), _
New Point(LeftPos, NodeOver.Bounds.Bottom - 5)}

Dim RightTriangle() As Point = { _
New Point(RightPos, NodeOver.Bounds.Bottom - 4), _
New Point(RightPos, NodeOver.Bounds.Bottom + 4), _
New Point(RightPos - 4, NodeOver.Bounds.Bottom), _
New Point(RightPos - 4, NodeOver.Bounds.Bottom - 1), _
New Point(RightPos, NodeOver.Bounds.Bottom - 5)}

g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle)
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle)
g.DrawLine(New System.Drawing.Pen(Color.Black, 2), New Point(LeftPos, NodeOver.Bounds.Bottom), New Point(RightPos, NodeOver.Bounds.Bottom))
Else
'folder over

If (NodeOver.Nodes.Count > 0) Then
NodeOver.Expand()
'Me.Refresh()
Else
'prevent node from being dragged onto itself
If NodeMoving Is NodeOver Then Return
'If NodeOver is a child then cancel
Dim tnParadox As TreeNode = NodeOver
While Not tnParadox.Parent Is Nothing
If tnParadox.Parent Is NodeMoving Then
NodeMap = ""
Return
End If
tnParadox = tnParadox.Parent
End While

'Store the placeholder info into a pipe delimited string
Dim tnPlaceholderInfo As TreeNode = NodeOver
Dim NewNodeMap As String = NodeOver.Index.ToString()

While Not tnPlaceholderInfo.Parent Is Nothing
tnPlaceholderInfo = tnPlaceholderInfo.Parent
NewNodeMap = tnPlaceholderInfo.Index.ToString + "|" + NewNodeMap
End While

NewNodeMap = NewNodeMap + "|0"
If (NewNodeMap = NodeMap) Then
Return
Else
NodeMap = NewNodeMap
End If

'Clear placeholders above and below
Me.Refresh()

' Draw the "add to folder" placeholder
Dim RightPos As Int16 = NodeOver.Bounds.Right + 6
Dim RightTriangle() As Point = {New Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4), New Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4), New Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2)), New Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 1), New Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 5)}
Me.Refresh()
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle)
End If 'folder over
End If 'folder top, bottom, over
End If 'node or folder
End If '1st if
End Sub
GeneralRe: Yes - here is a conversion to VB Pin
Member 15184114-Dec-04 4:46
Member 15184114-Dec-04 4:46 
GeneralRe: Yes - here is a conversion to VB Pin
Gabe Anguiano26-May-05 5:33
Gabe Anguiano26-May-05 5:33 
GeneralGood work Pin
Daniel Turini17-Jul-04 13:51
Daniel Turini17-Jul-04 13:51 
GeneralTHANX - Good job!! Pin
SurlyCanuck17-Jul-04 12:04
professionalSurlyCanuck17-Jul-04 12:04 
GeneralRe: THANX - Good job!! Pin
Gabe Anguiano19-Jul-04 17:55
Gabe Anguiano19-Jul-04 17:55 
QuestionGiveFeedback QueryContinueDrag ? Pin
Jarosław Zwierz7-Jun-04 1:17
Jarosław Zwierz7-Jun-04 1:17 
GeneralRe: &amp;#9786; Pin
Gabe Anguiano24-May-04 7:12
Gabe Anguiano24-May-04 7:12 
GeneralNo really good programming Pin
Member 69538423-May-04 7:46
Member 69538423-May-04 7:46 
GeneralRe: No really good programming Pin
Charlie Williams23-May-04 8:59
Charlie Williams23-May-04 8:59 
GeneralRe: No really good programming Pin
Member 69538423-May-04 9:38
Member 69538423-May-04 9:38 
GeneralRe: No really good programming Pin
Charlie Williams23-May-04 9:49
Charlie Williams23-May-04 9:49 
GeneralRe: No really good programming Pin
Member 69538423-May-04 10:57
Member 69538423-May-04 10:57 
GeneralRe: No really good programming Pin
Charlie Williams23-May-04 14:50
Charlie Williams23-May-04 14:50 
GeneralRe: No really good programming Pin
Gabe Anguiano23-May-04 20:28
Gabe Anguiano23-May-04 20:28 
GeneralRe: No really good programming Pin
Member 69538423-May-04 20:58
Member 69538423-May-04 20:58 
GeneralRe: No really good programming Pin
f27-Jul-07 21:36
f27-Jul-07 21:36 
GeneralRe: No really good programming Pin
Anonymous18-Dec-04 18:00
Anonymous18-Dec-04 18:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.