2015-03-01
- correction cosmétique
   du modèle du Blog
  ° diaporama occupant
     tout l'écran
  ° message défilant
     démarrant du bord
     droit sous Chrome

Trognon le chaton

En lumière..

Des articles Lesbiens: Camellia Rose ,
Lipsticks [:* Fanny] , Lisa
et des Histoires signées MyLzz59: Mylène écrit (http://mylene-ecrit.blogspot.fr)

Des articles Trans-*: Ma Vie En Rose ,
Wawa's Smile , FtM ? , Thomas Beatie 2

Des Coups de Coeur: EXL ,
Kashimashi ~Girl meets Girl~ ,
Sa Majesté Freddie , Mon Côté Midinette
des Coups de Gueule: Karol relève-toi ,
BlondeBox , 1 pub 2 mR2 [bon courage :D]
et des Coups de Blues: Pile 1 an ,
Baisser de Rideau , Interlude

Du Visual Basic (VB6-VBA): Mlle Hanoï
Boules , Bombes , AnaClock , DigiClock ,
Tris (tetris) ,
et de la Bricologie: Real Barbie Girl

Pis pour les plus grand(e)s, des
S*X TOYS:
DildoBike , Tech To Nique

Et même parfois de la vraie vie:
Impressions de Voyage (Maroc) ,
Chez Mickey , La Tonnelle ,
Nous Nous Sommes Rencontrées

.

La vraie Taunie ..


... Tu me manques :'(


Notre Taz :*




Clock & Zik..

Idée Cadeau..


Attrape-Mouches

dyke goudou gouine homo homoaffectivité homoaffectivity homosexual homosexualité homosexuality homosexuel homosexuelle inverti invertie lesbian lesbianism lesbianisme lesbien lesbienne lez néovagin neovagina réassignation saphique saphisme sapphic sapphism trans transgender transgenre transidentité transidentity transsexalité transsexality transsexual transsexualism transsexualisme transsexuel transsexuelle tribade tribadisme vaginoplastie ...

Le combat continue..

MyLzz59..

.. @gmail.com

Blog français

Ca va encore mieux en le disant.. Important
## Comment "marche" ce Blog / Comment laisser un Commentaire ##

Et pour finir,
Mylène écrit (http://mylene-ecrit.blogspot.fr)N'oubliez pas de visiter aussi
mon blog d'histoires ====>



-MyLzz59-

mardi 30 juin 1970

Canevas (P2)

..suite de Canevas (P1)

Dans cette seconde partie, nous allons offrir à ce code (que nous ne modifierons que très peu) une IHM (interface humain-machine) un peu plus digne d’un programme "professionnel"..

L'IHM en fonctionnement.

Nous allons la construire pas à pas

Commencez par faire une copie du .DOC obtenu dans la première partie. Dans l'éditeur VBA, affichez au besoin l'explorateur de projets et la fenêtre propriétés. Faîtes un clic droit dans l'explorateur de projets, et ajoutez une UserForm. Via la propriété "(name)" appelez-la "UF1". Donnez-lui un titre (Caption) et une couleur de fond (BackColor). Redimensionnez-la via son coin inférieur droit.

Créez un "cadre (frame)" (via la Boîte à Outils), nommez_le "F_1", intitulez-le " Paramètrage ". Dupliquez-le par Copier-Coller pour générer "F_2" intitulé " Créer le Canevas ". Créer (sans les renommer) les 5 "intitulés (labels)", de "Choix du Bitmap Source (24 bits) :" à "Lignes restantes :" (propriétés Caption, Font, et TextAlign).

Face aux trois derniers labels, nous allons en créer trois autres, respectivement nommés "L_X", "L_Y", et "L_R". Ajuster leur SpecialEffect à "Sunken (2)", TextAlign à "Center".

Face à "L_X" ajouter une "barre de défilement". Nommez_la "S_X", fixer Min et Value à 3, Max à 12. Dupliquez-la pour créer "S_Y".

"Comme en X" est le Caption d'une "Case à Cocher (CheckBox)" nommée "C_Y". Vérifiez néanmoins que "TripleState" (3ème état "grisé") soit à False..

La grande zone est une "Zone de Texte (TextBox)" nommée "T_Src", de propriétés "MultiLine" et "Locked" à True.

Reste à ajouter 3 (eh oui) "Boutons de Commande (CommandButtons)". "..." a pour nom "C_Src", "Lancer.." s'appelle "C_GO" (Enabled à False). Le troisième n'est pas visible: par Copier-Coller de "C_Go", recouvrir exactement ce dernier d'un bouton vert intense sans Caption, nommé "C_Prog". Enfin, fixer la propriété "Width" de "C_Prog" à 0 (zéro).

Tout y est, pensez à sauvegarder..

Le Code (à coller dans "UF1")

' -----------------
' Zone Déclarations
' -----------------
Dim FD As FileDialog

' ---------------------------
' EVT: Initialisation Feuille
' ---------------------------
Private Sub UserForm_Initialize()
T_Src.Text = "": L_R.Caption = ""
C_Prog.Width = 0: C_GO.Enabled = False
C_Y.Value = 0: S_X.Value = 5: S_Y.Value = 5
End Sub

' -----------------------------
' Bouton "Sélectionner Fichier"
' -----------------------------
Private Sub C_Src_Click()
Set FD = Application.FileDialog(msoFileDialogFilePicker)
With FD
.AllowMultiSelect = False: .ButtonName = "Charger"
.Filters.Clear: .Filters.Add "BMP (24bits)", "*.BMP": .Show
End With
If FD.SelectedItems.Count Then
C_Prog.Width = 0: Fic$ = FD.SelectedItems(1)
' Séparation Chemin-Nom
T1 = InStr(Fic$, "\"): While T1: T2 = T1: T1 = InStr(T2 + 1, Fic$, "\"): Wend
If T2 Then D$ = Left$(Fic$, T2): Fic$ = Mid$(Fic$, T2 + 1) Else D$ = ""
Open D$ + Fic$ For Random As #1 Len = 1
' Test
If HDR(Fic$, 1, 1, TT&, TE&, TP&, TD&, TB&, TI&, TX&, TY&) Then
T_Src.Text = D$ + Fic$: C_GO.Enabled = True
Else
T_Src = "": C_GO.Enabled = False
End If
Close #1
End If
End Sub

' -------------------------------
' EVT: Barres de Défilement Zooms
' -------------------------------
Private Sub S_X_Change()
L_X.Caption = CStr(S_X.Value): If C_Y.Value Then S_Y.Value = S_X.Value
End Sub
Private Sub S_X_Scroll()
S_X_Change
End Sub
Private Sub S_Y_Change()
L_Y.Caption = CStr(S_Y.Value)
End Sub
Private Sub S_Y_Scroll()
S_Y_Change
End Sub

' --------------------
' EVT: Coche "Comme Y"
' --------------------
Private Sub C_Y_Click()
S_Y.Enabled = (C_Y.Value = 0): S_X_Change
End Sub

' --------------------------
' Bouton "Lancer le Canevas"
' --------------------------
Private Sub C_GO_Click()
F_1.Enabled = False: F_2.Enabled = False
Canevas T_Src.Text, S_X.Value, S_Y.Value
F_1.Enabled = True: F_2.Enabled = True
End Sub

Explications

Le début du Code n'a rien de transcendant, on y retrouve dans "UserForm_Initialize" les initialisations qui seront exécutées au lancement de UF1. La déclaration du FileDialog "FD" disparaît du Module pour se placer ici. De même la procédure "C_Charge_Click" du Module est supprimée au profit de sa presque jumelle "C_Src_Click". Notez que cette dernière hérite d'une copie des lignes de séparation Chemin-Nom, et d'un appel à HDR..

Barres de Défilement
Deux événements sont à gérer à l'identique: "Change" lorsque l'utilisateur clique dans la barre, ou sur les flèches aux extrémités, et "Scroll" lorsqu'il saisit et déplace le curseur. Donc nous en codons un, et l'autre appelle le premier. Ces événements affichent dans le Label correspondant la valeur de leur Barre.

La Coche "Comme en X"
Cochée, la Barre Y est désactivée (Enabled=False) et suit celle en X. Décochée, la Barre Y redevient autonome.

Bouton "Lancer.."
Après désactivation des deux Cadres (blocage de l'interface), on invoque le Canevas (du module), en lui passant le Nom du Fichier ainsi que les deux Facteurs de Zoom. En sortie, on réactive les deux Cadres..

Ajout dans "ThisDocument"
' ---------------------------------
' EVT: A l'Ouverture de ce Document
' ---------------------------------
Private Sub Document_Open()
UF1.Show
End Sub
A l'ouverture du Document, lancer la Fenêtre UF1..

Modifications dans le Module

La procédure "C_Charge_Click" disparaît, remplacée par "C_Src_Click" dans "UF1".

Dans la procédure "Canevas", l'appel "If HDR(Fic$, 1, 0 [..]" n'affiche plus le résumé, déjà affiché dans l'appel via "C_Src_Click"..

De même, les "Debug.Print" sont supprimés, au profit d'un Sous-Programme supplémentaire, "SSUF1", inséré entre le "Return" de "SSRemp" et le "End Sub":
' SSub: MàJ UF1
SSUF1:
If Not (UF1 Is Nothing) Then
UF1.C_Prog.Width = UF1.C_GO.Width * (TY& - Y) / TY&: UF1.L_R.Caption = CStr(Y): DoEvents
End If
Return
Ce Sous-Programme est appelé à deux endroits dans "Canevas":
        Next X
Ecr CL&, 0, 3: GoSub SSRemp: GoSub SSUF1
Next Y2
et
    Next Y: GoSub SSUF1
' Fin
Voilou :P

Pensez à sauvegarder, fermez et rouvrez le document. UF1 devrait démarrer..

Dans une troisième partie nous étofferons notre interface d’un gadget "amusant" de sélection de couleur de grille..

-MyLzz59-

vendredi 26 juin 1970

Canevas (P1)

.
Présentation

Aujourd'hui je vous propose une nouvelle étape dans la découverte de la programmation VBA (Visual Basic pour Applications), avec une réalisation qui se poursuivra sur plusieurs articles. Néanmoins, dès ce premier volet, le code sera utilisable, car devoir attendre la fin d'une série avant de pouvoir en profiter est frustrant.

Il s'agit d'une idée qui m'a été soufflée par une collègue accro au point de croix découvrant BitMap_Mono : générer à partir d'images en couleurs des canevas servant de modèles à cette forme de broderie.

Principe de Fonctionnement

Ce programme travaillera avec des images (BitMap) en couleurs réelles (sur 24 bits), et en effectuera un agrandissement. Chaque pixel de l'image source sera converti en un rectangle de la même couleur, encadré par une fine bordure. Les bordures des rectangles contigus seront confondues, formant ainsi une Grille. L'image ainsi obtenue (le Canevas) sera enregistré au même endroit que l'image source.

Le Code

Dans cette première partie, le code ci-dessous est utilisable quel que soit l'hôte (word, excel, etc..), et peut être installé n'importe où (ThisDocument, ThisWorkbook, Feuilles, etc..) cependant je vous suggère déjà de le coller dans un Nouveau Module. Pour ce faire, un clic droit dans l'Explorateur de projets de l'éditeur VBA, puis Nouveau, et Module..

Vous pouvez lancer ce code en l'état, depuis l'interface VBA. Repérez la procédure nommée "C_Charge_Click". Placez le curseur n'importe où dedans (entre Private Sub et End Sub) et cliquez sur Play (ou touche F5)..

..ou effectuer un premier habillage, en créant sur la Page Word, ou la Feuille Excel, un Bouton nommé "C_Charge", puis en déplaçant la procédure "C_Charge_Click" dans l'objet associé (ThisDocument, Feuil1, etc..)

' -----------------
' Zone Déclarations
' -----------------
Const TRT = "Traitement impossible [", Src = "Création Canevas"
Const ZX = 5, ZY = 5 ' Facteurs d'Agrandissement
Const CCL = &H808080 ' Couleur de la Grille
Dim PT&(1 To 2), P As String * 1 ' Pointeurs et Buffer

' ----------------
' Bouton "Charger"
' ----------------
Private Sub C_Charge_Click()
Dim FD As FileDialog
Set FD = Application.FileDialog(msoFileDialogFilePicker)
With FD
.AllowMultiSelect = False: .ButtonName = "Charger"
.Filters.Clear: .Filters.Add "BMP (24bits)", "*.BMP": .Show
End With
If FD.SelectedItems.Count Then Canevas FD.SelectedItems(1)
End Sub

' ------------------------
' SUB: Création du Canevas
' ------------------------
Sub Canevas(ByVal Fic$, Optional ByVal FX& = ZX, Optional ByVal FY& = ZY, _
Optional CL& = CCL)
' Coefficients Zoom (Zoom maxi arbitraire)
If FX& < 3 Or FX& > 12 Or FY& < 3 Or FY& > 12 Then _
MsgBox TRT + "Fact Zoom]", vbCritical, Src: Exit Sub
' Séparation Chemin-Nom
T1 = InStr(Fic$, "\"): While T1: T2 = T1: T1 = InStr(T2 + 1, Fic$, "\"): Wend
If T2 Then D$ = Left$(Fic$, T2): Fic$ = Mid$(Fic$, T2 + 1) Else D$ = ""
Open D$ + Fic$ For Random As #1 Len = 1
' Récupération de l'En-Tête Source
If HDR(Fic$, 1, 1, TT&, TE&, TP&, TD&, TB&, TI&, TX&, TY&) = False Then
MsgBox TRT + "Lect HDR]", vbCritical, Src
Else
If TP& <> 0 Or TB& <> 24 Or TI& <> 1 Then
MsgBox TRT + "Cont HDR]", vbCritical, Src
Else
' Calculs Source et Canevas
TX2& = TX& * FX& + 1: TX3& = 4 * ((3 * TX2& + 3) \ 4): TY2& = TY& * FY& + 1
TM& = TE& + TP& + 1: TM2& = TM&: TX1& = 4 * ((3 * TX& + 3) \ 4)
TD2& = TX3& * TY2&
' Dimensions Maximales Source et Canevas (brides arbitraires)
If TX& > 1024 Or TY& > 1024 Then
MsgBox TRT + "Taille SRC]", vbCritical, Src
ElseIf TX2& > 9001 Or TY2& > 9001 Then
MsgBox TRT + "Taille CAN]", vbCritical, Src
Else
' Création de l'En-tête Canevas
Open D$ + "Can_" + Fic$ For Random As #2 Len = 1
P = Chr$(0): For T1 = 1 To 54: Put #2, T1, P: Next T1
Ecr 19778, 1, 2: Ecr TD2& + TE& + TP&, 3, 4
Ecr TM& - 1, 11, 2: Ecr TD2&, 35, 4: Ecr TB&, 29, 2: Ecr TI&, 27, 2
Ecr TX2&, 19, 2: Ecr TY2&, 23, 2: Ecr 40, 15, 2
' Ligne Séparatrice Basse
PT&(2) = TM2&
For T1 = 1 To TX2&: Ecr CL&, 0, 3: Next T1: GoSub SSRemp
' Ecriture Données
For Y = TY& To 1 Step -1: Debug.Print "Encore" + Str$(Y) + " Ligne(s)"
' Ecriture Ligne Image
For Y2 = 1 To FY& - 1
PT&(1) = TM&
For X = 1 To TX&
Ecr CL&, 0, 3: V& = Valr(0, 3)
For X2 = 2 To FX&: Ecr V&, 0, 3: Next X2
Next X
Ecr CL&, 0, 3: GoSub SSRemp
Next Y2
' Ecriture Ligne Séparatrice
PT&(2) = TM2&
For T1 = 1 To TX2&: Ecr CL&, 0, 3: Next T1: GoSub SSRemp
TM& = TM& + TX1&
Next Y: Debug.Print "Terminé.."
' Fin
Close #2
MsgBox "OK", vbInformation, Src
End If
End If
End If
Close #1
Exit Sub
' SSub: Termine au besoin la ligne par du zéro..
SSRemp:
P = Chr$(0): TM2& = TM2& + TX3&: For T1 = PT&(2) To TM2& - 1: Put #2, T1, P: Next T1: PT&(2) = TM2&
Return
End Sub

' ----------------------------------------------------
' FCT: Récupère le Numérique sur Nb Octets depuis Posi
' ----------------------------------------------------
Function Valr(Posi, Nb, Optional Luno As Integer = 1)
V& = 0: If Posi > 0 Then PT&(Luno) = Posi
For N& = (CLng(PT&(Luno)) + Nb - 1) To CLng(PT&(Luno)) Step -1
Get #Luno, N&, P: V& = V& * 256& + Asc(P)
Next N&
Valr = V&: PT&(Luno) = PT&(Luno) + Nb
End Function

' ----------------------------------------------------
' FCT: Ecrit le Numérique V& sur Nb Octets depuis Posi
' ----------------------------------------------------
Function Ecr(ByVal V&, Posi, Nb, Optional Luno As Integer = 2)
If Posi > 0 Then PT&(Luno) = Posi
For N& = CLng(PT&(Luno)) To (CLng(PT&(Luno)) + Nb - 1)
P = Chr$(V& Mod 256): Put #Luno, N&, P: V& = V& \ 256&
Next N&
PT&(Luno) = PT&(Luno) + Nb
End Function

' -------------------------------------
' FCT: Renvoie les Infos de l'en-tête..
' -------------------------------------
Private Function HDR(Fic$, Luno As Integer, Aff As Boolean, _
TT&, TE&, TP&, TD&, TB&, TI&, TX&, TY&) As Boolean
On Error Resume Next
Err.Number = 0
' Acquisition de l'En-Tête
TT& = Valr(3, 4, Luno): TE& = 54: TP& = Valr(11, 2, Luno) - 54
TD& = Valr(35, 4, Luno): TB& = Valr(29, 2, Luno): TI& = Valr(27, 2, Luno)
TX& = Valr(19, 2, Luno): TY& = Valr(23, 2, Luno)
' Afficher le Message d'Informations ?
If Aff Then
If Err.Number Then
MsgBox "Erreur HDR", vbCritical, "Fichier: " + Fic$
Else
MsgBox "Taille Totale:" + Str$(TT&) + " Octets" + vbCrLf _
+ "Taille En-Tête:" + Str$(TE&) + " Octets" + vbCrLf _
+ "Taille Palette:" + Str$(TP&) + " Octets" + vbCrLf _
+ "Taille de la Data:" + Str$(TD&) + " Octets" + vbCrLf _
+ "Bits par Couleur:" + Str$(TB&) + vbCrLf _
+ "Nombre de Plans:" + Str$(TI&) + vbCrLf _
+ "Dimension X:" + Str$(TX&) + " Pixels" + vbCrLf _
+ "Dimension Y:" + Str$(TY&) + " Pixels" + vbCrLf, _
vbInformation, "Fichier: " + Fic$
End If
End If
' Sortie
HDR = (Err.Number = 0)
End Function

Explications

Certes, ce code est plus long que d'habitude. Nous allons l'éplucher. Par la suite, il n'évoluera presque pas..

Commençons par le point d'entrée, la procédure "C_Charge_Click". Elle déclare et paramètre un FileDialog de type FileDialogFilePicker, nommé FD. C'est la boîte de sélection de fichiers d'Office. Elle n'autorise ici qu'un seul fichier à la fois, et invoque la procédure "Canevas", à laquelle elle transmet les Chemin+Nom dudit fichier.

Enchaînons avec les deux procédures de petite taille, "Valr" et "Ecr". Elles servent respectivement à la lecture et à l'écriture dans un Fichier.

Function Valr(Posi, Nb, Optional Luno As Integer = 1)
Il s'agit d'une Fonction, à laquelle on fournit 3 paramètres, le dernier étant optionnel. Posi correspond à l'octet de départ, Nb au nombre d'octets consécutifs à lire, et Luno le numéro de Canal associé au Fichier à lire, par défaut 1 ici. Valr renvoie une valeur numérique, assemblant les valeurs des octets lus ainsi:
Valr = 1 x Octet{Posi} + 256 x Octet{Posi+1}+ 256² x Octet{Posi+2}, etc..

Function Ecr(ByVal V&, Posi, Nb, Optional Luno As Integer = 2)
Certes cette procédure est une fonction, mais elle ne renvoie rien. Un Sub déguisé, en somme.. C'est le pendant de Valr, qui écrit suivant la même logique la décomposition de V& dans les Nb octets à partir de Posi.

Ces deux Fonctions serviront tout au long du reste du programme..

Une troisième fonction va nous servir à lire l'En-Tête de l'image source, et récupérer tous les paramètres descriptifs qu'il contient. C'est "HDR":

Private Function HDR(Fic$, Luno As Integer, Aff As Boolean, _
TT&, TE&, TP&, TD&, TB&, TI&, TX&, TY&) As Boolean

Les trois premiers paramètres sont en entrée, Fic$ est le nom de fichier qui sera éventuellement affiché, Luno le numéro de Canal associé à l'image source, et Aff un booléen: à True, HDR affichera une fenêtre récapitulant les paramètres descriptifs de l'image, à False non..

HDR renvoie les 8 paramètres descriptifs suivants:
TT&: Taille Totale (Octets)
TE&: Taille En-Tête (Octets)
TP&: Taille Palette (Octets)
TD&: Taille de la Data (Octets)
TB&: Bits par Couleur
TI&: Nombre de Plans
TX&: Dimension X (Pixels)
TY&: Dimension Y (Pixels)
ainsi qu'un résultat booléen, valant True si la lecture de l'En-Tête s'est déroulée sans erreur..

Rappel: dans un BitMap, le Fichier commence par un En-Tête de 54 octets, suivi éventuellement d'une Palette, puis de la zone Data, dans laquelle les lignes de l'image sont stockées de bas en haut sans forme de compression. Le nombre de plans signifie qu'un BitMap est capable de contenir plus d'une image, concrètement je ne l'ai jamais vu appliqué..

Maintenant on peut commencer :P

Sub Canevas(ByVal Fic$, Optional ByVal FX& = ZX, Optional ByVal FY& = ZY, Optional CL& = CCL)
Cette procédure (Sub) est le coeur de notre programme. Tous les paramètres sont en entrée. Fic$ contient les Chemin+Nom de l'image source, le "ByVal" signifie que "Canevas" recevra une copie de cette variable, donc que toute modification ne sera pas répercutée vers l'appelante (c'est un paramètre en entrée seulement). FX& et FY& sont les coefficients d'agrandissement horizontal et vertical. Ils sont optionnels, et en cas d'omission la copie créée (ByVal) prendra la valeur de la Constante ZX ou ZY correspondante. De même pour CL& qui précise la couleur de la Grille (constante CCL).

Canevas commence par vérifier que FX& et FY& (les zooms) sont compris entre 3 et (arbitrairement) 12. Ensuite nous recherchons le dernier séparateur "\" dans Fic$ pour dissocier le Chemin et le Nom de l'image source.

Open D$ + Fic$ For Random As #1 Len = 1
Cette instruction "ouvre" le fichier de l'Image Source en Lecture/Ecriture à Accès Direct (Random), en l'associant au Canal #1, avec des Enregistrements (zones accessibles individuellement) de taille (Len) 1 octet. En clair, le numéro de l'enregistrement devient le numéro de position de l'octet.

If HDR(Fic$, 1, 1, TT&, TE&, TP&, TD&, TB&, TI&, TX&, TY&) = False [..]
Cette ligne effectue deux actions: elle invoque d'abord "HDR" (sur le Canal 1, image source, et avec demande d'affichage du résumé). HDR renvoie un booléen, True si réussi, False sinon. Dans le cas d'échec (False), afficher un message d'erreur.

If TP& <> 0 Or TB& <> 24 Or TI& <> 1 [..]
Autre test: l'image source ne doit pas avoir de Palette (TP&=0), doit être en couleurs réelles 24 bits (TB&=24), et ne doit contenir qu'un seul plan (TI&=1).

La source validée, calculons les paramètres descriptifs du Canevas à générer:
TX2&: La Largeur en X
TX3&: Il s'avère que dans un BitMap, les Lignes sont complétées à droite jusqu'à concurrence d'une largeur multiple de 4 octets..
TY2&: La Taille en Y
TM&: Point de Départ de la Lecture d'une Ligne Source, initialement le premier octet suivant l'En-Tête et la Palette (source).
TM2&: Idem TM&, mais pour l'Ecriture dans le Fichier Canevas.
TX1&: Idem TX3&, mais pour l'Ecriture dans le Fichier Canevas.
TD2&: Taille de la Zone Data du Fichier Canevas.

If TX& > 1024 Or TY& > 1024 Then [..]
[..] ElseIf TX2& > 9001 Or TY2& > 9001 Then [..]
Deux autres tests, les dimensions maximales sont bridées (arbitrairement) à 1024 pour la Source, et 9001 pour le Canevas.

Open D$ + "Can_" + Fic$ For Random As #2 Len = 1
Comme l'autre "Open", cette instruction ouvre (et crée au besoin) le Fichier Canevas, sur le Canal #2, dans le même répertoire que la Source, et de même nom, cependant préfixé par "Can_".

P = Chr$(0): For T1 = 1 To 54: Put #2, T1, P: Next T1
Cette boucle initialise les 54 octets de l'en-tête avec du zéro. "P" est ici notre Buffer (tampon). Excepté celui qui charge "BM" dans les deux premiers octets (signature d'un BitMap), les "ECR" répondent aux "VALR" de "HDR"..

Boucles d’Image:

Nous allons parcourir la Zone Data de l’Image Source linéairement, en ne sautant que les remplissages de fins de lignes. Cela signifie que nous allons parcourir l’image de la dernière ligne (celle du bas) à la première (celle du haut). Pour chaque ligne source, la lecture se fera de gauche à droite, pixel par pixel, donc par 3 octets à la fois, via Valr( [..] , 3 ).

Ce sont les boucles "1" (lignes) et "3" (pixels):
"1": For Y = TY& To 1 Step -1
"3": For X = 1 To TX&

Pour chaque pixel source, nous devons créer un rectangle de FX& x FY& pixels dans le canevas. Afin de confondre les lignes de grille, seuls deux des côtés du rectangle seront bordés. Arbitrairement, ce seront les bords gauche et haut, les deux autres "récupérant" ceux de leurs voisins. Il nous faudra traiter séparément les extrémités droite et basse de l’image, exceptions à ce principe car n’ayant plus de voisins..

Accessoirement, notez la présence de "SSRemp". Il complète si nécessaire la ligne écrite par du zéro à droite, car la largeur, rappelez-vous, se doit d’être multiple de 4 octets. "SSRemp" sera invoqué à chaque écriture de ligne dans le Canevas.

Nous aurions pu opter pour l’écriture rectangle par rectangle, j’ai préféré celle ligne par ligne, plus simple à comprendre. Puisque nous partons du bas, démarrons par une ligne de grille (complétée par "SSRemp").

Pour chaque ligne source (que nous relirons donc autant de fois que nécessaire), nous allons créer (FY& - 1) lignes de Canevas (identiques), où chaque pixel source donnera lieu à un pixel (gauche) suivi de (FX& - 1) pixels de la couleur de celui source. Chacune de ces lignes sera complétée par le pixel de grille (l’extrémité droite) puis "SSRemp".

Ce sont les boucles "2" (nombre de lignes) et "4" (parcours de ligne):
"2": For Y2 = 1 To FY& - 1
"4": For X2 = 2 To FX&

Ces quatre boucles sont évidemment entrelacées: "pour chaque ligne source (1) créer plusieurs lignes canevas (2) dans lesquelles pour chaque pixel source (3) créer plusieurs pixels canevas (4)".

Pour chaque ligne source nous devons ajouter une ligne séparatrice (celle du haut), donc ..sous celles de nos rectangles.

Voilou :)

Dans la seconde partie { article Canevas (P2) }, nous offrirons à ce code (que nous ne modifierons que très peu) une IHM (interface humain-machine) un peu plus digne d’un programme "professionnel" (rigolez pas..). Ce sera une fenêtre permettant de paramétrer et de lancer "Canevas" sans passer pas l’éditeur VBA.. Un troisième article { Canevas (P3) } étoffera notre interface d’un gadget "amusant" de sélection de couleur de grille..

-MyLzz59-

mercredi 24 juin 1970

MB E-Klass - Remplacer les vérins
de la suspension active arrière (break)


Alors qu’on aurait pu les supposer relativement semblables,
   ma  E 300 TD break AvantGarde type 210 Phase 1
 et la  E 290 TD berline Élégance type 210 Phase 1
de ma p’tite femme se sont avérées être des véhicules finalement relativement différents, comme par exemple la « bonhomie » du 5 cylindres 2,9L face au caractère plus « joueur » du 6 cylindres 3L. Un vocabulaire pas spécifiquement dans le registre automobile, j’admets…

Une autre différence qui est l’objet de cet article, est la présence sur la break d’une suspension arrière active, hydropneumatique, destinée à maintenir constante la hauteur de caisse (« l’assiette ») en compensant le poids du chargement du coffre par la rigidification de la suspension obtenue par compression du gaz servant de ressort au moyen d’une pompe hydraulique commandée par un capteur de hauteur.
Dit comme ça…

Bref, un truc qui vous soulève l’arrière comme si de rien n’était et qui à l’exception des « sphères » (considérées comme pièces d’usure) ne devrait « théoriquement » pas nécessiter de maintenance. Mais ça
c’est évidemment la théorie. L’un des vérins de ma E300 a lâché à ce qui semble être son point faible, son attache supérieure, ce qui le relie à la caisse. Je présume qu’un jeu s’est installé suite au dessèchement de la rondelle caoutchouc côté extérieur (pas d’idées mal placées ) permettant l’usure par frottement de l’attache.

- Solution numéro un, laisser sa paye au garagiste spécialisé du coin, toujours moins pire qu’un passage à la concession à l’étoile.
- Solution numéro deux, tordre le cou aux idées reçues, et se lancer. Pour se rendre compte que moyennant un peu d’outillage assez ordinaire, quelques heures devant soi, de ne pas craindre de se salir, et de procéder avec application et méthode, c’est pas si insurmontable que ça peut le paraître. Et puis on n’est pas à l’abri de se retrouver dans quelque position incongrue, cocasse, voire suggestive, lorsque la femme de sa vie passera s’enquérir de l’état d’avancement des travaux.
J’dis ça, j’dis rien


*) Sécurité avant tout !



Ca peut aller de soi, mais on n’est jamais trop prudent(e) sur un chantier, et les risques lorsqu’on bricole sous une voiture, c’est qu’elle glisse, bouge, retombe, et dans la vraie vie ça se termine rarement comme dans les dessins animés.


*) Revue de matériel




[  ] -une paire de chandelles, car le cric ne sert qu’à changer la roue, sûrement pas à maintenir la voiture au-delà !!
[  ] -diverses clés (deux de 16mm, deux de 17mm, une de 13mm), de préférence coudées (« pipes »). Des clés à cliquet conviendront également.
[  ] -diverses clés (une de 17mm, une de 19mm, une de 10mm), obligatoirement plates et ouvertes.
[  ] -deux tournevis plats (un gros et un petit), il est inutile d’avoir un tournevis testeur.
[  ] -un gros tournevis cruciforme, au manche épais, éventuellement percé (non messieurs…)
[  ] -un jeu de tournevis en étoile (« Torx »)
[  ] -un grattoir, ou une spatule
[  ] -la bombe d’huile « miracle », qui « décoince, dérouille, dégrippe » mais ne pimente pas les pizzas
[  ] -un litre de liquide de suspension « ZHM » à se procurer spécifiquement (Attention, le « LHM » Citroën n’est PAS compatible Mercedes !)
[  ] -un récipient pour récupérer le liquide usagé qui s’écoulera. Une bouteille vide conviendra.
[  ] -de quoi protéger (bâche plastique, sacs de supermarché…)
[  ] -de quoi (se) nettoyer (éponge ou essuie-tout de bricolage, savon « gros travaux »)
[  ] -de quoi poser ses fessounettes ou s’allonger (un carton de déménagement, par exemple)
[  ] -un maillet (ça peut aider à convaincre un écrou récalcitrant )


*) Préliminaire se procurer de nouveaux vérins



