« WinForms » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
Aucun résumé des modifications
 
Ligne 1 : Ligne 1 :
=Événements Initialize, Load et Activate=
[[Category:CSharp]]
*Initialize: appelé lors de la création de la Form
= Événements Initialize, Load et Activate =
*Load: appelé lorsque la Form est chargée en mémoire
* Initialize: appelé lors de la création de la Form
*Activate: appelé à chaque fois que la Form devient la fenêtre active
* Load: appelé lorsque la Form est chargée en mémoire
* Activate: appelé à chaque fois que la Form devient la fenêtre active
[http://support.microsoft.com/kb/138819/en-us?fr=1 MSDN]
[http://support.microsoft.com/kb/138819/en-us?fr=1 MSDN]


=Dock et superposition=
= Dock et superposition =
ElementA docké en Fill et ElementB docké en bottom.<br/>
ElementA docké en Fill et ElementB docké en bottom.<br/>
ElementB se retrouve par dessous ElementA et masque le bas d'ElementA.<br/>
ElementB se retrouve par dessous ElementA et masque le bas d'ElementA.<br/>
<u>Solutions:</u>
<u>Solutions:</u>
*Right click sur ElementA and select “Bring to Front”
* Right click sur ElementA and select “Bring to Front”
*Ajouter ce code:
* Ajouter ce code:
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|<syntaxhighlight lang="csharp">
private void Form_Load(object sender, EventArgs e)
private void Form_Load(object sender, EventArgs e)
{
{
     ElementA.BringToFront();
     ElementA.BringToFront();
</syntaxhighlight>
</kode>
|}


=Centrer un Label=
= Centrer un Label =
AutoSize &rarr; False<br/>
AutoSize &rarr; False<br/>
TextAlign &rarr; MiddleCenter
TextAlign &rarr; MiddleCenter


=Simuler une entrée au clavier=
= Simuler une entrée au clavier =
[http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx]
[http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx]
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
SendKeys.Send("{Tab}");
SendKeys.Send("{Tab}");
</syntaxhighlight>
</kode>
|}


=Menu Contextuel=
= Menu Contextuel =
Ajouter un ContextMenuStrip → drag-drop depuis la boite à outils.<br/>
Ajouter un ContextMenuStrip → drag-drop depuis la boite à outils.<br/>
Lier le CMS à un élément graphique → via la propriété ContextMenuStrip<br/>
Lier le CMS à un élément graphique → via la propriété ContextMenuStrip<br/>
Ligne 40 : Ligne 36 :
Lier un événement à la sélection d'un menu → sélectionner l'élément du menu dans la vue du designer et ajouter un handler sur l'évènement Click<br/>
Lier un événement à la sélection d'un menu → sélectionner l'élément du menu dans la vue du designer et ajouter un handler sur l'évènement Click<br/>
La propriété ShotcutKeys permet d'associer un raccourci clavier à un élément du menu.
La propriété ShotcutKeys permet d'associer un raccourci clavier à un élément du menu.
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
// récupération du control contenant le menu contextuel
// récupération du control contenant le menu contextuel
private void tsmi_Click(object sender, EventArgs e)
private void tsmi_Click(object sender, EventArgs e)
Ligne 55 : Ligne 49 :
     var control = (DataGridView)ActiveControl;
     var control = (DataGridView)ActiveControl;
}
}
</syntaxhighlight>
</kode>
|}


=Form=
= Form =
==Propriétés intéressantes==
== Propriétés intéressantes ==
*ControlBox → Affiche/cache l'icône en haut à gauche ainsi que les boutons réduire, grandir et fermer en haut à droite.
* ControlBox → Affiche/cache l'icône en haut à gauche ainsi que les boutons réduire, grandir et fermer en haut à droite.


==Interdire le redimensionnement==
== Interdire le redimensionnement ==
*Propriété FormBorderStyle →  FixedSingle
* Propriété FormBorderStyle →  FixedSingle
*Propriété MaximizeBox → false
* Propriété MaximizeBox → false


