mardi 6 août 2013

Ajouter une RichTextBox dans une fenêtre.

Dans l'exemple suivant, nous allons voir comment créer une RichTextBox dans une fenêtre. Bien entendu je vais également ajouter quelques contrôles pour mettre en forme le texte.

 
#Ce script affiche une fenêtre avec une RichTextBox.
#En haut de la fenêtre, des boutons permettent de changer
#la mise en forme du texte (Police, Taille, couleur, ...).

#Chemin du fichier .rtf.
$filertb = "C:\note.rtf"

#Cette fonction permet de modifier un des paramètres de la police,
#tout en conservant les autres.
Function ChangeRT($rtmode,$rtdata)
 {
   #Je mémorise les valeurs actuelles du texte sélectionné.
   $rtfont  = $global:richtb.SelectionFont.FontFamily
   $rtsize  = $global:richtb.SelectionFont.Size
   $rtstyle = $global:richtb.SelectionFont.Style
   #Puis je change la valeur spécifique en fonction du mode :
   #1-Font, 2-Size, 3-Style.
   if ($rtmode -eq 1) { $rtfont = $rtdata }   #Mode 1 : Change la police.
   if ($rtmode -eq 2) { $rtsize = $rtdata }   #Mode 2 : Change la taille.
   if ($rtmode -eq 3)
    {
      #Mode 3 : Change une des caractéristiques du style (toggle).
      #Attention le style est en mode binaire. Je vais donc utiliser des
      #opérateur binaire pour calculer tout ça (band, bor et bxor).
      #Note : Bit 1 = Gras, bit 2 = Italic, bit 3 = Souligné, ...
      #J'isole le bit du style qui m'interesse dans le style courant.
      $tbit = $rtstyle -band $rtdata
      #Puis, je regarde si mon style est déjà appliqué ou non.
      if ($tbit -ne $rtdata)
        {
          #Si le bit est a 0, j'ajoute mon style au style courant.
          $rtstyle = $rtstyle -bor $rtdata
        }
      else
        {
          #Si le bit est a 1, j'inverse les bits de mon style.
          $rbit = 255 -bxor $rtdata
          #Puis je soustrais mon style au style courant.
          $rtstyle = $rtstyle -band $rbit
        }
    }
   #J'applique le changement sur le texte sélectionné avec "SelectionFont".
   $global:richtb.SelectionFont = New-Object System.Drawing.Font($rtfont, $rtsize, $rtstyle, 3, 0)
 }

#Ouvre une fenêtre.
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object Windows.Forms.Form
$form.text = "Exemple de RichTextBox."
$form.Size = New-Object System.Drawing.Size(367,500)

#Bloque le redimensionnement de la fenêtre.
$form.minimumSize = New-Object System.Drawing.Size(367,500)
$form.maximumSize = New-Object System.Drawing.Size(367,500)

#Bouton sauvegarder.
$bouton1 = New-Object Windows.Forms.Button
$bouton1.Location = New-Object Drawing.Point 0,0
$bouton1.Size = New-Object System.Drawing.Size(24,22)
$bouton1.Font = New-Object System.Drawing.Font("Wingdings","12",0,3,0)
$bouton1.text = "="

#Pour sauvegarder le text, j'utilise "SaveFile".
$bouton1.add_click({ $global:richtb.SaveFile($filertb) })

#Liste déroulante "Police" (ComboBox).
$liste1 = New-Object System.Windows.Forms.Combobox
$liste1.Location = New-Object Drawing.Point 29,1
$liste1.Size = New-Object System.Drawing.Size(170,30)
$liste1.DropDownStyle = "DropDownList"
$liste1.Items.AddRange(("Arial", "Lucida Console", "Tahoma", "Time New Roman", "Verdana"))
$liste1.SelectedIndex = 1

#Pour modifier la police, j'utilise "SelectionFont" (voir fonction). 
$liste1.add_SelectedValueChanged({ ChangeRT 1 $liste1.Text })

#Liste déroulante "Taille" (ComboBox).
$liste2 = New-Object System.Windows.Forms.Combobox
$liste2.Location = New-Object Drawing.Point 200,1
$liste2.Size = New-Object System.Drawing.Size(49,30)
$liste2.DropDownStyle = "DropDownList"
$liste2.Items.AddRange(("8","9","10","11","12","14","16","18","20","22","24"))
$liste2.SelectedIndex = 2

