Codage des réponses aux actions des utilisateurs dans l'éditeur de code (tutoriel de l'EDI)

De RAD Studio
Aller à : navigation, rechercher

Remonter à Démarrage de votre première application RAD Studio - Index (tutoriel de l'EDI)


En suivant les instructions de cette section, vous rendrez votre application interactive et lui fournirez les fonctionnalités de votre choix. Vous coderez les gestionnaires d'événement, c'est-à-dire les réponses aux clics sur les divers éléments du menu principal et à d'autres types d'interaction de l'utilisateur.

Commencement du code

Commencez l'écriture du code en définissant une variable String que vous utiliserez pendant l'exécution de l'application pour stocker le nom du fichier texte ouvert.

Dans Delphi, sélectionnez l'onglet Code dans la barre d'état pour ouvrir l'éditeur de code. Utilisez l'éditeur de code pour définir une variable String appelée CurrentFile dans la section private de la classe TTextEditorForm dans la partie interface :

Code Editor for Delphi
Définition de la variable private CurrentFile (vue Delphi)

Dans C++Builder, sélectionnez l'onglet TextEditorUnit.h dans la barre d'état pour ouvrir le fichier en-tête de l'unité dans l'éditeur de code. Utilisez l'éditeur de code pour déclarer une variable String appelée CurrentFile dans la section private de TTextEditorForm :

Code Editor for C++
Définition de la variable private CurrentFile (vue C++Builder)

Pour permuter entre les modes Concepteur de fiches et Editeur de code, appuyez sur F12.

Mise à jour de la barre d'état en réponse aux actions sur l'éditeur de texte

Lorsque les utilisateurs déplacent le signe d'insertion (curseur de texte) ou modifient le contenu de votre composant TMemo, vous devez mettre à jour la barre d'état. Comme vous devez mettre à jour la barre d'état en réponse à de nombreux événements différents, vous avez la possibilité de définir une procédure unique dans votre code et de l'appeler ultérieurement à partir d'un gestionnaire d'événement pour procéder à la mise à jour.

Dans Delphi, pour définir cette nouvelle procédure dans votre application, ajoutez la signature de procédure suivante à la section private de la classe TTextEditorForm dans la partie interface , juste en dessous de la variable CurrentFile que vous avez précédemment définie :

procedure UpdateStatusBar;

Cliquez avec le bouton droit sur UpdateStatusBar dans votre code, puis sélectionnez Compléter la classe au niveau du curseur de manière à ce que RAD Studio ajoute une définition squelette pour votre procédure à la partie implementation de votre code :

procedure TTextEditorForm.UpdateStatusBar;
begin

end;

Définissez la logique de la procédure UpdateStatusBar entre ces mots-clés begin et end comme suit :

LineNumber.Text := 'L: ' + (Editor.CaretPosition.Line+1).ToString;
ColumnNumber.Text := 'C: ' + (Editor.CaretPosition.Pos+1).ToString;
LineCount.Text := 'Lines: ' + Editor.Lines.Count.ToString;

Dans C++, pour définir cette nouvelle fonction dans votre application, ajoutez la signature de fonction suivante à la section private de la classe TTextEditorForm dans le fichier TextEditorUnit.h, juste en dessous de la variable CurrentFile que vous avez précédemment définie :

void UpdateStatusBar();

Sélectionnez le fichier d'implémentation, TextEditorUnit.cpp, et implémentez cette fonction comme suit :

void TTextEditorForm::UpdateStatusBar()
{
    TextEditorForm->LineNumber->Text = L"L: " + String(TextEditorForm->Editor->CaretPosition.Line+1);
    TextEditorForm->ColumnNumber->Text = L"C: " + String(TextEditorForm->Editor->CaretPosition.Pos+1);
    TextEditorForm->LineCount->Text = L"Lines: " + String(TextEditorForm->Editor->Lines->Count);
}

Vous pouvez à présent appeler UpdateStatusBar à partir de n'importe quel gestionnaire d'événement pour mettre à jour votre barre d'état.

Votre application doit mettre à jour pour la première fois les informations affichées sur la barre d'état lorsque votre application démarre. Pour cela, vous pouvez utiliser l'événement OnCreate de votre fiche :

  1. Sélectionnez l'onglet Conception pour revenir au Concepteur de fiches.
  2. Sur la vue Structure, sélectionnez votre composant fiche, que vous avez nommé TextEditorForm.
  3. Sur l'inspecteur d'objets, ouvrez l'onglet Evénements.
  4. Sur l'onglet Evénements, double-cliquez sur le champ de valeur de l'événement OnCreate. RAD Studio bascule vers l'éditeur de code et ajoute une définition squelette pour votre nouveau gestionnaire d'événement. Utilisez ce gestionnaire d'événement pour appeler votre procédure UpdateStatusBar :
Delphi :
procedure TTextEditorForm.FormCreate(Sender: TObject);
begin
  Editor.Lines.Add('');
  UpdateStatusBar;
end;
C++ :
void __fastcall TTextEditorForm::FormCreate(TObject *Sender)
{
        TextEditorForm->Editor->Lines->Add(L"");
        UpdateStatusBar();
}

Notez qu'avant d'appeler UpdateStatusBar, ce code ajoute une ligne vide à votre composant TMemo. Cette action initialise le nombre de lignes du mémo, de sorte que le libellé du nombre de lignes dans la barre d'état affiche "1" ligne à partir du début au lieu de "0" ligne.

Répétez les étapes ci-dessus avec les événements OnKeyUp et OnMouseUp de votre composant TMemo, que vous avez nommé Editor

Delphi :
procedure TTextEditorForm.EditorKeyUp(Sender: TObject; var Key: Word;
  var KeyChar: Char; Shift: TShiftState);
begin
  UpdateStatusBar;
end;

procedure TTextEditorForm.EditorMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  UpdateStatusBar;
end;

C++ :

void __fastcall TTextEditorForm::EditorKeyUp(TObject *Sender, WORD &Key, System::WideChar &KeyChar,
          TShiftState Shift)
{
    UpdateStatusBar();
}

void __fastcall TTextEditorForm::EditorMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, float X, float Y)
{
    UpdateStatusBar();
}