Sur ce coup-là, merci internet ! J’ai trouvé une paire de vérins identiques (même marque même modèle : Sachs 102 422) livrés pour moins de la moitié de ce que me demandait mon garagiste… Evidemment pas question de n’en remplacer qu’un, c’est comme les chaussettes ça va par paires

En cas de doute sur la pièce à acheter, ne croyez le conseiller QUE s’il vous demande l’immatriculation ou le n° de châssis (le « VIN »), ou plus simple : démontez la roue et lisez la référence directement sur la pièce à changer


*) Mettre la voiture sur chandelles



Choisir une surface plane, non meuble, la dalle de béton du garage s’y prêtera bien. Si vous disposez de quoi caler les roues avant, n’hésitez pas, en effet passer une vitesse (boîte manuelle) ou la position Parking (boîte automatique), et serrer le frein à main (en fait la pédale tout à gauche) ne sera pas d’un grand secours, vu qu’ils portent sur les roues arrière

!!! A partir de ce moment, il est impératif que le moteur soit arrêté !!!


[  ] -Récupérer le cric. Pour rappel, il est caché derrière la roue de secours, elle-même derrière le cache du flanc gauche, dans le coffre. Il vous faudra au minimum basculer la roue de secours pour cela. Quoi, quelle « french manucure » ??

