The Edit Menu


The Edit menu, shown in Figure 16-11, contains commands that work with the clipboard and enable the user to search and replace text in the editor.

image from book
Figure 16-11: The Edit menu

All commands in the Edit menu, except Find and Replace, are so easy to implement that they're almost no fun. Actually, everything in the Edit menu can be implemented in about five seconds because there are standard actions for all the commands displayed in Figure 16-11. But we're not going to use standard actions here. Instead, we're going to implement all the Edit menu commands manually.

Undo

First, let's create the Undo action:

  1. Create a new action.

  2. Set the Caption property to &Undo.

  3. Set the Hint property to "Undo the last action."

  4. Rename the action UndoAction.

  5. Set the ShortCut property to Ctrl+Z.

To undo changes in the editor, you have to call the Undo method. To determine if you can undo anything, you can call the CanUndo method. Better yet, you should call the CanUndo method in the action's OnUpdate event to disable the action when it's not possible to undo something, as shown in Listing 16-6.

Listing 16-6: The OnExecute and OnUpdate event handlers of the Undo action

image from book
procedure TMainForm.UndoActionExecute(Sender: TObject); begin   Editor.Undo; end; procedure TMainForm.UndoActionUpdate(Sender: TObject); begin   UndoAction.Enabled := Editor.CanUndo; end;
image from book

Cutting and Copying to the Clipboard

The Cut and Copy actions are very similar. The Copy action copies the selected text to the clipboard, and the Cut action first copies the selected text to the clipboard and then deletes the text from the editor.

Because the Cut and Copy actions share the same OnUpdate event handler, let's create both actions first and then write the necessary event handlers.

To create the Cut action, follow these steps:

  1. Create a new action in the Action List editor.

  2. Set the Caption of the new action to Cu&t.

  3. Set the Hint property to "Cut the selection to the clipboard."

  4. Rename the action CutAction.

  5. Set the ShortCut property to Ctrl+X.

To create the Copy action, follow these steps:

  1. Create a new action in the Action List editor.

  2. Set the Caption of the new action to &Copy.

  3. Set the Hint property to "Copy the selection to the clipboard."

  4. Rename the action CopyAction.

  5. Set the ShortCut property to Ctrl+C.

Both OnExecute event handlers are easy to implement. To copy the text from the editor to the clipboard, you have to call the CopyToClipboard method. To cut the text to the clipboard, call the editor's CutToClipboard method.

Listing 16-7: Cut and Copy OnExecute event handlers

image from book
procedure TMainForm.CutActionExecute(Sender: TObject); begin   Editor.CutToClipboard; end; procedure TMainForm.CopyActionExecute(Sender: TObject); begin   Editor.CopyToClipboard; end;
image from book

The code in the OnUpdate event handler needs to disable the action if there is no selected text in the editor. You can use the editor's SelLength property to determine how many characters are selected. If the value of the SelLength property is 0, there are no selected characters in the editor and we have to disable the action.

Now, write the following OnUpdate event handler for the Cut action and then assign it to the OnUpdate event of the Copy action:

procedure TMainForm.CutActionUpdate(Sender: TObject); begin   TAction(Sender).Enabled := Editor.SelLength > 0; end;

Pasting from the Clipboard

The Paste action pastes the contents of the clipboard into the editor. To be completely professional, you should only allow the user to select Paste when the clipboard contains text. To find out the format of the data stored in the clipboard, call the clipboard's HasFormat method. To see if the clipboard contains plain text data that can be pasted into the editor, call the HasFormat method and pass the CF_TEXT constant as the parameter. To use the global Clipboard object, you have to add the Clipbrd unit to the uses list.

To create the Paste action, here's what you have to do:

  1. Create a new action.

  2. Set the Caption property to &Paste.

  3. Set the Hint property to "Insert text from the clipboard."

  4. Rename the action PasteAction.

  5. Set the ShortCut property to Ctrl+V.

The implementation of the Paste action is displayed in Listing 16-8.

Listing 16-8: The Paste action

image from book
procedure TMainForm.PasteActionExecute(Sender: TObject); begin   Editor.PasteFromClipboard; end; procedure TMainForm.PasteActionUpdate(Sender: TObject); begin   PasteAction.Enabled := Clipboard.HasFormat(CF_TEXT); end;
image from book

If you're building the text editor using the C++ langugage, you'll need to include the Clipbrd.hpp header file, in order to access the TClipboard class, and the Clipboard function, which returns the instance of the TClipboard class that we should use in our VCL Forms applications.

