artykuły

Delphi - Piszemy prosty edytor tekstu

19:00
pon, 13 maj 2002
Artykuł prowadzący za rękę przy pisaniu pierwszego edytora tekstu w Delphi. Objaśnia wiele zagadnień związanych z tematem.

Wprowadzenie

Witam! W tym artykule zajmiemy się pisaniem prostego edytora tekstów. Fajnie?
Nasz Edytor będzie miał niektóre możliwości formatowania tekstu np. wytłuszczenie, pochylenie, podkreślenie czcionki.
W pierwszym artykule z tej serii - 'Delphi - Własny odtwarzacz' opisałem Delphi'ego powierzchownie. Także do tego art'u nie będzie nam potrzebna bliższa znajomość. Jednak pokaże dzisiaj co zrobić by w właściwościach naszego programu widniała zakładka 'Wersja'.
Przypomnę teraz sposób w jaki umieszczamy komponenty. Otóż należy kliknąc na odpowiedni komponent (np. Button - Przycisk) znajdujący się na palecie:
Paleta komponentów w Delphi
(siódmy od lewej), a następnie umieszczamy go klikając raz na formę. W ten sposób umieściliśmy komponent :)

Piszemy Edytor tekstu

Obróbka kosmetyczna


Na początku należy umieścić wszystkie komponenty i przygotować formularz. Po uruchomieniu Delphi'ego domyślnie tworzy się nowa aplikacja (pusty formularz). Na formularzu układamy (wybierając z palety element i klikając na formularzu) ToolBar [Zakładka Win32], Paleta komponentów w Delphi w inspektorze obiektów znajdującym się po lewej stronie na dole (opisywałem go w poprzednim arcie), odnajdujemy, a następnie zmieniamy właściwość 'Flat' na wartość 'True' i właściwość 'ShowCaptions' na 'True'. Klikamy na nasz ToolBar, prawym przyciskiem myszy wybierając 'New Button'. Tworzy się fajny przycisk :) Powtarzamy tę czynność 2 razy, tak aby w sumie tych przycisków było 3. Pierwszemu przyciskowi nadajemy tekst 'Nowy' odnajdując właściwość caption w inspektorze obiektów i wpisując w to pole tekst 'Nowy'. Dla drugiego przycisku wpisujemy 'Otwórz', trzeci będzie 'Zapisz'.

Teraz kolej na przyciski formatowania. Muszą być to być przyciski innego typu (tzw. SpeedButton'y by można je było wcisnąć i zostawić wciśnięte).
Wybieramy więc z palety 'Additional' komponent SpeedButton i wstawiamy go na formę. Zaznaczamy go i przechodzimy do Inspektora Obiektów, w którym odnajdujemy właściwość Caption i zmieniamy na 'Wytłuszczenie'. W ten sposób zmieniamy widoczną etykiete przycisku.
Wstawiamy jeszcze dwa tego typu przyciski (SpeedButton z palety Additional) i nadajemy im kolejno etykiety 'Pochylenie' i 'Podkreślenie'.

Zaznaczamy przycisk odpowiadający wytłuszczeniu i w inspektorze obiektów odnajdujemy właściwość GroupIndex, którą zmieniamy na 1, następnie odnajdujemy właściwość 'AllowAllUp' i zmieniamy ją na True.
Zaznaczamy przycisk odpowiadający pochyleniu i w inspektorze obiektów odnajdujemy właściwość GroupIndex, którą zmieniamy na 2, następnie odnajdujemy właściwość 'AllowAllUp' i zmieniamy ją na True.
Zaznaczamy przycisk odpowiadający podkreśleniu i w inspektorze obiektów odnajdujemy właściwość GroupIndex, którą zmieniamy na 3, następnie odnajdujemy właściwość 'AllowAllUp' i zmieniamy ją na True.

W ten sposób nasze przyciski będą się wciskać i pozostawać wciśnięte niezależnie od siebie.
Znów klikamy na ToolBar (prawym przyciskiem myszy) i wybieramy 'New Separator'. Pojawiła się jakby pionowa linia. Służy ona do oddzialania grup przycisków i nie ma znaczenia w działaniu programu tj. możemy równie dobrze o niej zapomnieć. Przeciągamy ową linię między przyciski 'Zapisz', a 'Wytłuszczenie'. W ten sposób oddzieliliśmy przyciski standardowe od przycisków formatowania.
Kolejnym krokiem jest umieszczenie na formularzu komponentu RichEdit [Zakładka Win32]. Po jego umieszczeniu klikamy nań, a w inspektorze obiektów odszukujemy i wybieramy z właściwości 'Align' wartość 'alClient'. Służy ona do dystrybuowania miejscem zajmowanym przez komponent na formie. Od tej chwili bezwzględnie czy zmaksymalizujemy nasz program, czy nie kontrolka (komponent) RichEdit zawsze będzie zajmował pozostałą część formy.
Ustawiliśmy RichEdit, ale w jego polu coś piszę: 'RichEdit1'??? Aby to zmienić musimy kliknąć na niego i z inspektora obiektów wybrać 'Lines' (klikajta te trzy kropki). Tym sposobem otworzyliśmy okno umożliwiające nam wpisane stałej treści komponentu. Usuwamy napis 'RichEdit1' i klikamy na OK. Mamy już puste pole :)
Kolejnym krokiem jest zmiana nazwy komponentu 'RichEdit1' na 're' (zmieniamy właściwość 'Name' w inspektorze obiektów na wartość 're').
Ostatnim krokiem jest umieszczenie na formularzu komponentów 'SaveDialog' i 'OpenDialog'. Służą one do wyświetlania popularnego okienka służącego do zapisywania czy otwierania dokumentu. Znajdują się one na zakładce 'Dialogs'.
Oki, skończyliśmy robotę z wyglądem. Teraz coś bardziej zaawansowanego...