[  ] -Insérer le gros tournevis plat dans le cache du trou destiné au cric, afin de l’ôter (voir le manuel). Ôter également (si jantes en tôle) l’enjoliveur.

[  ] -Avant de lever la voiture, il est nécessaire de desserrer légèrement les boulons qui tiennent la roue. Plutôt que la clé d’origine, procurez-vous une clé télescopique car les boulons peuvent être costauds à dévisser ! A défaut, vous pouvez vous procurer un bout de tube métallique afin de prolonger la clé et augmenter son bras de levier.

[  ] -Placez la clé manche vers la gauche, oubliez votre amour propre (prévenez votre moitié car le moment risque d’être désopilant ), accrochez-vous à la barre de toit, et sautez à pieds joints sur la clé… Desserrez d’environ un tour, et recommencez en prenant un boulon sur deux, comme si vous dessiniez une étoile.

[  ] -Ceci fait, et votre moitié remise, placez le cric dans le trou, prenez grand soin à ce qu’il soit strictement vertical (danger de basculement), et levez jusqu’à décoller d’un centimètre la roue du sol. Ôter les boulons puis la roue. Préparez une chandelle (trépied ouvert, tête levée, et sécurité mise), approchez-la de sa place. Près du trou du cric, repérez le patin en caoutchouc sous la caisse, c’est lui qui doit se placer sur la chandelle. Lever jusqu’à pouvoir placer la chandelle, puis redescendre et ôter le cric.

