Introduction
Today, you will learn how easy it is to create a simple family tree in .NET.
Family Trees and Genograms
A family tree is a chart that represents family relationships in a tree structure. A genogram is a pictorial display of a person’s family relationships and medical history. The difference between a genogram and a family tree is that a genogram allows the user to visualize hereditary patterns and psychological factors that punctuate relationships.
To create a family tree, I needed some photos of my family. Unfortunately, I do not have many, so I opted to cover a different family instead.
Ancient Egypt
How good is your history?
Ancient Egypt was a civilization of ancient Northeastern Africa along the lower Nile River. It is now known as Egypt. The ancient Egyptian civilization coalesced around 3100 B.C. with the political unification of Upper and Lower Egypt. The history of ancient Egypt occurred as a series of stable kingdoms, separated by Intermediate Periods (periods of relative instability): the Old Kingdom (Early Bronze Age), the Middle Kingdom (Middle Bronze Age), and the New Kingdom (Late Bronze Age).
Fourth Dynasty of Egypt
The Fourth Dynasty of ancient Egypt is also known as the “golden age” of the Old Kingdom. The Fourth Dynasty lasted from 2613 to 2494 B.C. This, the Age of the Pyramids, was a time of peace and prosperity and a time where trade with other countries is started.
The Fourth Dynasty heralded the height of the pyramid-building age. No other period in Egypt’s history equaled The Fourth Dynasty’s architectural accomplishments.
Enough history. I love Ancient Egypt and have studied it a while back for a book project which I was busy with (and still am…)
Practical
To create a Family Tree, you need to extend the capabilities of the built-in Windows PictureBox object. More on this later. Create a new C# or VB Windows Forms project. Resize the Form and add a Docked PictureBox and a StatusStrip onto it. The Design resembles Figure 1.
Figure 1: Design
Add a new Interface, name it IDrawable, and add the following code into it.
C#
using System.Drawing; namespace FamilyTree_C { interface IDrawable { SizeF GetSize(Graphics gr, Font fFont); bool Point(Graphics gr, Font fFont, PointF ptCentre, PointF ptTarget); void Draw(float x, float y, Graphics gr, Pen pen, Brush BackBrush, Brush Brush, Font fFont); } }
VB.NET
Imports System.Drawing Interface IDrawable Function GetSize(ByVal gr As Graphics, ByVal fFont As Font) _ As SizeF Function Point(ByVal gr As Graphics, ByVal fFont As Font, _ ByVal ptCentre As PointF, ByVal ptTarget As PointF) _ As Boolean Sub Draw(ByVal x As Single, ByVal y As Single, _ ByVal gr As Graphics, ByVal pen As Pen, ByVal BackBrush _ As Brush, ByVal Brush As Brush, ByVal fFont As Font) End Interface
The Draw sub, GetSize, and Point methods get created here. Make use of this Interface in the PicNode Class that you should add next.
C#
using System.Drawing; using System.Windows.Forms; namespace FamilyTree_C { class PicNode : IDrawable { public Image Pic = null; public string Desc; public bool Sel = false; public PicNode(string desc, Image pic) { Desc = desc; Pic = pic; } public SizeF NodeSize = new SizeF(100, 100); public SizeF GetSize(Graphics gr, Font fFont) { return NodeSize; } private RectangleF Loc(PointF ptCentre) { return new RectangleF(ptCentre.X - NodeSize.Width / 2, ptCentre.Y - NodeSize.Height / 2, NodeSize.Width, NodeSize.Height); } public bool Point(Graphics gr, Font font, PointF ptCentre, PointF ptTarget) { RectangleF rect = Loc(ptCentre); return rect.Contains(ptTarget); } public void Draw(float x, float y, Graphics gr, Pen pen, Brush backbrush, Brush brush, Font font) { RectangleF locrec = Loc(new PointF(x, y)); Rectangle rect = Rectangle.Round(locrec); if (Sel) { gr.FillRectangle(Brushes.White, rect); ControlPaint.DrawBorder3D(gr, rect, Border3DStyle.Sunken); } else { gr.FillRectangle(Brushes.Orange, rect); ControlPaint.DrawBorder3D(gr, rect, Border3DStyle.Raised); } locrec.Inflate(-5, -5); locrec = Position(Pic, locrec); gr.DrawImage(Pic, locrec); } private RectangleF Position(Image pic, RectangleF rect) { float fWidth = pic.Width; float fHeight = pic.Height; float fCentre = fWidth / fHeight; float fRecCentre = rect.Width / rect.Height; float scale = 1; if (fCentre > fRecCentre) { scale = rect.Width / fWidth; } else { scale = rect.Height / fHeight; } fWidth *= scale; fHeight *= scale; RectangleF drawing_rect = new RectangleF(rect.X + (rect.Width - fWidth) / 2, rect.Y + (rect.Height - fHeight) / 2, fWidth, fHeight); return drawing_rect; } } }
VB.NET
Imports FamilyTree_VB Public Class PicNode Implements IDrawable Public Pic As Image = Nothing Public Desc As String Public Sel As Boolean = False Public Sub New(ByVal desc As String, ByVal pic As Image) desc = desc pic = pic End Sub Public NodeSize As SizeF = New SizeF(100, 100) Public Function GetSize(ByVal gr As Graphics, _ ByVal fFont As Font) As SizeF Return NodeSize End Function Private Function Loc(ByVal ptCentre As PointF) As RectangleF Return New RectangleF(ptCentre.X - NodeSize.Width / 2, _ ptCentre.Y - NodeSize.Height / 2, NodeSize.Width, _ NodeSize.Height) End Function Public Function Point(ByVal gr As Graphics, ByVal font _ As Font, ByVal ptCentre As PointF, ByVal ptTarget _ As PointF) As Boolean Dim rect As RectangleF = Loc(ptCentre) Return rect.Contains(ptTarget) End Function Public Sub Draw(ByVal x As Single, ByVal y As Single, _ ByVal gr As Graphics, ByVal pen As Pen, ByVal backbrush _ As Brush, ByVal brush As Brush, ByVal font As Font) Dim locrec As RectangleF = Loc(New PointF(x, y)) Dim rect As Rectangle = Rectangle.Round(locrec) If Sel Then gr.FillRectangle(Brushes.White, rect) ControlPaint.DrawBorder3D(gr, rect, Border3DStyle.Sunken) Else gr.FillRectangle(Brushes.Orange, rect) ControlPaint.DrawBorder3D(gr, rect, Border3DStyle.Raised) End If locrec.Inflate(-5, -5) locrec = Position(Pic, locrec) gr.DrawImage(Pic, locrec) End Sub Private Function Position(pic As Image, rect As RectangleF) _ As RectangleF Dim fWidth As Single = pic.Width Dim fHeight As Single = pic.Height Dim fCentre As Single = fWidth / fHeight Dim fRecCentre As Single = rect.Width / rect.Height Dim scale As Single = 1 If fCentre > fRecCentre Then scale = rect.Width / fWidth Else scale = rect.Height / fHeight End If fWidth *= scale fHeight *= scale Dim drawing_rect As RectangleF = New RectangleF(rect.X + _ (rect.Width - fWidth) / 2, rect.Y + _ (rect.Height - fHeight) / 2, fWidth, fHeight) Return drawing_rect End Function Private Function IDrawable_GetSize(gr As Graphics, _ fFont As Font) As SizeF Implements IDrawable.GetSize Throw New NotImplementedException() End Function Private Function IDrawable_Point(gr As Graphics, _ fFont As Font, ptCentre As PointF, ptTarget As PointF) _ As Boolean Implements IDrawable.Point Throw New NotImplementedException() End Function Private Sub IDrawable_Draw(x As Single, y As Single, _ gr As Graphics, pen As Pen, BackBrush As Brush, _ Brush As Brush, fFont As Font) Implements IDrawable.Draw Throw New NotImplementedException() End Sub End Class
The PicNode class draws a box for each family member. Add the FamilyMember class.
C#
using System.Collections.Generic; using System.Drawing; namespace FamilyTree_C { class FamilyMember<T> where T : IDrawable { public T Obj; public List<FamilyMember<T>> lstChildren = new List<FamilyMember<T>>(); private const float fX = 5; private const float fY = 30; private PointF ptCenter; public Font fFont = null; public Pen pPen = Pens.Black; public Brush bBrush = Brushes.Red; public Brush bBackBrush = Brushes.White; public FamilyMember(T obj) : this(obj, new Font("Arial", 8)) { Obj = obj; } public FamilyMember(T obj, Font fFont) { Obj = obj; this.fFont = fFont; } public void Add(FamilyMember<T> obj) { lstChildren.Add(obj); } public void Organize(Graphics gr, ref float X, ref float Y) { SizeF szObj = Obj.GetSize(gr, fFont); float x = X; float MaxY = Y + szObj.Height; float SubY = Y + szObj.Height + fY; foreach (FamilyMember<T> tChild in lstChildren) { float MinY = SubY; tChild.Organize(gr, ref x, ref MinY); if (MaxY < MinY) MaxY = MinY; x += fX; } if (lstChildren.Count > 0) x -= fX; float SubWidth = x - X; if (szObj.Width > SubWidth) { x = X + (szObj.Width - SubWidth) / 2; foreach (FamilyMember<T> tChild in lstChildren) { tChild.Organize(gr, ref x, ref SubY); x += fX; } SubWidth = szObj.Width; } ptCenter = new PointF(X + SubWidth / 2, Y + szObj.Height / 2); X += SubWidth; Y = MaxY; } public void DrawFamily(Graphics gr, ref float x, float y) { Organize(gr, ref x, ref y); DrawFamily(gr); } public void DrawFamily(Graphics gr) { DrawLinks(gr); DrawNodes(gr); } private void DrawLinks(Graphics gr) { if (lstChildren.Count == 1) { gr.DrawLine(pPen, ptCenter, lstChildren[0].ptCenter); } else if (lstChildren.Count > 1) { float xmin = lstChildren[0].ptCenter.X; float xmax = lstChildren[lstChildren.Count - 1] .ptCenter.X; SizeF my_size = Obj.GetSize(gr, fFont); float y = ptCenter.Y + my_size.Height / 2 + fY / 2f; gr.DrawLine(pPen, xmin, y, xmax, y); gr.DrawLine(pPen, ptCenter.X, ptCenter.Y, ptCenter.X, y); foreach (FamilyMember<T> tChild in lstChildren) { gr.DrawLine(pPen, tChild.ptCenter.X, y, tChild.ptCenter.X, tChild.ptCenter.Y); } } foreach (FamilyMember<T> tChild in lstChildren) { tChild.DrawLinks(gr); } } private void DrawNodes(Graphics gr) { Obj.Draw(ptCenter.X, ptCenter.Y, gr, pPen, bBackBrush, bBrush, fFont); foreach (FamilyMember<T> tChild in lstChildren) { tChild.DrawNodes(gr); } } public FamilyMember<T> NodePoint(Graphics gr, PointF ptTarget) { if (Obj.Point(gr, fFont, ptCenter, ptTarget)) return this; foreach (FamilyMember<T> tChild in lstChildren) { FamilyMember<T> hit_node = tChild.NodePoint(gr, ptTarget); if (hit_node != null) return hit_node; } return null; } public bool Delete(FamilyMember<T> tTarget) { foreach (FamilyMember<T> tChild in lstChildren) { if (tChild == tTarget) { lstChildren.Remove(tChild); return true; } if (tChild.Delete(tTarget)) return true; } return false; } } }
VB.NET
Imports System.Collections.Generic Imports System.Drawing Class FamilyMember(Of T As IDrawable) Public Obj As T Public lstChildren As List(Of FamilyMember(Of T)) = New _ List(Of FamilyMember(Of T))() Private Const fX As Single = 5 Private Const fY As Single = 30 Private ptCenter As PointF Public fFont As Font = Nothing Public pPen As Pen = Pens.Black Public bBrush As Brush = Brushes.Red Public bBackBrush As Brush = Brushes.White Public Sub New(ByVal obj As T) obj = obj End Sub Public Sub New(ByVal obj As T, ByVal fFont As Font) obj = obj Me.fFont = fFont End Sub Public Sub Add(ByVal obj As FamilyMember(Of T)) lstChildren.Add(obj) End Sub Public Sub Organize(ByVal gr As Graphics, ByRef X As Single, _ ByRef Y As Single) Dim szObj As SizeF = Obj.GetSize(gr, fFont) Dim xX As Single = X Dim MaxY As Single = Y + szObj.Height Dim SubY As Single = Y + szObj.Height + fY For Each tChild As FamilyMember(Of T) In lstChildren Dim MinY As Single = SubY tChild.Organize(gr, X, MinY) If MaxY < MinY Then MaxY = MinY xX += fX Next If lstChildren.Count > 0 Then xX -= fX Dim SubWidth As Single = xX - xX If szObj.Width > SubWidth Then xX = xX + (szObj.Width - SubWidth) / 2 For Each tChild As FamilyMember(Of T) In lstChildren tChild.Organize(gr, xX, SubY) xX += fX Next SubWidth = szObj.Width End If ptCenter = New PointF(xX + SubWidth / 2, Y + _ szObj.Height / 2) xX += SubWidth Y = MaxY End Sub Public Sub DrawFamily(ByVal gr As Graphics, ByRef x As Single, _ ByVal y As Single) Organize(gr, x, y) DrawFamily(gr) End Sub Public Sub DrawFamily(ByVal gr As Graphics) DrawLinks(gr) DrawNodes(gr) End Sub Private Sub DrawLinks(ByVal gr As Graphics) If lstChildren.Count = 1 Then gr.DrawLine(pPen, ptCenter, lstChildren(0).ptCenter) ElseIf lstChildren.Count > 1 Then Dim xmin As Single = lstChildren(0).ptCenter.X Dim xmax As Single = lstChildren(lstChildren.Count - 1) _ .ptCenter.X Dim my_size As SizeF = Obj.GetSize(gr, fFont) Dim y As Single = ptCenter.Y + my_size.Height / 2 + _ fY / 2.0F gr.DrawLine(pPen, xmin, y, xmax, y) gr.DrawLine(pPen, ptCenter.X, ptCenter.Y, ptCenter.X, y) For Each tChild As FamilyMember(Of T) In lstChildren gr.DrawLine(pPen, tChild.ptCenter.X, y, _ tChild.ptCenter.X, tChild.ptCenter.Y) Next End If For Each tChild As FamilyMember(Of T) In lstChildren tChild.DrawLinks(gr) Next End Sub Private Sub DrawNodes(ByVal gr As Graphics) Obj.Draw(ptCenter.X, ptCenter.Y, gr, pPen, bBackBrush, _ bBrush, fFont) For Each tChild As FamilyMember(Of T) In lstChildren tChild.DrawNodes(gr) Next End Sub Public Function NodePoint(ByVal gr As Graphics, ByVal ptTarget _ As PointF) As FamilyMember(Of T) If Obj.Point(gr, fFont, ptCenter, ptTarget) Then Return Me For Each tChild As FamilyMember(Of T) In lstChildren Dim hit_node As FamilyMember(Of T) = _ tChild.NodePoint(gr, ptTarget) If hit_node IsNot Nothing Then Return hit_node Next Return Nothing End Function Public Function Delete(ByVal tTarget As FamilyMember(Of T)) _ As Boolean For Each tChild As FamilyMember(Of T) In lstChildren If tChild.Equals(tTarget) Then lstChildren.Remove(tChild) Return True End If If tChild.Delete(tTarget) Then Return True Next Return False End Function End Class
The FamilyMember class gets all family members, along with their images and other properties. Then, it connects all members.
Inside the Form, Instantiate a Family Member:
C#
private FamilyMember<PicNode> SelectedNode;
VB.NET
Private SelectedNode As FamilyMember(Of PicNode)
Create a Sub procedure to Create the Tree.
C#
private void ShowTree() { using (Graphics gr = picFamily.CreateGraphics()) { float xmin = 0, ymin = 0; Unknown.Organize(gr, ref xmin, ref ymin); // HetepheresI.Organize(gr, ref xmin, ref ymin); // SNEFERU.Organize(gr, ref xmin, ref ymin); xmin = (this.ClientSize.Width - xmin) / 2; ymin = 10; Unknown.Organize(gr, ref xmin, ref ymin); } picFamily.Refresh(); }
VB.NET
Private Sub ShowTree() Using gr As Graphics = picFamily.CreateGraphics() Dim xmin As Single = 0, ymin As Single = 0 Unknown.Organize(gr, xmin, ymin) 'HetepheresI.Organize(gr, xmin, ymin)' 'SNEFERU.Organize(gr, xmin, ymin)' xmin = (Me.ClientSize.Width - xmin) / 2 ymin = 10 Unknown.Organize(gr, xmin, ymin) End Using picFamily.Refresh() End Sub
This tree can sprout from Queen Hetepheres I and King Sneferu, or from an Unknown entity. The Trees are loosely based on the Family Tree found here on Wikipedia.
Add the SelNode Sub procedure to determine which entity has been clicked.
C#
private void SelNode(PointF pt) { if (SelectedNode != null) { SelectedNode.Obj.Sel = false; lblNodeText.Text = ""; } using (Graphics gr = picFamily.CreateGraphics()) { SelectedNode = HetepheresI.NodePoint(gr, pt); } if (SelectedNode != null) { SelectedNode.Obj.Sel = true; lblNodeText.Text = SelectedNode.Obj.Desc; } picFamily.Refresh(); }
VB.NET
Private Sub SelNode(ByVal pt As PointF) If SelectedNode IsNot Nothing Then SelectedNode.Obj.Sel = False lblNodeText.Text = "" End If Using gr As Graphics = picFamily.CreateGraphics() SelectedNode = HetepheresI.NodePoint(gr, pt) End Using If SelectedNode IsNot Nothing Then SelectedNode.Obj.Sel = True lblNodeText.Text = SelectedNode.Obj.Desc End If picFamily.Refresh() End Sub
Create the Root Family members.
C#
private FamilyMember<PicNode> HetepheresI = new FamilyMember<PicNode>( new PicNode("HetepheresI", Properties.Resources.Hetepheres_I)); private FamilyMember<PicNode> SNEFERU = new FamilyMember<PicNode>( new PicNode("SNEFERU", Properties.Resources.SNEFERU)); private FamilyMember<PicNode> Unknown = new FamilyMember<PicNode>( new PicNode("Unknown", Properties.Resources.Unknown));
VB.NET
Private HetepheresI As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("HetepheresI", _ My.Resources.Hetepheres_I)) Private SNEFERU As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("SNEFERU", _ My.Resources.SNEFERU)) Private Unknown As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Unknown", _ My.Resources.Unknown))
In Form_Load, add the other family members and their positions.
C#
private void Form1_Load(object sender, EventArgs e) { FamilyMember<PicNode> MerititesI = new FamilyMember<PicNode>( new PicNode("MerititesI", Properties.Resources.Meritites_I)); FamilyMember<PicNode> KHUFU = new FamilyMember<PicNode>( new PicNode("KHUFU", Properties.Resources.KHUFU)); FamilyMember<PicNode> Henutsen = new FamilyMember<PicNode>( new PicNode("Henutsen", Properties.Resources.Henutsen)); FamilyMember<PicNode> Rahotep = new FamilyMember<PicNode>( new PicNode("Rahotep", Properties.Resources.Rahotep)); FamilyMember<PicNode> NefermaatI = new FamilyMember<PicNode>( new PicNode("NefermaatI", Properties.Resources.Nefermaat_I)); FamilyMember<PicNode> Itet = new FamilyMember<PicNode>( new PicNode("Itet", Properties.Resources.Itet)); FamilyMember<PicNode> Djedefhor = new FamilyMember<PicNode>( new PicNode("Djedefhor", Properties.Resources.Djedefhor)); FamilyMember<PicNode> Kawab = new FamilyMember<PicNode>( new PicNode("Kawab", Properties.Resources.Kawab)); FamilyMember<PicNode> HetepheresII = new FamilyMember<PicNode>( new PicNode("HetepheresII", Properties.Resources.Hetepheres_II)); FamilyMember<PicNode> DJEDEFRE = new FamilyMember<PicNode>( new PicNode("DJEDEFRE", Properties.Resources.DJEDEFRE)); FamilyMember<PicNode> Khentetka = new FamilyMember<PicNode>( new PicNode("Khentetka", Properties.Resources.Khentetka)); FamilyMember<PicNode> KHAFRE = new FamilyMember<PicNode>( new PicNode("KHAFRE", Properties.Resources.KHAFRE)); FamilyMember<PicNode> KhamerernebtyI = new FamilyMember<PicNode>( new PicNode("KhamerernebtyI", Properties.Resources.Khamerernebty_I)); FamilyMember<PicNode> Hemiunu = new FamilyMember<PicNode>( new PicNode("Hemiunu", Properties.Resources.Hemiunu)); FamilyMember<PicNode> MeresankhII = new FamilyMember<PicNode>( new PicNode("MeresankhII", Properties.Resources.Meresankh_II)); FamilyMember<PicNode> Setka = new FamilyMember<PicNode>( new PicNode("Setka", Properties.Resources.Setka)); FamilyMember<PicNode> Hernet = new FamilyMember<PicNode>( new PicNode("Hernet", Properties.Resources.Hernet)); FamilyMember<PicNode> MeresankhIII = new FamilyMember<PicNode>( new PicNode("MeresankhIII", Properties.Resources.Meresankh_III)); FamilyMember<PicNode> MENKAURA = new FamilyMember<PicNode>( new PicNode("MENKAURA", Properties.Resources.MENKAURA)); FamilyMember<PicNode> KhamerernebtyII = new FamilyMember<PicNode>( new PicNode("KhamerernebtyII", Properties.Resources.Khamerernebty_II)); FamilyMember<PicNode> Baka = new FamilyMember<PicNode>( new PicNode("Baka", Properties.Resources.Baka)); FamilyMember<PicNode> Neferhetepes = new FamilyMember<PicNode>( new PicNode("Neferhetepes", Properties.Resources.Neferhetepes)); FamilyMember<PicNode> SHEPSESKAF = new FamilyMember<PicNode>( new PicNode("SHEPSESKAF", Properties.Resources.SHEPSESKAF)); FamilyMember<PicNode> Bunefer = new FamilyMember<PicNode>( new PicNode("Bunefer", Properties.Resources.Bunefer)); FamilyMember<PicNode> Djedefptah = new FamilyMember<PicNode>( new PicNode("Djedefptah", Properties.Resources.Djedefptah)); FamilyMember<PicNode> Khamaat = new FamilyMember<PicNode>( new PicNode("Khamaat", Properties.Resources.Khamaat)); HetepheresI.Add(MerititesI); HetepheresI.Add(KHUFU); HetepheresI.Add(Henutsen); Unknown.Add(Rahotep); Unknown.Add(NefermaatI); Unknown.Add(Itet); MerititesI.Add(Djedefhor); MerititesI.Add(Kawab); KHUFU.Add(HetepheresII); KHUFU.Add(DJEDEFRE); KHUFU.Add(Khentetka); KHUFU.Add(KHAFRE); KHUFU.Add(KhamerernebtyI); NefermaatI.Add(Hemiunu); Djedefhor.Add(MeresankhII); DJEDEFRE.Add(Setka); DJEDEFRE.Add(Hernet); DJEDEFRE.Add(MeresankhIII); DJEDEFRE.Add(MENKAURA); DJEDEFRE.Add(KhamerernebtyII); Setka.Add(Baka); Setka.Add(Neferhetepes); MENKAURA.Add(SHEPSESKAF); MENKAURA.Add(Bunefer); SHEPSESKAF.Add(Djedefptah); SHEPSESKAF.Add(Khamaat); ShowTree(); }
VB.NET
Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As EventArgs) Dim MerititesI As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("MerititesI", _ My.Resources.Meritites_I)) Dim KHUFU As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("KHUFU", _ My.Resources.KHUFU)) Dim Henutsen As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Henutsen", _ My.Resources.Henutsen)) Dim Rahotep As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Rahotep", _ My.Resources.Rahotep)) Dim NefermaatI As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("NefermaatI", _ My.Resources.Nefermaat_I)) Dim Itet As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Itet", _ My.Resources.Itet)) Dim Djedefhor As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Djedefhor", _ My.Resources.Djedefhor)) Dim Kawab As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Kawab", _ My.Resources.Kawab)) Dim HetepheresII As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("HetepheresII", _ My.Resources.Hetepheres_II)) Dim DJEDEFRE As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("DJEDEFRE", _ My.Resources.DJEDEFRE)) Dim Khentetka As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Khentetka", _ My.Resources.Khentetka)) Dim KHAFRE As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("KHAFRE", _ My.Resources.KHAFRE)) Dim KhamerernebtyI As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("KhamerernebtyI", _ My.Resources.Khamerernebty_I)) Dim Hemiunu As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Hemiunu", _ My.Resources.Hemiunu)) Dim MeresankhII As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("MeresankhII", _ My.Resources.Meresankh_II)) Dim Setka As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Setka", _ My.Resources.Setka)) Dim Hernet As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Hernet", _ My.Resources.Hernet)) Dim MeresankhIII As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("MeresankhIII", _ My.Resources.Meresankh_III)) Dim MENKAURA As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("MENKAURA", _ My.Resources.MENKAURA)) Dim KhamerernebtyII As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("KhamerernebtyII", _ My.Resources. Dim Baka As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Baka", _ My.Resources.Baka)) Dim Neferhetepes As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Neferhetepes", _ My.Resources.Neferhetepes)) Dim SHEPSESKAF As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("SHEPSESKAF", _ My.Resources.SHEPSESKAF)) Dim Bunefer As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Bunefer", _ My.Resources.Bunefer)) Dim Djedefptah As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Djedefptah", _ My.Resources.Djedefptah)) Dim Khamaat As FamilyMember(Of PicNode) = New _ FamilyMember(Of PicNode)(New PicNode("Khamaat", _ My.Resources.Khamaat)) HetepheresI.Add(MerititesI) HetepheresI.Add(KHUFU) HetepheresI.Add(Henutsen) Unknown.Add(Rahotep) Unknown.Add( Unknown.Add(Itet) MerititesI.Add(Djedefhor) MerititesI.Add(Kawab) KHUFU.Add(HetepheresII) KHUFU.Add(DJEDEFRE) KHUFU.Add(Khentetka) KHUFU.Add(KHAFRE) KHUFU.Add(KhamerernebtyI) NefermaatI.Add(Hemiunu) Djedefhor.Add(MeresankhII) DJEDEFRE.Add(Setka) DJEDEFRE.Add(Hernet) DJEDEFRE.Add(MeresankhIII) DJEDEFRE.Add(MENKAURA) DJEDEFRE.Add(KhamerernebtyII) Setka.Add(Baka) Setka.Add(Neferhetepes) MENKAURA.Add(SHEPSESKAF) MENKAURA.Add(Bunefer) SHEPSESKAF.Add(Djedefptah) SHEPSESKAF.Add(Khamaat) ShowTree() End Sub
Finish up.
C#
private void picFamily_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; Unknown.DrawFamily(e.Graphics); // HetepheresI.DrawFamily(e.Graphics); // SNEFERU.DrawFamily(e.Graphics); } private void picFamily_MouseClick(object sender, MouseEventArgs e) { SelNode(e.Location); }
VB.NET
Private Sub picFamily_Paint(ByVal sender As Object, ByVal e _ As PaintEventArgs) e.Graphics.SmoothingMode = SmoothingMode.AntiAlias e.Graphics.TextRenderingHint = _ TextRenderingHint.AntiAliasGridFit Unknown.DrawFamily(e.Graphics) 'HetepheresI.DrawFamily(e.Graphics)' 'SNEFERU.DrawFamily(e.Graphics)' End Sub Private Sub picFamily_MouseClick(ByVal sender As Object, _ ByVal e As MouseEventArgs) SelNode(e.Location) End Sub
When you run the program, you can get three different Trees. These trees are shown in Figures 2-4.
Figure 2: Hetepheres I
Figure 3: SNEFERU
Figure 4: Unknown
C# Source on GitHub
VB.NET Source on GitHub
Conclusion
There, see how easy it was to create family tree in .NET? I hope you have learnt a lot about programming today, and a bit of history as well.