ComPort.WriteStr - dziwne zachowanie

ComPort.WriteStr - dziwne zachowanie
MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Cześć,

Piszę program do obsługi robota przez USB w Delphi. Wykorzystuję bibliotekę ComPort. W laptopie podłączenie USB do robota poprawnie zgłasza się jako Virtual Port Com. Gdy wysyłam komendę:

Kopiuj
ComPort.WriteStr('komenda');

to procesor w robocie w ogóle jej nie zauważa. Natomiast gdy wysyłam z programu Terminal to jest OK.

Ustawienia transmisji mam takie same.

Gdzie może być przyczyna tego problemu?

Pozdrawiam.

edytowany 2x, ostatnio: flowCRANE
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12166
0
Markoni napisał(a):

Gdzie może być przyczyna tego problemu?

Brak terminatora?


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

O jaki terminator chodzi?
Podsłuchuję transmisję w drugim Terminalu i wszystkie znaki nadawane (z Delphi/ z Terminala) są takie same.

Podsłuchuje na zasadzie przejściówka USB-RS232 <-> RS232-USB. Ale do robota transmisja jest bez przejściówki, czyli bezpośrednio USB <-> USB. Może tu jest problem?

edytowany 2x, ostatnio: Markoni
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12166
2
Kopiuj
ComPort.WriteStr('komenda'#13#10);

Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
MA
Dodam, że może być też samo #13.
flowCRANE
Pasuje sprawdzić w dokumentacji jak powinno się terminować ciągi.
MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Ja w swoim programie kończę komendy samym: #10. Tak samo wysyłam z Terminala do robota i nadawanie/odbiór jest OK.
ComPort.WriteStr('komenda'+#10);
Dlaczego wysyłanie z ComPortu komendy z zakończeniem #10 (z zapisem, tak samo jak z Terminala) powoduje problemy?

Czy ComPort ma jakieś ograniczenia w Windowsie?

edytowany 2x, ostatnio: Markoni
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
1
Markoni napisał(a):

Czy ComPort ma jakieś ograniczenia w Windowsie?

Nie, nie ma ograniczeń jako takich. Ja u siebie obsługuję port COM bez problemów. Nie kończę żadnymi znakami #13#10 i jest ok. To, czy konieczny jest znak nowego wiersza zależy tylko i wyłącznie od urządzenia podłączonego pod port COM. Zatem należałoby sprawdzić w jego dokumentacji jakich komend oczekuje i takowe wysłać.

Dawno się nie bawiłem terminalem. Jednak takie modemy GSM wymagają podania na końcu znaku nowego wiersza. Dlatego wysyłając komendy AT miało to znaczenie. Jednak w przypadku np. drukarek fiskalnych takie znaki są wręcz niepożądane.

To, że komendy wysyłane z terminala działają, natomiast z programu nie może sugerować, ze urządzenie przetwarza komendy po odbiorze pełnego wiersza. Jednak 100% pewność da Ci dokumentacja danego urządzenia.

MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

To urządzenie, to robot na którego napisałem oprogramowanie. Zatem wiem jakich komend oczekiwać :)
Tylko nie rozumiem, dlaczego z ComPortu/Delphi i Terminala jest inna reakcja?

W zasadzie z urządzenia/robota nie wychodzi COM, tylko USB bezpośrednio podłączone do procesora.

edytowany 1x, ostatnio: Markoni
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
1
Markoni napisał(a):

To urządzenie, to robot na którego napisałem oprogramowanie. Zatem wiem jakich komend oczekiwać :)

Zatem musisz się pochylić bardziej nad softem wewnętrznym i sprawdzić w jaki sposób wczytujesz dane z portu. Czy wymagany jest znak entera czy nie. Nie znam się aż tak na embedded, ale to pewnie zależy od funkcji jakich używasz w kodzie wewnętrznym robota.

Markoni napisał(a):

Tylko nie rozumiem, dlaczego z ComPortu/Delphi i Terminala jest inna reakcja?