[  ] -Un conseil, placer la roue à plat sous le véhicule, près de la chandelle. En cas de basculement, mieux vaut endommager la roue, que vous !

Procéder à l’identique de l’autre côté, et vérifier que le véhicule soit bien stable.


*) Préparation Bras de roues



Rappel (pas forcément inutile) : vu de l’extérieur, on dévisse en tournant dans le sens opposé à celui des aiguilles d’une montre (à aiguilles), on revisse dans le sens des aiguilles

[  ] -Le cache plastique sous le bras de roue est fixé par deux vis, vers l’extrémité proche du milieu de la voiture. Les ôter avec la clé plate de 10mm, puis déclipser le cache (4 clips) avec le gros tournevis plat.

[  ] -Repérer et asperger d’huile dégrippante le ou les boulons qui fixent le vérin au bras de roue. Asperger également le raccord de la tuyauterie du vérin. Laisser agir.


*) Préparation dans le coffre



[  ] -Basculer les deux parties de dossiers de la banquette arrière, et avancer les caoutchoucs rectangulaires des anneaux de fixation des deux dossiers de banquette.

[  ] -Avec le petit tournevis plat, déclipser le cache central des 4 anneaux les plus éloignés de la porte du coffre, en exerçant une pression sur le côté.

[  ] -Ensuite utiliser la clé « Torx » appropriée pour dévisser et ôter ces 4 anneaux.

Les deux côtés du coffre se dégarnissent de façon quasi identique.

[  ] -Ouvrir et ôter les deux parois basculantes amovibles

[  ] -Côté gauche : penser à déconnecter la prise d’alimentation « allume-cigare »

[  ] -Avec le tournevis cruciforme, ôter la vis au plancher, près de l’anneau.

[  ] -Ôter également la vis cruciforme à la verticale de la précédente. Côté gauche, cette vis est cachée par la garniture surplombant la roue de secours.


*) Dévisser l’attache supérieure des vérins



[  ] -A l’aide du tournevis plat, soulever le rebord inférieur de la garniture ainsi préparée, et la tenir écartée afin de dévoiler la fixation du vérin. Dévisser avec la clé de 13mm cette fixation. Le vérin libéré descendra quelque peu.

[  ] -Retirer la vis ainsi que la large rondelle métallique et la rondelle caoutchouc intérieure.

Procéder de même pour l’autre vérin.


*) Dévisser le(s) boulon(s) au bas des vérins



[  ] -Utiliser pour cela la paire de clés de 16mm ou de 17mm (dans mon cas, les boulons d’origine étaient du 16mm et leurs remplaçants du 17mm). Si l’huile « magique » n’a pu dégripper ces boulons, n’hésitez pas à poser au sol l’extrémité de la clé de gauche, et forcer vers le bas (par exemple au maillet, ou avec le tube prolongateur) celle de droite.

[  ] -Tapoter (maillet, manche du tournevis…) l’extrémité du boulon afin de le décoincer, et l’ôter.

[  ] -Retirer ainsi le reste des boulons, mais laisser les vérins en place.


*) Déconnecter la tuyauterie des vérins



Attention : le liquide de suspension est certainement encore sous pression à ce moment, c’est pourquoi nous allons protéger le logement du premier vérin !

[  ] -Placer une protection (bâche plastique, feuilles…) sur le sol, sous le logement. Entourer le support de la roue, disque et étrier de frein (sac plastique).

[  ] -Placer le récipient sous le raccord de la tuyauterie du vérin. Dans le cas d’une bouteille, à défaut d’entonnoir, découper la partie conique supérieure.

!!! Protégez-vous le visage, au moins les yeux. Au pire mettez des lunettes, même de soleil, ce sera toujours moins pire que rien en cas de projection. Gardez la bouche fermée en commençant cette phase. !!!

A l’aide des clés plates de 17mm et 19mm (vous pouvez recouvrir d’essuie-tout l’extrémité côté mains de ces clés), desserrer TRES légèrement le raccord, en procédant comme suit :

[  ] -Dans un premier temps, maintenir FIXE la clé de 17mm (côté tuyau rigide), et tourner celle de 19mm (tuyau souple côté vérin). Du liquide de suspension va commencer à « pisser » du raccord. Le collecter.

[  ] -Dans un second temps, tout en maîtrisant l’écoulement, bouger TRES légèrement dans les deux sens de rotation la clé de 17mm. En effet, il s’agit de décoincer cet écrou que la crasse ou l’oxydation a peut-être solidarisé au tuyau fixe (à ne pas tordre !)

[  ] -Dans un troisième temps, une fois que l’écrou de 17mm semble tourner librement autour du tuyau rigide, le desserrer au gré de l’écoulement, en gardant fixe la clé de 19mm.

[  ] -Dès que possible, terminer par déconnecter le tuyau du vérin.

Attention : le vérin contient lui aussi du liquide, le collecter poussant vers le bas la partie haute du vérin, tuyau dirigé vers le récipient !

[  ] -Eponger, essuyer, ôter la protection du support de roue. Veiller à ne pas avoir de liquide sur le disque de frein !

[  ] -Répéter pour le second vérin, à noter que le liquide ne sera plus sous pression (c’est le même circuit).


*) Retirer les vérins, et nettoyer leur emplacement



[  ] -Incliner le haut du vérin pour l’écarter de la coupelle d’accueil de la caisse.

[  ] -Introduire l’extrémité du gros tournevis sous le vérin, dans le trou du bras de roue à l’opposé de vous, faire levier pour décoincer le vérin.

[  ] -Le sortir, finir de le vider en « jouant de l’accordéon » avec.

[  ] -A l’aide du grattoir, du tournevis, etc., décrasser le plat de la coupelle de caisse (là où se fixe l’extrémité haute du vérin), ainsi que l’intérieur du bras de roue.


*) Installer les nouveaux vérins



[  ] -Il peut y avoir un bouchon de protection au bout du tuyau, le desserrer légèrement au préalable, sans l’ôter de suite.

[  ] -Enquiller la base du vérin dans son logement, utiliser les tournevis pour faire correspondre les trous de fixation.

[  ] -Passer le(s) boulon(s) par l’avant, sans oublier de mettre une rondelle de chaque côté (si fournie), et accrocher l’écrou manuellement, face plane à l’intérieur, face bombée à l’extérieur (si différentes).

[  ] -Coiffer le vérin avec la plus grosse rondelle caoutchouc, orienter la partie supérieure (tuyau), serrer (alternativement) sans forcer le(s) boulon(s) avec les clés de 16mm ou 17mm, puis au maximum possible

[  ] -Nettoyer soigneusement l’extrémité du tuyau rigide (car ce n’est pas un joint « classique » mais une olive) avec son écrou prisonnier, enlever le bouchon de protection côté vérin, raccorder manuellement les deux parties. Je ne sais si cela a une utilité, mais j’ai rabaissé le vérin au minimum de sa longueur avant d’effectuer ce raccord.

[  ] -Serrer sans trop forcer (pour ne pas endommager l’olive) à l’aide des deux clés plates, en maintenant fixe celle de 19mm (côté vérin) tout en tournant celle de 17mm (côté tuyau rigide). Veiller à ne pas tordre les tuyaux !

[  ] -Reclipser le cache plastique sous le bras de la roue, s’aider éventuellement du tournevis plat, ou d’un maillet. Revisser les deux vis avec la clé plate de 10mm.


*) Fixer l’attache supérieure (la tête) des vérins



Pour cela nous allons utiliser le poids du véhicule

!!! Attention ici aussi à replacer le cric de façon strictement verticale, pour éviter tout risque de blessure !!!

[  ] -Replacer le cric et soulever légèrement le véhicule. SANS enlever la chandelle, descendre sa tête au maximum (ôter la sécurité pour cela).

[  ] -Récupérer et présenter la roue près de son support. Descendre le cric jusqu’à ce que le support soit presque en face de la roue, ce qui vous évitera de la soulever pour rien

[  ] -Mettre la roue sur le support (par exemple en roulant sur une clé), la tourner jusqu’à visser un des boulons. Placer tous les boulons de la roue avec la clé SANS les serrer.

[  ] -L’espace restant autour de la roue est suffisant pour glisser la main et guider la tête du vérin dans le trou de la coupelle, tout en descendant lentement le cric (non messieurs, aucune allusion). Arrêter lorsqu’il reste encore un léger jeu.


[  ] -Depuis le coffre, positionner la seconde rondelle caoutchouc dans la coupelle. Placer la rondelle métallique sur la vis, et enquiller le tout dans la rondelle (messieurs, m’enfin…). Visser à la main puis avec la clé de 13mm. Serrer jusqu’au blocage en butée de l’ensemble.

[  ] -Ôter la chandelle et le cric.

Procéder de même pour le second vérin.


*) Première mise en marche



[  ] -Ouvrir le capot, repérer le bidon de liquide de suspension, il se situe à proximité du (des) bidon(s) de lave-glace (et de lave-phares). Remarque : selon les véhicules, ce bidon peut être commun à la suspension et à l’assistance de la direction, ou être spécifique à la suspension si la pompe de direction intègre son propre réservoir.


