Utilizarea interfețelor în Delphi. Crearea unei interfețe cu utilizatorul. Elemente de interfață standard

Programarea orientată pe obiecte (OOP), pe lângă conceptul de clasă, oferă și conceptul fundamental de interfață.

Ce este o interfață și care sunt caracteristicile lucrului cu ea în limbajul de programare Delphi?

Interfața este un construct semantic și sintactic în codul programului utilizat pentru a specifica serviciile furnizate de o clasă sau componentă (Wikipedia).

În esență, o interfață definește o listă de proprietăți și metode care trebuie utilizate atunci când se lucrează cu clasa pe care o implementează această interfață, precum și semnătura acestora (nume, tip de date, parametri acceptați (pentru proceduri și funcții), etc.). Astfel, o clasă care implementează o anumită interfață trebuie să implementeze toate componentele acesteia. Mai mult, în strictă conformitate cu modul în care sunt descrise în el.

Interfețele sunt adesea comparate cu clase abstracte, dar în ciuda tuturor asemănărilor, această comparație nu este în întregime corectă. Cel puțin, clasele abstracte vă permit să controlați vizibilitatea membrilor. În același timp, domeniile nu sunt definite pentru interfețe.

Interfețele vă permit să faceți arhitectura mai flexibilă, deoarece unifică accesul la această sau aceea funcționalitate și vă permit, de asemenea, să evitați o serie de probleme asociate cu moștenirea clasei (interfețele pot fi, de asemenea, moștenite una de la alta).

Pentru a declara o interfață în Delphi, utilizați cuvântul cheie interfață. Acesta este același cuvânt cheie care definește secțiunea modulului care poate fi accesată din exterior (între interfață și cuvintele cheie de implementare). Cu toate acestea, atunci când declarați o interfață, este utilizată o sintaxă diferită, similară cu declararea claselor.

Delphi/Pascal

IMyNewInterface = procedura de interfata InterfaceProc; Sfârşit;

IMyNewInterface =interfață

procedura InterfaceProc ;

Sfârşit ;

Astfel, sintaxa declarației interfeței în sine nu este fundamental diferită de alte limbaje de programare (caracteristicile sintaxei bazate pe Pascal nu contează). În același timp, implementarea interfețelor are o serie de caracteristici.

Faptul este că interfețele Delphi au fost introduse inițial pentru a suporta tehnologia COM. Prin urmare, interfața IInterface, care în Delphi este strămoșul tuturor celorlalte interfețe (un fel de analog al TObject), conține deja trei metode de bază de lucru cu această tehnologie: QueryInterface, _AddRef, _Release. Ca rezultat, dacă o clasă implementează orice interfață, atunci trebuie să implementeze și aceste metode. Chiar dacă această clasă nu este destinată lucrului COM.

Datorită acestei caracteristici a interfeței IInterface, în Delphi utilizarea interfețelor, în cele mai multe cazuri, duce la adăugarea de capabilități evident neutilizate la clasă.

Există o clasă de bibliotecă TInterfaceObject care conține deja implementarea acestor metode și, atunci când se moștenește de la aceasta, nu este nevoie să le implementați singur. Dar, deoarece Delphi nu acceptă moștenirea mai multor clase, utilizarea sa cauzează adesea doar dificultăți suplimentare în proiectarea și implementarea funcționalității deja necesare.

Toate acestea au dus la faptul că, în ciuda tuturor posibilităților oferite de interfețe, utilizarea lor practică în Delphi aproape că nu a depășit lucrul cu COM.

Fiind optimizate pentru a lucra în principal cu această tehnologie, interfețele, sau mai bine zis funcționalitatea și restricțiile arhitecturale pe care le adaugă neapărat, nu se justifică atunci când rezolvă alte probleme.

Prin urmare, mulți programatori Delphi sunt încă, de fapt, lipsiți de un instrument puternic și flexibil pentru dezvoltarea arhitecturii aplicațiilor.

Creare interfață utilizatorul este redus să selecteze din paleta de componente componentele Delphi necesare pentru ca programul să funcționeze, servind interfață management, precum și interfață afișarea informațiilor și transferarea acestora în Formular cu aspectul ulterioar.