Piszemy program...

Zaznaczam tutaj, że do przełączania się między edytorem kodu, a formularzem posłuży nam klawisz F12. Klikamy teraz podwójnie na przycisk 'Nowy'. Ukazuje się nam edytor kodu, w którym widzimy na razie coś takiego:

procedure TForm1.ToolButton1Click(Sender: TObject); begin end;

Pomiędzy słówka 'begin' i 'end' będziemy wpisywali kod procedury tworzącej nam nowy dokument. Czyli po kliknięciu na przycisk 'Nowy' program ma wyczyścić zawartość komponentu 'RichEdit' ('re') (w tym wypadku wpisany przez użytkownika tekst). Instrukcja wykonująca tę czynność jest banalna:

procedure TForm1.ToolButton1Click(Sender: TObject); begin re.Clear; end;

Kod przycisku Otwórz uzupełniamy następująco (musimy przejść do widoku formy - klawisz F12 - i kliknąć dwukrotnie przycisk 'Otwórz')

procedure TForm1.ToolButton2Click(Sender: TObject); begin If OpenDialog1.Execute Then         // Wywołanie okna służącego do otwierania plików re.Lines.LoadFromFile(OpenDialog1.FileName); // Wczytanie zawartości pliku w RichEdit end;

Tu mamy już coś trudniejszego. Pierwsza linijka wywołuje nam okno (otwiera je) otwierania pliku. Można ją tłumaczyć następująco: Jeśli OpenDialog1 jest otwarty to... OpenDialog właśnie w tej linijce się otwiera. Dziwne? Przyzwyczaicie się... Jeśli powyższe wytłumaczenie do Was nie przemawia to mogę wyjaśnić to w ten sposób: Obiekt OpenDialog1 posiada funkcję Execute() - służy ona do wyświetlania okna i zwraca pewną wartość po jego zamknięciu. Jeśli użytkownik zamknie okno wyboru pliku poprzez OK, funkcja Execute() zwróci True, jeśli natomiast kliknie Anuluj - funkcja zwróci False (i w tym przypadku w naszym programie nie zostaną wykonane czynności zawarte po słówku Then - czyli instrukcje wczytywania pliku do komponentu RichEdit (nazwanego u nas 're').)

Druga linia ładuje do RichEdit ('re') linijki zawarte w pliku wskazanym przez użytkownika. OpenDialog1.FileName to nic innego jak ścieżka do pliku, który chce otworzyć użytkownik.
Notka: Aby załadować do komponentu RichEdit jakiś plik np. informacje o autorze nie wyświetlając okna 'Otwórz plik...' zamiast tych dwóch linii możemy napisać:

procedure TForm1.ToolButton2Click(Sender: TObject); begin re.Lines.LoadFromFile('C:\autor.txt'); // Otworzenie pliku w RichEdit end;

Jednak taki sposób w Edytorze tekstu nie jest nam potrzebny, gdyż przy każdym kliknięciu na przycisk 'Otwórz' do RichEdit'a ładowałby się nam plik C:\autor.txt.

