Trimiterea mesajelor Delphi. Mesajele utilizatorului. Utilizarea mesajelor în cadrul aplicației

undeva ca asta

IdTCPClient1.Host:= "127.0.0.1"; IdTCPClient1.Connect;// conectat IdTCPClient1.Socket.WriteLn("comanda"); // a trimis comanda de comandă și fluxul de linie // Așteptați răspunsul și închideți conexiunea txtResults.Lines.Append(IdTCPClient1.Socket.ReadLn); IdTCPClient1.Deconectare;

în acest caz, comanda este doar text cu un avans de linie. Acest lucru face mult mai ușor să primiți comanda din cealaltă parte (doar ReadLn). În cazul general, trebuie să veniți cu (sau să utilizați un protocol gata făcut).

deasupra era un client. Și acum serverul. Cu serverul, totul este puțin mai complicat. Este clar că este normal ca un server să servească nu doar un client, ci mai mulți. Și există mai multe „scheme” pentru aceasta.

    Clasic - un client - un fir. Schema este ușor de codificat și intuitivă. Este bine paralelizat între nuclee. Dezavantajul este că de obicei este foarte dificil să creezi multe fire, iar acest lucru limitează numărul de clienți. Pentru programele pe 32 de biți, limita superioară este undeva în jur de 1500 (o mie și jumătate) de fire per proces. Dar, în acest caz, costurile generale de schimbare a acestora pot „mânca” întregul procent. Aceasta este schema folosită în indy.

    Al doilea clasic este toți clienții pe un fir. Această schemă este adesea mai complexă de codat, dar cu abordarea corectă vă permite să păstrați 20-30k de „utilizatori lenți” fără încărcare practic pe kernel. Un avantaj puternic al acestei scheme este că vă puteți descurca fără mutexuri și alte primitive de sincronizare. Această schemă este folosită de NodeJS și de clasele standard pentru lucrul cu rețeaua în Qt.

    Amestecat. În acest caz, sunt create mai multe fire, fiecare dintre ele deservește un anumit număr de clienți. Cel mai dificil de codificat, dar vă permite să utilizați la maximum resursele hardware.

Cum se face în Indy. Serverul Indy tcp creează un fir separat (TThread) pentru fiecare conexiune și munca in continuare cu clientul mergând în ea. Indy ascunde acest lucru frumos, lăsând utilizatorului doar să implementeze metoda IdTCPServer.onExecute. Dar, așa cum am spus mai sus, această metodă este lansată într-un thread separat și este personală pentru fiecare client. Aceasta înseamnă următoarele:

  • în această metodă poți apela sleep și doar un client va aștepta. Toate celelalte vor funcționa (dar dacă apelați sleep în gestionarea de clic pe buton, atunci rezultatul este cunoscut)
    • Este mai bine să accesați variabilele globale numai prin primitive de sincronizare.
    • Trebuie să accesați elementele gui cu atenție și corect. Este mai bine să nu o faceți direct (unele componente permit accesul la ele din alte fire, dar trebuie să citiți cu atenție documentele).
    • Trebuie să accesați alți clienți prin blocare (pentru că dacă două fire vor să scrie aceluiași utilizator, nu va ieși nimic bun din asta).

Să ne uităm la un exemplu foarte simplu. Răspundem la orice solicitare a clientului în natură și închidem conexiunea (un fel de server echo).

Procedura TForm1.IdTCPServer1Execute(AContext: TIdContext); var strText: șir; begin //Primește un șir de la client strText:= AContext.Connection.Socket.ReadLn;

//Răspunde AContext.Connection.Socket.WriteLn(strText); //Închide conexiunea cu utilizatorul AContext.Connection.Disconnect; Sfârşit; AContext este un obiect special care conține toate

informatiile necesare

despre client. Însuși idTcpServer conține o listă a acestor contexte și poate fi accesat. Să luăm în considerare o emisiune mai complexă. Adică, trimiteți un mesaj tuturor

