Afficher un arbre dans une fenêtre en C#

Nous avons vu comment récupérer les informations d'une classe par réflexion, et comment peupler un arbre avec ces données, et nous avons vu comment afficher ces arbres dans la console. Nous avons aussi vu comment créer une fenêtre pour notre application, et comment sélectionner le fichier à analyser.

Maintenant, nous allons voir comment afficher les arbres dans notre fenêtre.

Ajouter un TreeView

Nous allons utiliser un composant TreeView, qui appartient à System.Windows.Forms.

Dans l'onglet Solution Explorer de Visual Studio, nous devons sélectionner notre fichier Form1.cs, qui s'ouvrira par défaut en mode design.

Dans l'onglet Toolbox, nous pouvons sélectionner un composant TreeView, et le glisser à l'aide de la souris (drag and drop) directement sur la représentation de la fenêtre. Comme dans le cas d'un éditeur graphique, nous pouvons déplacer le TreeView pour le positionner correctement sur la fenêtre de notre application, puis sélectionner un des coins du TreeView, et l'étendre jusqu'au moment ou sa taille nous convient.

Nous pouvons modifier le nom du composant pour lui donner un nom significatif dans le code (par exemple classInfoTreeView).

Construire le TreeView

Nous avons donc une fenêtre avec un composant TreeView, mais ce dernier est vide. Nous pouvons doublecliquer sur notre menu File/Open de notre fenêtre en mode design et Visual Studio nous place directement dans notre méthode fileToolStripMenuItem_Click (qui jusqu'ici permettait l'affichage du nom du fichier sélectionné).

A cet endroit, nous allons faire appel à une méthode (que nous pouvons appeler fillTreeView()) qui permettra de peupler le TreeView avec les TreeNodes que nous récupérons gràce à notre classe ClassInfo.


Code c# (Form1.cs fileToolStripMenuItem_Click) (6 lignes) :
  1. private void fileToolStripMenuItem_Click(object sender, EventArgs e)
  2. {
  3. openFileDialog.ShowDialog();
  4. fillAndDisplayPathLabel();
  5. fillTreeView();
  6. }

Code c# (Form1.cs fillTreeView) (6 lignes) :
  1. private void fillTreeView()
  2. {
  3. classInfoTreeView.Nodes.Clear();
  4. classInfoTreeView.Nodes.Add(ClassInfo.getFileName(openFileDialog.FileName));
  5. classInfoTreeView.Nodes[0].Nodes.AddRange(ClassInfo.getInfos(openFileDialog.FileName));
  6. }

Ce n'est pas plus compliqué que ça.

Arbres en GUI

Les différents nœuds de l'arbre sont automatiquement représentés en couleur, car la couleur est définie dans la classe ClassInfo au moment de la création des TreeNodes. Cette manière de procéder est pratique et rapide, mais nous pouvons toutefois douter de la pertinence de notre choix de laisser la responsabilité de la présentation (le choix des couleurs) dans la classe qui appartient plus au modèle qu'à la vue.