Création de gestionnaires d'événement pour les entrées du menu Fichier

Vous êtes maintenant prêt à définir les réponses aux clics sur les éléments de menu. Dans le Concepteur de fiches ouvert, sélectionnez NewAction dans la vue Structure :

Selecting New Action

Sélectionnez ensuite l'onglet Evénements dans l'inspecteur d'objets, et double-cliquez sur la zone d'édition correspondant à l'événement OnExecute. L'éditeur de code s'ouvre et affiche un squelette pour votre nouveau gestionnaire d'événement. Ecrivez dans ce gestionnaire d'événement le code qui s'exécute lorsque les utilisateurs choisissent Fichier > Nouveau.

Delphi :
procedure TTextEditorForm.NewActionExecute(Sender: TObject);
var
  UserResponse: Integer;
begin
  // Ask for confirmation if the memo is not empty.
  if not Editor.Text.IsEmpty then
  begin
    UserResponse := TDialogServiceSync.MessageDialog(
      'This will clear the current document. Do you want to continue?',
      TMsgDlgType.mtInformation, mbYesNo, TMsgDlgBtn.mbYes, 0);
    if UserResponse = mrYes then
    begin
      Editor.Text := '';
      Editor.Lines.Add(''); // Initialize the memo line count to "1".
      UpdateStatusBar;
      CurrentFile := ''; // New files have no file name until saved.
    end;
  end;