[  ] -Compléter une première fois le niveau si nécessaire, par rapport aux repères moulés sur le bidon, en dévissant le gros bouchon sur lequel arrive la tuyauterie. Attention au filtre dans le bouchon. Revisser impérativement ce bouchon avant de démarrer le moteur !

[  ] -Mettre le contact, donner quelques coups d’accélérateur (boîte manuelle au point mort, boîte automatique sur « P »), tourner le volant dans les deux sens (si bidon unique suspension et direction).

[  ] -Couper le contact, attendre un peu, et « refaire » le niveau de liquide.

[  ] -Retourner au niveau des roues arrière, et vérifier l’absence de fuite de liquide au raccord du tuyau des vérins. Resserrer un peu au besoin. S’il s’avérait nécessaire d’enlever la roue (quoique normalement…), repositionner la chandelle.


*) Remontage



Frein à main mis et boîte bloquée (manuelle sur « 1 » ou « R », automatique sur « P »), serrez copieusement les boulons de roue.

[  ] -Après avoir rappelé votre moitié, placez la clé manche à droite, et donnez-vous à nouveau en spectacle

[  ] -Procédez de même en passant un boulon sur deux, et le tour fini revérifiez le tout premier.

[  ] -Jantes en tôle, replacer l’enjoliveur.

Dans le coffre,

[  ] -Repositionner les garnitures, remettre et serrer les deux vis de chaque côté.

[  ] -Côté gauche, ne pas oublier de rebrancher la prise « allume-cigare ».

[  ] -Replacer ensuite le tour en plastique et l’anneau de chaque fixation, remettre et serrer les quatre vis « Torx », reclipser les caches.

[  ] -Repositionner les deux caoutchoucs rectangulaires au fond des attaches des dossiers de la banquette arrière, la remettre en position en prenant soin de ne pas coincer les ceintures !

Attention : vérifier que les dossiers se soient bien reverrouillés, si le bouton rouge sous la manette d’un dossier est visible, l’enfoncer !!

[  ] -Basculer la roue de secours afin de ranger le cric, revisser la fixation de la roue.

[  ] -Ne reste plus qu’à réinstaller les parois basculantes amovibles et refermer le coffre


*) Par la suite



[  ] -Il y a de fortes chances que vous n’ayez pu remettre l’équivalent de la quantité de liquide de suspension sorti. Aussi, gardez le bidon à proximité ou dans le véhicule, afin de compléter quand vous vérifierez le niveau, d’ici quelques jours.

[  ] -Par contre, le liquide usagé ne se réutilise pas, l’apporter au recyclage, tout comme les anciens vérins si vous ne les conservez par comme « trophées de guerre »

[  ] -Si vous en avez la possibilité, faîtes rouler votre voiture avec le coffre lourdement rempli, afin de solliciter la suspension active.
Quoi, votre ex ???


AVERTISSEMENT: cet article ne fait que décrire, sous forme de tutoriel certes, comment j'ai procédé sur mon propre véhicule. Je serais heureuse si cet article vous rendait service, mais veuillez noter au préalable qu'il ne saurait engager sous quelque forme que ce soit ma responsabilité suite à l'utilisation que vous en feriez !


-MyLzz59-

mardi 23 juin 1970

MB E-Klass - Tips and Tricks


Mon Joli Monstre..


Dans l'article "Mylène 2012" j'écrivais: << ..C'est ainsi que nous avons fait l'acquisition d'un salon roulant de marque allemande (celle avec le viseur au bout du capot :D), une Classe E break (d'occasion) truffée d'options dont certaines sont plutôt fun (siège conductrice à mémoires, arrose-phares, chauffe-fesses à l'avant, miroir avec éclairage dans les pare-soleil, ou mini-frigo dans l'accoudoir central :P) .. >>

Une    E 300 TD break AvantGarde type 210 Phase 1
qui, si elle n'a jamais eu vocation d'occuper la place laissée vacante par Taunie, m'a rapidement envoûtée. Et si son charme a également agi sur ma p'tite femme, le gabarit de l'engin lui aura posé quelque difficulté. Aussi quelques mois après nous avons profité d'une opportunité,
et une    E 290 TD berline Élégance type 210 Phase 1
également nous rejoindra.


Tips and Tricks :


- Cet article est susceptible d'être étoffé, n'hésitez pas à le reconsulter -
- Les illustrations couleur sont extraites du Betriebsanleitung (manuel utilisateur) de ma E 300 -




(Dé) Brider la Vitesse Maximale


* Cette astuce ne fonctionne que si la E est équipée d'un limiteur de vitesse en plus du régulateur.

Il est possible de brider électroniquement la vitesse maximale entre 190 et 250 km/h (ben oui, quand même) par pas de 5 km/h, ou par la même manipulation annuler cette bride (la valeur supérieure à 250 affichant "---").

Méthode :
- Mettre la boîte automatique sur "P" (Parking)
- Mettre la clé sur "2" (tableau de bord allumé)
    sans démarrer le moteur
- Enclencher le limiteur en enfonçant [=>5] la manette supérieure
    (un voyant orange s'allume sur la manette,
    et "LIM" sur le cadran de vitesse)
- Dans la première seconde, tirer [=>4] la manette vers soi
    (une vitesse s'inscrit à la place du compteur intermédiaire)
- Monter [=>1] ou descendre [=>2] cette même manette
    pour faire varier cette limite de +/- 5 km/h,
    entre 190 km/h (valeur basse) et 250 km/h (valeur haute).
- Ou monter d'un cran au-delà de la valeur haute
    pour afficher "---", ceci désactive la bride.
- Couper le contact (clé en position "0")

Si la bride est active, la valeur s'affichera au démarrage, ou lorsque la vitesse fixée sera atteinte.




Changer la langue de l'afficheur


Provenant du marché allemand, ma E300 parlait originellement cette langue. Même si ceci ne me posait pas spécifiquement de problème, je me suis demandé comment changer ce réglage..

Méthode :
- Mettre la clé sur "2" (tableau de bord allumé)
    sans démarrer le moteur
- Presser simultanément les boutons "0" (en bas à gauche)
    et "R" (en bas à droite) du Tableau de bord,
    jusqu'à apparition du nom d'une Langue sur l'Afficheur
- Relâcher les deux boutons, puis appuyer brièvement sur "0" pour
    changer de langue (Anglais, Français, Espagnol, Italien, Allemand)
- Couper le contact (clé en position "0") pour valider le choix



Réinitialiser l'Affichage
d'Avertissement de Maintenance


* Ceci ne dispense pas d'effectuer l'entretien régulier du véhicule !

A l'approche de la date ou du kilométrage du prochain Entretien régulier, l'afficheur le rappellera pendant une dizaine de secondes après avoir mis le contact (clé en position "2"). Il est possible de "faire croire" que cet entretien a été effectué, et passer au calcul du prochain Entretien.

Méthode :
- Mettre la clé sur "2" (tableau de bord allumé)
- Dans la première seconde, presser 2 fois le bouton "0"
    (l'afficheur doit indiquer l'Avertissement de Maintenance,
    sinon appuyer encore)
- Appuyer à nouveau et maintenir le bouton "0"
    (en bas à gauche du Tableau de bord)
- Couper (position "1" ou "0") puis remettre le contact (position "2")
    SANS relâcher le bouton "0"
- Maintenir encore une dizaine de secondes le bouton "0",
    un "bip" retentira et l'afficheur présentera le prochain entretien
- Relâcher seulement maintenant le bouton "0"



Tester l'émetteur infrarouge
d'une Clé "Plip"


* 3 clés sont livrées avec la E, chacune possède une identification unique associée au processeur du (pseudo) barillet de contact, qui peut en gérer 8 différentes.

La clé plate (clé de secours) n'intègre qu'un transpondeur radio capable d'émettre son identification (même principe qu'un passe Navigo), alors que les deux autres (aussi appelées "plips") embarquent également un dispositif infrarouge permettant de verrouiller et déverrouiller les portes, ouvrir le coffre (berline), ouvrir et fermer les vitres et le toit depuis l'extérieur du véhicule. Cette électronique fonctionne grâce à deux piles CR2025 (aucune pile dans la clé plate).

Pour tester le transpondeur, il suffit d'enquiller la clé dans le barillet de contact, la colonne de direction produit un bruit dû au déverrouillage, idem en retirant la clé (verrouillage).

Méthode :
L’œil humain ne perçoit pas l'infrarouge (certaines personnes le distinguent vaguement dans le noir), mais les caméras si. Pour ce test il faut donc un dispositif équipé, ce peut être un téléphone, un ordinateur avec webcam, un caméscope, un appareil photo numérique, un visiophone..
- Afficher l'image de la caméra
- Pointer le "nez" de la clé "plip" (la partie qui rentre dans le barillet
   de contact) devant la caméra
- Appuyer sur un des boutons de la clé pendant au moins 3 secondes, et observer

=> Clignotement rapide continu:
    la clé fonctionne et les piles sont bonnes
=> Clignotement rapide alternant avec un arrêt
    (1 à 2 par seconde): la clé
    fonctionne mais les piles sont en fin de vie
=> Aucune lumière (quel que soit le bouton):
    soit les piles sont à remplacer, soit la clé est défectueuse

Rem: le test des piles au multimètre n'est pas forcément significatif, une CR2025 peut afficher "à vide" ses 3 volts "réglementaires" sans être suffisante pour la clé, elle ouvrira peut-être les portières avec une portée plus courte, mais n'agira plus sur les vitres (les clignotants s'allumant alors en boucle).



N'ouvrir que la portière Conductrice,
ou ouvrir toutes les portières


S'il est évident que les clés "plips" permettent de verrouiller et déverrouiller les portières, il est moins connu qu'il existe deux modes d'ouverture à choisir en fonction de l'usage du véhicule:

*) si vous voyagez le plus souvent à plusieurs, le mode "famille" par défaut conviendra: le premier appui sur le bouton "cadenas ouvert" déverrouille toutes les portières

*) si vous voyagez le plus souvent seule, le mode "conductrice" sera plus approprié: le premier appui ne déverrouille que la portière conductrice et la trappe à carburant, un second appui déverrouille les autres portières

Pour passer d'un mode à l'autre, appuyer simultanément et maintenir environ 6 secondes les deux touches "cadenas ouvert" et "cadenas fermé", jusqu'à ce que le voyant rouge du "plip" clignote deux fois.


- Cet article est susceptible d'être étoffé, n'hésitez pas à le reconsulter -
- Les illustrations couleur sont extraites du Betriebsanleitung (manuel utilisateur) de ma E 300 -


-MyLzz59-

jeudi 11 juin 1970

Tris (P)06/2010 MyLzz59

(Rubrique VB-VBA)

0) Intro

J'enrichis ce jour cette rubrique VB/VBA avec un nouveau programme VBA sous Excel, dans la continuité des deux précédents, Boules, et Bombes. Un programme "suggéré" par Taz lors d'un commentaire récent, que j'ai pris comme un "petit défi". Oh, toutes proportions gardées, car bien que ce programme soit un peu plus "étoffé" que les précédents, il n'en reste pas moins une réalisation simple..

