mercredi 2 octobre 2013

TabControl Sample

Qu'elles sont les manipulations de base que l'on doit savoir facilement effectuer avec un TabControl. Voici un exemple de code source. Que se passe t-il lors du redimensionnement de la fenêtre principale ?

On a vu précédemment dans TabControl and TabPage Visible que l'on rencontre rapidement de petits soucis. Voici donc un exemple de code source de manipulation rapide des TabPages dans un TabControl.

Requirements :
Visual Studio 2010
Langage C#

Gestion des TabPages dans un TabControl

Un TabControl permet de gérer une collection de TabPages. Pour ajouter une TabPage, on se rend sur la Form principale et l'on sélectionne le TabControl :

Gestion des TabPages d'un TabControl
Dans la fenêtre des propriétés du TabControl on sélectionne la collection de TabPage :

Propriétés TabPages du TabControl 
En cliquant sur le bouton on obtient une fenêtre de gestion des TabPages :

Gérer la collection de TabPages dans un TabControl
Un autre moyen rapide de gestion des TabPages c'est en cliquant sur le petit triangle en haut à droite du TabControl :

Gestion rapide des TabPages d'un TabControl - TabControl Tasks
Voilà c'est tout pour le côté graphique.

TabControl code source 

La propriété TabPages du TabControl est une collection TabPageCollection et se gère comme telle, d'où le code pour changer l'ordre des TabPages :
private void buttonChangerOrdre_Click(object sender, EventArgs e)
{
tabControlMain.SuspendLayout();
tabControlMain.TabPages.Clear();
tabControlMain.TabPages.Add(tabPage3);
tabControlMain.TabPages.Add(tabPage2);
tabControlMain.TabPages.Add(tabPage1);
tabControlMain.ResumeLayout();
}

Sur un ordinateur rapide les fonctions SuspendLayout et ResumeLayout ne changent pas grand chose pour moi il y a encore quelques "sursauts graphiques".

Pour passer programmatiquement d'un TabPage à l'autre :
private void afficherTabPage2()
{
tabPage1.Hide();
tabPage2.Show();
tabControlMain.SelectedIndex = 1;
}

Pensez à sélectionner le bon index.

TabControl redimensionnement de la fenêtre principale

Le redimensionnement des contrôles dans les TabPages lors du changement de taille de la fenêtre principale Form1 est assuré par les deux fonctions :
private void Form1_ResizeBegin( object sender, EventArgs e )
{
    // Sauver les données de taille et de place au départ du déplacement
}

Et :
private void Form1_ResizeEnd( object sender, EventArgs e )
{
     // Calculer les nouvelles places et taille à la fin du déplacement
}

TabPage mauvais redimensionnement lors du Resize de la page

Problème rencontré : Lors du déploiement de cet exemple sur une plateforme Windows XP et lors du redimensionnement de la fenêtre principale voici le résultat :

TabControl problème lors de Resize de la fenêtre principale
On remarquera le mauvais redessinement du TabPage en bas.

Solution

C'est problèmes d'incompatibilité des composants standards multiplateforme windows sont assez délicats pour que l'on prenne le temps de s'y attarder. Ils engendrent souvent un délais non maîtrisable supplémentaire lors du développement. On ne les découvre souvent que trop tard une fois le client mécontent.

Il faut effectuer un Refresh du TabPage actif de la façon suivante :