W zasadzie z urządzenia/robota nie wychodzi COM, tylko USB bezpośrednio podłączone do procesora.

Takie USB instaluje się w systemie jako wirtualny port COM który to tak naprawdę nie różni się od strony programisty niczym od fizycznego portu COM.

To może być kwestia ustawień, terminal może używać zupełnie innych ustawień portu COM niż Twój program. A żeby być pewnym co do znaków #13#10 posłuż się snifferem i podsłuchaj komunikację wraz z jej parametrami gdy działa program terminalu, oraz Twój. Wtedy zobaczysz jakie masz różnice.

MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Jaki jest sniffer pod Windowsa7/10?

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
2

Osobiście do sprawdzenia jakie parametry ustawia sobie obcy proces przed nawiązaniem połączenia z portem COM używałem tego http://www.rohitab.com/apimonitor Ustawianie parametrów podejrzałem w funkcji SetCommState Program ładnie zdekodował mi strukturę DCB https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb

Natomiast do zwykłego podglądania tego co przesyła się po porcie COM używałem https://docs.microsoft.com/en-us/sysinternals/downloads/portmon

MA
  • Rejestracja:ponad 16 lat
  • Ostatnio:18 dni
0
Markoni napisał(a):

Jaki jest sniffer pod Windowsa7/10?

https://www.eltima.com/products/serial-port-monitor/

Tylko po co Ci sniffer, skoro wiesz co wysłać terminalem i to działa.

edytowany 1x, ostatnio: marogo
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12166
2

Nie chcę się wypowiadać za bardzo w tym wątku, dlatego że doświadczenie w temacie komunikacji szeregowej mam praktycznie żadne (nie licząc Arduino, ale to inna bajka). Mimo wszystko – tak na logikę – komunikacja musi być oparta o jakieś metadane lub z góry narzucony stały rozmiar ramki. Urządzenie odbierające dane musi wiedzieć ile ich otrzyma (z góry określony rozmiar bufora), a jeśli nie wiadomo ile tych danych będzie, wymagane jest oznaczenie końca danych znakiem terminatora. Tak działają np. kasy fiskalne.

W sieci masz kupę przykładów i wątków dotyczących ComPort.WriteStr – wszystkie wykorzystują terminator.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
2
furious programming napisał(a):

Mimo wszystko – tak na logikę – komunikacja musi być oparta o jakieś metadane lub z góry narzucony stały rozmiar ramki. Urządzenie odbierające dane musi wiedzieć ile ich otrzyma (z góry określony rozmiar bufora), a jeśli nie wiadomo ile tych danych będzie, wymagane jest oznaczenie końca danych znakiem terminatora. Tak działają np. kasy fiskalne.

Tak jest, większość urządzeń z jakimi miałem do czynienia właśnie tak działały jak piszesz. Ale.... raz się spotkałem z urządzeniem które nie miało takich ramek. Ot po prostu po każdym znaku analizowało komendę i jak była prawidłowa wykonywała ją. Dziwne to było, jednak trzeba było się dostosować. Nadmienię, że to był pomysł architektów systemów wewnętrznych i urządzenie nie wyszło poza firmę. Jednak musiałem gadać z nim i sama integracja trwała długo. Niemniej jednak terminatorem nie musi być znak nowej linii. W drukarkach fiskalnych które miałem obsługiwać taka ramka ma postać:

ESC komenda ESC \

Poza tym bardzo ważne są dokładne ustawienia portu COM, musi się zgadzać z tym co ustawione w urządzeniu.

edytowany 1x, ostatnio: Mr.YaHooo
flowCRANE
*niemniej jednak
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12166
1
Mr.YaHooo napisał(a):

Ale.... raz się spotkałem z urządzeniem które nie miało takich ramek. Ot po prostu po każdym znaku analizowało komendę i jak była prawidłowa wykonywała ją. Dziwne to było, jednak trzeba było się dostosować.

