Agora
Media
Libraria Byblos



AgoraNews  





PC Magazine Ro  




NET Report   




Ginfo   




agora ON line   





PC Concrete   





Liste de discuții   




Cartea de oaspeți   




Mesaje   





Agora   





Clic aici
PC Magazine





Soluții - PC Magazine Romania, Aprilie 2004

ActiveX (2)

Konstantin Klyagin

Proprietăți read sau write only

E posibil că ai mai văzut la controalele ActiveX mai avansate față de amărâtul nostru Vasile (așa ne-am botezat controlul luna trecută), proprietăți care se pot numai citi sau numai scrie. Această capacitate este de folos atunci când e vorba de parametri cu ajutorul cărora utilizatorul poate afla starea curentă a controlului. Evident, că astfel de informații pot fi setate numai de către control și n-ar avea sens să îl lasăm pe utilizator să le modifice. De exemplu, succesul ultimei operațiuni, cantitatea de date transferate sau numărul de înregistrări găsite în baza de date.

Proprietățile de genul "write-only" pot fi utile când vrei să le folosești pentru a trimite informații către control într-o singură direcție. De exemplu, se poate face un fel de stream, la care tot ceea ce se transmite unei proprietăți să fie considerat ca un flux neîntrerupt de date. Exact cum este controlul MsComm, el având proprietatea Output folosită pentru a trimite caractere către portul serial.

Ca să faci o proprietate "read-only" sau "write-only" trebuie doar să nu definești metoda Set sau Get respectivă. Următoarea proprietate va fi read-only.

De reținut: Dacă lași un șir gol în câmpul "Set method" sau "Get method", proprietatea devine automat write-only sau respectiv read-only.

De asemenea, proprietățile write-only nu vor apărea pe lista de "Properties browser" dintr-un motiv evident.

De fapt, orice proprietate poate fi făcută vizibilă numai în timpul executării încât să nu aglomereze lista în regimul de design. Într-adevăr, ce sens are să vezi și să schimbi valoarea unor parametri care sunt de actualitate numai când programul e pornit? Ca un exemplu, gândește-te la dimensiunea și poziția curentă într-un fișier transferat prin FTP.

Pentru asta, trebuie să mai "îmbunătățești" codul metodei Get în modul următor.

long CFTPCtrl::
GetCurrentFilePosition()
{
if(!AmbientUserMode())
ThrowError(CTL_E_GETNOTSUPPORTED);
return m_CurrentFilePosition;
}

Secretul constă în folosirea metodei AmbientUserMode() care returnează TRUE când componenta se află în mod design. Altfel primim FALSE. Așadar, după o asemenea modificare proprietatea va fi disponibilă numai în timpul executării, fără să se vadă în "Properties browser". Exact ce am vrut să facem.

Liste de valori

Unele controale pentru anumite proprietăți oferă alegere din listă în loc de a introduce manual o valoare. Pentru a crea o asemenea listă definim un enum. Acesta trebuie adăugat la fișierul .odl al proiectului, sintaxa fiind asemănătoare celei din C.

 typedef enum {
clrAlbastru = 0,
clrGalben = 1,
clrRosu = 2
} vasile_Culoare;

După care, tot manual schimbăm tipul proprietății în modul următor:

[id(1)] vasile_Culoare Culoare; 

Fii atent că metodele Get și Set corespunzătoare nu trebuie schimbate. Având ca tip int, short sau long, ele vor lucra perfect cu enum-ul definit, fiindcă acestea sunt interconvertibile. De asemenea, în cod poți folosi constante din enum în loc de numere asociate (de exemplu, clrAlbastru în loc de 0), ceea ce ușurează mult citirea codului sursă. Asta însă necesită un pas adițional: la începutul fișierului .cpp după include-uri adaugă următoarea directivă de import:

#import "Debug\vasile.tlb"

În acest caz va trebui să adaugi prefixul VASILElib:: la toate denumirile din ODL, ca de exemplu VASILElib::clrAlbastru. Iar ca să eviți această necesitate, faci import așa:

#import "Debug\vasile.tlb"
no_namespace

Iar acum, încercând să schimbe valoarea proprietății din "Properties browser" utilizatorul va vedea lista cu denumiri de valori din enum.