Przyszła kolej na ostatni przycisk z serii Standard ;) Kod przycisku Zapisz uzupełniamy następująco:

procedure TForm1.ToolButton3Click(Sender: TObject); begin If SaveDialog1.Execute Then // Otworzenie okna 'Zapisz plik...' Begin re.PlainText := True;     // Zwykły tekst re.Lines.SaveToFile(SaveDialog1.FileName);  // Zapisanie Lini RichEdit'a do pliku end; end;

Taki kod nie jest zbyt rozbudowany. Wywołując okno zapisu musimy ręcznie określać rozszerzenie dla naszego pliku np. plik.txt
W pierwszej linii mamy do czynienia z otworzeniem okna. Druga linia naszego kodu to słówko 'Begin' stawia się je wtedy go pod warunkim If ... Then mamy więcej niż jedną linie (zauważ, że w procedurze otwierania pliku nie było 'Begin' ponieważ kod warunku

If OpenDialog1.Execute Then

Miał tylko jedną linię czyli :

re.Lines.LoadFromFile(OpenDialog1.FileName);

Trzecia linika naszego kodu (procedura służąca do zapisywania pliku) to jakby skonwertowanie zawartości RichEdit na zwykły tekst tj. taki który można otworzyć za pomocą innego programu i nie pokażą się dziwne znaki jak :

{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fnil MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\fswiss\fcharset1 MS Sans Serif;}} {\colortbl\red0\green0\blue0;} \deflang1045\pard\plain\f2\fs16 ssssssssssssssss \par }

Dziwne? To po prostu zapis formatowania tekstu (np. użyta czcionka itp.)
Czwarta linijka to zapisanie lini RichEdit'a do pliku o ścieżce tkwiącej w 'FileName'

Teraz mamy kolejne, trzy ostatnie przyciski formatowania:

  • wytłuszczenie
  • pochylenie
  • podkreślenie

Uzupełniamy ich kod następująco:

Wytłuszczenie:

procedure TForm1.SpeedButton1Click(Sender: TObject); begin If SpeedButton1.Down Then re.SelAttributes.Style:= re.SelAttributes.Style + [fsBold] else re.SelAttributes.Style:= re.SelAttributes.Style - [fsBold]; end;

Można to przetłumaczyć: Jeśli przycisk odpowiadający wytłuszczeniu jest wciśnięty to dodaj do zaznaczonego tekstu styl pogrubienia (fsBold), jeśli natomiast przycisk nie jest wciśnięty to odbierz zaznaczonemu fragmentowi tekstu styl pogrubienia. Dla pochylenia i podkreślenia postępujemy analogicznie.

Pochylenie:

procedure TForm1.SpeedButton2Click(Sender: TObject); begin If SpeedButton2.Down Then re.SelAttributes.Style:= re.SelAttributes.Style + [fsItalic] else re.SelAttributes.Style:= re.SelAttributes.Style - [fsItalic]; end;

Podkreślenie:

procedure TForm1.SpeedButton3Click(Sender: TObject); begin If SpeedButton3.Down Then re.SelAttributes.Style:= re.SelAttributes.Style + [fsUnderline] else re.SelAttributes.Style:= re.SelAttributes.Style - [fsUnderline]; end;

Pogrubianie, pochylanie i podkreślanie tekstu zachowuje się już u nas tak jak w Wordzie:
Jeśli chcesz zobaczyć taki program, napisz: lukas.home.page@gmail.com .

Zapisywanie z użyciem różnych formatów plików:

Rozwiązałem ten problem następująco:

var roz: integer; begin SaveDialog1.FileName := 'Dokument'; If SaveDialog1.Execute Then Begin roz := SaveDialog1.FilterIndex; // Wybór rozszerzenia (roz=numer filtru rozszerzenia pliku) If roz=1 Then begin SaveDialog1.FileName := SaveDialog1.FileName+'.tek'; end; If roz=2 Then begin SaveDialog1.FileName := SaveDialog1.FileName+'.doc'; end; If roz=3 Then begin re.PlainText := True; // wyłączanie formatowania tekstu SaveDialog1.FileName := SaveDialog1.FileName+'.txt'; end; If roz=4 Then begin re.PlainText := True; // wyłączanie formatowania tekstu SaveDialog1.FileName := SaveDialog1.FileName+'.html'; end; If roz=5 Then begin re.PlainText := True; // wyłączanie formatowania tekstu SaveDialog1.FileName := SaveDialog1.FileName+'.pas'; end; re.Lines.SaveToFile(SaveDialog1.FileName); re.PlainText := False; // ponowne włączenie formartowania end;