Może nie tyle dziwne, co nietypowe. Sam bym takiego sposobu nie wybrał. Raz, że trzeba by więcej kodu klepać, aby móc poprawnie interpretować nadchodzące dane, a dwa, że testowanie zawartości bufora po każdym otrzymanym znaku jest tak samo wydajne co sortowanie bąbelkowe. No bez sensu.

Nie mniej jednak terminatorem nie musi być znak nowej linii.

Nigdzie nie pisałem, że musi nim być konkretnie CR lub LF (albo sekwencja CRLF). :P


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 5x, ostatnio: flowCRANE
MY
Tak, faktycznie błędnie założyłem w kontekście wysyłania przez Terminal i zatwierdzania Enterem wysyłki komendy.
MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Tylko, że jak pisałem z Terminala odbiera, a z ComPortu NIE. Gdyby z Terminala nie odbierał, to błąd byłby po stronie urządzenia/robota.
Poza tym ramka ma zmienną długość, ale ma znaki początku i zakończenia ramki.

edytowany 1x, ostatnio: Markoni
MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Zainstalowałem API Monitor i w funkcji SetCommState ustawienia dla Terminala i ComPort są te same. Różnica jest tylko w wReserved, XonLim, XoffLim.
Często mam też problemy z otwarciem portu: SetCommState=Error: 87.
Ale w Terminalu otwiera się zawsze.

Jak można usunąć problem z SetCommState=Error: 87?

edytowany 1x, ostatnio: Markoni
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
0

@Markoni ten błąd niestety jest dość parszywy. Przyczyna może być różna od śmieci które się pojawiają podczas tworzenia struktury DCB poprzez błędne parametry których nie obsługuje port. Zatem osobiście próbowałbym ustawić dokładnie takie same parametry jak Terminal który nie ma problemu z połączeniem.

Swoją drogą błąd 87 masz podczas otwarcia portu, czy wykonania funkcji SetCommState Generalnie sprawdź czy masz mniej więcej podobnie jak tutaj https://docs.microsoft.com/pl-pl/windows/win32/devio/configuring-a-communications-resource?redirectedfrom=MSDN przepisz to na Delphi i sprawdź czy zadziała, podstawiając swoje parametry.

Osobiście nigdy podczas obsługi portu COM nie spotkałem się z tym błędem, więc trochę ciężko mi doradzić.

MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Błąd pojawia się podczas otwierania portu.

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
0

W takim razie być może źle tworzysz nazwę pliku który otwierasz jako port COM. Ciężko coś powiedzieć bez kodu. Fajnie by było abyś dał jakiś przykład jak otwierasz oraz ustawiasz parametry portu.

MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Prawdę mówiąc to otwieram klasycznie, przez wprowadzenie parametrów transmisji do TComPort, podania numeru portu i komendę ComPort.Open.
Jak powinno się "profesjonalnie" otwierać port COM?

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12166
1
Markoni napisał(a):

Prawdę mówiąc to otwieram klasycznie, przez wprowadzenie parametrów transmisji do TComPort, podania numeru portu i komendę ComPort.Open.

Wklej kod zamiast opisywać jak on wygląda…


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Nie wstawiałem, ponieważ do otwarcia portu za dużo kodu to nie ma:

Kopiuj
procedure TForm1.btnOpenClick(Sender: TObject);
begin
    if ComPort.Connected = false then
    begin
        if ComComboBox1.Text = '' then exit;
        ComPort.Port:= ComComboBox1.Text;
        ComPort.Open;
        btnOpen.Caption := 'Close';
    end else
    begin
        ComPort.Close;
        btnOpen.Caption := 'Open';
    end
end;
flowCRANE
Właśnie dlatego powinieneś go od razu wrzucić – skoro nie ma tego dużo. ;)
Marius.Maximus
  • Rejestracja:ponad 14 lat
  • Ostatnio:4 minuty
  • Postów:2070
2