Var Clienti: TList;

i:întreg; începe // probă :) dacă nu este atribuit(IdTCPServer1.Contexts) atunci ieși; // obțineți o listă de clienți și blocați-o Clients:=IdTCPServer1.Contexts.LockList; tastați TObject. Puteți să vă scrieți obiectul în el și să stocați acolo toate datele necesare. Un caz de utilizare tipic ar fi următorul. Când clientul tocmai sa conectat, acest câmp este gol. Când trece de verificarea nume-parolă, creăm un obiect (al nostru), salvăm numele acolo și îl scriem în proprietatea Data. Și apoi, când trebuie să parcurgeți clienții conectați, îl citim pur și simplu. Desigur, dacă există mii de utilizatori, va fi costisitor să vedeți toți utilizatorii de fiecare dată. Dar cum să faci asta mai optim este subiectul unui alt articol mare.

Trimiterea și primirea e-mailurilor este destul de simplă folosind Delphi. Pentru a trimite mail, avem nevoie de componenta idSMTP din pagina Clienti Indy a paletei de componente Delphi.

Această componentă implementează tot ce este necesar pentru a trimite e-mail prin protocolul SMTP (Simple Mail Protocolul de transfer- protocol simplu de transfer mail), folosind portul 25, prin care sunt trimise comenzile și textul scrisorii. Pașii pentru trimiterea e-mailului sunt următorii:

1) conexiune la serverul SMTP pe portul 25;
2) pregătirea corpului scrisorii, identificarea expeditorului și destinatarului scrisorii;
3) trimiterea unei scrisori către serverul SMTP;

După ce ați plasat componenta idSMTP pe formular, să o configuram. Portul poate fi configurat în inspectorul de obiecte setând proprietatea Port la 25 sau puteți face același lucru în codul programului:

IdSMTP1.Port:=25;

Conexiune la server

Pentru a vă conecta la serverul SMTP care va trimite e-mailul nostru, trebuie să specificați URL-ul acestuia pentru serverul mail.ru, acest lucru se face după cum urmează:

IdSMTP1.Host:= ′smtp.mail.ru′;

Conexiunea la server se face folosind metoda Connect:


procedura Connect(const ATimeout: Integer); suprascrie;

unde ATimeout este un parametru opțional care specifică timpul maxim în milisecunde pentru așteptarea unui răspuns de la serverul SMTP, după care încercarea de a stabili o conexiune este încheiată.

De exemplu,

IdSMTP1.Connect(5000);

Dacă este necesară autorizarea la conectarea la server, atunci valoarea proprietății AuthenticationType trebuie setată la atLogin, în timp ce în inspectorul de obiecte trebuie să definiți și proprietățile Username (nume de utilizator. De exemplu, Username). cutie poştală [email protected]- delphi) și Password (parola căsuței poștale) sau procedați la fel în mod programatic:

IdSMTP1.AuthenticationType:=atLogin;
IdSMTP1.Nume utilizator:=′delphi′;
IdSMTP1.Parola:='ceva';

IdSMTP1.AuthenticationType:=atNone;

După utilizarea metodei Connect, trebuie să analizați proprietatea logică Connected, care, dacă conexiunea este reușită, este setată la True. După aceasta, puteți trimite un mesaj folosind metoda Trimitere:

if Connected=True, atunci IdSMTP1.Send(Msg);

Structura literei

Metoda Send trimite corpul mesajului, care este o structură de tip TIdMessage;

Structura mesajului este implementată în Delphi de o componentă separată TIdMessage situată pe paleta de componente Indy Misc și arată astfel

TidMessage Structura TIdMessage este definită după cum urmează:

Cred că totul este clar cu subiectul mesajului. Proprietate

Numele conturilor electronice cărora le este adresată scrisoarea sunt determinate în mod specific. Numele trebuie specificate folosind un separator de forma ",", adică separate prin virgulă. De exemplu:

De exemplu,

De exemplu,

Proprietatea Text conține informații din ambele proprietăți. Corpul mesajului este un obiect de tip TStrings:

unde Collection este un obiect al clasei TIdMessageParts, care este o colecție de aplicații către e-mail.
constant AFileName de tip TFileName - este un șir de text obișnuit care indică calea corectă către fișier, de exemplu „C:file.zip”, valoarea implicită este „”.

Astfel, continuând exemplul nostru cu o linie like

La dezvoltarea aplicațiilor, poate exista o situație în care o aplicație trebuie să trimită un mesaj fie către ea însăși, fie către o altă aplicație utilizator. Unii oameni ar putea fi confuzi de afirmația anterioară: de ce și-ar trimite o aplicație un mesaj atunci când ar putea apela doar procedura corespunzătoare? Acest buna intrebare, și există mai multe răspunsuri la aceasta. În primul rând, utilizarea mesajelor este un mecanism de susținere a polimorfismului real, deoarece nu necesită cunoștințe despre tipul obiectului care primește mesajul. Astfel, tehnologia mesajelor are aceeași putere ca și mecanismul metodei virtuale, dar cu mult mai multă flexibilitate. În al doilea rând, mesajele permit procesarea opțională - dacă obiectul destinatar nu procesează mesajul primit, atunci nu se va întâmpla nimic rău. Și în al treilea rând, mesajele permit difuzarea către mai mulți destinatari și ascultarea paralelă, ceea ce este destul de dificil de implementat folosind un mecanism de apel de procedură.

Utilizarea mesajelor în cadrul aplicației

A face ca o aplicație să trimită un mesaj către ea însăși este foarte simplu - trebuie doar să utilizați funcțiile API Win32 SendMessage() sau Post-Message() sau metoda Perform(). Mesajul trebuie să aibă un ID în intervalul WM_USER+100 până la $7FFFF (Windows rezervă acest interval pentru mesajele utilizatorului). De exemplu:const

SX_MYMESSAGE = WM_USER + 100;

SomeForm.Perform(SX_MYMESSAGE, 0, 0);

SendMessage(SomeForm.Handle, SX_MYMESSAGE, 0, 0);

PostMessage(SomeForm.Handle, SX_MYMESSAGE, 0, 0);

Apoi, pentru a intercepta acest mesaj, creați o procedură obișnuită de gestionare care efectuează acțiunile necesare pe formular:

TForm1 = clasa (TForm)

procedura SXMyMessage(var Msg: TMessage); mesajul SX_MYMESSAGE;

procedura TForm1.SXMyMessage(var Msg: TMessage);

MessageDlg(‘M-a transformat într-un triton!’,

mtInformation, , 0);

După cum puteți vedea din exemplu, există o mică diferență în procesarea unui mesaj personalizat și a unui mesaj standard Windows. Acestea constau în utilizarea identificatorilor în intervalul WM_USER+100 și mai sus, precum și în a da fiecărui mesaj un nume care să reflecte cumva semnificația acestuia.

Nu trimiteți niciodată mesaje cu o valoare WM_USER mai mare de $7FFF decât dacă sunteți absolut sigur că destinatarul este capabil să proceseze corect mesajul. Deoarece fiecare fereastră poate selecta în mod independent valorile pe care le folosește, este probabil să apară erori subtile, cu excepția cazului în care tabelele cu ID-urile mesajelor sunt create în prealabil pentru ca toți expeditorii și destinatarii mesajelor să lucreze.

Mesaje între aplicații

Dacă trebuie să faceți schimb de mesaje între două sau mai multe aplicații, ar trebui să utilizați funcția RegisterWindowMessage() API. Această metodă asigură că pentru un anumit tip de mesaj, fiecare aplicație va folosi același numărul mesajului(numărul mesajului).

Funcția RegisterWindowMessage() ia ca parametru un șir de caractere