Interfața de utilizator pe care o creați ar trebui să utilizeze elemente standard familiare utilizatorilor și să ofere confort maxim. Toate acestea sunt în cele din urmă determinate de un astfel de criteriu precum eficiența interfeței - rezultate maxime cu efort minim.
Sunt cunoscute principiile creării unei interfețe prietenoase cu utilizatorul. Trei principii principale pot fi considerate drept cele mai generale principii atunci când se creează interfețe cu utilizatorul:

  1. Programul ar trebui să ajute la finalizarea unei sarcini și nu să devină acea sarcină.
  2. Când lucrează cu programul, utilizatorul nu ar trebui să se simtă ca un prost.
  3. Programul ar trebui să funcționeze în așa fel încât utilizatorul să nu considere computerul un prost.
Primul principiu- aceasta este așa-numita „transparență” a interfeței. Interfața cu utilizatorul trebuie să fie intuitivă, ușor de învățat și să nu creeze utilizatorului probleme pe care acesta va trebui să le depășească în timpul procesului de lucru. Utilizați componente standard fără ornamente inutile, utilizați tehnici de control familiare utilizate de programe similare și veți atinge criteriile de performanță primul principiu.

Al doilea principiu este de a neglija abilitățile intelectuale ale utilizatorilor. Din propria mea experiență, știu că de multe ori utilizatorii nu numai că nu știu să lucreze pe un computer, ci pur și simplu le este frică să facă ceva pe cont propriu. Prin urmare, interfața cu utilizatorul ar trebui să fie cât mai prietenoasă posibil.
Mai mult decât atât, temerile utilizatorilor sunt adesea justificate, deoarece costul programului, și chiar al computerului în sine, nu poate fi comparat cu costul, de exemplu, al unei baze de date create pe parcursul multor ani de efort. De aceea, atunci când creează o interfață cu utilizatorul, un programator trebuie să includă întotdeauna „protecție fără greșeli” în program - împotriva acțiunilor incorecte și a introducerii de către utilizator a datelor incorecte. Dar unii programatori se lasă prea duși de o astfel de protecție, o fac prea intruzivă și, ca urmare, funcționarea programului seamănă cu faimosul „un pas la stânga, un pas la dreapta este considerat o scăpare”! Și ceea ce programatorul creează ca soluție la o problemă începe să creeze probleme în sine.
A se conforma al doilea principiu nu este nevoie să permiteți programului să „corecteze” acțiunile utilizatorului și să indice exact cum ar trebui să acționeze, forțându-l într-un cadru îngust. De asemenea, nu ar trebui să vă lăsați prea conduși de afișarea mesajelor informaționale prompte, în special a celor de dialog, deoarece acest lucru distrage atenția utilizatorului de la serviciu. Ar fi mai bine să oferiți posibilitatea de a dezactiva complet indicii.

Al treilea principiu este de a crea un program cu cele mai înalte capacități „mentale” posibile. În ciuda dezvoltării rapide a tehnologiei informatice, chiar și programele utilizate pe scară largă pot fi numite doar foarte condiționat având inteligență artificială. Ele interferează cu munca utilizatorului prin afișarea unor casete de dialog cu întrebări stupide care provoacă confuzie chiar și în cele mai simple situații. Drept urmare, utilizatorii exclamă în inimile lor: „Ce mașinărie proastă!”
Personal, sunt iritat de întrebările constante de la aproape toți editorii de text despre salvarea textului modificat, deși textul original și actualul nu diferă cu un singur caracter. Da, am tastat ceva, dar apoi am returnat totul înapoi, este chiar imposibil să-mi dau seama! Trebuie să verific dacă nu am stricat nimic până la urmă.

Încercați să respectați următoarele reguli:

Elemente de interfață standard
Utilizați componente care sunt standard pentru acest element de interfață. După ce a întâlnit programul dvs., utilizatorul nu va pierde timpul să se cunoască, ci va începe imediat să lucreze - acesta este unul dintre semnele unui program realizat profesional.
Paletă mică de instrumente
Încercați să nu utilizați prea multe componente diferite. Și, firește, după ce ați folosit o componentă standard undeva într-un singur loc, într-un caz similar, folosiți-o și ea.
Distanță egală între comenzi
Plasați elementele de interfață la aceeași distanță unele de altele. Componentele împrăștiate la întâmplare creează senzația unui produs realizat neprofesionist. Și invers, amplasarea verificată cu atenție a butoanelor, comutatoarelor, casetelor de selectare și a altor componente care alcătuiesc interfața pe Formular este un semn de muncă de înaltă calitate.
TabOrder. "Ordinea corectă
TabOrder este ordinea în care cursorul ecranului se deplasează pe controale atunci când este apăsată o tastă Tab. Într-un program scris corect, cursorul se deplasează urmând logica lucrului utilizatorului cu programul. Când creează un program, programatorul schimbă adesea componente, elimină unele și adaugă altele după cum este necesar. Ca rezultat, în programul terminat, cursorul sare haotic în jurul Formului. După finalizarea programului, nu uitați să configurați TabOrder.
Selectarea fontului
Doar lăsați fonturile în pace. Fonturile implicite ale Delphi sunt potrivite pentru orice sistem pe care poate rula programul dumneavoastră. Folosiți fontul aldine numai pentru a evidenția elementele importante. Aplicație cursive si in special subliniere, pe care utilizatorul l-ar putea confunda cu un hyperlink este o formă proastă.
Alegerea culorilor
În ceea ce privește culorile elementelor de interfață, la fel ca și în cazul fonturilor, este mai bine să le lăsați standard, implicit. Delphi folosește paleta sistemului Windows, iar utilizatorul poate personaliza cu ușurință culorile prin schimbarea acesteia.
Management alternativ
Un program realizat profesional ar trebui să poată fi controlat nu numai cu mouse-ul, ci și cu tastatura. Nu ar trebui să existe funcții care să poată fi efectuate doar cu mouse-ul (desenul în editorii grafici nu contează!). Pentru cele mai utilizate funcții, ar trebui să furnizați „taste rapide” pentru acces rapid.
Cărămizi de interfață
În ceea ce privește elementele specifice ale interfeței cu utilizatorul, calitatea interacțiunii utilizatorului cu programul depinde de:
  • conformitatea elementului de control cu ​​sarcina pe care o îndeplinește;
  • regulile prin care funcţionează elementul de control.
    Această pagină discută regulile pentru crearea unor elemente de interfață.
Și acum vreau să arăt ce instrumente oferă Delphi pentru gestionarea componentelor din formular, poziția lor relativă și comportamentul cursorului atunci când o tastă este apăsată Tab.

Pentru a aranja componentele unul față de celălalt în ordinea corectă, mai întâi este necesar să le evidenţiem. Puteți pur și simplu să încercuiți zona din Formular care conține componentele selectate. Sau ținând „ Schimb", utilizați același mouse pentru a indica fiecare componentă care trebuie selectată. Faceți clic din nou pe componenta selectată (în timp ce apăsați " Schimb") îl deselectează.

Componentele selectate pot fi gestionate ca un întreg - mutate în jurul formularului, atribuite valori acelorași proprietăți, copiate (pentru instalare, de exemplu, pe alt formular), chiar șterse.

Acum faceți clic dreapta pe una dintre componente și selectați din meniul pop-up Poziție -> Aliniere... Va apărea o casetă de dialog care vă permite să reglați poziția orizontală și verticală a componentelor din grup. De exemplu, trebuie să ne aliniem cele patru butoane la stânga și să ne asigurăm că au aceeași distanță verticală între ele. Pentru a face acest lucru, selectați butoanele radio Orizontală: pe partea stângăȘi Verticală: spațiu în mod egal.

Prin selectarea articolului Centru, vom aranja componentele astfel încât centrele lor să fie situate pe aceeași linie orizontal sau vertical, iar elementul Centru în fereastră mută componentele în centrul ferestrei, de asemenea, orizontal sau vertical.

În aceeași linie de meniu Tab O comanda... determină apariția unei casete de dialog care controlează modul în care cursorul se deplasează prin elementele interfeței atunci când este apăsată o tastă Tab. Când formularul apare pe ecran, cursorul se va afla în mod natural pe componenta situată pe prima linie a casetei de dialog. Și apoi se va muta în jos în listă. În caseta de dialog, două săgeți albastre sus și jos controlează poziția componentei selectate. Selectați componenta necesară, utilizați săgețile pentru a o muta la linia dorită din listă și așa mai departe.

La selectarea unui element de meniu Control -> Apare un submeniu format din două elemente:

  • Aduceți în față
  • Trimite în spate
Acestea sunt metode componente care sunt disponibile și în mod programatic. Button1.SendToBack mută butonul în „fond” și Button1.BringToFront- aduceți în față”. Adică, dacă o componentă este poziționată deasupra alteia, aceste metode își schimbă pozițiile. Cazurile în care s-ar putea aplica acest lucru sunt destul de evidente.

Am o problemă la utilizarea unei clase Delphi din codul C++. delphi dll demo, care exportă o funcție care returnează un obiect.
codul meu Delphi Dll arată astfel:

Biblioteca DelphiTest; // folosește partea.... tip IMyObject = procedura de interfață DoThis(n: Integer); funcția DoThat: PWideChar; Sfârşit; TMyObject = class(TInterfacedObject,IMyObject) procedura DoThis(n: Integer); funcția DoThat: PChar; Sfârşit; // Implementarea TMyObject merge aici ... procedura TMyObject.DoThis(n: Integer); begin showmessage ("apelați metoda DoThis cu "+intToStr(n) +"parametru"); Sfârşit; funcția TMyObject.DoThat: PChar; begin showmessage(„apelați funcția DoThat”); Rezultat:= Pchar("Buna, sunt Dothat"); Sfârşit;

// exportă funcția DLL:

Funcția CreateMyObject: IMyObject; stdcall;export; var txt: TextFile; începe AssignFile(txt,"C:\log.log"); Resetare(txt); Writeln(txt,"bună ziua"); Rezultat:= TMyObject.Create; Sfârşit; exportă CreateMyObject;

în proiectul meu C++ am declarat interfața IMyObject astfel:

Clasa IMyObject ( public: IMyObject(); virtual ~IMyObject(); virtual void DoThis(int n) = 0; virtual char* DoThat() = 0; );

și funcția mea principală este așa:

Typedef IMyObject* (__stdcall *CreateFn)(); int main() ( HMODULE hLib; hLib = LoadLibrary(L"DelphiTest.dll"); assert(hLib != NULL); // trece !! CreateFn pfnCreate; pfnCreate = (CreateFn)GetProcAddress((HINSTANCE)hLib, "CreateMyObject "); if (pfnCreate == NULL) ( DWORD errc = GetLastError(); printf("%u\n", errc); // primește eroarea 127 ) else( printf("încărcare de succes\n"); ) IMyObject* objptr = pfnCreate(); DoThis(5);

în acest exemplu, am primit o eroare de rulare când încerc să accesez funcția exportată. erori in linie:
IMyObject* objptr = pfnCreate();

Îmi puteți spune ce este în neregulă cu exemplul meu.
și dacă este posibil, orice exemplu de lucru pentru accesarea unei clase Delphi (într-un DLL) din codul C++.

Soluţie

Prima problemă este apelarea convenției metodei. Interfața Delphi folosește un registru care este o convenție de apelare specifică Delphi. utilizarea stdcall De exemplu, pentru metodele de interfață.

Următoarea problemă este în C++. Interfața dvs. C++ trebuie să derive din IUnknown În plus, nu trebuie să declare un constructor sau un destructor.

În afară de aceasta, codul dvs. Delphi este exportat de PWideChar, care nu este mapat la char* .

Privind mai departe, returnarea PChar funcționează bine aici, deoarece implementarea dvs. returnează un literal. Dar un cod mai serios va dori probabil să folosească un șir alocat dinamic, moment în care designul tău este defectuos.

Vă rugăm să rețineți că pentru a crea un fișier în rădăcina unității de sistem, trebuie să fiți administrator cu nivel superior. Deci acesta este un alt punct potențial de eșec.

Mă aștept să fie și alte erori, dar asta este tot ce am găsit până acum.

Acesta este un articol bazat pe întrebări de pe forumuri: „Cum pot returna un șir de caractere dintr-un DLL?”, „Cum să transmit și să returnez o serie de înregistrări?”, „Cum să transmit un formular la un DLL?”.

Ca să nu-ți petreci jumătate din viață să-ți dai seama, în acest articol voi aduce totul pe un platou.

Subiectele acestui articol au fost atinse de mai multe ori în acest blog în diferite grade, dar în acest articol sunt adunate împreună și justificate. Pe scurt, puteți arunca un link către acest articol celor care dezvoltă DLL-uri.

Notă importantă: articolul trebuie citit secvenţial. Exemplele de cod sunt furnizate numai ca exemple, la fiecare pas (punct) al articolului se adauga codul exemplu cu detalii noi. De exemplu, chiar la începutul articolului nu sunt indicate metode „clasice” (cum ar fi utilizarea GetLastError , convenția sdtcall etc.), care sunt înlocuite cu altele mai adecvate pe măsură ce articolul progresează. Acest lucru a fost făcut pentru ca modelele „noi” („neobișnuite”) să nu ridice întrebări. În caz contrar, ar fi necesar să inserați o notă pentru fiecare exemplu de genul: „acest lucru este discutat în acel paragraf de mai jos, dar asta este discutat în acest paragraf”. În orice caz, la sfârșitul articolului există un link către un cod gata făcut, scris ținând cont de tot ce este spus în articol. Poți doar să-l iei și să-l folosești. Și articolul explică de ce și de ce. Dacă nu sunteți interesat de „de ce și de ce”, derulați până la sfârșit până la concluzie și linkul pentru a descărca exemplul.