end;
C++ :
void __fastcall TTextEditorForm::NewActionExecute(TObject *Sender)
{
    if (!TextEditorForm->Editor->Text.IsEmpty()) {
        int UserResponse = TDialogServiceSync::MessageDialog(
            L"This will clear the current document. Do you want to continue?",
            TMsgDlgType::mtInformation, mbYesNo, TMsgDlgBtn::mbYes, 0);
        if (UserResponse == mrYes) {
            TextEditorForm->Editor->Text = L"";
            TextEditorForm->Editor->Lines->Add(L"");  // Initialize the memo line count to "1".
            UpdateStatusBar();
            CurrentFile = L"";  // New files have no file name until saved.
        }
    }
}

Cliquez sur l'onglet Conception pour revenir au Concepteur de fiches, et répétez le processus pour les actions restantes utilisées par les entrées du menu Fichier : OpenAction, SaveAction, SaveAsAction, ExitAction. Il s'agit des implémentations des gestionnaires d'événement de l'événement OnExecute de chacune de ces actions :

Delphi :
// File > Open
procedure TTextEditorForm.OpenActionExecute(Sender: TObject);
var
  FileName: String;
begin
  if OpenFileDialog.Execute = True then
  begin
    FileName := OpenFileDialog.FileName;
    if FileExists(FileName) then
    begin
      Editor.Lines.LoadFromFile(FileName);
      CurrentFile := FileName;
      Caption := 'Text Editor - ' + ExtractFileName(FileName);
    end;
  end;
end;

// File > Save
procedure TTextEditorForm.SaveActionExecute(Sender: TObject);
begin
  if CurrentFile = '' then
    SaveAsAction.Execute()
  else
    Editor.Lines.SaveToFile(CurrentFile);
end;

// File > Save As
procedure TTextEditorForm.SaveAsActionExecute(Sender: TObject);
var
  FileName: String;
  UserResponse: TModalResult;
begin
  if SaveFileDialog.Execute = True then
  begin
    FileName := SaveFileDialog.FileName;
    if FileExists(FileName) then
    begin
      UserResponse := TDialogServiceSync.MessageDialog(
        'File already exists. Do you want to overwrite?',
        TMsgDlgType.mtInformation, mbYesNo, TMsgDlgBtn.mbYes, 0);
      if UserResponse = mrNo then
        Exit;
    end;
    Editor.Lines.SaveToFile(FileName);
    CurrentFile := FileName;
    Caption := 'Text Editor - ' + ExtractFileName(FileName);
  end;
end;

// File > Exit
procedure TTextEditorForm.ExitActionExecute(Sender: TObject);
begin
  Application.Terminate;
end;
C++ :
// File > Open
void __fastcall TTextEditorForm::OpenActionExecute(TObject *Sender)
{
    if (TextEditorForm->OpenFileDialog->Execute()) {
        String FileName = TextEditorForm->OpenFileDialog->FileName;
        if (FileExists(FileName)) {
            TextEditorForm->Editor->Lines->LoadFromFile(FileName);
            CurrentFile = FileName;
            Caption = L"Text Editor - " + ExtractFileName(FileName);
        }
    }
}

// File > Save
void __fastcall TTextEditorForm::SaveActionExecute(TObject *Sender)
{
    if (CurrentFile == L"") {
        TextEditorForm->SaveAsAction->Execute();
    } else {
        TextEditorForm->Editor->Lines->SaveToFile(CurrentFile);
    }
}

// File > Save As
void __fastcall TTextEditorForm::SaveAsActionExecute(TObject *Sender)
{
    if (TextEditorForm->SaveFileDialog->Execute()) {
        String FileName = TextEditorForm->SaveFileDialog->FileName;
        if (FileExists(FileName)) {
            String UserResponse = TDialogServiceSync::MessageDialog(
                L"File already exists. Do you want to overwrite?",
                TMsgDlgType::mtInformation, mbYesNo, TMsgDlgBtn::mbYes, 0);
            if (UserResponse == System::Uitypes::TMsgDlgBtn::mbNo) {
                return;
            }
        }
        TextEditorForm->Editor->Lines->SaveToFile(FileName);
        CurrentFile = FileName;
        Caption = L"Text Editor - " + ExtractFileName(FileName);
    }
}

// File > Exit
void __fastcall TTextEditorForm::ExitActionExecute(TObject *Sender)
{
    Application->Terminate();
}