==AutoScaleMode==
== AutoScaleMode ==
Détermine le comportement du formulaire lors d'un changement de la résolution (dpi) ou de la police (font).<br/>
Détermine le comportement du formulaire lors d'un changement de la résolution (dpi) ou de la police (font).<br/>
Choisir l'AutoScaleMode du formulaire principal, les sous formulaires peuvent hériter de l'AutoScaleMode de leur parent (Inherit).<br/>
Choisir l'AutoScaleMode du formulaire principal, les sous formulaires peuvent hériter de l'AutoScaleMode de leur parent (Inherit).<br/>
La valeur par défaut est font, cela peut causer des problèmes d'affichage. Préférer ''dpi'' ou ''none''.<br/>
La valeur par défaut est font, cela peut causer des problèmes d'affichage. Préférer ''dpi'' ou ''none''.<br/>


==Boutons OK et CANCEL dans une Form==
== Boutons OK et CANCEL dans une Form ==
Il faut affecter respectivement les valeurs OK et CANCEL à la propriété DialogResult des boutons.
Il faut affecter respectivement les valeurs OK et CANCEL à la propriété DialogResult des boutons.
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
NewForm form = new NewForm();
NewForm form = new NewForm();
if (form.ShowDialog(this) == DialogResult.OK) // fenetre modale
if (form.ShowDialog(this) == DialogResult.OK) // fenetre modale
{ ... }
{ ... }
form.Dispose();
form.Dispose();
</syntaxhighlight>
</kode>
|}


==Thread graphique et thread de calcul==
== Thread graphique et thread de calcul ==
Pour que le formulaire soit toujours visible et interactif, il est nécessaire de lancer un second thread qui s'occupera des calcul pendant que le premier thread (thread graphique) s'occupera de l'affichage du formulaire.<br/>
Pour que le formulaire soit toujours visible et interactif, il est nécessaire de lancer un second thread qui s'occupera des calcul pendant que le premier thread (thread graphique) s'occupera de l'affichage du formulaire.<br/>
Attention, le thread de calcul ne peut pas modifier directement les éléments du formulaire car ils appartiennent à un autre thread. Il faut donc utiliser les callback.
Attention, le thread de calcul ne peut pas modifier directement les éléments du formulaire car ils appartiennent à un autre thread. Il faut donc utiliser les callback.
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
Thread thread = new Thread(new ThreadStart(delegate()
Thread thread = new Thread(new ThreadStart(delegate()
{ // code qui doit être réalisé par le thread de calcul }));
{ // code qui doit être réalisé par le thread de calcul }));
Ligne 98 : Ligne 86 :


thread.Start();
thread.Start();
</syntaxhighlight>
</kode>
|}


==Callback et thread-safe==
== Callback et thread-safe ==
Fonction de rappel, permet de passer un pointeur sur fonction en paramètre (délégué).<br/>
Fonction de rappel, permet de passer un pointeur sur fonction en paramètre (délégué).<br/>
Dans cet exemple, c’est une méthode qui s’appelle elle-même de manière asynchrone via un délégué.
Dans cet exemple, c’est une méthode qui s’appelle elle-même de manière asynchrone via un délégué.
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
public class MainForm : Form
public class MainForm : Form
{
{
Ligne 136 : Ligne 121 :
   }
   }
}
}
</syntaxhighlight>
</kode>
|}
[http://msdn.microsoft.com/fr-fr/library/ms171728.aspx]
[http://msdn.microsoft.com/fr-fr/library/ms171728.aspx]


=DataGridView=
= DataGridView =
==Coller des données provenant d'Excel==
== Coller des données provenant d'Excel ==
{|
<kode lang="csharp">
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
|
<syntaxhighlight lang="csharp">
// récupération du contenu du presse papier
// récupération du contenu du presse papier
string clipboardText = Clipboard.GetText();
string clipboardText = Clipboard.GetText();
Ligne 197 : Ligne 178 :
// cette ligne peut générer une exception si la cellule est hidden
// cette ligne peut générer une exception si la cellule est hidden
dgv.CurrentCell = dgv[newColumnIndex, dgv.CurrentCell.RowIndex];
dgv.CurrentCell = dgv[newColumnIndex, dgv.CurrentCell.RowIndex];
</syntaxhighlight>
</kode>
|}
   
   
==EditMode==
== EditMode ==
<u>EditOnKeyStrokeOrF2 :</u> Mode par défaut, il faut double-cliquer sur une cellule pour l’éditer.<br/>
<u>EditOnKeyStrokeOrF2 :</u> Mode par défaut, il faut double-cliquer sur une cellule pour l’éditer.<br/>
<u>EditOnEnter :</u> Dans ce mode il suffit de cliquer sur la cellule pour l’éditer. Par contre un clique sur le header d’une ligne édite la première cellule, ce qui empêche de supprimer la ligne.<br/>
<u>EditOnEnter :</u> Dans ce mode il suffit de cliquer sur la cellule pour l’éditer. Par contre un clique sur le header d’une ligne édite la première cellule, ce qui empêche de supprimer la ligne.<br/>
EditOnEnter et suppression de ligne :
EditOnEnter et suppression de ligne :
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
private void DGV_MouseClick(object sender, MouseEventArgs e)
private void DGV_MouseClick(object sender, MouseEventArgs e)
{
{
Ligne 221 : Ligne 199 :
     }
     }
}
}
</syntaxhighlight>
</kode>
|}
 
 
==Tester les données des cellules dès leurs saisies==
== Tester les données des cellules dès leurs saisies ==
La validation bloque l’utilisateur tant qu’il n’a pas saisie de valeur valide et affiche un message d’erreur.
La validation bloque l’utilisateur tant qu’il n’a pas saisie de valeur valide et affiche un message d’erreur.
{|
 
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
<kode lang="csharp">
|
<syntaxhighlight lang="csharp">
private void dataGridView_CellValidating(object sender,
private void dataGridView_CellValidating(object sender,
   DataGridViewCellValidatingEventArgs e)
   DataGridViewCellValidatingEventArgs e)
Ligne 248 : Ligne 223 :
     ((DataGridView)sender).Rows[e.RowIndex].ErrorText = String.Empty;
     ((DataGridView)sender).Rows[e.RowIndex].ErrorText = String.Empty;
}
}
</syntaxhighlight>
</kode>
|}