Here's how you call the HasFormat method in C++ to determine if the clipboard contains plain text data that can be pasted into the document:

void __fastcall TMainForm::PasteActionUpdate(TObject *Sender) {    PasteAction->Enabled = Clipboard()->HasFormat(CF_TEXT); }

Deleting

The Delete action does pretty much the same thing as the Cut action. Just like Cut, the Delete action removes the selected text from the editor. The difference is that Delete doesn't copy the text to the clipboard before removing it from the editor.

To create the Delete action, follow these steps:

  1. Create a new action.

  2. Set the Caption property of the new action to De&lete.

  3. Set the Hint property to "Erase the selection."

  4. Rename the action DeleteAction.

  5. Set the ShortCut property to Del.

To delete the text from the editor without changing the contents of the clipboard, use the ClearSelection method. Also, assign the Cut action's OnUpdate event handler to the OnUpdate event of the Delete action to enable the user to delete the selected text only if such text exists. The implementation of the Delete action is displayed in Listing 16-9.

Listing 16-9: The Delete action

image from book
procedure TMainForm.DeleteActionExecute(Sender: TObject); begin   Editor.ClearSelection; end;
image from book

Selecting the Entire Document

Probably the simplest of all actions is Select All, which enables the user to select the entire contents of the editor. To create the Select All action, do the following:

  1. Create a new action.

  2. Set the Caption property to Select &All.

  3. Set the Hint property to "Select the entire document."

  4. Rename the action SelectAllAction.

  5. Set the ShortCut property to Ctrl+A.

To select the entire contents of a TMemo component, you have to call the SelectAll method:

procedure TMainForm.SelectAllActionExecute(Sender: TObject); begin   Editor.SelectAll; end;

Searching for Text in Delphi

To implement the Find command, first add the TFindDialog component to the Designer Surface. The TFindDialog component encapsulates the common Find dialog that enables the user to search for a string (see Figure 16-12). The string that the user wants to search for is stored in the FindText property.

image from book
Figure 16-12: The Find dialog

To enable the user to search for text, we have to create the Find action that displays the Find dialog and write a handler for the dialog's OnFind event to actually perform the search. Since the Find dialog enables the user to search for multiple instances of a string, we need to declare an Integer variable to store the last search position:

type   TMainForm = class(TForm)   private     FLastSearch: Integer;   public   end;

Now, follow these steps to create the Find action:

  1. Set the Caption property of the new action to &Find…

  2. Set the Hint property to "Find the specified text."

  3. Rename the action FindAction.

  4. Set the ShortCut property to Ctrl+F.

  5. Write the following code in the action's OnExecute event handler:

    procedure TMainForm.FindActionExecute(Sender: TObject); begin   { start at the beginning of the document }   FLastSearch := 0;   { display the dialog }   FindDialog1.Execute; end; 

The code that performs the search is displayed in Listing 16-10A. The C++ implementation is displayed in Listing 16-10B.

Listing 16-10A: Searching for text, Delphi version

image from book
procedure TMainForm.FindDialog1Find(Sender: TObject); var   memoText: string;   searchPos: Integer;   dialog: TFindDialog; begin   dialog := TFindDialog(Sender);   memoText := Editor.Lines.Text;   if FLastSearch <> 0 then Delete(memoText, 1, FLastSearch);   searchPos := Pos(dialog.FindText, memoText);   if searchPos = 0 then     MessageDlg(Format('Cannot find "%s"', [dialog.FindText]),       mtInformation, [mbOK], 0)   else begin     Inc(FLastSearch, searchPos);     Editor.SelStart := Pred(FLastSearch);     Editor.SelLength := Length(dialog.FindText);     Editor.SetFocus;   end; end;
image from book

The first line (typecast of the Sender parameter to TFindDialog) is not necessary if you're only going to use this method in the Edit ® Find command. In this case, we need the typecast because it enables us to reuse this method in the OnFind event of the TReplaceDialog component.

The next two lines create a temporary copy of the entire document and remove the section of the document that the user previously searched. If we don't remove the previously searched section, the Pos function that is used to perform the search will always return the first instance of the search string.

If the Pos function finds an instance of the search string, we have to store the location of the found instance in the FLastSearch variable and then select the search string in the editor. To select the string in the editor, we have to modify the SelStart and SelLength properties. SelStart indicates the position of the cursor and SelLength specifies the number of selected characters. Finally, to display the selection we have to call the SetFocus method to focus the editor.