#Pour modifier la taille, j'utilise "SelectionFont" (voir fonction).
$liste2.add_SelectedValueChanged({ ChangeRT 2 $liste2.Text })

#Bouton de style - Gras (Bold).
$bouton2 = New-Object Windows.Forms.Button
$bouton2.Location = New-Object Drawing.Point 255,0
$bouton2.Size = New-Object System.Drawing.Size(24,22)
$bouton2.Font = New-Object System.Drawing.Font("Cambria","10",[System.Drawing.FontStyle]::Bold,3,0)
$bouton2.text = "B"

#Pour modifier le style, j'utilise "SelectionFont" (voir fonction).
$bouton2.add_click({ ChangeRT 3 ([System.Drawing.FontStyle]::Bold) })

#Bouton de style - Italique (Italic).
$bouton3 = New-Object Windows.Forms.Button
$bouton3.Location = New-Object Drawing.Point 278,0
$bouton3.Size = New-Object System.Drawing.Size(24,22)
$bouton3.Font = New-Object System.Drawing.Font("Cambria","10",([System.Drawing.FontStyle]::Bold -bor [System.Drawing.FontStyle]::Italic),3,0)
$bouton3.text = "I"
$bouton3.add_click({ ChangeRT 3 ([System.Drawing.FontStyle]::Italic) })

#Bouton de style - Souligné (Underline).
$bouton4 = New-Object Windows.Forms.Button
$bouton4.Location = New-Object Drawing.Point 301,0
$bouton4.Size = New-Object System.Drawing.Size(24,22)
$bouton4.Font = New-Object System.Drawing.Font("Cambria","10",([System.Drawing.FontStyle]::Bold -bor [System.Drawing.FontStyle]::Underline),3,0)
$bouton4.text = "U"
$bouton4.add_click({ ChangeRT 3 ([System.Drawing.FontStyle]::Underline) })

#Création d'une image (PictureBox).
$image1 = New-Object System.Windows.Forms.pictureBox
$image1.Location = New-Object Drawing.Point 330,1
$image1.Size = New-Object System.Drawing.Size(10,10)
$image1.backcolor = "Black"

#Pour modifier la couleur, j'utilise "SelectionColor".
#Note : FromArgb(255,0,0,0) -> FromArgb(Alpha, Rouge, Vert, Blue).
$image1.add_click({ $global:richtb.SelectionColor = [System.Drawing.Color]::FromArgb(255,0,0,0) })

#Création d'une image (PictureBox).
$image2 = New-Object System.Windows.Forms.pictureBox
$image2.Location = New-Object Drawing.Point 340,1
$image2.Size = New-Object System.Drawing.Size(10,10)
$image2.backcolor = "Red"
$image2.add_click({ $global:richtb.SelectionColor = [System.Drawing.Color]::FromArgb(255,255,0,0) })

#Création d'une image (PictureBox).
$image3 = New-Object System.Windows.Forms.pictureBox
$image3.Location = New-Object Drawing.Point 330,11
$image3.Size = New-Object System.Drawing.Size(10,10)
$image3.backcolor = "Green"
$image3.add_click({ $global:richtb.SelectionColor = [System.Drawing.Color]::FromArgb(255,0,255,0) })

#Création d'une image (PictureBox).
$image4 = New-Object System.Windows.Forms.pictureBox
$image4.Location = New-Object Drawing.Point 340,11
$image4.Size = New-Object System.Drawing.Size(10,10)
$image4.backcolor = "Blue"
$image4.add_click({ $global:richtb.SelectionColor = [System.Drawing.Color]::FromArgb(255,0,0,255) })

#Création d'une RichTextBox (RichTextBox).
$global:richtb = New-Object Windows.Forms.RichTextBox
$global:richtb.Location = New-Object Drawing.Point 0,22
$global:richtb.Size = New-Object System.Drawing.Size(352,444)
$global:richtb.Font = New-Object System.Drawing.Font("Lucida Console","10",0,3,0)

#Active la détection des liens HyperText dans la richtextbox.
$global:richtb.DetectUrls = $true   #Active les liens Hyperlink.
$global:richtb.add_LinkClicked({ Invoke-Expression "start $($_.LinkText)" })

#Charge le fichier rtf au lancement du programme.
if (Test-Path $filertb) { $global:richtb.LoadFile($filertb) }