Je vous propose de me suivre pas à pas dans la mise en place de ce nouveau jeu, en fait un ..Tétris dans une feuille Excel . Une petite remarque: n'hésitez pas à vous référer aux explications des deux programmes précédents, la "difficulté" étant croissante je me focaliserai sur les "nouveautés".

1) Un Tétris ?

a] Généralités

Ce jeu de pièces à imbriquer façon puzzle a été inventé en urss en 1984 par Alexei Pajitnov, et a très vite conquis la planète par sa simplicité d'utilisation et son côté prenant, alliant adresse et réflexion. Rappelons-en le principe..

Une aire de jeu rectangulaire verticale en haut de laquelle apparaissent aléatoirement des formes planes composées de carrés, lesquelles descendent lentement jusqu'à s'empiler les unes sur les autres, au bas de l'aire. L'utilisateur/trice peut influer sur ces pièces de deux façons: les faire tourner autour de leur pivot (leur carré le plus central), et les déplacer latéralement, vers la gauche ou la droite de l'aire.

Le but est de les empiler au mieux en fonction des formes, de manière à constituer des lignes horizontales complètes. Chaque fois qu'une telle ligne est formée, elle se supprime et les carrés situés dessus descendent en conséquence, fournissant des points au passage.

La partie est considérée comme perdue lorsque l'aire est saturée de pièces posées, empêchant l'entrée d'une nouvelle pièce. Il n'y a pas d'état gagné, ce sont les scores qui importent en fin de jeu.

b] Ma version ("Tris")


Commençons par une photo d'écran, ce sera plus clair . L'aire de Jeu (B2:K21) comporte 10 colonnes sur une hauteur de 20 lignes. Toutes les pièces générées sont formées de 4 cases agencées en "T" (comme la pièce du haut), en "I" (les deux jaunes en bas à droite), en "J" (comme celle représentée en Suivante), en "L" (la verte), ou en "O" (ou carré).

Trois compteurs comptabilisent respectivement: le nombre de Lignes complètes qui ont été supprimées, le nombre de Points gagnés via ces lignes complètes, et le numéro d'ordre séquentiel de la Pièce en haut de l'Aire.

La zone "Suivante" présente la pièce qui succèdera à celle en haut de l'Aire lorsqu'elle sera posée. Les couleurs (6 différentes) n'ont aucune incidence sur le jeu.

La zone "Automatique" comporte deux options de jeu, petite case vide ("M17" ou "M18") = option désactivée, non vide = activée. L'option Suivante signifie que la pièce suivante apparaît automatiquement en haut de l'Aire, sinon il faut l'appeler soi-même. Cela ne donne pas le choix d'une autre Suivante. L'option Descente enclenche une chute automatique de la Pièce à raison d'une ligne par seconde, sinon elle reste en haut de l'écran jusqu'à ce qu'on la "fasse tomber".

Les Double-Clic et Clic-Droit sur la Feuille Excel sont interceptés et désactivés, sauf sur le Titre du Jeu ("M20:P21"). Notez l'existence d'une petite fenêtre flottante nommée "Pilote Tris". Elle est vitale pour ce jeu, car c'est le seul moyen de récupérer les appuis de touches au clavier, et donc de faire fonctionner ce jeu ! Lorsque vous fermez cette fenêtre, une question apparaît.


Cliquer sur "Oui" réinitialise le jeu en vue d'une nouvelle partie. Les deux Options ne sont "lues" qu'à ce moment. "Non" ferme la fenêtre "Pilote Tris", ce qui arrête le jeu. "Annuler" (par défaut) supprime la question et retourne au jeu.

Si vous avez arrêté le "Pilote Tris", vous pouvez le relancer via un Double-Clic sur le Titre du Jeu. Les deux Options ne sont modifiables que lorsque le "Pilote Tris est arrêté.

Comptabilisation des Points: lorsqu'une Pièce est posée, une suppression de Lignes complètes peut se produire, et jusqu'à quatre Lignes peuvent être supprimées en une seule fois. La première Ligne vaut 10 Pts, la seconde 15 Pts, la 3ème 20 Pts, et la 4ème 25 Pts. Si la suppression vide totalement l'Aire, la partie ne prend pas fin, mais 1000 Pts supplémentaires sont crédités !

c] Les Touches

"Tris" se joue entièrement au clavier, mais de deux manières différentes. Manière simple: les 4 touches du Pavé Fléché, Manière plus détaillée: le Pavé Numérique.

Au Pavé Fléché: les Flèches Gauche et Droite déplacent la Pièce latéralement, la Flèche Bas fait "tomber" la Pièce, la Flèche Haut a deux fonctions, faire Tourner la Pièce de 90° vers la droite (sens des aiguilles d'une montre (à aiguilles )), et engager la Pièce Suivante si l'option Descente n'est pas active.

Au Pavé Numérique: les Touches "4" et "6" déplacent la Pièce latéralement, resp. Gauche et Droite, la Rotation Droite est sur la Touche "9" et une Rotation Gauche (90°) est associée à la Touche "7", engager la Pièce Suivante est affecté à la Touche "5", et faire "tomber" la Pièce en cours à la Touche "Entrée".

La Touche "Echap (Esc)" affiche la question ci-dessus.

2) Préparatifs

a] Dessiner l'Interface

Comme précédemment, je vous ai concocté un bout de code qui va réaliser le nécessaire, je suppose que vous savez dimensionner et colorier des cellules excel, cela ne présente aucun intérêt propre ici..

Récupérez par copier-coller ce code, faîtes-en au besoin un copier-coller dans WordPad pour "normaliser" les sauts de lignes, et partez d'un nouveau classeur excel (vierge). Dans l'éditeur VBA, repérez le Projet correspondant (nommé sans doute "classeurnn") dans l'Explorateur de Projets, via un Clic-Droit sur celui-ci ajoutez un Nouveau Module, et collez-y le code.

Cliquez n'importe où dans le code, entre "Sub MeFTris" et "End Sub", et lancez l'exécution (Touche "F5", ou l'icône triangle vert).

Ceci fait, vous devriez n'avoir qu'une seule Feuille "Tris", semblable à l'image ci-dessus en 1b]. Vous pouvez supprimer (sans sauvegarder) le module contenant notre code, il ne servira plus.

*** RENOMMEZ DANS VBA LA FEUILLE de l'interface ***
*** (sans doute "Feuil1") EN "Tris" ***



b] Mise en Place

Nous avons la Feuille Excel renommée "Tris" tant au niveau de son Onglet (par le code) que dans VBA (vous venez de le faire). Nous aurons besoin de deux autres éléments VBA, un module que nous allons renommer "pTris", et une UserForm (une fenêtre windows) que nous appellerons "UF1". Sur cette dernière, simplement changer sa Propriété Caption (son titre) en "Pilote Tris", et la réduire à la plus petite taille permise par l'éditeur..

Sauvegardez déjà votre classeur .

La répartition du Code se fera comme suit:

* ThisWorkBook: (rien)

* la feuille "Tris": les procédures événementielles d'interception des Double-Clic et Clic-Droit, ainsi que notre simulation de Timer (à une seconde) pour l'option "Descente".

* le module "pTris": les paramètres du jeu (constantes et variables publiques), ainsi qu'une "trousse à outils" de procédures effectuant des actions identifiées du jeu, telles que Générer une Pièce, Tourner la Pièce, Tester la position de la Pièce, ou Rechercher les Lignes complètes..

* la UserForm "UF1": contient toute la logique du Jeu, essentiellement la gestion des Touches.

c] Les Paramètres du Jeu

Pour leur majorité, ils sont regroupés en Zone Déclarations du module "pTris". On y trouve les coordonnées et couleurs du jeu, etc.. Détaillons:

* Quatre constantes définissant les bords de l'Aire de Jeu: CUp et CDn, CLf et Crt (haut, bas, gauche, droite)
* C0 est la couleur (gris-bleu) du fond de l'Aire (est frais )
* CUp0 et CLf0 sont les coordonnées du coin supérieur gauche de la Zone "Suivante"
* de XYLi à XYaD l'adresse excel des différents compteurs et options..
* XYTi: l'adresse complète de la Zone de Titre, pour le Double-Clic dessus.

Voilà pour les Constantes, venons-en aux Variables: en fait le jeu va gérer trois Pièces simultanément . Il y aura la Pièce en cours de jeu (Pièce No=1), la même Pièce dont on calculera les nouvelles coordonnées afin de les valider (ou espace de travail, No=2), et enfin la Pièce Suivante, stockée en attente (No=0). Chacune de ces 3 Pièces est formée de 4 carrés (numérotés 1 à 4), lesquels ont un couple de coordonnées (PY, PX), et d'une Couleur associée PC. Excepté la Pièce Suivante (No=0), les Pièces ont un couple de coordonnées supplémentaire (Y0, X0) représentant la position absolue de leur carré pivot dans l'Aire de Jeu, les couples (PY, PX) étant en coordonnées relatives au Pivot (lequel a donc (PY, PX) = (0, 0) )

Les deux booléens (vrai/faux) Sui et Dsc correspondent resp. aux options Suivante et Descente.

Sta est une variable à trois états: Sta=0 signifie qu'aucune Pièce n'est en cours, Sta=1 signifie qu'une Pièce est engagée dans l'Aire de Jeu, et enfin Sta=2 pour matérialiser que la partie est perdue..

' -----------------
' Zone Déclarations
' -----------------
Public Const CUp As Integer = 2, CDn As Integer = 21, CLf As Integer = 2, CRt As Integer = 11
Public Const C0 As Long = &HFFCCCC, CUp0 As Integer = 13, CLf0 As Integer = 13
Public Const XYLi = "M4", XYPt = "M7", XYPc = "M10"
Public Const XYaS = "M17", XYaD = "M18", XYTi = "$M$20:$P$21"
Public X0(1 To 2) As Integer, Y0(1 To 2) As Integer
Public PX(0 To 2, 1 To 4) As Integer, PY(0 To 2, 1 To 4) As Integer
Public PC(0 To 2) As Long, Sta As Integer, Sui As Boolean, Dsc As Boolean

d] La feuille excel "Tris"

Les procédures événementielles "BeforeDoubleClick" et "BeforeRightClick" permettent d'intercepter les actions resp. Double-Clic et Clic-Droit sur la feuille excel. Dans les deux cas, nous allons annuler l'action par défaut d'excel (Cancel = True). Pour le Double-Clic, rajoutons que sur le Titre, l'on lance le "Pilote Tris" (en non modal !!) ainsi que notre ersatz de Timer "MyTimer".

"MyTimer" est une boucle infinie de DoEvents, qui lorsqu'au moins 1 seconde s'est écoulée entre deux prises de temps successives et qu'une Pièce est engagée et que l'option Descente est activée, simule un appui au clavier sur le touche (inexistante) signifiant "descendre la Pièce d'une ligne".
' -----------------
' Annuler l'Edition
' -----------------
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Cancel = True: If Target.Address = XYTi Then UF1.Show 0: MyTimer
End Sub

' --------------------------
' Annuler le Menu Contextuel
' --------------------------
Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
Cancel = True
End Sub