image from book
Figure 16-13: Using the Find dialog to search for text

Searching for Text in C++

Almost every line of code in Listing 16-10A can be easily translated into C++. The only problem lies in the line that calls the Format function to format the string displayed by the MessageDlg dialog box.

The problem is that the Format function accepts, as the second parameter, an array of const, which is the Delphi way of enabling the function to accept a variable number of parameters:

procedure TForm1.FormatPlay(Sender: TObject); var   x, y: Integer; begin   x := 1; y := 2;   Caption := Format('%d + %d = %d', [x, y, x + y]); // 1 + 2 = 3   Caption := Format('%s%s', ['Bor', 'land']);       // Borlandend;

To call the Format function (or other functions with variable parameter lists) in C++, you have to replace the open array constructor (brackets and statements inside the brackets) with the ARRAYOFCONST macro, which has the following syntax:

ARRAYOFCONST((value_1, value_2, value_n))

Here's an example of how to call the Format function in C++:

void __fastcall TForm1::FormatPlay(TObject *Sender) {    int x = 1, y = 2;    Caption = Format("%d + %d = %d", ARRAYOFCONST((x, y, x + y)));    Caption = Format("%s%s", ARRAYOFCONST(("Bor", "land"))); } 

Listing 16-10B shows how to search for text using the C++ language.

Listing 16-10B: Searching for text, C++ version

image from book
void __fastcall TMainForm::FindDialog1Find(TObject *Sender) {    AnsiString memoText = Editor->Lines->Text;    int searchPos;    TFindDialog* dialog = dynamic_cast<TFindDialog*>(Sender);    if(FLastSearch != 0)       memoText.Delete(1, FLastSearch);    searchPos = memoText.Pos(dialog->FindText);    if(searchPos == 0)       MessageDlg(Format("Cannot find \"%s\"",         ARRAYOFCONST((dialog->FindText))), mtInformation,         TMsgDlgButtons() << mbOK, 0);    else {       FLastSearch += searchPos;       Editor->SelStart = FLastSearch - 1;       Editor->SelLength = dialog->FindText.Length();       Editor->SetFocus();    } }
image from book

Replacing Text

To complete the Edit menu, we have to create the Replace action, which will enable us to search for and replace a string. To implement Replace, we have to do the following:

  • Drop a TReplaceDialog component on the Designer Surface (see Figure 16-14).

    image from book
    Figure 16-14: The TReplaceDialog component

  • Create the action that will display the Replace dialog.

  • Write handlers for the OnFind and OnReplace events of the TReplaceDialog component.

To create the Replace action, do the following:

  1. Set the Caption property of the new action to &Replace…

  2. Set the Hint property to "Replace found text with different text."

  3. Rename the action ReplaceAction.

  4. Set the ShortCut property to Ctrl+H.

  5. Set the Tag property to 1 or any other number not equal to 0.

  6. Assign the OnExecute event handler of the Find action to the OnExecute event.

We have to change the Tag property to reuse the OnExecute event handler of the Find action. Once you've changed the Tag property of the Replace action, you can modify the OnExecute event handler of the Find action to display both dialogs:

procedure TMainForm.FindActionExecute(Sender: TObject); begin   FLastSearch := 0;   if TComponent(Sender).Tag = 0 then     FindDialog1.Execute   else     ReplaceDialog1.Execute; end;

Finally, we have to write handlers for the OnFind event, which occurs when the user clicks the Find button, and the OnReplace event, which occurs when the user clicks the Replace or Replace All buttons.

Actually, we don't have to write a handler for the OnFind event, because we can use the already existing OnFind event handler of the TFindDialog component. We can use the existing OnFind event handler because of the initial typecast of the Sender parameter to a TFindDialog component and because TReplaceDialog descends from TFindDialog.

In the OnReplace event handler, we have to check if there is selected text in the editor (SelText <> ''), and if there is, replace it with the string from the ReplaceText property.

Listing 16-11: The OnReplace event handler

image from book
procedure TMainForm.ReplaceDialog1Replace(Sender: TObject); begin   if Editor.SelText <> '' then     Editor.SelText := ReplaceDialog1.ReplaceText; end;
image from book



Inside Delphi 2006
Inside Delphi 2006 (Wordware Delphi Developers Library)
ISBN: 1598220039
EAN: 2147483647
Year: 2004
Pages: 212
Authors: Ivan Hladni

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net