I to są właśnie uroki tworzenia aplikacji KLIKANIE+KODOWANIE
Jak wysyłasz taki kawałek kodu to nikt nie wie co jest w środku obiektu "ComPort" bo masz go WYKLINANEGO na FORMIE

Masz ustawione poprawne parametry transmisji ?
Zacznij moze od jakiego "terminal-a" i wyslij komendę przez coś co na 100% działa , potwierdzisz tym sposobem ze jest komunikacja WINDOWS -> robot

Kopiuj
Ewentualnie zacznij od kodu 
var
  ComPort:TComport; 
begin
  ComPort:=TComport.create(...)
  // ustaw parametry 

--
Nie przyjmuję reklamacji za moje rady, używasz na własną odpowiedzialność.
Programowanie bez formatowania to jak chodzenie ze spodniami spuszczonymi na kostki. Owszem da się ale po pierwsze nie wygodne, po drugie nieprzyzwoicie wygląda.
Przed zaczęciem nowego wątku przeczytam problem XY
edytowany 1x, ostatnio: flowCRANE
LA
ustawienie comportu recznie o ile pamietam nie jest takie proste na pierwszy rzut oka, juz lepiej jakby pokazal plik dfm gdzie te wlasciwosci śą ustawione
MY
@lampasss może zabrzmi to grubiańsko, ale jeśli ktoś nie umie skorzystać z dokumentacji i poświęcić godziny na poczytanie MSDN to faktycznie ustawienie parametrów jest trudne. Link do artykułu który mi posłużył jako punktu wyjścia przy pisaniu własnego unita https://docs.microsoft.com/en-us/previous-versions/ff802693(v=msdn.10)?redirectedfrom=MSDN
LA
jesli widze if ComPort.Connected = false then to wiem, ze moze byc ciezko, nie pisalem o sobie :)! zreszta 'wyklikujesz' na formatce, patrzysz w plik DFM i masz to co potrzebujesz
MY
@lampasss aaaa no to w takim razie wszystko ok :)
MA
  • Rejestracja:ponad 16 lat
  • Ostatnio:18 dni
1
Markoni napisał(a):

Błąd pojawia się podczas otwierania portu.

A czy ty przypadkiem nie masz otwartego tego portu w terminalu i próbujesz go równocześnie otworzyć w swoim programie? 🤔

MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Nie rozumiem tych ostatnich postów, przecież wcześniej napisałem, że bez problemu łącze się między Terminalem i ComPortem, przy pomocy przejściówek COM-USB .
Problem jest w łączności USB<->USB.

MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
2
Markoni napisał(a):

Prawdę mówiąc to otwieram klasycznie, przez wprowadzenie parametrów transmisji do TComPort, podania numeru portu i komendę ComPort.Open.
Jak powinno się "profesjonalnie" otwierać port COM?

Klasycznie w stylu Delphi ;) Wziąć komponent, ustawić parametry i już. To jak robi się klasycznie widziałeś w linku który Ci przesłałem wcześniej https://docs.microsoft.com/pl-pl/windows/win32/devio/configuring-a-communications-resource?redirectedfrom=MSDN Plus CreateFile, WriteFile oraz ReadFile Niestety nie wiemy co komponent robi pod spodem i jak jest oprogramowany. Z drugiej strony podałeś też chyba nie do końca cały kod, ponieważ pisałeś w poprzednim poście

Markoni napisał(a):

Zainstalowałem API Monitor i w funkcji SetCommState ustawienia dla Terminala i ComPort są te same. Różnica jest tylko w wReserved, XonLim, XoffLim.
Często mam też problemy z otwarciem portu: SetCommState=Error: 87.
Ale w Terminalu otwiera się zawsze.

Jak można usunąć problem z SetCommState=Error: 87?

Zatem gdzie jest wywołanie tej metody i jak sprawdzasz wystąpienie błędu w wyniku czego wiesz, że to akurat błąd 87?

Markoni napisał(a):