Tous les codes

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4. namespace ClassExplorer
  5. {
  6. static class Program
  7. {
  8. /// <summary>
  9. /// The main entry point for the application.
  10. /// </summary>
  11. [STAThread]
  12. static void Main()
  13. {
  14. Application.EnableVisualStyles();
  15. Application.SetCompatibleTextRenderingDefault(false);
  16. Application.Run(new Form1());
  17. }
  18. }
  19. }
  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using System.Reflection;
  5. using System.IO;
  6. using System.Windows.Forms;
  7. using System.Drawing;
  8. namespace ClassExplorer
  9. {
  10. class ClassInfo
  11. {
  12. public static TreeNode[] getInfos(String classPath)
  13. {
  14. TreeNode classesTreeNode = new TreeNode("Classes");
  15. TreeNode enumsTreeNode = new TreeNode("Enums");
  16. TreeNode interfacesTreeNode = new TreeNode("Interfaces");
  17. try
  18. {
  19. Assembly assembly = Assembly.LoadFrom(classPath);
  20. Type[] types = assembly.GetTypes();
  21. foreach (Type type in types)
  22. {
  23. if (type.IsClass) classesTreeNode.Nodes.Add(getClassNode(type));
  24. else if (type.IsEnum) enumsTreeNode.Nodes.Add(type.Name);
  25. else if (type.IsInterface) interfacesTreeNode.Nodes.Add(type.Name);
  26. }
  27. }
  28. catch (Exception e)
  29. {
  30. }
  31. TreeNode[] infos = { classesTreeNode, enumsTreeNode, interfacesTreeNode };
  32. return infos;
  33. }
  34. public static String getFileInfos(String classPath)
  35. {
  36. FileSystemInfo f = new FileInfo(classPath);
  37. StringBuilder str = new StringBuilder(f.Name);
  38. str.Append("\n\nInfos :");
  39. str.Append("\nCreation time : ");
  40. str.Append(f.CreationTime);
  41. str.Append("\nLast access : ");
  42. str.Append(f.LastAccessTime);
  43. str.Append("\nAttributes : ");
  44. str.Append(f.Attributes);
  45. str.Append("\nFullName : ");
  46. str.Append(f.FullName);
  47. return str.ToString();
  48. }
  49. public static String getFileName(String classPath)
  50. {
  51. FileSystemInfo f = new FileInfo(classPath);
  52. return f.Name;
  53. }
  54. private static TreeNode getClassNode(Type type)
  55. {
  56. TreeNode classNode = new TreeNode(type.Name);
  57. MethodInfo[] methodsInfos = type.GetMethods(
  58. BindingFlags.NonPublic |
  59. BindingFlags.Instance |
  60. BindingFlags.Public |
  61. BindingFlags.Static |
  62. BindingFlags.DeclaredOnly
  63. );
  64. if (methodsInfos.Length > 0)
  65. {
  66. TreeNode methodsNode = new TreeNode("Methods (" + methodsInfos.Length +")");
  67. methodsNode.ForeColor = System.Drawing.Color.Blue;
  68. foreach (MethodInfo methodInfo in methodsInfos)
  69. {
  70. methodsNode.Nodes.Add(getMethodNode(methodInfo));
  71. }
  72. classNode.Nodes.Add(methodsNode);
  73. }
  74. else classNode.Nodes.Add("No methods available");
  75. ConstructorInfo[] constructorsInfos = type.GetConstructors(
  76. BindingFlags.NonPublic |
  77. BindingFlags.Instance |
  78. BindingFlags.Public |
  79. BindingFlags.Static |
  80. BindingFlags.DeclaredOnly
  81. );
  82. if (constructorsInfos.Length > 0)
  83. {
  84. TreeNode constructorsNode = new TreeNode("Constructors (" + constructorsInfos.Length + ")");
  85. constructorsNode.ForeColor = System.Drawing.Color.Green;
  86. foreach (ConstructorInfo constructorInfo in constructorsInfos)
  87. {
  88. constructorsNode.Nodes.Add(getConstructorNode(constructorInfo));
  89. }
  90. classNode.Nodes.Add(constructorsNode);
  91. }
  92. else classNode.Nodes.Add("No constructors available");
  93. FieldInfo[] fieldsInfos = type.GetFields(
  94. BindingFlags.NonPublic |
  95. BindingFlags.Instance |
  96. BindingFlags.Public |
  97. BindingFlags.Static |
  98. BindingFlags.DeclaredOnly
  99. );
  100. if (fieldsInfos.Length > 0)
  101. {
  102. TreeNode fieldsNode = new TreeNode("Fields (" + fieldsInfos.Length + ")");
  103. fieldsNode.ForeColor = System.Drawing.Color.Navy;
  104. foreach (FieldInfo fieldInfo in fieldsInfos)
  105. {
  106. fieldsNode.Nodes.Add(getFieldNode(fieldInfo));
  107. }
  108. classNode.Nodes.Add(fieldsNode);
  109. }
  110. else classNode.Nodes.Add("No fields available");
  111. PropertyInfo[] propsInfos = type.GetProperties(
  112. BindingFlags.NonPublic |
  113. BindingFlags.Instance |
  114. BindingFlags.Public |
  115. BindingFlags.Static |
  116. BindingFlags.DeclaredOnly
  117. );
  118. if (propsInfos.Length > 0)
  119. {
  120. TreeNode propsNode = new TreeNode("Properties (" + propsInfos.Length + ")");
  121. foreach (PropertyInfo propInfo in propsInfos)
  122. {
  123. propsNode.Nodes.Add(propInfo.Name);
  124. }
  125. classNode.Nodes.Add(propsNode);
  126. }
  127. else classNode.Nodes.Add("No properties available");
  128. return classNode;
  129. }
  130. private static TreeNode getConstructorNode(ConstructorInfo constructorInfo)
  131. {
  132. StringBuilder constrStr = new StringBuilder();
  133. if (constructorInfo.IsPrivate) constrStr.Append("Private ");
  134. else if (constructorInfo.IsStatic) constrStr.Append("Static ");
  135. else if (constructorInfo.IsPublic) constrStr.Append("Public ");
  136. constrStr.Append(constructorInfo.Name);
  137. TreeNode constructorNode = new TreeNode(constrStr.ToString());
  138. constructorNode.ForeColor = System.Drawing.Color.GreenYellow;
  139. ParameterInfo[] paramInfos = constructorInfo.GetParameters();
  140. foreach (ParameterInfo paramInfo in paramInfos)
  141. {
  142. constructorNode.Nodes.Add(
  143. String.Format("{0} {1}", paramInfo.ParameterType.ToString(), paramInfo.Name)
  144. );
  145. }
  146. return constructorNode;
  147. }
  148. private static TreeNode getMethodNode(MethodInfo methodInfo)
  149. {
  150. StringBuilder methodStr = new StringBuilder();
  151. if (methodInfo.IsPrivate) methodStr.Append("Private ");
  152. else if (methodInfo.IsStatic) methodStr.Append("Static ");
  153. else if (methodInfo.IsPublic) methodStr.Append("Public ");
  154. methodStr.Append(methodInfo.Name);
  155. TreeNode methodNode = new TreeNode(methodStr.ToString());
  156. methodNode.ForeColor = System.Drawing.Color.Red;
  157. ParameterInfo[] paramInfos = methodInfo.GetParameters();
  158. foreach (ParameterInfo paramInfo in paramInfos)
  159. {
  160. methodNode.Nodes.Add(
  161. String.Format("{0} {1}", paramInfo.ParameterType.ToString(), paramInfo.Name)
  162. );
  163. }
  164. return methodNode;
  165. }
  166. private static TreeNode getFieldNode(FieldInfo fieldInfo)
  167. {
  168. StringBuilder fieldStr = new StringBuilder();
  169. if (fieldInfo.IsPrivate) fieldStr.Append("Private ");
  170. else if (fieldInfo.IsStatic) fieldStr.Append("Static ");
  171. else if (fieldInfo.IsPublic) fieldStr.Append("Public ");
  172. fieldStr.Append(fieldInfo.Name);
  173. TreeNode fieldNode = new TreeNode(fieldStr.ToString());
  174. fieldNode.ForeColor = System.Drawing.Color.DarkGreen;
  175. return fieldNode;
  176. }
  177. }
  178. }
  1. using System.Windows.Forms;
  2. namespace ClassExplorer
  3. {
  4. partial class Form1
  5. {
  6. /// <summary>
  7. /// Required designer variable.
  8. /// </summary>
  9. private System.ComponentModel.IContainer components = null;
  10. /// <summary>
  11. /// Clean up any resources being used.
  12. /// </summary>
  13. /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
  14. protected override void Dispose(bool disposing)
  15. {
  16. if (disposing && (components != null))
  17. {
  18. components.Dispose();
  19. }
  20. base.Dispose(disposing);
  21. }
  22. #region Windows Form Designer generated code
  23. /// <summary>
  24. /// Required method for Designer support - do not modify
  25. /// the contents of this method with the code editor.
  26. /// </summary>
  27. private void InitializeComponent()
  28. {
  29. System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
  30. this.toolStrip1 = new System.Windows.Forms.ToolStrip();
  31. this.fileToolStripButton = new System.Windows.Forms.ToolStripDropDownButton();
  32. this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
  33. this.filePathLabel = new System.Windows.Forms.Label();
  34. this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
  35. this.classInfoTreeView = new System.Windows.Forms.TreeView();
  36. this.toolStrip1.SuspendLayout();
  37. this.SuspendLayout();
  38. //
  39. // toolStrip1
  40. //
  41. this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
  42. this.fileToolStripButton});
  43. this.toolStrip1.Location = new System.Drawing.Point(0, 0);
  44. this.toolStrip1.Name = "toolStrip1";
  45. this.toolStrip1.Size = new System.Drawing.Size(292, 25);
  46. this.toolStrip1.TabIndex = 0;
  47. this.toolStrip1.Text = "toolStrip1";
  48. //
  49. // fileToolStripButton
  50. //
  51. this.fileToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
  52. this.fileToolStripButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
  53. this.fileToolStripMenuItem});
  54. this.fileToolStripButton.Image = ((System.Drawing.Image)(resources.GetObject("fileToolStripButton.Image")));
  55. this.fileToolStripButton.ImageTransparentColor = System.Drawing.Color.Magenta;
  56. this.fileToolStripButton.Name = "fileToolStripButton";
  57. this.fileToolStripButton.Size = new System.Drawing.Size(36, 22);
  58. this.fileToolStripButton.Text = "File";
  59. //
  60. // fileToolStripMenuItem
  61. //
  62. this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
  63. this.fileToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
  64. this.fileToolStripMenuItem.Text = "Open...";
  65. this.fileToolStripMenuItem.Click += new System.EventHandler(this.fileToolStripMenuItem_Click);
  66. //
  67. // filePathLabel
  68. //
  69. this.filePathLabel.AutoSize = true;
  70. this.filePathLabel.Location = new System.Drawing.Point(12, 40);
  71. this.filePathLabel.Name = "filePathLabel";
  72. this.filePathLabel.Size = new System.Drawing.Size(0, 13);
  73. this.filePathLabel.TabIndex = 1;
  74. this.filePathLabel.Visible = false;
  75. //
  76. // openFileDialog
  77. //
  78. this.openFileDialog.Filter = "Executable files (.exe)|*.exe|Dynamic librairies (.dll)|*.dll";
  79. //
  80. // classInfoTreeView
  81. //
  82. this.classInfoTreeView.Location = new System.Drawing.Point(0, 80);
  83. this.classInfoTreeView.Name = "classInfoTreeView";
  84. this.classInfoTreeView.Size = new System.Drawing.Size(292, 201);
  85. this.classInfoTreeView.TabIndex = 2;
  86. //
  87. // Form1
  88. //
  89. this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
  90. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  91. this.ClientSize = new System.Drawing.Size(292, 273);
  92. this.Controls.Add(this.classInfoTreeView);
  93. this.Controls.Add(this.filePathLabel);
  94. this.Controls.Add(this.toolStrip1);
  95. this.Name = "Form1";
  96. this.Text = "My Class Explorer";
  97. this.toolStrip1.ResumeLayout(false);
  98. this.toolStrip1.PerformLayout();
  99. this.ResumeLayout(false);
  100. this.PerformLayout();
  101. }
  102. #endregion
  103. private ToolStrip toolStrip1;
  104. private ToolStripDropDownButton fileToolStripButton;
  105. private ToolStripMenuItem fileToolStripMenuItem;
  106. private Label filePathLabel;
  107. private OpenFileDialog openFileDialog;
  108. private TreeView classInfoTreeView;
  109. }
  110. }
  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. using System.Reflection;
  5. using System.IO;
  6. using System.Windows.Forms;
  7. using System.Drawing;
  8. namespace ClassExplorer
  9. {
  10. class ClassInfo
  11. {
  12. public static TreeNode[] getInfos(String classPath)
  13. {
  14. TreeNode classesTreeNode = new TreeNode("Classes");
  15. TreeNode enumsTreeNode = new TreeNode("Enums");
  16. TreeNode interfacesTreeNode = new TreeNode("Interfaces");
  17. try
  18. {
  19. Assembly assembly = Assembly.LoadFrom(classPath);
  20. Type[] types = assembly.GetTypes();
  21. foreach (Type type in types)
  22. {
  23. if (type.IsClass) classesTreeNode.Nodes.Add(getClassNode(type));
  24. else if (type.IsEnum) enumsTreeNode.Nodes.Add(type.Name);
  25. else if (type.IsInterface) interfacesTreeNode.Nodes.Add(type.Name);
  26. }
  27. }
  28. catch (Exception e)
  29. {
  30. }
  31. TreeNode[] infos = { classesTreeNode, enumsTreeNode, interfacesTreeNode };
  32. return infos;
  33. }
  34. public static String getFileInfos(String classPath)
  35. {
  36. FileSystemInfo f = new FileInfo(classPath);
  37. StringBuilder str = new StringBuilder(f.Name);
  38. str.Append("\n\nInfos :");
  39. str.Append("\nCreation time : ");
  40. str.Append(f.CreationTime);
  41. str.Append("\nLast access : ");
  42. str.Append(f.LastAccessTime);
  43. str.Append("\nAttributes : ");
  44. str.Append(f.Attributes);
  45. str.Append("\nFullName : ");
  46. str.Append(f.FullName);
  47. return str.ToString();
  48. }
  49. public static String getFileName(String classPath)
  50. {
  51. FileSystemInfo f = new FileInfo(classPath);
  52. return f.Name;
  53. }
  54. private static TreeNode getClassNode(Type type)
  55. {
  56. TreeNode classNode = new TreeNode(type.Name);
  57. MethodInfo[] methodsInfos = type.GetMethods(
  58. BindingFlags.NonPublic |
  59. BindingFlags.Instance |
  60. BindingFlags.Public |
  61. BindingFlags.Static |
  62. BindingFlags.DeclaredOnly
  63. );
  64. if (methodsInfos.Length > 0)
  65. {
  66. TreeNode methodsNode = new TreeNode("Methods (" + methodsInfos.Length +")");
  67. methodsNode.ForeColor = System.Drawing.Color.Blue;
  68. foreach (MethodInfo methodInfo in methodsInfos)
  69. {
  70. methodsNode.Nodes.Add(getMethodNode(methodInfo));
  71. }
  72. classNode.Nodes.Add(methodsNode);
  73. }
  74. else classNode.Nodes.Add("No methods available");
  75. ConstructorInfo[] constructorsInfos = type.GetConstructors(
  76. BindingFlags.NonPublic |
  77. BindingFlags.Instance |
  78. BindingFlags.Public |
  79. BindingFlags.Static |
  80. BindingFlags.DeclaredOnly
  81. );
  82. if (constructorsInfos.Length > 0)
  83. {
  84. TreeNode constructorsNode = new TreeNode("Constructors (" + constructorsInfos.Length + ")");
  85. constructorsNode.ForeColor = System.Drawing.Color.Green;
  86. foreach (ConstructorInfo constructorInfo in constructorsInfos)
  87. {
  88. constructorsNode.Nodes.Add(getConstructorNode(constructorInfo));
  89. }
  90. classNode.Nodes.Add(constructorsNode);
  91. }
  92. else classNode.Nodes.Add("No constructors available");
  93. FieldInfo[] fieldsInfos = type.GetFields(
  94. BindingFlags.NonPublic |
  95. BindingFlags.Instance |
  96. BindingFlags.Public |
  97. BindingFlags.Static |
  98. BindingFlags.DeclaredOnly
  99. );
  100. if (fieldsInfos.Length > 0)
  101. {
  102. TreeNode fieldsNode = new TreeNode("Fields (" + fieldsInfos.Length + ")");
  103. fieldsNode.ForeColor = System.Drawing.Color.Navy;
  104. foreach (FieldInfo fieldInfo in fieldsInfos)
  105. {
  106. fieldsNode.Nodes.Add(getFieldNode(fieldInfo));
  107. }
  108. classNode.Nodes.Add(fieldsNode);
  109. }
  110. else classNode.Nodes.Add("No fields available");
  111. PropertyInfo[] propsInfos = type.GetProperties(
  112. BindingFlags.NonPublic |
  113. BindingFlags.Instance |
  114. BindingFlags.Public |
  115. BindingFlags.Static |
  116. BindingFlags.DeclaredOnly
  117. );
  118. if (propsInfos.Length > 0)
  119. {
  120. TreeNode propsNode = new TreeNode("Properties (" + propsInfos.Length + ")");
  121. foreach (PropertyInfo propInfo in propsInfos)
  122. {
  123. propsNode.Nodes.Add(propInfo.Name);
  124. }
  125. classNode.Nodes.Add(propsNode);
  126. }
  127. else classNode.Nodes.Add("No properties available");
  128. return classNode;
  129. }
  130. private static TreeNode getConstructorNode(ConstructorInfo constructorInfo)
  131. {
  132. StringBuilder constrStr = new StringBuilder();
  133. if (constructorInfo.IsPrivate) constrStr.Append("Private ");
  134. else if (constructorInfo.IsStatic) constrStr.Append("Static ");
  135. else if (constructorInfo.IsPublic) constrStr.Append("Public ");
  136. constrStr.Append(constructorInfo.Name);
  137. TreeNode constructorNode = new TreeNode(constrStr.ToString());
  138. constructorNode.ForeColor = System.Drawing.Color.GreenYellow;
  139. ParameterInfo[] paramInfos = constructorInfo.GetParameters();
  140. foreach (ParameterInfo paramInfo in paramInfos)
  141. {
  142. constructorNode.Nodes.Add(
  143. String.Format("{0} {1}", paramInfo.ParameterType.ToString(), paramInfo.Name)
  144. );
  145. }
  146. return constructorNode;
  147. }
  148. private static TreeNode getMethodNode(MethodInfo methodInfo)
  149. {
  150. StringBuilder methodStr = new StringBuilder();
  151. if (methodInfo.IsPrivate) methodStr.Append("Private ");
  152. else if (methodInfo.IsStatic) methodStr.Append("Static ");
  153. else if (methodInfo.IsPublic) methodStr.Append("Public ");
  154. methodStr.Append(methodInfo.Name);
  155. TreeNode methodNode = new TreeNode(methodStr.ToString());
  156. methodNode.ForeColor = System.Drawing.Color.Red;
  157. ParameterInfo[] paramInfos = methodInfo.GetParameters();
  158. foreach (ParameterInfo paramInfo in paramInfos)
  159. {
  160. methodNode.Nodes.Add(
  161. String.Format("{0} {1}", paramInfo.ParameterType.ToString(), paramInfo.Name)
  162. );
  163. }
  164. return methodNode;
  165. }
  166. private static TreeNode getFieldNode(FieldInfo fieldInfo)
  167. {
  168. StringBuilder fieldStr = new StringBuilder();
  169. if (fieldInfo.IsPrivate) fieldStr.Append("Private ");
  170. else if (fieldInfo.IsStatic) fieldStr.Append("Static ");
  171. else if (fieldInfo.IsPublic) fieldStr.Append("Public ");
  172. fieldStr.Append(fieldInfo.Name);
  173. TreeNode fieldNode = new TreeNode(fieldStr.ToString());
  174. fieldNode.ForeColor = System.Drawing.Color.DarkGreen;
  175. return fieldNode;
  176. }
  177. }
  178. }