terminat cu un caracter nul și returnează un identificator în intervalul $C000 - $FFFF pentru noul mesaj. Aceasta înseamnă că apelarea acestei funcții cu același șir ca un parametru în orice aplicație va fi suficientă pentru a garanta aceleași numere de mesaje în toate aplicațiile care participă la schimb. Un alt avantaj al unei astfel de caracteristici este că sistemul asigură că identificatorul atribuit oricărui șir dat este unic. Acest lucru vă permite să trimiteți mesaje difuzate către toate ferestrele existente în sistem fără teama de efecte secundare nedorite. Dezavantaj această metodă există unele complicații în procesarea unor astfel de mesaje. Ideea este că ID-ul mesajului este cunoscut doar atunci când aplicația rulează, deci folosind proceduri standard procesarea mesajelor devine imposibilă. Pentru a lucra cu astfel de mesaje, va trebui să redefiniți metode standard Controale WndProc() sau DefaultHandler() sau proceduri de clasă ferestre corespunzătoare.

NOTA

Numărul returnat de funcția RegisterWindowMessage() este creat dinamic și poate lua valori diferite în diferite sesiuni Windows, ceea ce înseamnă că nu poate fi determinat până când programul nu este executat.

Difuzați mesaje

Orice clasă care derivă din clasa TWinControl vă permite să utilizați metoda Broadcast() pentru a trimite mesaj difuzat(mesaj difuzat) către orice control al cărui proprietar este. Această tehnologie este utilizată în cazurile în care doriți să trimiteți același mesaj unui grup de componente. De exemplu, pentru a trimite un mesaj personalizat numit um_Foo tuturor controalelor care aparțin obiectului Panel1, puteți utiliza următorul cod:

Mesaj:= UM_FOO;

Trimiterea mesajelor

La fel ca sistem Windows trimite mesajele lui diverse ferestre, aplicația în sine poate avea nevoie, de asemenea, să facă schimb de mesaje între propriile ferestre și controale. Există mai multe moduri de a trimite mesaje: metoda PerForm() (care funcționează independent de API-ul Windows), precum și funcțiile API Win32 SendMessage() și PostMessage().

Metoda PerForm(), pe care toți descendenții clasei TControl o au:

funcția TControl.Perform(Msg: Cardinal; WParam, LParam: Longint): Longint;

Pentru a trimite un mesaj către un formular sau un control, utilizați următoarea sintaxă:

RetVal:= ControlName.PerForm(MessageID, wParam, lParam);

Când PerForm() este apelat, controlul nu va reveni la programul apelant până când mesajul nu a fost procesat. Această metodă transmite mesajul fără a trece prin sistemul de mesagerie Windows API.

Funcții API SendMessage() și PostMessage() declarate într-un modul Windows în continuare mod:

funcția SendMessage(hWnd: HWND; Msg: UINT; wParam: WPARAM;

lParam: LPARAM): LRESULT; stdcall;