#Attache les contrôles à la fenêtre.
$form.controls.add($global:richtb)
$form.controls.add($bouton1)
$form.controls.add($bouton2)
$form.controls.add($bouton3)
$form.controls.add($bouton4)
$form.controls.add($liste1)
$form.controls.add($liste2)
$form.controls.add($image1)
$form.controls.add($image2)
$form.controls.add($image3)
$form.controls.add($image4)

#Affiche le tout.
$form.ShowDialog()

#Fin.

J'imagine que vous avez certainement remarqué le petit passage sur la gestion des bits dans la fonction ChangeRT. Pour ceux qui parle pas binaire couramment voici quelques explications.

En général on connais bien les décimales (base 10) dont l'unité va de 0 à 9. En informatique, a la base 10 s'ajoute souvent la base 16 (Hexa) et la base 2 (le binaire). Le binaire a une unité qui va de 0 a 1. sin on compte jusqu'à 7 en binaire cela donne :
0000 (= 0 en décimale)
1000 (= 1 en décimale)
0100 (= 2 en décimale)
1100 (= 3 en décimale)
0010 (= 4 en décimale)
1010 (= 5 en décimale)
0110 (= 6 en décimale)
1110 (= 7 en décimale)
Dans notre cas, chaque rang correspond à un style :
Rang 1 = Bold
Rang 2 = Italic
Rang 3 = Underline
Ainsi en binaire :
1000 = Bold
0100 = Italic
0010 = Underline 
Bien sur on peu mélanger les styles :
1100 = Bold et Italic
0110 = Italic et Underline
1110 = Bold, Italic et Underline
Dans la fonction le but est de changer l'un des rangs. Pour cela il faut connaitre l'état du rang que l'on souhaite changer et le changer en 1 ou en 0 sans toucher aux autres rangs. Pour cela j'utilise les 3 opérateurs -band -bor et bxor :
-bor (ou Bit OR) va faire regarder chaque rang de deux binaire et appliquer une opération "ou".
-and (ou Bit AND) va faire regarder chaque rang de deux binaire et appliquer une opération "et".
-bxor (ou Bit XOR) va faire regarder chaque rang et appliquer une opération "ou exclusif".
Par exemple :
1010 -bor 0010 = 1010
1010 -band 0010 = 0010
1010 -bxor 0010 = 1000
Si a ce stade vous êtes largué désolé ^^.
Si vous avez accroché jusque là, la suite devrait vous parler.

Dans mon script je veux modifier un des rangs tout en conservant les autres intactes. Pour l'exemple je vais prendre en entrée le style bold (1000). Imaginons que j'ai déjà appliqué le style Italic (0100) sur mon texte.
1- Je récupère mon style courant.
$rtstyle = $global:richtb.SelectionFont.Style
$rtstyle = 0100

2- J'extrais le rang que je veux tester dans le style courant.
$tbit = $rtstyle -band $rtdata
$tbit = 0100 -band 1000 = 0000
Note : $rtdata ne peut avoir qu'un seul de ses rangs à 1.

3- Je teste si le rang extrait est égale au rang recherché.
if ($tbit -ne $rtdata)
if (0 -ne 1) 
Dans ce cas il s'agit d'une bonne vielle comparaison décimale normal.

4- Si le style testé n'est pas présent, je l'ajoute au style courant.
$rtstyle = $rtstyle -bor $rtdata
$rtstyle = 0100 -bor 1000 = 1100 = Bold et Italic

Pour le deuxième cas je vais prendre en entrée le style bold (1000). Imaginons que j'ai déjà appliqué le style Bold et Italic (1100) sur mon texte.
1- Je récupère mon style courant.
$rtstyle = $global:richtb.SelectionFont.Style
$rtstyle = 1100

2- J'extrais le rang que je veux tester dans le style courant.
$tbit = $rtstyle -band $rtdata
$tbit = 1100 -band 1000 = 1000
Note : $rtdata ne peut avoir qu'un seul de ses rangs à 1.

3- Je teste si le rang extrait est égale au rang recherché.
if ($tbit -ne $rtdata)
if (1 -ne 1) 
Dans ce cas il s'agit d'une bonne vielle comparaison décimale normal.

4- Si le style testé est présent, je dois de retirer du style courant.
4.1- Pour cela je vais inverser tout les rangs de $rtdata.
$rbit = 15 -bxor $rtdata
$rbit = 1111 -bxor 1000 = 0111

4.2- Puis je soustrais mon style au style courant.
$rtstyle = $rtstyle -band $rbit
$rtstyle = 1100 -band 0111 = 0100 = Italic