Réseaux sociaux

Vous pouvez modifier vos préférences dans votre profil pour ne plus afficher les interactions avec les réseaux sociaux sur ces pages.

 

Structure du document

Astuce pour imprimer les couleurs des cellules de tableaux : http://www.gaudry.be/ast-rf-450.html
Aucun commentaire pour cette page

© Ce document issu de l′infobrol est enregistré sous le certificat Cyber PrInterDeposit Digital Numbertection. Enregistrement IDDN n° 5329-3667
Document créé le 02/10/06 18:37, dernière modification le Vendredi 17 Juin 2011, 12:11
Source du document imprimé : http:///www.gaudry.be/csharp-gui-tree.html
St.Gaudry©07.01.02
Outils (masquer)
||
Recherche (afficher)
Recherche :

Utilisateur (masquer)
Apparence (afficher)
Stats (afficher)
15838 documents
455 astuces.
550 niouzes.
3107 definitions.
447 membres.
8121 messages.

Document genere en :
0,15 seconde

Mises à jour :
Mises à jour du site
Citation (masquer)
Code is how we tell our colleagues how we feel about them.

Venkat Subramaniam [devoxx 2016]
 
l'infobrol
Nous sommes le Mardi 23 Mai 2017, 22:28, toutes les heures sont au format GMT+1.00 Heure, heure d'été (+1)