Należy w inspektorze obiektów (w komponencie SaveDialog1) wybrać Filter (pojawi się okno) i uzupełnić je następująco:
Okno z tabelą rozszerzeń (filtrów) w Delphi.
W ten sposób umożliwimy zapisanie pliku w wielu formatach...

Zakończenie

Mam nadzieję, że artykuł się podobał? Było coś dla początkujących, było dla 'średnio-zaawansowanych'. Wydaje mi się, że wszystko tłumaczyłem, ale jeśli czegoś nie rozumiesz - pisz: lukas.home.page@gmail.com
Do artykułu dołączam również kod źródłowy pisanego edytora tekstu.

12345
Delphi - Piszemy prosty edytor tekstu Autor opinii: Czytelnicy, data przesłania: 5

Podobne artykuly:

Skomentuj

Aby zamieścić komentarz, proszę włączyć JavaScript - niestety roboty spamujące dają mi niezmiernie popalić.






Komentarze czytelników

    • lukasz9646
    • nie, 12 grudzień 2010, 0:04
    • zastosowałem filters na rozszerzenia plików, ale po wybraniu rozszerzenia w okienku zapisu np txt zapisuje się sama nazwa pliku bez rozszerzenia.. jak to naprawić?




      Odp: Jeśli chodzi o Pana problem, to rozumiem, że rozpoznaje Pan w kodzie wybrane rozszerzenie pliku (FilterIndex) i dokleja odpowiednie rozszerzenie do nazwy pliku? Nie wiem na jakim poziomie zaawansowania Pan jest, początkujący niestety często o tym zapominają. Jednym słowem należy, uzupełnić w Inspektorze Obiektów pole „Filters” okienka SaveDialog, a w procedurze zapisującej plik dodać kod odpowiedzialny za dodawanie do nazwy pliku rozszerzenia odpowiadającego wybranemu przez użytkownika. Robi się to w następujący sposób. Przypuśćmy, że na formularzu ma Pan komponent Memo, oraz przycisk Button. Kod zdarzenia OnClick przycisku Button powinien być następujący:


      procedure TForm1.Button1Click(Sender: TObject);
      var
      rozszerzenie : string;
      begin
      if not SaveDialog1.Execute Then Exit;


      rozszerzenie := Trim(ExtractFileExt(SaveDialog1.FileName));

      if (rozszerzenie='') Then
      begin
      case (SaveDialog1.FilterIndex) of
      1: rozszerzenie := '.txt';
      2: rozszerzenie := '.sub';
      3: rozszerzenie := '.html';
      end;
      end else
      begin
      // ponieważ nazwa pliku SaveDialog1.FileName zawiera już w tym wypadku rozszerzenie
      rozszerzenie := '';
      end;

      Memo1.Lines.SaveToFile(SaveDialog1.FileName+rozszerzenie);
      end;
    • Damian
    • sob, 6 listopad 2010, 18:14
    • Wszystko pięknie działa!! Wielkie dzięki za pomoc ;)
    • Damian
    • pią, 5 listopad 2010, 20:19
    • Witaj, mam pytanie. Pracuje wlasnie nad edytorem tekstu w delphi, i napotkalem problem, nie moge poprawnie użyć funkcji Alignment(Wysrodkowywanie tekstu, do lewej, do prawej...) w komponencie RichEdit. Czytałem na internecie w tej sprawie, lecz nie uzyskalem odpowiedzi. Dodam ,iz w komponencie Memo wszysttko dziala bez problemu. Delphi zachowuje się jakby poprostu nie umiał wykonać tej operacji. Jeżeli potrafisz mi pomóc prosze o odpowiedź.



      Odp: Próbowałeś w ten sposób?:

      RichEdit1.Paragraph.Alignment := taRightJustify;
    • 1234
    • pią, 5 listopad 2010, 18:27
    • Bardzo ciekawy i przydatny komentarz. Dzieki ;]
    • Dżyszla
    • czw, 30 październik 2008, 14:11
    • Ten zapis do HTML i innych to taki pic na wodę trochę chyba ;)
    • mam problem 2 :
    • czw, 1 maj 2008, 15:04
    • kurcze ten sam błąd co w odtwarzaczu :( Klkam na "pogrubienie" i błąd ...
Dexter