' --------------------------
' Sorte de Timer (1 seconde)
' --------------------------
Private Sub MyTimer()
K& = Timer
Do
DoEvents: K2& = Timer
If K2& <> K& Then K& = K2&: If Dsc = True And Sta = 1 Then UF1.UFKD -1
Loop
End Sub

3) La Trousse à Outils (module pTris)

a] GenerePiece - Crée une nouvelle Pièce

Tirons aléatoirement une séquence (Z$). Elle contient 4 couples xxyy en coordonnées relatives par rapport au pivot, et nettoyons la Zone Suivante afin d'y dessiner la nouvelle Pièce (Z$).

Après recopie de la Pièce No=0 en No=2 (l'ancienne Suivante devient la future En Cours ), chargeons nos 4 couples xxyy dans les (PY(0,t), PX(0,t)) correspondants, et dessinons les carrés dans la Zone Suivante.

La Couleur de la Pièce est créée à partir d'une valeur tirée entre 1 et 6, que l'on va décomposer en binaire (3 bits: 2^0=1=rouge, 2^1=2=vert, 2^2=4=bleu) pour "allumer" la composante couleur associée (ex: 5=4+1=bleu+rouge=rose) du code couleur PC.
' ----------------------------------------------------------
' Crée une Pièce (en No=0, et Recopie la Précédente en No=2)
' ----------------------------------------------------------
Sub GenerePiece()
' Tirage
Select Case Int(Rnd * 5)
Case 0: Z$ = "-1 0-1 1 0 0 1 0" ' L
Case 1: Z$ = "-1 0 0 0 0 1 1 0" ' T
Case 2: Z$ = " 0 0 0 1 1 0 1 1" ' O
Case 3: Z$ = "-1 0 0 0 1 0 2 0" ' I
Case 4: Z$ = "-1 0 0 0 1 0 1 1" ' J
End Select
' Nettoyage "Suivante"
With Tris
.Range(.Cells(CUp0, CLf0), .Cells(CUp0 + 1, CLf0 + 3)).Interior.Color = C0
End With
' Affectation et Dessin "Suivante
T = 1 + Int(Rnd * 6)
PC(2) = PC(0): PC(0) = -(65536 * ((T And 4) <> 0) _
+ 256& * ((T And 2) <> 0) + 1& * ((T And 1) <> 0)) * 204
For T = 1 To 4
PX(2, T) = PX(0, T): PX(0, T) = Val(Mid$(Z$, 4 * T - 3, 2))
PY(2, T) = PY(0, T): PY(0, T) = Val(Mid$(Z$, 4 * T - 1, 2))
Tris.Cells(CUp0 + PY(0, T), CLf0 + PX(0, T) + 1).Interior.Color = PC(0)
Next T
End Sub

b] TestePiece() - Fonction Booléenne

Renvoie True (Vrai) si la Pièce dont le No est donné en paramètre (No=1 ou No=2) est située à un emplacement autorisé. Pour chacun des 4 carrés de la Pièce, on vérifie qu'il figure dans les limites de l'Aire de Jeu, et qu'il n'est pas au même emplacement qu'une Pièce déjà posée.

L'on aurait pu pour cela vérifier la couleur de la case, j'ai opté pour l'astuce suivante: chaque case occupée par une Pièce contient une astérisque invisible car de la même couleur que la case, alors que les autres sont vides. La détection se fait donc sur l'état vide ou non, car les codes couleur peuvent ne pas être fidèles, par exemple ils seront approximés sur un vieil ordi dont l'affichage serait en 65000 couleurs seulement .

En interne un booléen B est à Vrai par défaut, jusqu'à ce qu'un carré en erreur le positionne à Faux..
' ----------------------------------------------
' Teste la Pièce (No=1: en cours, No=2: travail)
' ----------------------------------------------
Function TestePiece(No As Integer) As Boolean
If No = 1 Or No = 2 Then
B = True
For T = 1 To 4
X = X0(No) + PX(No, T): Y = Y0(No) + PY(No, T)
If X < CLf Or X > CRt Then
B = False
ElseIf Y < CUp Or Y > CDn Then
B = False
ElseIf Tris.Cells(Y, X).Text <> "" Then
B = False
End If
Next T
Else
B = False
End If
TestePiece = B
End Function

c] DessinePiece - Affiche ou Efface la Pièce No

Cette procédure affecte à chaque case de l'Aire de Jeu "occupée" par la Pièce No soit la couleur de fond et de police PC de la Pièce No ainsi qu'une astérisque (pour Aff à Vrai), ou la couleur de fond et aucun texte (pour Aff à Faux).
' ------------------------------------------------------
' Dessine (Aff=True) ou Efface (Aff=False) la Pièce (No)
' ------------------------------------------------------
Sub DessinePiece(No As Integer, Aff As Boolean)
For T = 1 To 4
X = X0(No) + PX(No, T): Y = Y0(No) + PY(No, T)
With Tris.Cells(Y, X)
.Interior.Color = IIf(Aff, PC(No), C0)
.Font.Color = IIf(Aff, PC(No), C0)
.Value = IIf(Aff, "*", "")
End With
Next T
End Sub

d] Recopie - Clône les (PY, PX) et PC entre les Pièces No=1 et No=2

Classiquement, l'on recopie la Pièce en cours (No=1) dans la zone de travail (No=2), on modifie cette Pièce (No=2), on teste le résultat via TestePiece(2), et si elle est validée on la reporte en Pièce en cours (No=1)..

Le booléen D12 détermine le sens de recopie. A Vrai le sens est No=1 vers No=2, à Faux de No=2 vers No=1.
' -----------------------------------
' Recopie 2=>1 (False) ou 1=>2 (True)
' -----------------------------------
Sub Recopie(D12 As Boolean)
PC(1 - D12) = PC(2 + D12): X0(1 - D12) = X0(2 + D12): Y0(1 - D12) = Y0(2 + D12)
For T = 1 To 4: PX(1 - D12, T) = PX(2 + D12, T): PY(1 - D12, T) = PY(2 + D12, T): Next T
End Sub

e] TGTD - Rotations Gauche et Droite

Le booléen Dr détermine le sens de rotation. A Vrai elle sera de 90° vers la droite (dans le sens des aiguilles d'une montre), à Faux vers la gauche.

Cette procédure commence par recopier les coordonnées de la Pièce No=1 sur la Pièce No=2 en effectuant la Rotation appropriée, et comptabilise dans (Y1, X1) les débordements de l'Aire de Jeu de la Pièce obtenue (No=2), débordements qu'il suffit de soustraire aux coordonnées du pivot pour ramener cette Pièce dans l'Aire de Jeu..

Dans le cas d'une Rotation Droite, la composante X devient Y, et Y devient -X. Dans le cas d'une Rotation Gauche, X devient -Y et Y devient X.
' --------------------------------------------
' Rotation 90° Gauche (False) ou Droite (True)
' --------------------------------------------
Sub TGTD(Dr As Boolean)
X1 = 0: Y1 = 0
For T = 1 To 4
PY(2, T) = IIf(Dr, 1, -1) * PX(1, T): PX(2, T) = IIf(Dr, -1, 1) * PY(1, T)
X = X0(1) + PX(2, T): Y = Y0(1) + PY(2, T)
If X < CLf Then If X - CLf < X1 Then X1 = X - CLf
If Y < CUp Then If Y - CUp < Y1 Then Y1 = Y - CUp
If X > CRt Then If X - CRt > X1 Then X1 = X - CRt
If Y > CDn Then If Y - CDn > Y1 Then Y1 = Y - CDn
Next T
X0(2) = X0(1) - X1: Y0(2) = Y0(1) - Y1
End Sub

f] TesteLignes - Traitement des Lignes complètes

Pour chaque Ligne du bas vers le haut de l'Aire de Jeu, on positionne un booléen B à Vrai, et l'on parcourt toute la Ligne. Si une case vide est trouvée, B passe à Faux.

Si B est resté à Vrai, c'est que la Ligne est complète. On incrémente alors le compteur Lignes de 1, celui de Points de 10 + T, où T est initialement à 0 (zéro), et enfin T de 5. Ensuite, si la Ligne n'est pas celle du haut de l'Aire de Jeu, alors on sélectionne tout le dessus de l'Aire, que l'on recopie une Ligne plus bas, écrasant la complète. Dans tous les cas l'on vide la Ligne du haut. Si la Ligne est celle du Bas, l'on redessine la Bordure épaisse tout en bas de l'Aire.

Autre partie, l'on teste à l'inverse le contenu de la Ligne du bas. Partant de B à Vrai, l'on positionne B à Faux si l'on trouve une case occupée. B resté à Vrai signifie que la Ligne du bas est vide, donc que toute l'Aire de jeu l'est. Dans ce cas, 1000 Points supplémentaires.
' ------------
' Teste Lignes
' ------------
Sub TesteLignes()
With Tris
T = 0 ' 1ère Ligne: 10Pts, 2ème Ligne: 15Pts, etc..
For Y1 = CDn To CUp Step -1
' Est-ce une Ligne ?
B = True
For X1 = CLf To CRt
If .Cells(Y1, X1).Text = "" Then B = False
Next X1
' Action
If B Then
.Range(XYLi).Value = .Range(XYLi).Value + 1 ' Lignes
.Range(XYPt).Value = .Range(XYPt).Value + 10 + T: T = T + 5 ' Points
' Décalage du Dessus de la Ligne
If Y1 > CUp Then
.Range(.Cells(CUp, CLf), .Cells(Y1 - 1, CRt)).Copy _
Tris.Range(.Cells(CUp + 1, CLf), .Cells(Y1, CRt))
End If
With .Range(.Cells(CUp, CLf), .Cells(CUp, CRt))
.Interior.Color = C0: .Font.Color = C0: .ClearContents
End With
' Redessiner Bordure Epaisse en Bas
If Y1 = CDn Then _
.Range(.Cells(CDn, CLf), .Cells(CDn, CRt)) _
.Borders(xlEdgeBottom).Weight = xlThick
Y1 = Y1 + 1
End If
Next Y1
B = True ' Bonus: Ecran Vide=1000Pts
For X1 = CLf To CRt
If .Cells(CDn, X1).Text <> "" Then B = False
Next X1
If B Then .Range(XYPt).Value = .Range(XYPt).Value + 1000
End With
End Sub

g] Griser - rend monochrome tout le contenu de l'Aire de Jeu

Une coquetterie pour finir, cette procédure recalcule les couleurs de toutes les cases de l'Aire de Jeu afin de les convertir en une teinte grise, pour bien matérialiser que la partie est perdue..

Le principe est de sommer les trois composantes de la couleur (rouge, vert, bleu), diviser par 3 pour en obtenir la moyenne, et l'affecter aux 3 composantes de la nouvelle couleur grise (65793=65536+256+1=256^2+256^1+256^0).
' --------------
' Griser (Perdu)
' --------------
Sub Griser()
With Tris
For Y1 = CDn To CUp Step -1: For X1 = CLf To CRt
V& = .Cells(Y1, X1).Interior.Color: V2& = 0
For T = 0 To 2: V2& = V2& + V& Mod 256: V& = V& \ 256: Next T
V2& = 65793 * (V2& \ 3): .Cells(Y1, X1).Interior.Color = V2&
.Cells(Y1, X1).Font.Color = V2&
Next X1, Y1
End With
End Sub