Denumiri textuale pentru valori

De asemenea, mai este posibil ca după ce utilizatorul introduce o valoare în "Properties browser", în loc de aceasta să apară un șir de caractere descriind valoarea aleasă. Rareori poate fi de folos, dar e bine să știi și această metodă.

Deci, apelăm la bunul cunoscut al nostru ClassWizard, și alegem din listă metoda OnGetDisplayString() care trebuie redefinită.

Să spunem, că dorim în loc de "0 - clrAlbastru" la valoarea lui Culoare să ne apară textul "ALBASTRU!", fără să dezvăluie numărul intern al opțiunii la dușmani.

BOOL CVasileCtrl::
OnGetDisplayString(DISPID dispid,
CString& strValue)
{
if(dispid == dispidCuloare) {
if(m_Culoare ==
clrAlbastru) {
strValue = "ALBASTRU!";
return TRUE;
}
}
}

Fii atent că trebuie returnat TRUE în caz că s-a găsit un text potrivit. O altă aplicare bună a acestei metode ar fi menținerea unor denumiri generale pentru intervale de valori.

Presupunând că avem o proprietate AgeRange și variabila m_AgeRange asociată cu ea, putem face o asemenea șmecherie:

BOOL CVasileCtrl::
OnGetDisplayString(DISPID dispid,
CString& strValue)
{
if(dispid == dispidAgeRange) {
if(m_AgeRange < 18) strValue =
"copil"; else
if(m_AgeRange < 25) strValue =
"tânar"; else
if(m_AgeRange < 60) strValue =
"matur"; else
strValue = "boșorog";
}
return !strValue.IsEmpty();
}

Liste de echivalente textuale

Unii mai mofturoși pot dori să vadă o listă de opțiuni complet textuale (sau chiar localizate) în loc de meniuri de genul "0 - text", "1 - text". Tehnologia ActiveX are ce le oferi și lor. Ca să facem înlocuirea, redefinim metodele OnGetPredefinedStrings() și OnGetPredefinedValue():

BOOL CVasileCtrl::OnGetPrede-
finedStrings(DISPID dispid,
CStringArray* pStringArray,
CDWordArray* pCookieArray)
{
if(dispid == dispidCuloare) {
pStringArray->Add("ALBASTRU!");
pCookieArray->Add(clrAlbastru);
pStringArray->Add("ROSU!");
pCookieArray->Add(clrRosu);
pStringArray->Add("GALBEN!");
pCookieArray->Add(clrGalben);
return TRUE;
}
return COleControl::OnGetPrede-
finedStrings(dispid,
pStringArray, pCookieArray);
}
BOOL CVasileCtrl::OnGetPredefined-
Value(DISPID dispid, DWORD
dwCookie, VARIANT* lpvarOut)
{
if(dispid == dispidCuloare) {
CComVariant(dwCookie, VT_I4).
Detach(lpvarOut);
return TRUE;
}
return COleControl::OnGetPrede-
finedValue(dispid, dwCookie,
lpvarOut);
}
Legatura între elemente de meniu și valori actuale se face aici pe baza array-ului    pCookieArray. Simultan cu pStringArray care conține opțiunile disponibile, pCookieArray    se umple cu numerele reprezintând variantele respective. După ce o nouă valoare    este selectată, OnGetPredefinedValue() setează valoarea actuală în funcție de    cookie. VARIANT este o structură de date care de fapt poate conține valori de    orice tip. Deoarece în cazul nostru cookie-uri și valorile au același conținut,    pur și simplu creăm un variant cu aceeași valoare DWORD. Rezultatul se pune    în variabila lpvarOut. Să nu uităm de OnGetDisplayString(), care trebuie modificat    astfel încât valoarea aleasă să fie afișată în "Properties browser"    după ce lista dispare.

Urmare în numărul viitor.


PC Magazine Ro | CD ROM | Redactia | Abonamente | CautareArhive

Copyright © 1999-2004 Agora Media.

[email protected]

LG - LifeŽs Good

deltafri

Concurs de Grafica Digitala si Web Design

www.agora.ro

www.agora.ro