funcția PostMessage(hWnd: HWND; Msg: UINT;

wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;

hWnd – mânerul ferestrei destinatarului mesajului; Msg – identificatorul mesajului; wParam și lParam – date suplimentare.

Funcția SendMessage(), ca și metoda PerForm(), trimite un mesaj direct către procedura ferestrei și așteaptă ca acesta să fie procesat, în timp ce funcția PostMessage() plasează mesajul într-o coadă de mesaje și returnează controlul programului care a apelat fără a aștepta rezultatele procesării.

Funcția SendMessage() returnează valoarea obținută ca urmare a procesării mesajului. Funcția PostMessage() - returnează o valoare care indică dacă mesajul a fost postat cu succes în coada de mesaje.

Mesajele utilizatorului

La dezvoltarea aplicațiilor, poate exista o situație în care o aplicație trebuie să trimită un mesaj special fie către ea însăși, fie către o altă aplicație pentru a efectua o acțiune. Pentru mesajele create de utilizator, Windows rezervă valori de la WM_USER la $7FFF.

Exemplu de mesaj personalizat:

TestMsg = WM_USER + 100; // ID mesaj

TForm1 = clasa (TForm)

// metoda de procesare a mesajelor:

procedura MyMessage(var Msg: TMessage); mesaj TestMsg;

procedura TForm1.MyMessage(var Msg: TMessage);

ShowMessage(„Mesajul TestMsg rulează”);

Msg.Result:= 1; // a returnat rezultatul

Exemple de trimitere a unui mesaj către formular:

dacă Form1.PerForm(TestMsg, 0, 0) = 1 atunci

dacă SendMessage(Form1.Handle, TestMsg, 0, 0) = 1 atunci

ShowMessage("Mesajul procesat cu succes");

dacă PostMessage(Form1.Handle, TestMsg, 0, 0), atunci

ShowMessage("Mesajul a fost plasat în coada de mesaje");

Evenimente Delphi

Un eveniment este ceva care se întâmplă în timp ce un program rulează. Din punctul de vedere al limbajului Delphi, un eveniment este o proprietate de tip procedural, iar valoarea sa este un pointer către o metodă. Atribuirea unei valori unei astfel de proprietăți înseamnă specificarea adresei metodei care va fi executată la producerea evenimentului. Astfel de metode se numesc handler de evenimente.

Utilizarea evenimentelor vă permite să adăugați funcționalități noi la o clasă existentă fără a crea o clasă descendentă.

Proprietățile evenimentului încearcă să înceapă cu cuvântul „Activat” urmat de numele evenimentului.

Relația dintre mesaje și evenimente

Delphi este o interfață cu care interacționați Mesaje Windows, cel putin cu unele dintre ele. Multe evenimente ale componentelor VCL sunt direct legate de mesaje tip Windows WM_XXX.

Adesea, programele Delphi folosesc e-mailul. Acest articol va explica pe deplin cum să vă trimiteți e-mailul unui alt utilizator. folosind Delphi. În acest caz, vom folosi doar componente standard Delphi.

Mai întâi, să creăm un nou proiect și să-l numim „Trimiterea de e-mailuri folosind delphi\”. Apoi, trebuie să transferați mai multe componente în formular: 1x Memo, 3x Editare, 2x Botton și, de asemenea, trebuie să transferați IdSMTP, IdAntiFreeze, IdMessage. Apoi, pe evenimentul onclick al oricărui buton scriem:

//selectați un server SMTP. ÎN în acest moment costă Yandex. IdSMTP1.Host:= „smtp.yandex.ru”; //autentificarea dvs. (pentru unii trebuie să scrieți cu un domeniu). IdSMTP1.Nume utilizator:= " [email protected]"; //parolă de e-mail. IdSMTP1.Password:= "qwerty123"; //port, vă recomandăm să utilizați 587. IdSMTP1.Port:=587; //Edit2 va include subiectul scrisorii. IdMessage1.Subject:= Edit2. Text; //Edit1 va conține adresa destinatarului IdMessage1.Recipients.EMailAddresses: = Edit1.Text; [email protected]"; // în memo1 va fi textul pe care doriți să-l trimiteți. IdMessage1.Body.Text:= memo1.Text ; // în Edit3 va fi dvs. semnătură electronică(Nume). IdMessage1.From.Name:= Edit3.Text; //conectați IdSMTP1.connect; //trimite IdSMTP1.Send(IdMessage1); //dezconectați IdSMTP1.Deconectați;

Dacă IdMessage afișează semne de întrebare

Acest bug se datorează faptului că introduceți litere rusești, iar componenta memo nu le poate citi corect pentru aceasta trebuie să specificați codarea Utf8.

// setați codificarea IdMessage1.Charset:="UTF-8"; // traduce textul în codificarea necesară IdMessage1.Body.Text:=UTF8Encode(memo1.text);