=ComboBox=
= ComboBox =
L'événement SelectionChangeCommitted, à la différence des événements SelectedIndexChanged ou SelectedValueChanged, ne se produit que  lorsque l'utilisateur et non le programme modifie la sélection de la liste déroulante.
L'événement SelectionChangeCommitted, à la différence des événements SelectedIndexChanged ou SelectedValueChanged, ne se produit que  lorsque l'utilisateur et non le programme modifie la sélection de la liste déroulante.


=Pop-up message=
= Pop-up message =
{|
<kode lang="csharp">
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
|
<syntaxhighlight lang="csharp">
MessageBox.Show("message", "titre", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
MessageBox.Show("message", "titre", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
</syntaxhighlight>
</kode>
|}


=Progress Bar et Timer=
= Progress Bar et Timer =
{|
<kode lang="csharp">
!style="padding: 0 10px 0 0"| [[File:csharp.png|40px]]
|
<syntaxhighlight lang="csharp">
public partial class Form1 : Form
public partial class Form1 : Form
{
{
Ligne 322 : Ligne 289 :
     }
     }
}
}
</syntaxhighlight>
</kode>
|}
 
[[Category:CSharp]]

Dernière version du 12 avril 2020 à 22:06

Événements Initialize, Load et Activate

  • Initialize: appelé lors de la création de la Form
  • Load: appelé lorsque la Form est chargée en mémoire
  • Activate: appelé à chaque fois que la Form devient la fenêtre active

MSDN

Dock et superposition

ElementA docké en Fill et ElementB docké en bottom.
ElementB se retrouve par dessous ElementA et masque le bas d'ElementA.
Solutions:

  • Right click sur ElementA and select “Bring to Front”
  • Ajouter ce code:
Csharp.svg
private void Form_Load(object sender, EventArgs e)
{
    ElementA.BringToFront();

Centrer un Label

AutoSize → False
TextAlign → MiddleCenter

Simuler une entrée au clavier

[1]

Csharp.svg
SendKeys.Send("{Tab}");

Menu Contextuel

Ajouter un ContextMenuStrip → drag-drop depuis la boite à outils.
Lier le CMS à un élément graphique → via la propriété ContextMenuStrip
Ajouter des éléments au menu → via la propriété Items ou via la petite flèches au dessus du CMS dans le bas de la vue du designer
Lier un événement à la sélection d'un menu → sélectionner l'élément du menu dans la vue du designer et ajouter un handler sur l'évènement Click
La propriété ShotcutKeys permet d'associer un raccourci clavier à un élément du menu.

Csharp.svg
// récupération du control contenant le menu contextuel
private void tsmi_Click(object sender, EventArgs e)
{
    var menu = (ToolStripDropDownItem)sender;
    var strip = (ContextMenuStrip)menu.Owner;
    // SourceControl est null lors de l'utilisation des raccourcis clavier
    var control = (DataGridView)strip.SourceControl;

    // Dans ce cas et si le control n'est pas dans un SplitContainer
    var control = (DataGridView)ActiveControl;
}

Form

Propriétés intéressantes

  • ControlBox → Affiche/cache l'icône en haut à gauche ainsi que les boutons réduire, grandir et fermer en haut à droite.

Interdire le redimensionnement

  • Propriété FormBorderStyle → FixedSingle
  • Propriété MaximizeBox → false

AutoScaleMode

Détermine le comportement du formulaire lors d'un changement de la résolution (dpi) ou de la police (font).
Choisir l'AutoScaleMode du formulaire principal, les sous formulaires peuvent hériter de l'AutoScaleMode de leur parent (Inherit).
La valeur par défaut est font, cela peut causer des problèmes d'affichage. Préférer dpi ou none.

Boutons OK et CANCEL dans une Form

Il faut affecter respectivement les valeurs OK et CANCEL à la propriété DialogResult des boutons.

Csharp.svg
NewForm form = new NewForm();
if (form.ShowDialog(this) == DialogResult.OK) // fenetre modale
{ ... }
form.Dispose();

Thread graphique et thread de calcul

Pour que le formulaire soit toujours visible et interactif, il est nécessaire de lancer un second thread qui s'occupera des calcul pendant que le premier thread (thread graphique) s'occupera de l'affichage du formulaire.
Attention, le thread de calcul ne peut pas modifier directement les éléments du formulaire car ils appartiennent à un autre thread. Il faut donc utiliser les callback.

Csharp.svg
Thread thread = new Thread(new ThreadStart(delegate()
{ // code qui doit être réalisé par le thread de calcul }));

// ou
Thread thread = new Thread(methode);

thread.Start();

Callback et thread-safe

Fonction de rappel, permet de passer un pointeur sur fonction en paramètre (délégué).
Dans cet exemple, c’est une méthode qui s’appelle elle-même de manière asynchrone via un délégué.

Csharp.svg
public class MainForm : Form
{
  delegate void mainFormCallback(string text);

  private void button_Click(object sender, EventArgs e)
  {
    Thread thread = new Thread(new ThreadStart(delegate()
      {
          SetText("OK");
      });
    thread.Start();
  }
  private void SetText (string text)
  {
    // InvokeRequired compares the thread ID of the
    // calling thread to the thread ID of the creating thread.
    // If these threads are different, it returns true.
    if (this.button.InvokeRequired)
    {   // calls itself asynchronously
        mainFormCallback callback = new mainFormCallback(SetText);
        this.Invoke(callback, text);
    }
    else
    {
        button.Text = text;
    }
  }
}

[2]

DataGridView

Coller des données provenant d'Excel

Csharp.svg
// récupération du contenu du presse papier
string clipboardText = Clipboard.GetText();

// séparation par lignes et suppression des lignes vides
string[] clipboardLines = clipboardText.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

// séparation par cellules afin de connaitre le nombre d'éléments à coller
var clipboardElements = new List<string>();
foreach (var line in clipboardLines)
{
    clipboardElements.AddRange(line.Split('\t'));
}

// trie des éléments dans l'ordre croissant car les SelectedCells sont dans l'ordre de la sélection
// si elle s'est faite de gauche à droite et/ou de haut en bas
// les cellules sont en ordre décroissant d'index
var orderedSelectedCells = new List<DataGridViewCell>();
foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
{
    orderedSelectedCells.Add(cell);
}
orderedSelectedCells.Sort((dgvc1, dgvc2) =>
{
    var rowCompare = dgvc1.RowIndex.CompareTo(dgvc2.RowIndex);
    if (rowCompare != 0) return rowCompare;
    else
    {
        return dgvc1.ColumnIndex.CompareTo(dgvc2.ColumnIndex);
    }
});

// seulement si le nombre d'éléments à copier est <= à l'espace sélectionné pour la copie
if (clipboardElements.Count <= orderedSelectedCells.Count)
{
    for (int i = 0; i < clipboardElements.Count; i++)
    {
        orderedSelectedCells[i].Value =
            Convert.ChangeType(clipboardElements[i], orderedSelectedCells[i].ValueType);
    }
}

// si le mode d'édition est EditOnEnter, la dernière cellule collée est toujours en édition
// et son contenu visuellement pas à jour.
// pour corrigé ça on déplace le focus sur la cellule suivante ou sur la première
int newColumnIndex = 0;
if (dgv.CurrentCell.ColumnIndex + 1 <= dgv.Columns.Count)
{
    newColumnIndex = dgv.CurrentCell.ColumnIndex + 1;
}
// cette ligne peut générer une exception si la cellule est hidden
dgv.CurrentCell = dgv[newColumnIndex, dgv.CurrentCell.RowIndex];

EditMode

EditOnKeyStrokeOrF2 : Mode par défaut, il faut double-cliquer sur une cellule pour l’éditer.
EditOnEnter : Dans ce mode il suffit de cliquer sur la cellule pour l’éditer. Par contre un clique sur le header d’une ligne édite la première cellule, ce qui empêche de supprimer la ligne.
EditOnEnter et suppression de ligne :

Csharp.svg
private void DGV_MouseClick(object sender, MouseEventArgs e)
{
    DataGridView.HitTestInfo hitInfo = this.DGV.HitTest(e.X, e.Y);
    if (hitInfo.Type == DataGridViewHitTestType.RowHeader)
    {
        this.DGV.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2;
        this.DGV.EndEdit();
    }
    else
    {
        this.DGV.EditMode = DataGridViewEditMode.EditOnEnter;
    }
}

Tester les données des cellules dès leurs saisies

La validation bloque l’utilisateur tant qu’il n’a pas saisie de valeur valide et affiche un message d’erreur.

Csharp.svg
private void dataGridView_CellValidating(object sender,
  DataGridViewCellValidatingEventArgs e)
{
    DataGridView dgv = (DataGridView)sender;
    if (dgv.Columns[e.ColumnIndex] == "ColumnName")
    {
        if (string.IsNullOrEmpty(e.FormattedValue.ToString())
        {
            dgv.Rows[e.RowIndex].ErrorText = "Cell must not be empty";
            e.Cancel = true;
        }
    }
}
private void cduDataGridView_CellEndEdit(object sender,
  DataGridViewCellEventArgs e)
{
    ((DataGridView)sender).Rows[e.RowIndex].ErrorText = String.Empty;
}

ComboBox

L'événement SelectionChangeCommitted, à la différence des événements SelectedIndexChanged ou SelectedValueChanged, ne se produit que lorsque l'utilisateur et non le programme modifie la sélection de la liste déroulante.

Pop-up message

Csharp.svg
MessageBox.Show("message", "titre", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);

Progress Bar et Timer

Csharp.svg
public partial class Form1 : Form
{
    ToDO toDO;
    public Form1()
    {
        progressBar1.Minimum = 1;
        progressBar1.Maximum = 20;
        progressBar1.Value = 1;
        progressBar1.Step = 1;
        toDO = new ToDO();
        toDO.ReportStatusUpdated +=
            new ToDO.Delegate(toDO_ReportStatusUpdated);
        toDO.EndOfWork += new ToDO.Delegate(toDO_EndOfWork);
    }
    void toDO_EndOfWork()
    {
        button1.Text = "OK";
    }
    void toDO_ReportStatusUpdated()
    {
        progressBar1.PerformStep();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        toDO.DoWork();
    }
}
public class ToDO
{
    public delegate void Delegate();
    public event Delegate ReportStatusUpdated;
    public event Delegate EndOfWork;
    Timer timer;
    int count = 1;
    void timer_Tick(object sender, EventArgs e)
    {
        if (count++ > 19)
            WorkFinished();
        else
            ReportStatusUpdated();
    }
    private void WorkFinished()
    {
    timer.Enabled = false;
        EndOfWork();
    }
    public void DoWork()
    {
        timer = new Timer();
        timer.Interval = 1000;
        timer.Tick += new EventHandler(timer_Tick);
        timer.Enabled = true;
    }
}