Nie rozumiem tych ostatnich postów, przecież wcześniej napisałem, że bez problemu łącze się między Terminalem i ComPortem, przy pomocy przejściówek COM-USB .
Problem jest w łączności USB<->USB.

Nic bardziej mylnego. Skoro inny program łączy się poprawnie z robotem, to winą jest Twój program, a konkretnie podejrzewałbym komponent którego używasz TComPort. Osobiście nie znalazłem w miarę nowego komponentu/klasy o tej nazwie. A w swoim projekcie po prostu zakodowałem sam swoją klasę do wysyłania danych po porcie COM. Zajęło mi to 100 linijek (niestety piszę w C++) i takich problemów jak Ty nie miałem nigdy.

Zatem albo po prostu masz parę możliwości:

  • zrobisz jak ja i napiszesz własną krótką klasę
  • poszukasz innego, nowszego komponentu
  • przeanalizujesz kod źródłowy komponentu i znajdziesz błąd
  • zgłosisz ticketa u dostawcy komponentu

Oczywiście zakładam, że nie popełniasz głupiego błędu jak łączenie się do portu przez dwa programu na raz

MA
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 lata
  • Postów:53
0

Mr.YaHooo, przesłany przez ciebie kod jest do C++. Jak to zamienić do Delphiego (pascala)?

Co do błędu 87, to wyskakuje taki komunikat podczas otwierania portu.

To że błąd leży po stronie TComPortu to oczywiste i od dłuższego czasu próbuję to rozwiązać.

Napisać własną krótką klasę - na to jestem jeszcze za cienki ;)

Na jakich komponentach od COM-a pracujecie, na których nie macie problemów?

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 3 godziny
  • Lokalizacja:Tuchów
  • Postów:12166
0
Markoni napisał(a):

Napisać własną krótką klasę - na to jestem jeszcze za cienki ;)

Nie umiesz napisać kodu otwierającego plik np. o nazwie COM1 oraz zapisujący do i odczytujący z niego dane? A później opakować go w jakąś małą klasę, żeby zamknąć całą logikę związaną z komunikacją w jednym kontenerku?


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
PD
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 4 godziny
3

Synapse:

Kopiuj
uses
  synaser;

procedure TForm1.Button1Click(Sender: TObject);
var
  com: TBlockSerial;
begin
  try
    com:=TBlockSerial.Create;
    com.Connect('COM1');
    com.Config(9600, 8, 'N', 1, False, False); 
    com.SendString('komenda'+#13#10);
  finally
    com.Free;
  end;
end;  

pozdrawiam
paweld
edytowany 1x, ostatnio: Paweł Dmitruk
cerrato
popieram - synapse to chyba najlepsza opcja :)
MY
  • Rejestracja:ponad 9 lat
  • Ostatnio:2 dni
  • Postów:1082
1
Markoni napisał(a):

Na jakich komponentach od COM-a pracujecie, na których nie macie problemów?

To jest na tyle proste, że sam oprogramowałem klasę. Zmieścisz się w mniej niż 100 liniach kodu.

Co do rozumienia C/C++. Jeśli poważnie traktujesz programowanie pod Windows to musisz nauczyć się czytać kod C/C++ ponieważ wszystkie przykłady WinAPI (które czasami jest niezbędne) są właśnie w tych językach.

Paweł Dmitruk napisał(a):
com.Connect('COM1');

A co w przypadku gdy mamy port większy niż 9? Synapse nie wymaga składni takiej jak funkcja https://support.microsoft.com/en-us/help/115831/howto-specify-serial-ports-larger-than-com9 Akurat w przypadku portów wirtualnych instalowanych po podłączeniu różnych urządzeń pod USB często ustawia się numer portu większy od 10 i można się nadziać w ten sposób.

PD
com.Connect('COM28');
MY
@Paweł Dmitruk super sprawa w takim razie :) Niestety z pobieżnego przeszukania dokumentacji metody Connect nie znalazłem odpowiedzi na moje pytanie. A w źródłach nie szukałem.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)