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.

webmaster@pcmagazine.ro

LG - Life´s Good

deltafri

Concurs de Grafica Digitala si Web Design

www.agora.ro

www.agora.ro