private void Form1_ResizeEnd( object sender, EventArgs e )
{
    tabControlMain.TabPages[tabControlMain.SelectedIndex].Refresh();

Download Source Code


Have fun !



mardi 1 octobre 2013

Search Text in RichTextBox - Find function

Comment rechercher du Texte dans un contrôle RichTextBox. Voici une application Windows  un peu aboutie permettant d'ouvrir un fichier en édition dans une RichTextBox, de modifier ce fichier et de le sauvegarder.

Requirements :
Visual Studio 2010 C#
.NET Framework 3.5
Contrôle : RichTextBox

Structure et spécifications de l'application

Vous avez certainement déjà joué avec des fichiers sur disque dur afin de les ouvrir, de les traiter, de les afficher. Ici on va ouvrir un fichier et faire des recherches de texte dans ce fichier.

Il y a bon nombre de choses à faire lors de l'ouverture de la modification et de la sauvegarde d'un fichier, tous ces cas seront traité par l'application qui se compose d'un TabControl principal tabControlMain et de deux TabPages, tabPageFichier qui va permettre d'ouvrir de modifier et sauver le fichier dans le contrôle RichTextBox et tabPageConsole qui va permettre d'afficher le comportement de l'application et certains messages d'erreur lors de l'utilisation de l'application :

Application RichTextBox Find - Structure
Je vais créer un composant utilisateur dérivé RichTextBox et encapsuler mon contrôle dans une DLL ceci afin de créer un contrôle utilisateur que je pourrais à la fois utiliser dans mon application principale puis réutiliser dans une autre application.

A ma solution principale nommée RichTextBoxFind j'ajoute donc une Class Librairie WindowsFormsControlLibraryRichTextBoxFind qui va contenir une boite de dialogue DialogFind et mon nouveau contrôle utilisateur dérivé d'un contrôle RichTextBox, RichTextBoxFind :

Application RichTextBox Find - Visual Studio Solution
Ma boite de dialogue créé un Event particulier auquel mon nouveau composant utilisateur RichTextBoxFind va pouvoir s'abonner afin d'être prévenu lorsque l'utilisateur cliquera sur le bouton "Chercher". DialogFind est toute simple et propose les RichTextBoxFinds Options à l'utilisateur :

RichTextBoxFinds Options 
Je veux pouvoir montrer cette boite de dialogue lorsque l'utilisateur pressera les touches "Ctrl-F" dans la RichTextBox.

Détails de l'implémentation

Dans la DLL WindowsFormsControlLibraryRichTextBoxFind de ma RichTextBoxFind Windows Application, je créé un composant utilisateur que je nomme RichTextBoxFind :

Contrôle ou Composant Utilisateur RichTextBoxFind
Je dérive mon contrôle d'un contrôle RichTextBox de base :
public partial class RichTextBoxFind : RichTextBox // Component,

Dans ce contrôle, je créé un KeyEventHandler : RichTextBoxFind_KeyUp :
private void RichTextBoxFind_KeyUp( object sender, System.Windows.Forms.KeyEventArgs e )
{
// If key pressed in RichTextBox is "Ctrl+F" then Find
if ( e.Modifiers == Keys.Control & e.KeyCode == Keys.F )
{
if (findDialog == null)
{
findDialog = new DialogFind();
findDialog.Finded += new FindEventHandler(OnDialogFind);
}
this.HideSelection = false;

// Recuperer le texte sélectionné dans le RTB
string sel = this.SelectedText;
if ( sel != string.Empty )
{
TextBox tb = ( TextBox )GetControl( findDialog, "textBoxFind" );
tb.Text = sel.Trim();
}
findDialog.ShowDialog();
}
}

Qui s'occupe de capter les touches pressées par l'utilisateur et récupère le "Ctrl-F" pour afficher la boite de dialogue DialogFind et au passage on abonne la fonction OnDialogFind à l'événement Finded. 
L'algorithme de recherche de texte dans un RichTextBox se trouve dans la fonction OnDialogFind de ce nouveau composant utilisateur.

Ma boite de dialogue DialogFind créé un User Event Handler : Finded :
namespace WindowsFormsControlLibraryRichTextBoxFind
{
    // A delegate type for hooking find notifications.
    public delegate void FindEventHandler( string findWhat, RichTextBoxFinds findOption );
    
    public partial class DialogFind : Form
    {
        public event FindEventHandler Finded;
        ...

Qui va permettre de déclencher un événement Finded à destination de mon contrôle RichTextBoxFind lorsque l'utilisateur cliquera sur le bouton "Chercher".

Ma boite de dialogue possède ainsi un EventHandler qui s'occupe de gérer les options de recherche et de déclencher l'événement Find à destination de la RichTextBox :
private void buttonFind_Click( object sender, EventArgs e )
{
if ( textBoxFind.TextLength > 0 )
{
RichTextBoxFinds findOption = new RichTextBoxFinds();
if ( checkBoxMatchCase.Checked ) 
findOption = RichTextBoxFinds.MatchCase;
if ( checkBoxWholeWord.Checked ) 
findOption = findOption | RichTextBoxFinds.WholeWord;
if ( radioButtonUp.Checked ) 
findOption = findOption | RichTextBoxFinds.Reverse;
if ( Finded != null )
{
this.Finded( textBoxFind.Text, findOption );
}
}
}

Pour utiliser mon nouveau composant utilisateur dans mon application principale. J'utilise une possibilité de la ToolBox bouton droit -> "Choose Items" :

ToolBox de Visual Studio Ajouter un composant utilisateur
Qui me permet de browser ma DLL WindowsFormsControlLibraryRichTextBoxFind.dll et ainsi d'ajouter dans la ToolBox mon nouveau composant :

ToolBox Nouveau composant RichTextBoxFind
En drag and dropant ce nouveau contrôle dans la fenêtre de mon application je peux l'utiliser :

RichTextBoxFind - Fenêtre principale
L'application principale s'occupe de jouer avec le fichier de l'afficher et lorsque je presse les touches "Ctrl-F" de mon application en ayant au préalable sélectionné le texte que je souhaite rechercher voici l'exécution :


RichTextBoxFind - Windows Application - Exécution

Download Source Code

Ce code source en C# fait bien d'autres choses qui ne sont pas détaillées ici concernant le traitement des fichiers ... à vous de creuser. Tout l'intérêt de cet exemple réside dans l'utilisation de la fonction Find() du RichTextBox au sein de l'algorithme OnDialogFind car j'ai trouvé sur internet d'autres exemples bien plus hasardeux.