4) "Pilote Tris" - Noyau de ce Jeu

Cette petite fenêtre flottante a pour fonction d'intercepter les appuis de Touches Clavier, et d'intéragir en fonction des phases du Jeu.

a] Initialisation

"Pilote Tris" démarre avec un Double-Clic sur la zone de Titre du Jeu, et initie une Nouvelle Partie. Commençons donc, dans la procédure événementielle "UserForm_Initialize" (UserForm est un nom imposé indépendant du nom réel de la fenêtre, ici UF1), par récupérer l'état des deux Options Suivante et Descente dans les booléens Sui et Dsc, lesquels seront valables durant toute l'existence de "Pilote Tris".

Après initialisation du générateur aléatoire, repositionnons Sta, l'indicateur de phase du Jeu, à zéro (aucune Pièce en cours), réinitialisons l'Aire de Jeu (UFCL, voir plus bas), générons (GenerePiece) une Pièce qui s'affichera dans la Zone Suivante, et simulons l'appui au clavier de la Touche "Engager Pièce Suivante" (code 101), afin de ne pas répéter le code associé.
' ----------------
' Démarrage Pilote
' ----------------
Private Sub UserForm_Initialize()
With Tris
Sui = .Range(XYaS).Text <> "": .Range(XYaS).Value = IIf(Sui, "X", "")
Dsc = .Range(XYaD).Text <> "": .Range(XYaD).Value = IIf(Dsc, "X", "")
End With
Randomize Timer: Sta = 0: UFCL: GenerePiece: UFKD 101
End Sub

b] Evénements Touches

Nous allons utiliser conjointement deux événements de détection des Touches Clavier, qui sont "UserForm_KeyDown" et "UserForm_KeyPress". KeyDown a l'avantage d'être indépendant du code pays configuré car elle récupère le numéro interne des touches et non le code ascii que lui associe le pilote du Clavier, de plus KeyPress ne gère pas le Pavé Fléché. Aussi allons-nous installer toute la gestion Clavier dans KeyDown, et juste déléguer à KeyPress la touche Echap (Esc). Certes nous aurions pu l'intégrer aussi, mais cela me semblait plus clair ainsi..

Commençons par KeyPress.. Si la Touche pressée a pour code ascii 27 (la Touche Echap), alors simulons une demande de fermeture de "Pilote Tris", en appelant l'événement associé, "UserForm_QueryClose", exactement comme lors d'un clic de souris sur la croix de fermeture de la Fenêtre.

Passons à KeyDown.. Nous nous contentons de ..passer le code de Touche à son presque clône, la procédure (non événementielle) UFKD !! La raison tient en la présence d'un format de paramètre non pratique, KeyCode n'est pas un simple entier (Integer) mais un MSForms.ReturnInteger ! Or, nous avons besoin de simuler des appuis touches à plusieurs endroits, et il est bien plus aisé de gérer un simple Integer que ce machin (). Aussi, dans UFKD, KeyCode devient un Integer ().

Nous analyserons UFKD un peu plus bas.
' ------------
' EVTs Touches
' ------------
' Touches du Jeu
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
UFKD KeyCode ' A cause du MSForms.ReturnInteger
End Sub
' Touche "Echap"
Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii = 27 Then UserForm_QueryClose 0, 1
End Sub

c] Fermeture de "Pilote Tris"

Comme dévoilé plus haut, le code de fermeture se tiendra dans l'événement de fermeture nommé "UserForm_QueryClose" (et non Terminate..)

La tentative de fermeture de "Pilote Tris", qu'elle soit réelle ou simulée, affiche une question à trois réponses. MsgBox() étant une Fonction, appliquons directement sa sortie dans un Select Case.

- [Oui] (Nouvelle Partie) : L'initialisation de "Pilote Tris" crée déjà une Nouvelle Partie, il suffit donc d'invoquer l'événement ("UserForm_Initialise").

- [Non] (Fermer "Pilote Tris") : l'on réinitialise l'Aire de Jeu (encore UFCL, voir ci-dessous), et l'on met fin à l'exécution du code par un simple End. Notez que ceci met également fin à MyTimer, lequel tournait en parallèle du "Pilote Tris"

- [Annuler] (retour au Jeu) : aucun code n'est nécessaire, la fenêtre modale MsgBox se refermant seule.

Parlons du "Cancel = True". Nombre d'événements permettent d'annuler l'exécution automatique de l'ordre associé à l'événement, comme c'était le cas (plus haut) pour les "WorkSheet_BeforeDoubleClick" et "WorkSheet_BeforeRightClick". Simplement ici, Cancel est au format Integer, mais fonctionne comme un booléen. Positionné à Vrai (comprendre différent de zéro, la seule valeur signifiant Faux, alors pourquoi pas à True = -1 en numérique ?), Cancel aura pour fonction d'interdire la fermeture automatique de "Pilote Tris". Notez que End s'en fiche..
' ----------------
' Fermeture Pilote
' ----------------
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Cancel = True
Select Case MsgBox("** Menu Principal **" + vbCr + vbCr _
+ "[Oui] Démarrer une Nouvelle Partie" + vbCr _
+ "[Non] Fermer la Fenêtre Pilote" + vbCr + "[Ann] Retour au Jeu" _
, vbDefaultButton3 + vbYesNoCancel + vbInformation, Tris.Range("M20").Text)
Case vbYes: UserForm_Initialize
Case vbNo: UFCL: End
End Select
End Sub

d] UFCL - Nettoyage de l'Interface

Un truc simple, pour souffler . UFCL remet à zéro les trois Compteurs, efface la Zone Suivante, et nettoie l'Aire de Jeu (couleurs de fond et de police, suppression du texte).
' ------------------------
' Nettoyage de l'Interface
' ------------------------
Private Sub UFCL()
Tris.Range(XYLi).Value = 0: Tris.Range(XYPt).Value = 0: Tris.Range(XYPc).Value = 0
With Tris
.Range(.Cells(CUp0, CLf0), .Cells(CUp0 + 1, CLf0 + 3)).Interior.Color = C0
End With
With Tris.Range(Tris.Cells(CUp, CLf), Tris.Cells(CDn, CRt))
.Interior.Color = C0: .Font.Color = C0: .ClearContents
End With
End Sub

e] UFKD - Gestion Touches - Le "Noyau" du Jeu

Comme ce Jeu se joue entièrement au Clavier (réel ou simulé), toute sa logique se résume à une Gestion de Touches.. Distinguons les trois phases (Sta=0: aucune Pièce engagée, Sta=1: Pièce en cours, et Sta=2: partie perdue).

Sta=2: il n'y a rien à gérer, aussi aucune ligne de code ne lui est dédiée. Donc la structure principale sera Si Sta=1 Alors.. Sinon Si Sta=0 Alors.. (sinon rien). Dans les deux cas, interceptons certaines Touches.

Sta=0: aucune Pièce engagée. Seul l'appui d'une Touche d'Engagement (Flèche Haut du Pavé Fléché (KeyCode=38) ou le "5" du Pavé Numérique (KeyCode=101)) est vérifié. Repositionnons le Pivot de la Pièce de Travail au milieu de la Ligne du Haut de l'Aire., et générons une Pièce (GenerePiece), ce qui recopiera la Pièce No=0 en No=2. Notre Pièce de Travail est désormais prête à être testée..

Si elle peut apparaître dans l'Aire (TestePiece(2)=Vrai), alors l'on passe en phase Sta=1 (Pièce engagée), l'on incrémente le Compteur de Pièces, on la recopie dans Pièce en Cours (No=1) et on la dessine. Sinon, l'on passe en phase Sta=2 (partie perdue) où l'on grise l'Aire (Griser) et affiche "Perdu".

Sta=1: Pièce engagée. Effaçons tout d'abord la Pièce de là où elle se trouve, et testons les Touches d'actions dessus..

- Déplacements Latéraux (Flèches Gauche (37), Droite (39), "4" (100) et "6" (102)): l'on copie la Pièce en Cours sur Travail, et on décrémente ou incrémente sa position horizontale (Travail).

- Rotations (Flèche Haut (38), "7" (103) et "9" (105)): l'on appelle simplement la procédure TGTD, avec Faux pour "7" (Rotation Gauche), Vrai sinon (Rotation Droite).

- Descendre d'une Ligne (la Touche de KeyCode -1 n'existe pas, c'est MyTimer qui la simule): l'on copie la Pièce en Cours sur Travail, et on incrémente sa position verticale (Travail). Si ce nouvel emplacement est invalide, c'est que la Pièce s'est posée, aussi passons Sta à zéro.

- Faire tomber la Pièce (Flèche Bas (40) et Entrée (13)): comme précédemment, l'on copie la Pièce en Cours sur Travail, et on incrémente sa position verticale (Travail), ce jusqu'à ce qu'on ne puisse plus la poser au nouvel emplacement. Remontons alors d'une Ligne, et marquons-la comme posée (Sta=0).

Ceci fait, terminons. Si le nouvel emplacement obtenu est valide, transférons-le sur la Pièce en Cours. Ne reste plus qu'à la dessiner, et si elle est posée effectuer une vérification de Lignes Complètes (via la procédure TesteLignes) puis engager la Pièce Suivante si l'option Descente est activée.
' ---------------
' Gestion Touches
' ---------------
Public Sub UFKD(ByVal KeyCode As Integer)
If Sta = 1 Then
' En cours
DessinePiece 1, False
Select Case KeyCode
' Déplacements (Gauche: "4" ou Pavé Gauche, Droite: "6" ou Pavé Droite)
Case 37, 100: Recopie True: X0(2) = X0(2) - 1 ' Gauche
Case 39, 102: Recopie True: X0(2) = X0(2) + 1 ' Droite
' Bas (Auto)
Case -1: Recopie True: Y0(2) = Y0(2) + 1: If TestePiece(2) = False Then Sta = 0
' Rotations (TG:"7", TD:"9" ou Pavé Haut)
Case 38, 103, 105: TGTD KeyCode <> 103
' Tomber (Pavé Bas ou Entrée)
Case 13, 40: Recopie True
Do: Y0(2) = Y0(2) + 1: Loop While TestePiece(2): Y0(2) = Y0(2) - 1: Sta = 0
End Select
If TestePiece(2) Then Recopie False
DessinePiece 1, True: If Sta = 0 Then TesteLignes: If Sui Then UFKD 101
ElseIf Sta = 0 Then
' Aucune
Select Case KeyCode
' Nouveau ("5" ou Pavé Haut)
Case 38, 101: X0(2) = (CLf + CRt) \ 2: Y0(2) = CUp: GenerePiece
If TestePiece(2) Then
Sta = 1: Tris.Range(XYPc).Value = Tris.Range(XYPc).Value + 1 ' Pièces
Recopie False: DessinePiece 1, True
Else
Sta = 2: Griser: MsgBox "Perdu", vbCritical
End If
End Select
End If
End Sub
Le Code Complet de ce Jeu est disponible ICI..

-MyLzz59-