Création de gestionnaires d'événement pour les entrées du menu Edition et Format

Pour implémenter les actions des entrées du menu dans les menus Edition et Format, vous devez suivre la même procédure que pour les actions du menu Fichier. Ces gestionnaires d'événement sont très simples : ils transmettent simplement l'action à votre mémo, car toutes les fonctionnalités requises sont déjà implémentées dans la classe TMemo, et ils appellent UpdateStatusBar si l'action peut avoir un effet sur la position du signe d'insertion ou sur le nombre de lignes.

Delphi :
// Edit > Cut
procedure TTextEditorForm.CutActionExecute(Sender: TObject);
begin
  Editor.CutToClipboard;
  UpdateStatusBar;
end;

// Edit > Copy
procedure TTextEditorForm.CopyActionExecute(Sender: TObject);
begin
  Editor.CopyToClipboard;
end;

// Edit > Paste
procedure TTextEditorForm.PasteActionExecute(Sender: TObject);
begin
  Editor.PasteFromClipboard;
  UpdateStatusBar;
end;

// Edit > Select All
procedure TTextEditorForm.SelectAllActionExecute(Sender: TObject);
begin
  Editor.SelectAll;
  UpdateStatusBar;
end;

// Edit > Undo
procedure TTextEditorForm.UndoActionExecute(Sender: TObject);
begin
  Editor.UnDo;
  UpdateStatusBar;
end;

// Edit > Delete
procedure TTextEditorForm.DeleteActionExecute(Sender: TObject);
begin
  if Editor.SelLength > 0 then
    Editor.DeleteSelection
  else
    Editor.DeleteFrom(Editor.CaretPosition, 1, [TDeleteOption.MoveCaret]);
  UpdateStatusBar;
end;

// Format > Word Wrap
procedure TTextEditorForm.WordWrapActionExecute(Sender: TObject);
begin
  Editor.WordWrap := not Editor.WordWrap;
  WordWrapAction.Checked := Editor.WordWrap;
  UpdateStatusBar;
end;
C++ :
// Edit > Cut
void __fastcall TTextEditorForm::CutActionExecute(TObject *Sender)
{
    TextEditorForm->Editor->CutToClipboard();
    UpdateStatusBar();
}

// Edit > Copy
void __fastcall TTextEditorForm::CopyActionExecute(TObject *Sender)
{
    TextEditorForm->Editor->CopyToClipboard();
}

// Edit > Paste
void __fastcall TTextEditorForm::PasteActionExecute(TObject *Sender)
{
    TextEditorForm->Editor->PasteFromClipboard();
    UpdateStatusBar();
}

// Edit > Select All
void __fastcall TTextEditorForm::SelectAllActionExecute(TObject *Sender)
{
    TextEditorForm->Editor->SelectAll();
    UpdateStatusBar();
}

// Edit > Undo
void __fastcall TTextEditorForm::UndoActionExecute(TObject *Sender)
{
    TextEditorForm->Editor->UnDo();
    UpdateStatusBar();
}

// Edit > Delete
void __fastcall TTextEditorForm::DeleteActionExecute(TObject *Sender)
{
    if (TextEditorForm->Editor->SelLength > 0) {
        TextEditorForm->Editor->DeleteSelection();
    } else {
        TextEditorForm->Editor->DeleteFrom(
            TextEditorForm->Editor->CaretPosition, 1,
            Fmx::Memo::TDeleteOptions() << Fmx::Memo::TDeleteOption::MoveCaret);
    }
    UpdateStatusBar();
}

// Format > Word Wrap
void __fastcall TTextEditorForm::WordWrapActionExecute(TObject *Sender)
{
    TextEditorForm->Editor->WordWrap = !TextEditorForm->Editor->WordWrap;
    TextEditorForm->WordWrapAction->Checked = TextEditorForm->Editor->WordWrap;
    UpdateStatusBar();
}

Suivant

Compilation et exécution de l'application