Teknologjia e komponentëve të jashtëm (). Teknologjia e komponentëve të jashtëm () Lloji i të dhënave tVariant

ansmirnov 22 gusht 2013 në 2:12 pasdite

Komponentët e jashtëm në 1C 8.2

  • Programimi,
  • C++
  • Tutorial

Prezantimi

Ky artikull jep një ide se si funksionojnë komponentët e jashtëm në sistemin 1C: Enterprise.
Do të shfaqet procesi i zhvillimit të një komponenti të jashtëm për versionin 8.2 të sistemit 1C: Enterprise, i cili funksionon nën OS Windows me një mënyrë funksionimi skedari. Ky opsion përdoret në shumicën e zgjidhjeve të dizajnuara për bizneset e vogla. VK do të zbatohet në gjuhën e programimit C++.

Komponentët e jashtëm "1C: Ndërmarrja"

"1C: Enterprise" është një sistem i shtrirë. Për të zgjeruar funksionalitetin e sistemit, përdoren komponentë të jashtëm (EC). Nga këndvështrimi i zhvilluesit, një VC është një objekt i jashtëm që ka veti dhe metoda, dhe gjithashtu mund të gjenerojë ngjarje për përpunim nga sistemi 1C: Enterprise.
Komponentët e jashtëm mund të përdoren për të zgjidhur një klasë problemesh që janë të vështira apo edhe të pamundura për t'u zbatuar në gjuhën e programimit të integruar në 1C: Enterprise. Në veçanti, kjo klasë përfshin detyra që kërkojnë ndërveprim të nivelit të ulët me sistemin operativ, për shembull, për të punuar me pajisje specifike.
Sistemi 1C: Enterprise përdor dy teknologji për krijimin e komponentëve të jashtëm:
  • duke përdorur Native API
  • duke përdorur teknologjinë COM
Duke pasur parasysh kufizimet e dhëna, ndryshimi midis dy teknologjive të sipërpërmendura është i parëndësishëm, kështu që ne do të shqyrtojmë zhvillimin e lojërave video duke përdorur API-në vendase. Nëse është e nevojshme, zhvillimet e zbatuara mund të aplikohen në zhvillimin e softuerit kompjuterik duke përdorur teknologjinë COM, dhe gjithashtu, me modifikime të vogla, të aplikohen për përdorim në sistemin 1C: Enterprise me opsione të tjera funksionimi përveç mënyrës së funksionimit të skedarit.
Struktura VK
Komponenti i jashtëm i sistemit 1C: Enterprise paraqitet në formën e një biblioteke DLL. Kodi i bibliotekës përshkruan klasën pasardhëse IComponentBase. Klasa e krijuar duhet të përcaktojë metodat përgjegjëse për zbatimin e funksioneve të komponentit të jashtëm. Metodat e anashkaluara do të përshkruhen më hollësisht më poshtë ndërsa paraqitet materiali.

Nisja e një VK demo

Detyra:
  1. Mblidhni një komponent të jashtëm të furnizuar me një abonim ITS dhe synon të demonstrojë aftësitë kryesore të mekanizmit të komponentit të jashtëm në 1C
  2. Lidhni komponentin demo me konfigurimin 1C
  3. Sigurohuni që funksionet e deklaruara të funksionojnë saktë
Përmbledhje
Demoja VK ndodhet në diskun e abonimit ITS në drejtorinë "/VNCOMP82/shembull/NativeAPI".
Për të ndërtuar VC-në demo, ne do të përdorim Microsoft Visual Studio 2008. Versionet e tjera të këtij produkti nuk e mbështesin formatin e projektit Visual Studio të përdorur.


Hapni projektin AddInNative. Në cilësimet e projektit, ne përfshijmë direktorinë me skedarët e titullit të nevojshëm për të ndërtuar projektin. Si parazgjedhje, ato janë të vendosura në diskun ITS në drejtori /VNCOMP82/përfshi.
Rezultati i ndërtimit është skedari /bind/AddInNative.dll. Kjo është biblioteka e përpiluar për t'u lidhur me konfigurimin 1C.
Lidhja e konfigurimit VK me 1C
Le të krijojmë një konfigurim bosh 1C.
Më poshtë është kodi për modulin e aplikacionit të menaxhuar.
ndryshore DemoComp; Procedura kur fillon sistemi () Lidhni komponentin e jashtëm ("...\bind\AddInNative.dll", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.AddInNativeExtension"); Fundi i procedurës
Nëse nuk u raportua asnjë gabim gjatë fillimit të konfigurimit 1C, atëherë VK u lidh me sukses.
Si rezultat i ekzekutimit të kodit të mësipërm, një objekt shfaqet në dukshmërinë globale të konfigurimit DemoComp, i cili ka veti dhe metoda që përcaktohen në kodin e komponentit të jashtëm.
Demonstrimi i funksionalitetit të integruar
Le të kontrollojmë funksionalitetin e demo VK. Për ta bërë këtë, le të përpiqemi të vendosim dhe lexojmë disa veti, të thërrasim disa metoda VK dhe gjithashtu të marrim dhe përpunojmë mesazhin VK.
Dokumentacioni i dhënë në diskun ITS deklaron funksionalitetin e mëposhtëm të VC-së demo:
  1. Menaxhimi i gjendjes së objektit të komponentit
    Metodat: Ndez, Fikeni
    Vetitë: Të përfshira
  2. Menaxhimi i kohëmatësit
    Çdo sekondë komponenti dërgon një mesazh në sistemin 1C: Enterprise me parametra Komponenti, Timer dhe një linjë numëruesi të orës së sistemit.
    Metodat: StartTimer, StopTimer
    Vetitë: Ka një kohëmatës
  3. Metoda ShowInStatusLine, i cili shfaq tekstin e kaluar në metodë si parametra në shiritin e statusit
  4. Metoda NgarkoFoto. Ngarkon një imazh nga skedari i specifikuar dhe e transferon atë në sistemin 1C: Enterprise në formën e të dhënave binare.
Le të sigurohemi që këto funksione të funksionojnë. Për ta bërë këtë, ekzekutoni kodin e mëposhtëm:
ndryshore DemoComp; Procedura kur fillon sistemi() ConnectExternalComponent(...); DemoComp = I ri ("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Raporti (DemoComp.Enabled); DemoComp.Enable(); Raporti (DemoComp.Enabled); DemoComp.StartTimer(); Procedura e përfundimit të procedurës Përpunimi i ngjarjeve të jashtme (Burimi, Ngjarja, të Dhënat) Raporti (Burimi + " " + Ngjarja + " " + Të dhënat); Fundi i procedurës
Rezultati i ekzekutimit të konfigurimit tregohet në imazh


Paneli "Mesazhet" shfaq rezultatet e thirrjeve të metodës DemoComp.Disable() Dhe Demo.Comp.Enable(). Rreshtat pasues në të njëjtin panel përmbajnë rezultatet e përpunimit të mesazheve të marra nga VK - Burimi, Ngjarje Dhe Të dhënat përkatësisht.

Emri i personalizuar i komponentit të jashtëm

Detyrë: Ndryshoni emrin e komponentit të jashtëm në një arbitrar.
Seksioni i mëparshëm përdori identifikuesin AddInNativeExtension, kuptimi i të cilit nuk u shpjegua. Në këtë rast AddInNativeExtension- ky është emri i shtesës.
Kodi VK përcakton një metodë Register ExtensionAs, duke e kthyer emrin në sistemin 1C: Enterprise, i cili është i nevojshëm për regjistrimin e mëvonshëm të VK në sistem. Rekomandohet të specifikoni një identifikues që zbulon në një farë mase thelbin e komponentit të jashtëm.
Këtu është kodi i plotë i metodës Register ExtensionAs me emrin shtesë të ndryshuar:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* (wsExtension) + 1; ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, wsExtension, iActualSize); kthe e vërtetë; ) kthe false; )
Në shembullin e dhënë, emri VK është ndryshuar në Dikush Emri. Pastaj kur lidhni VK, duhet të specifikoni një emër të ri:
DemoComp = I ri ("AddIn.DemoVK.SomeName");

Zgjerimi i listës së pronave VK

Detyra:
  1. Studioni zbatimin e vetive VK
  2. Shtoni një veçori leximi/shkrimi të llojit të vargut
  3. Shtoni një veçori të vargut të leximit/shkrimit që ruan llojin e të dhënave të grupit të fundit të vetive. Asnjë veprim nuk ndërmerret gjatë vendosjes së vlerës së pronës

Për të përcaktuar vetitë e komponentit që krijohet, zhvilluesi duhet të zbatojë metodat e mëposhtme në kodin e bibliotekës AddInNative.cpp:
GetNProps
Rikthen numrin e vetive të kësaj shtese, 0 nëse nuk ka veçori
FindProp
Kthen numrin serial të pronës, emri i së cilës kalohet në parametrat
GetPropName
Kthen emrin e pronës me numrin e saj serial dhe me identifikuesin e gjuhës së kaluar
GetPropVal
Kthen vlerën e pronës me numrin rendor të specifikuar
SetPropVal
Vendos vlerën e pronës me numrin rendor të specifikuar
IsPropReadable
Kthen flamurin e lexueshmërisë së pronës me numrin e sekuencës së specifikuar
IsPropWritable
Kthen flamurin e shkrueshmërisë së pronës me numrin e sekuencës së specifikuar


Le të shqyrtojmë zbatimin e metodave të klasës së mësipërme CAddInNative.
Në VC-në demo, përcaktohen 2 veti: Të përfshira Dhe Ka një kohëmatës (Është Enabled Dhe IsTimerPresent).
Në shtrirjen globale të kodit të bibliotekës, përcaktohen dy vargje:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Enabled", L"Ka një kohëmatës");
të cilat ruajnë emrat e pronave ruse dhe angleze. Në skedarin e kokës AddInNative.h numërimi është përcaktuar:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Gjithmonë e fundit);
ePropIsEnabled Dhe ePropIsTimerPresent, përkatësisht që kanë vlerat 0 dhe 1, përdoren për të zëvendësuar numrat serialë të pronave me identifikues kuptimplotë. ePropLast, i cili ka vlerën 2, përdoret për të marrë numrin e vetive (duke përdorur metodën GetNProps). Këta emra përdoren vetëm brenda kodit të komponentit dhe nuk janë të disponueshëm nga jashtë.
Metodat FindProp dhe GetPropName kryejnë kërkime në grup g_PropEmrat Dhe g_PropNamesRu.
Për të ruajtur vlerat e fushave në modulin e bibliotekës, klasa CAddInNative ka veti që ruajnë vlerën e vetive të komponentit. Metodat GetPropVal Dhe SetPropVal ktheni dhe vendosni vlerën e këtyre vetive në përputhje me rrethanat.
Metodat IsPropReadable Dhe IsPropWritable dhe kthehu e vërtetë ose i rremë, në varësi të numrit rendor të kaluar të pronës në përputhje me logjikën e aplikimit.
Për të shtuar një pronë të personalizuar ju duhet:

  1. Shtoni emrin e pronës që po shtohet në vargje g_PropEmrat Dhe g_PropNamesRu(skedar AddInNative.cpp)
  2. Për të listuar Props(skedar AddInNative.h) më parë ePropLast shtoni një emër që identifikon në mënyrë unike pronën që po shtohet
  3. Organizoni memorien për ruajtjen e vlerave të vetive (krijoni fusha përbërëse të modulit që ruajnë vlerat përkatëse)
  4. Bëni ndryshime në metoda GetPropVal Dhe SetPropVal për të bashkëvepruar me memorien e alokuar në hapin e mëparshëm
  5. Në përputhje me logjikën e aplikimit, bëni ndryshime në metoda IsPropReadable Dhe IsPropWritable
Pikat 1, 2, 5 nuk kanë nevojë për shpjegim. Detajet e zbatimit të këtyre hapave mund të gjenden duke studiuar shtojcën e artikullit.
Le t'u japim emra vetive të provës Test Dhe Lloji Kontrollo përkatësisht. Pastaj, si rezultat i hapit 1, kemi:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Enabled", L"Ka një kohëmatës", L"Test", L"Kontrollimi i tipit");
Transferimi Props do të duket si:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Gjithmonë e fundit);
Për të thjeshtuar ndjeshëm kodin, ne do të përdorim STL C++. Në veçanti, për të punuar me vargje WCHAR, le të lidhim bibliotekën string.
Për të ruajtur një vlerë të metodës Test, përcaktojmë në klasë CAddInNative në fushën e një fushe private:
testi i vargut1;
Për të transferuar parametrat e vargut midis 1C: Enterprise dhe komponentëve të jashtëm, përdoret menaxheri i kujtesës 1C: Enterprise. Le të hedhim një vështrim më të afërt në punën e tij. Funksionet përdoren për ndarjen dhe lirimin e memories përkatësisht AllocMemory Dhe Memoria e Lirë të përcaktuara në dosje ImemoryManager.h. Nëse është e nevojshme të kaloni një parametër të vargut në sistemin 1C: Enterprise, komponenti i jashtëm duhet të ndajë memorie për të duke thirrur funksionin AllocMemory. Prototipi i tij duket si ky:
virtual bool ADDIN_API AllocMemory (void** pMemory, ulCountByte e gjatë e panënshkruar) = 0;
Ku pKujtesa- adresa e treguesit në të cilin do të vendoset adresa e zonës së caktuar të memories,
ulCountByte- madhësia e zonës së caktuar të memories.
Një shembull i alokimit të memories për një varg:
WCHAR_T *t1 = NULL, *test = L"TEST_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize);
Për lehtësinë e punës me llojet e të dhënave të vargut, ne do të përshkruajmë funksionin wstring_to_p. Ai merr një varg wstring si parametër. Rezultati i funksionit është një strukturë e mbushur tVariant. Kodi i funksionit:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) (char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (rr. gjatësia ()+1) madhësia e(WCHAR_T));memcpy(t1, str.c_str(), (str.gjatësia()+1) * madhësia(WCHAR_T));val -> pstrVal = t1; val -> strLen = str.gjatësia(); kthehu i vërtetë;)
Pastaj seksioni përkatës i rastit të deklaratës switch të metodës GetPropVal do të marrë formën:
rasti ePropTest1: wstring_to_p(test1, pvarPropVal); pushim;
Metoda SetPropVal:
rasti ePropTest1: nëse (TV_VT(varPropVal) != VTYPE_PWSTR) kthen false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); pushim;
Për të zbatuar vetinë e dytë, ne përcaktojmë një fushë të klasës CaddInNative
uint8_t lloji i fundit;
në të cilin do të ruajmë llojin e vlerës së fundit të transferuar. Për ta bërë këtë, shtoni komandën në metodën CaddInNative::SetPropVal:
Lloji_i fundit = TV_VT(varPropVal);
Tani, kur kërkojmë të lexojmë vlerën e pronës së dytë, ne do ta kthejmë vlerën lloji i fundit, çfarë kërkon detyra e caktuar.
Le të kontrollojmë funksionalitetin e ndryshimeve të bëra.
Për ta bërë këtë, le të paraqesim pamjen e konfigurimit 1C si më poshtë:
ndryshore DemoComp; Procedura Kur Sistemi Fillon() Lidh Komponentin e Jashtëm("...", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Raporti(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Raporti(String(DemoComp.Test)); DemoComp.Test = "Petya"; Raporti(String(DemoComp.Test)); Raporti(String(DemoComp.TypeCheck)); Fundi i procedurës
Si rezultat i nisjes, ne do të marrim një sekuencë mesazhesh:
3
Vasya
Pjetri
22

Mesazhi i dytë dhe i tretë janë rezultat i leximit të vetive të vendosura në hapin e mëparshëm. Mesazhi i parë dhe i dytë përmbajnë kodin e tipit të grupit të fundit të vetive. 3 korrespondon me një vlerë të plotë, 22 me një vlerë vargu. Në dosje vendoset korrespondenca e llojeve dhe kodeve të tyre llojet.h, i cili ndodhet në diskun e ITS.

Zgjerimi i listës së metodave

Detyra:
  1. Zgjeroni funksionalitetin e komponentit të jashtëm me funksionalitetin e mëposhtëm:
  2. Eksploroni mënyra për të zbatuar metodat e komponentëve të jashtëm
  3. Shtoni një metodë funksioni Funksioni 1, i cili merr dy vargje (“Parameter1” dhe “Parameter2”) si parametër. Rezultati është një varg si: “Kontrollo. Parametri 1, Parametri 2"
  4. Sigurohuni që ndryshimet që bëni të funksionojnë.

Për të përcaktuar metodat e komponentit që krijohet, zhvilluesi duhet të zbatojë metodat e mëposhtme në kodin e bibliotekës AddInNative:
GetNMethods, FindMethod, GetMethodName
Projektuar për të marrë numrin përkatës të metodave, kërkoni numrin dhe emrin e metodës. Ngjashëm me metodat përkatëse për vetitë
GetNParams
Rikthen numrin e parametrave të metodës me numrin e sekuencës së specifikuar; nëse një metodë me këtë numër mungon ose nuk ka parametra, kthen 0
GetParamDefValue
Kthen vlerën e paracaktuar të parametrit të specifikuar të metodës së specifikuar
HasRetVal
Kthen flamurin nëse metoda me vlerën e specifikuar të kthimit ka një vlerë kthyese: e vërtetë për metodat me një vlerë kthyese dhe i rremë ndryshe
CallAsProc
i rremë, ndodh një gabim në kohën e ekzekutimit dhe ekzekutimi i modulit 1C: Enterprise përfundon. Kujtesa për grupin e parametrave ndahet dhe lëshohet nga 1C: Enterprise.
CallAsFunc
Ekzekuton metodën me numrin e sekuencës së specifikuar. Nëse metoda kthehet i rremë, ndodh një gabim në kohën e ekzekutimit dhe ekzekutimi i modulit 1C: Enterprise përfundon. Kujtesa për grupin e parametrave ndahet nga 1C: Enterprise. Nëse vlera e kthyer është një varg ose tip i të dhënave binar, komponenti alokon memorie me funksionin AllocMemory menaxheri i memories, shkruan aty të dhënat dhe e ruan këtë adresë në fushën përkatëse të strukturës. 1C: Ndërmarrja do ta çlirojë këtë memorie duke telefonuar Memoria e Lirë.
Një përshkrim i plotë i metodave, duke përfshirë një listë të parametrave, përshkruhet në detaje në dokumentacionin e dhënë në diskun ITS.
Le të shqyrtojmë zbatimin e metodave të përshkruara më sipër.
Në kodin e komponentit, përcaktohen dy vargje:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
dhe numërimi:
enum Metodat (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Gjithmonë e fundit );
Ato përdoren në funksione GetNMethods, FindMethod Dhe GetMethodName, në analogji me përshkrimin e vetive.
Metodat GetNParams, GetParamDefValue, HasRetVal ndërprerësi i implementimit, në varësi të parametrave të kaluar dhe logjikës së aplikimit, ktheni vlerën e kërkuar. Metoda HasRetVal në kodin e tij ai ka një listë të metodave të vetme që mund të kthejnë një rezultat. Për ta ai kthehet e vërtetë. Për të gjitha metodat e çelikut kthimet i rremë.
Metodat CallAsProc Dhe CallAsFunc përmbajnë kodin direkt të ekzekutueshëm të metodës.
Për të shtuar një metodë që mund të thirret vetëm si funksion, duhet të bëni ndryshimet e mëposhtme në kodin burimor të komponentit të jashtëm:
  1. Shtoni emrin e metodës në vargje g_Emrat e metodave Dhe g_Emrat e metodësRu(skedar AddInNative.cpp)
  2. Shtoni një identifikues kuptimplotë të metodës në numërimin e metodave (skedari AddInNative.h)
  3. Bëni ndryshime në kodin e funksionit GetNParams sipas logjikës së programit
  4. Nëse është e nevojshme, bëni ndryshime në kodin e metodës GetParamDefValue, nëse dëshironi të përdorni vlerat e paracaktuara të parametrave të metodës.
  5. Bëni ndryshime në funksion HasRetVal
  6. Bëni ndryshime në logjikën e funksioneve CallAsProc ose CallAsFunc, duke vendosur kodin direkt të ekzekutueshëm të metodës atje
Le të paraqesim vargjet g_Emrat e metodave Dhe g_Emrat e metodësRu, si dhe listimi Metodat në formën:
static wchar_t *g_MethodNames = (L"Aktivizo", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Metodat Enum (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Gjithmonë e fundit );
Le të modifikojmë funksionin GetNProps në mënyrë që të kthejë numrin e parametrave të metodës "Test":
i gjatë CAddInNative::GetNParams(konst long lMethodNum) ( switch(lMethodNum) (rasti eMethShowInStatusLine: kthen 1; rasti eMethLoadPicture: kthen 1; rasti eMethTest: kthen 2; parazgjedhje: kthen 0; ) kthen 0; )
Le të bëjmë ndryshime në funksion:
bool CAddInNative::GetParamDefValue(konst i gjatë lMethodNum, konst i gjatë lParamNum, tVariant *pvarParamDefValue) (TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) (Numri i metodës në rast: në rast të rastit:L rasti i rastit e meth) MethStartTimer: rasti eMethStopTimer: rasti eMethTest : / / Nuk ka vlera parametrash sipas parazgjedhjes; default: kthe false; ) kthe false; )
Falë linjës së shtuar
rasti eMethTest:
nëse një ose më shumë argumente mungojnë, parametrat përkatës do të kenë një vlerë boshe ( VTYPE_EMPTY). Nëse keni nevojë për një vlerë të paracaktuar për një parametër, duhet ta vendosni atë në seksion eMethTest deklarata e ndërruesit të funksionit CAddInNative::GetParamDefValue.
Meqenëse metoda e Testit mund të kthejë një vlerë, duhet të bëni ndryshime në kodin e funksionit HasRetVal:
bool CAddInNative::HasRetVal(konst long lMethodNum) ( switch(lMethodNum) (rasti eMethLoadPicture: rasti eMethTest: kthen true; default: kthen false; ) kthen false; )
Dhe shtoni kodin e ekzekutueshëm të metodës në funksion CallAsFunc:
bool CAddInNative::CallAsFunc(konst long lMethodNum, tVariant* pvarRetValue, tVariant* paparams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) (rasti eMethLoadT;P nëse (!lSizeArray || !paParams) kthen false; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstrVal; wstring_to_p(std::wstring(s1+s2), pvarRetValue); ret = true ; pushim; ) kthim ret;)
Le të përpilojmë komponentin dhe të sjellim kodin e konfigurimit në formën:
ndryshore DemoComp; Procedura Kur Sistemi Fillon() Lidh Komponentin e Jashtëm("...", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.SomeName"); korsi = DemoComp.Test ("Përshëndetje", "Botë!"); Raporti (për); Fundi i procedurës
Pas nisjes së konfigurimit, do të marrim mesazhin: "Përshëndetje, Botë!", që tregon se metoda funksionoi me sukses.

Timer

Detyra:
  1. Studioni zbatimin e kohëmatësit në demo VK
  2. Modifikoni metodën "StartTimer" duke shtuar aftësinë për të kaluar në parametra intervalin e përgjigjes së kohëmatësit (në milisekonda)
  3. Sigurohuni që ndryshimet që bëni të funksionojnë.

Në WinAPI, ju mund të përdorni mesazhin për të punuar me kohën WM_TIMER. Ky mesazh do t'i dërgohet programit tuaj në intervalin kohor që keni vendosur kur krijoni kohëmatësin.
Për të krijuar një kohëmatës, përdorni funksionin SetTimer:
UINT SetTimer(HWND hWnd, // përshkruesi i dritares UINT nIDevent, // identifikuesi i kohëmatësit (numri) UINT nElapse, // vonesa TIMERPROC lpTimerFunc); // tregues për të funksionuar
Sistemi operativ do të dërgojë një mesazh WM_TIMER në program me intervalin e specifikuar në argument nKalimi(në milisekonda). Në parametrin e fundit mund të specifikoni një funksion që do të ekzekutohet sa herë që ndizet kohëmatësi. Kreu i këtij funksioni duhet të duket kështu (emri mund të jetë çdo gjë):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Le të shqyrtojmë zbatimin e një kohëmatës në demo VC.
Meqenëse po shqyrtojmë procesin e zhvillimit të një komponenti të jashtëm për familjen Windows OS, nuk do të shqyrtojmë zbatimin e kohëmatësit në sistemet e tjera operative. Për GNU/Linux OS, në veçanti, zbatimi do të ndryshojë në sintaksën e funksionit SetTimer Dhe TimerProc.
Kodi i ekzekutueshëm thërret metodën SetTimer, të cilit i kalon funksioni MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
ID-ja e kohëmatësit të krijuar vendoset në një variabël m_uiTimer në mënyrë që të mund të çaktivizohet më vonë.
Funksioni MyTimerProc si në vazhdim:
BANKËSHTJA E Thirrjes VOID MyTimerProc(HWND hwnd, // doreza e dritares për mesazhet e kohëmatësit UINT uMsg, // mesazhi WM_TIMER UINT idEvent, // identifikuesi i kohëmatësit DWORD dwTime // koha aktuale e sistemit) ( nëse (!pAsyncEvent) *who = wchar "ComponentNative", *what = L"Timer"; wchar_t *wstime = new wchar_t; if (wstime) ( wmemset(wstime, 0, TIME_LEN); ::_ultow(dwTime, wstime, 10); pAsyncEvent->ExternalEvent(who , çfarë, wstime); fshi wstime; ))
Thelbi i funksionit është se thirret metoda Ngjarje e jashtme, i cili dërgon një mesazh në sistemin 1C: Enterprise.
Për të zgjeruar funksionalitetin e metodës StartTimer Le të bëjmë sa vijon:
Modifikimi i kodit të metodës GetNParams në mënyrë që të jetë për metodën eMethStartTimer vlera e kthyer 1:
rasti eMethStartTimer: kthimi 1;
Këtu është kodi i metodës CallAsProc në formën:
rasti eMethStartTimer: nëse (!lSizeArray || TV_VT(paParams) != VTYPE_I4 || TV_I4(paParams)<= 0) return false; pAsyncEvent = m_iConnect; #ifndef __linux__ m_uiTimer = ::SetTimer(NULL,0,TV_I4(paParams),(TIMERPROC)MyTimerProc); #else // код для GNU/Linux #endif break;
Tani le të kontrollojmë funksionalitetin. Për ta bërë këtë, ne do të shkruajmë kodin në modulin e aplikacionit të menaxhuar të konfigurimit:
ndryshore DemoComp; Procedura Kur Sistemi Fillon() Lidh Komponentin e Jashtëm("...", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.SomeName"); DemoComp.StartTimer (2000); Fundi i procedurës
Pas fillimit të konfigurimit, programi do të marrë mesazhe në intervale prej 2 sekondash, gjë që tregon se kohëmatësi po funksionon siç duhet.

Ndërveprimi me sistemin 1C: Enterprise

Për të bashkëvepruar midis komponentit të jashtëm dhe sistemit 1C: Enterprise, metodat e klasës IAddInDefBase, të përshkruara në skedar AddInDefBase.h. Ne rendisim ato më të përdorurat:
Gjenerimi i një mesazhi gabimi
virtual bool ADDIN_API AddError (kodi i shkurtër i panënshkruar, burimi konst WCHAR_T*, përshkrimi WCHAR_T* konst, kodi i gjatë)
wcode, kodi- kodet e gabimit (një listë e kodeve të gabimit me përshkrime mund të gjendet në diskun ITS)
burimi- burimi i gabimit
përshkruaj- përshkrimi i gabimit
Dërgimi i një mesazhi në sistemin 1C: Enterprise
virtual bool ADDIN_API Ngjarje e jashtme (WCHAR_T* wszBurimi, WCHAR_T* wszMesazh, WCHAR_T* wszData) = 0;
wszBurimi- burimi i mesazhit
wszMesazhi- Teksti i mesazhit
wszTë dhënat- të dhënat e transmetuara
Përgjimi i mesazheve kryhet nga procedura e Përpunimit të Ngjarjeve të Jashtme
Regjistrimi i një komponenti të jashtëm në sistemin 1C: Enterprise
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszEmri i profilit- emri i komponentit.
Këto metoda janë të mjaftueshme për ndërveprim të plotë midis VK dhe 1C. Për të marrë të dhëna nga një komponent i jashtëm nga sistemi 1C: Enterprise dhe anasjelltas, komponenti i jashtëm dërgon një mesazh të veçantë, i cili nga ana tjetër kapet nga sistemi 1C dhe, nëse është e nevojshme, thërret metodat e komponentit të jashtëm për të transmetuar të dhënat prapa. .

Lloji i të dhënave tVariant

Kur shkëmbeni të dhëna midis komponentit të jashtëm dhe sistemit 1C: Enterprise, përdoret lloji i të dhënave tVariant. Ai përshkruhet në skedarin type.h, i cili mund të gjendet në diskun ITS:
struct _tVariant ( _ANONYMOUS_UNION union ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; i panënshkruar int uintVal; int64_t llVal; uint8_t ui8Val; uint16_t ui8Valt; uint32_t lVal; int intVal; i panënshkruar int uintVal; int64_t llVal; uint8_t ui8Val; uint32Vintalt; ; int32_t errCode; hRes të gjata; float fltVal; dyfishtë dblVal; bool bVal; char chVal; wchar_t wchVal; DATE data; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; _ANONYMOUS_STRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NAMEY_2/UST int3 2_t strLen ; //numri i bajteve ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //numërimi i simboleve ) __VARIANT_NAME_4/*wstr*/; ) _2_VARIANT_NAME_4/*wstr*/; ) _2_VARIANT;) _2_VARIAN; - grupi dimensional në pvarVal TYPEVAR vt; );
Lloji tVariantështë një strukturë që përfshin:
  • përzierje (bashkim) i destinuar drejtpërdrejt për ruajtjen e të dhënave
  • identifikues i llojit të të dhënave
Në përgjithësi, puna me variabla të llojit tVariant ndodh sipas algoritmit të mëposhtëm:
  1. Përcaktimi i llojit të të dhënave të ruajtura aktualisht në një variabël
  2. Hyni në fushën përkatëse të përzierjes për të hyrë drejtpërdrejt në të dhënat
Duke përdorur llojin tVariant thjeshton ndjeshëm ndërveprimin e sistemit 1C: Enterprise dhe komponentëve të jashtëm

Aplikacion

Drejtoria "shembuj" përmban shembuj për artikullin
shembuj/1 - nisni komponentin demo
shembuj/2 - demonstrim i zgjerimit të listës pronësore
shembuj/3 - demonstrim i zgjerimit të listës së metodave
Çdo direktori përmban një projekt VS 2008 dhe një konfigurim të gatshëm 1C.

Titulli i artikullit përfshin frazën "për dummies". Me çajnik nënkuptova, para së gjithash, veten time. Të gjitha njohuritë e mia për C++ mbetën në nivelin e 3-4 viteve të universitetit, kur u futa në rrugën e shtrembër të 1C. Dhe gjithçka do të ishte mirë, por kohët e fundit u ngrit një detyrë që kërkonte shkrimin e një komponenti të jashtëm. Më duhej të kujtoja kujtimet e mia dhe të hiqja pluhurin nga njohuritë e mia në C++. Rezulton se gjithçka nuk është aq e frikshme. Unë dua t'ju ofroj një hyrje të shkurtër në shkrimin e komponentëve të jashtëm.

Komponentët e shabllonit në ITS

Disku ITS përmban dokumentacion të plotë mbi mekanizmin e komponentëve të jashtëm, të plotësuar nga një projekt shembull dhe një shabllon për zhvillimin tuaj. Materiali quhet "Teknologjia e Komponentit të Jashtëm". Dokumentacioni është i shkëlqyeshëm, por ju ende duhet ta kuptoni atë, dhe koha, si zakonisht, është e shkurtër. Në fakt, ka vetëm disa pika kyçe që ia vlen t'u kushtohet vëmendje, pjesa tjetër është prishja dhe kotësia :)

Materialet e nevojshme

Për të krijuar një komponent të jashtëm do të na duhet:

  1. Materiali "Teknologjia për krijimin e komponentëve të jashtëm" të vendosura në ITS
  2. Shablloni bosh i komponentit të jashtëm i përfshirë me materialin
  3. MS Visual Studio. Versioni Express është falas dhe më se i mjaftueshëm për nevojat tona.
  4. Të ketë njohuri bazë të sintaksës C++, përkatësisht:
  • Aftësia për të dalluar një deklaratë variabël nga një lak ose kusht
  • Duke kuptuar që vargjet në formën e tyre të pastër nuk ekzistojnë në C++, ka vargje për të cilat qartë duhet të shqetësoheni me kujtesën
  • Epo, sigurisht, kërkohet aftësia për të zbatuar detyrën në gjuhën e specifikuar. Së paku, aftësia për të thirrur një bibliotekë të palëve të treta nga C++ që do të bëjë gjithçka vetë.

Le të fillojmë të gërmojmë

Dokumentacioni për Native API është mjaft i detajuar. Për ta përmbledhur, ai thotë sa vijon:

  1. Një komponent i jashtëm ju lejon të zgjeroni gjuhën e integruar me një objekt të ri (ose disa). Ato. do të krijojmë një klasë që mund ta krijojmë duke përdorur operatorin “New” dhe do të thërrasim metodat e këtij objekti nga gjuha e integruar.
  2. Në mënyrë që objekti ynë të funksionojë, platforma do të "komunikojë" me të duke përdorur një protokoll të caktuar, të cilin ne jemi të detyruar ta ofrojmë.
  3. Vetë kodi i komponentit konvencionalisht përbëhet nga dy pjesë: e para është regjistrimi i vetë komponentit në sistem, e dyta është funksionimi i klasës së re dhe ndërveprimi i saj me platformën.

Nuk do të hyjmë në specifikat e zbatimit, po na mbarojnë afatet dhe nuk kemi kompetencë të mjaftueshme. Ne duhet të kuptojmë shpejt se ku duhet të futim linjat tona në mënyrë që komponenti të funksionojë. Për ta bërë këtë, merrni shabllonin e komponentit me ITS dhe hapeni në Visual Studio. Shablloni ndodhet në dosjen e shabllonit të arkivit të papaketuar. Le të shohim se çfarë kemi këtu.

Ne jemi të interesuar për skedarin AddInNative.cpp. I gjithë realizimi qëndron në të. Ai përmban shabllone për të gjitha metodat e nevojshme; ju vetëm duhet t'i personalizoni ato pak. Sidoqoftë, doli se ishte më e lehtë të mos përdorësh një shabllon bosh si bazë, por të merreshe me një shembull pune. Ka disa zile dhe bilbila të dobishme që nuk përfshihen në shabllonin bosh. Kur të vijë mirëkuptimi, do t'ju duhet të merrni një shabllon të zbrazët dhe ta rafinoni atë me njohuri për çështjen. Një shembull i një komponenti të punës ndodhet në dosjen shembull\NativeAPI dhe një shabllon bosh ndodhet në dosjen e shabllonit.

Le ta hapim projektin nga dosja e shembullit dhe në të - skedari AddInNative.cpp

Në fillim të skedarit ka deklarata të konstantave dhe funksioneve ndihmëse. Ne jemi të interesuar në linjat e mëposhtme:

Objekti ynë, si një "i vërtetë", do të mbështesë metoda të shkruara në rusisht dhe anglisht. Për këtë qëllim, emrat e shkruar të vetive dhe metodave deklarohen në dy gjuhë. Korniza blu është për banjot angleze, korniza e kuqe është për banjot ruse. Fotografia tregon se shembulli tashmë zbaton një numër metodash dhe veçorish. Detyra jonë është t'i heqim ato dhe të fusim tonat.

Rreshti në të cilin është deklaruar emri i klasës është theksuar me një kornizë të gjelbër. Për të qenë i sinqertë, nuk e kuptova se çfarë do të thoshte. Nëse e ndryshoni, asgjë nuk funksionon. Meqenëse ata fillimisht bënë rezervimin se unë isha "bedel", mund të falem. :)

Kështu, nëse objekti ynë përmban metodën "RunCalculation" dhe veçorinë "Destination", atëherë duhet ta përshkruajmë këtë emër në grupet g_MethodNamesRu dhe g_PropNamesRu, përkatësisht.

Thirrje nga gjuha 1C

Pra, objekti ynë do të përmbajë një metodë dhe një veti leximi-shkruash.

Le të kemi skenarin e mëposhtëm të përdorimit:

OurObject = New (“AddIn. MyComponent. DataSender”); Objekti ynë. Destinacioni = "somemail@server. com";
Objekti ynë. RunCalculation (Shuma e pagesës, "Për shërbimet komunale");

Ekziston një veçori e vargut dhe një metodë me një parametër numerik dhe një varg. Në mënyrë që e gjithë kjo të funksionojë, 1C kryen afërsisht protokollin e mëposhtëm të komunikimit me komponentin:

Platforma thërret funksione të paracaktuara në objektin tonë, dhe ajo i përgjigjet atij dhe ekzekuton komandat e saj. Situata është e ngjashme me metodat, vetëm atje, përveç numrit të metodës, kërkohet numri i parametrave, prania e një vlere të kthyer dhe prania e parametrave opsionalë.

Le të kthehemi te kodi ynë. Për të shmangur "numrat magjikë", dy numërime deklarohen në klasën CAddInNative, të cilat janë përgjegjëse për përcaktimin e numrit të metodave dhe vetive. Le të hapim skedarin CAddInNative.h dhe t'i shohim ato që në fillim:

Modeli i zbrazët nuk përmban këto numërime, dhe gjithashtu nuk ka asnjë shembull për ndarjen e thirrjeve në rusisht nga thirrjet në jo-rusisht. Kjo qasje është fakultative. Është e rëndësishme të ndiqni ndërfaqen dhe nëse do të ketë transferime apo jo, varet nga ju që të vendosni.

Vargjet e Unicode

Shumë njerëz me siguri e dinë që platforma funksionon me karaktere të dyfishta në formatin Unicode. Shablloni deklaron një lloj të veçantë WCHAR_T për këtë qëllim. Ky lloj është një mbështjellës ndër-platformë dhe siguron të njëjtën madhësi të karaktereve në Windows dhe Linux. Lloji standard wchar_t mund të ndryshojë në madhësi në sisteme të ndryshme. Ju lutemi vini re gjithashtu se të gjitha literalet e vargut deklarohen me një parashtesë të shkronjës L. Kjo do të thotë se një varg i tillë është i llojit wchar_t.

Ekziston një rregull i thjeshtë: nga brenda, përbërësit e vargut përpunohen si wchar_t (në Linux mund të ketë 4 bajt, në Windows - 2), por sapo ta transferojmë vargun në 1C ose ta marrim prej andej, na duhet WCHAR_T (rreptësisht 2 bajt në të gjitha sistemet).

Për të kthyer një lloj vargu në një tjetër, shablloni ofron funksione ndihmëse:

E para formon WCHAR_T nga standardi wchar_t:

uint32_t convToShortWchar(WCHAR_T** Destinimi, konst wchar_t* Burimi, uint32_t len ​​= 0);

E dyta është e kundërta. Formon wchar_t nga WCHAR_T.

uint32_t convFromShortWchar (wchar_t** Destin, konst WCHAR_T* Burimi, uint32_t len ​​= 0);

Kur ndërveproni me platformën, përdoret gjithmonë vetëm WCHAR_T.

Lloji variant

Një tjetër gjë interesante është lloji i të dhënave gjenerike Variant. Na lejon të ndërveprojmë me gjuhën 1C, e cila, siç e dini, nuk është e shtypur dhe secila variabël në të mund të përmbajë gjithçka. Ky lloj përdoret gjatë shkëmbimit të vlerave. Ne kalojmë dy parametra në metodën RunCalculation - një numër dhe një varg. Komponenti do të marrë dy vlera Variante. Është përgjegjësia jonë të kontrollojmë llojin e tyre aktual. Askush nuk do t'ju pengojë të kaloni jo një numër në përbërës, por, të themi, një tabelë vlerash.

Edhe pse duket se e kam gabim. Më duket se ende nuk do të jetë e mundur të transferohet Tabela e Vlerave në NativeAPI, sepse ... nuk është në listën e llojeve të lejuara, por, megjithatë, mund të kaloni Date në vend të String. Kjo gjithashtu nuk është e mirë. Duhet të kontrollojmë llojin real të ndryshores që ka ardhur nga 1C.

Lloji Variant është i thjeshtë. Kjo është një strukturë, vetitë e së cilës janë vlera të llojeve të ndryshme. Ka veti si DATE, wchar_t, int dhe të tjera. Pjesa kryesore e një Varianti është vetia "vt", e cila ruan llojin real të ndryshores dhe nga e cila mund të kuptoni saktësisht se si ta interpretoni këtë Variant. Përveç kësaj, një numër makrosh ndihmës janë deklaruar për të thjeshtuar punën me llojin Variant.

Shkoni te pika

Duket se kjo është e gjitha me hyrjen. Unë propozoj të shqyrtojmë një shembull të zbatimit të një komponenti të jashtëm. TK do të jetë një shembull i një komponenti nga disku ITS. Ky shembull përshkruan karakteristikat e mëposhtme:

  • Shfaqja e tekstit në shiritin e statusit të dritares kryesore;
  • Dërgimi i një ngjarjeje me kohëmatës të jashtëm;
  • Transferimi i të dhënave binare në 1C: Enterprise;
  • Zbatimi i pronave;
  • Zbatimi i procedurave;
  • Zbatimi i funksioneve;

Komponenti ka API-në e mëposhtme:

  • Vetitë:
    • Enabled/IsEnabled;
    • IsTimer/IsTimerPresent;
    • Metodat:
      • Aktivizo;
      • Çaktivizo / Çaktivizo;
      • ShowInStatusLine;
      • EnableTimer/StartTimer;
      • Fik Timer/StopTimer;
      • LoadPicture/LoadPicture;

Një ngjarje e jashtme ndodh sipas kohëmatësit, në të cilin mund të regjistroheni nga kodi 1C.

Të udhëhequr nga njohuritë që kemi, le të shohim komponentin që në fillim.

Komponentët e regjistrimit

Objekti ynë zbatohet si një klasë e veçantë C++, në këtë rast CAddInNative. Në mënyrë që 1C të shohë klasën tonë, biblioteka dll duhet të eksportojë 3 funksione:

  • GetClassObject
  • DestroyObject
  • GetClassEmrat

Këto eksporte mund të shihen në skedarin AddInNative.def në pemën e projektit VisualStudio. Le të shohim kodin e këtyre funksioneve:

Më e thjeshta - funksioni GetClassNames - i tregon platformës 1C se cilat klasa janë në komponentin tonë. Le të më korrigjojnë gurutë e C++, më duket se këtu platforma duhet të përgjigjet me emrat e klasave të C++ në mënyrë që t'i importojë ato. Pikërisht për këtë përdoret grupi g_kClassNames, ai me "kornizën" jeshile. Unë nuk e kontrollova në mënyrë specifike, por nëse thjesht duhet ta bëni komponentin të funksionojë, atëherë duhet të lini gjithçka siç është në shembull. Tashmë po funksionon, nuk ka nevojë të shqetësohet për momentin.

Pra, GetClassNames kthen në platformë një grup emrash klasash që implementojnë objekte të dobishme të komponentit të jashtëm. Në shembullin tonë, komponenti do të kthejë në platformë një grup prej një elementi me emrin e klasës CAddInNative.

Ju lutemi vini re se platforma do të marrë një vlerë të tipit WCHAR_T dhe emri i klasës në grupin g_kClassEmrat është i llojit wchar_t. Prandaj, hedhja kryhet duke përdorur funksionin ndihmës të diskutuar më sipër.

Funksioni tjetër është GetClassObject. Thirret kur kemi shkruar "E re" në kodin e ndërmarrjes. Platforma kërkon që ne të krijojmë një shembull të ri të klasës dhe të kthejmë një tregues në objektin e ri.

Përsëri, vini re se parametri i parë që na tregon platforma është se cilën klasë të krijojmë (nga ato që i janë dhënë nga metoda GetClassNames). Meqenëse kemi vetëm një klasë, ky emër nuk kontrollohet fare këtu, një objekt thjesht krijohet përmes new dhe kthehet përmes parametrit dalës pInterface.

Dhe funksioni i fundit i kërkuar i eksportit është DestroyObject. Emri flet vetë. Kur një objekt nuk i nevojitet më platformës, ai duhet të fshihet. Na jepet një tregues për një objekt të krijuar më parë. Ne e çlirojmë atë duke përdorur fshirje dhe rivendosje të treguesve të panevojshëm.

Zbatimet e përshkruara janë mjaft universale. Nëse komponenti ynë zbaton vetëm një klasë (si në shembull), atëherë këto funksione duhet thjesht të kopjohen në vetvete. Kushti i vetëm është të krijoni klasën e duhur në funksionin GetClassObject, nëse emri juaj nuk është CAddInObject, por diçka tjetër.

Inicializimi/përfundimi i një komponenti

Pas krijimit të një klase që implementon një komponent, platforma thërret metodat e kësaj klase. Para fillimit të punës, platforma do të na tregojë një objekt "vetëvete", me të cilin mund të quajmë disa metoda të vetë platformës. Kjo ndodh në metodën Init. Në shembull, objekti i platformës ruhet në variablin m_iConnect.

Një metodë tjetër e rëndësishme është setMemManager. Ju lejon të ndani blloqe memorie që vetë platforma do t'i lirojë. Ajo zbatohet si më poshtë:

Ne thjesht ruajmë një tregues për menaxherin e memories që platforma na e kalon neve. Më pas, me këtë menaxher do të ndajmë memorien e çliruar nga vetë platforma.

Dhe përsëri, si në rastin e funksioneve të eksportit, metodat e inicializimit janë mjaft universale; thjesht mund t'i kopjoni ato tek vetja dhe të mos shqetësoheni për "përfundimin" e tyre derisa të bëhet vërtet e nevojshme.

Ngarkesa. Metodat dhe vetitë e objektit përbërës

Regjistrimi

Epo, natyrisht, ne e krijuam komponentin jo për hir të inicializimit të tij, por për hir të disa funksionaliteteve të dobishme. Është koha për të parë se si po zbatohet.

Së pari, ne duhet të regjistrojmë një objekt që mund të krijohet dhe thirret nga gjuha 1C. Ky objekt regjistrohet në metodën RegisterExtensionAs.

Në këtë metodë, ne i informojmë platformës emrin e klasës sonë, pasi do të jetë i dukshëm nga gjuha 1C. Është me këtë emër që ne do ta krijojmë atë përmes "New". Në këtë rast, krijimi i objektit do të kryhet me kodin e mëposhtëm:

ConnectExternalComponent(File, "MyComponent", ExternalComponentType. Native);
Komponentët e objektit = i ri( "AddIn.MyComponent.AddInNativeExtension");

Sipas dokumentacionit, memoria për vargun me emrin e klasës ndahet nga menaxheri i kujtesës, dhe emri shkruhet në këtë adresë - "AddInNativeExtension". Këtu mund të shkruani emrin tuaj pa dhimbje. Ju lutemi vini re se përsëri ka një konvertim nga wchar_t në platformën WCHAR_T.

Përdorimi

Siç shkrova më lart, platforma kërkon komponentin për veçori të ndryshme gjuhësore. A ekziston vetia e specifikuar, a është e shkruajtshme, a ka parametri i funksionit një vlerë të paracaktuar, a ka një vlerë kthyese, etj. Nëse marrim shembullin e kodit të dhënë më parë:

Objekti ynë = E re( "AddIn.MyComponent.DataSender"); // DataSender është emri nga funksioni RegisterExtensionAs (diskutuar më poshtë).
Objekti ynë. Adresa = " [email i mbrojtur]" ;
Objekti ynë. Ekzekutoni llogaritjen (shuma e pagesës, "Për shërbimet komunale");

atëherë do të kryhet sondazhi i mëposhtëm:

  1. A ka një pronë "Destination"?
  2. A e mbështet regjistrimin?
  3. A ekziston një metodë e quajtur RunCalculation?
  4. Sa parametra ka?
  5. A ka një vlerë të kthimit
  6. Cilat janë parazgjedhjet për parametrat opsionalë (nëse ka)

Këtu është më e dobishme të shikoni një shembull dhe të kontrolloni dokumentacionin. Zbatimi i të gjitha këtyre anketave është mjaft i thjeshtë. Një kopsht zoologjik i tërë metodash është përgjegjës për ndërveprimin. Unë nuk do të kaloj nëpër gjithçka, ato janë mjaft të dokumentuara, dhe përveç kësaj, ato janë të thjeshta për t'u zbatuar. Do të merren parasysh vetëm momentet më domethënëse, në të cilat ne, si bedel, do të duhet t'i kapim ato :). Qasja bazë është si më poshtë: herën e parë që përmendet një pronë ose metodë, platforma do të na kërkojë ta kërkojmë me emër. Ne do të duhet të përgjigjemi me numrin unik të kësaj prone (metodë). I gjithë komunikimi i mëtejshëm do të bëhet vetëm me numra. Këtu do të ndihmojnë numërimet e përmendura që ruajnë këta numra.

Vetitë

Gjëja e parë që duhet marrë parasysh është infrastruktura e pronës. Platforma kërkon ekzistencën e një prone duke përdorur metodën FindProp

Platforma na jep emrin e pronës që kërkojmë në formën WCHAR_T. Ai konvertohet në wchar_t duke përdorur një metodë ndihmëse dhe ky tekst kërkohet fillimisht në termat në gjuhën angleze dhe më pas në ato në gjuhën ruse. Duhet të kthejmë numrin e pronës. Vini re se funksioni ndihmës findName është i përfshirë këtu. Zbatimi i tij është në shembull, por komponenti nuk është në shabllonin bosh. Duket e përshtatshme ta tërhiqni drejt jush nëse planifikoni të keni terma dygjuhësh në komponentin tuaj.

Më pas, metoda GetPropName kryen detyrën e kundërt, duke marrë emrin e pronës me numrin e saj. Vargu i emrit ndahet gjithashtu përmes menaxherit të memories së ndërmarrjes. Dyshoj se metoda GetPropName së bashku me GetNProps përdoret kur zgjerojmë vetitë e një objekti me një shenjë plus në korrigjues. Më pas platforma do të marrë numrin total të pronave dhe do të kërkojë një emër për secilën prej tyre.

Çifti tjetër i metodave është IsPropReadable/IsPropWritable. Gjithçka është e thjeshtë këtu, për numrin e specifikuar të pronës duhet të themi nëse mund të lexohet/shkruhet.

Marrja dhe shkrimi i vlerave kryhen duke përdorur metodat GetPropVal/SetPropVal. Këtu ia vlen të futemi në më shumë detaje. Ne po fillojmë të punojmë me llojet 1C: Enterprise, që do të thotë se Varianti po vjen në skenë.

Shablloni i komponentit përcakton një grup makrosh ndihmës për të thjeshtuar punën me Variantin. E para është kontrolli i llojit të vlerës. Për shembull, makro TV_VT ju lejon të kontrolloni/caktoni llojin e një vlere. Konstantet e emërtuara janë përcaktuar gjithashtu për secilin nga llojet e mbështetur. Këto konstante dhe korrespondenca e tyre me 1C: llojet e ndërmarrjeve janë të listuara në dokumentacion.

Makroja TV_BOOL merr një vlerë Boolean nga varianti me të cilin mund të punoni. Për analogji, merren vlerat e numrave të plotë (TV_INT), vargjet (TV_WSTR) dhe të tjera. Vlerat e sakta janë në kod, ju gjithmonë mund t'i shihni ato.

Një pikë e rëndësishme është se nuk mjafton t'i caktoni një vlerë një variantit; duhet të caktoni gjithashtu një lloj real. Kushtojini vëmendje GetPropVal. Përveç caktimit TV_BOOL = caktimi i vërtetë, ekziston një caktim tip: TV_VT = VTYPE_BOOL. Nëse lloji nuk është caktuar, platforma nuk do të dijë se çfarë lloj vlere i është kthyer. Sigurisht, mund të ngatërroni dhe të vendosni llojin e gabuar. Kjo shpesh shoqërohet me rënien e platformës.

Le të përmbledhim sa më sipër:

Ne marrim vlerën nga opsioni:

bool someVariable = TV_BOOL(pVariant);

Shkruani vlerën e opsionit:

TV_VT(pVariant) = VTYPE_BOOL; // Lloji i vlefshëm i të dhënave

TV_BOOL(pVariant) = someBooleanVariable; // vendosni vetë vlerën

Dhe tani - metodat me gunga!

Metodat janë pak më të komplikuara, por në përgjithësi ato janë të ngjashme me vetitë. Së pari, ekziston saktësisht i njëjti funksion i kërkimit të një metode me emër, marrja e numrit total të metodave, marrja e emrit me numër. Sidoqoftë, përveç sa më sipër, shtohen karakteristikat e mëposhtme:

  • Nëse një metodë mund të kthejë një vlerë, atëherë ajo mund të përdoret në "Llogarit" dhe të shkruhet në të djathtë të operacionit të caktimit në gjuhën 1C. Nëse jo, atëherë është një procedurë dhe gjëra të tilla do të hedhin një përjashtim "Përdorimi i një procedure si funksion".
  • Metoda ka parametra. Platforma duhet të dijë numrin e tyre. Nëse thirrja specifikon më shumë argumente sesa janë specifikuar në nënshkrimin e metodës, ndodh gabimi "Shumë parametra".
  • Nëse një metodë nuk i kalohen argumente të mjaftueshme, atëherë disa prej tyre mund të jenë opsionale, dhe nëse nuk ka parametra opsionalë, atëherë ndodh një gabim "Parametra të pamjaftueshëm".
  • Kur thirret, nëse është një procedurë, atëherë nuk mund të ketë një vlerë kthyese. Nëse është një funksion, atëherë ka një vlerë të kthimit. Duhet gjithashtu të përpunohet.

Ka një sërë metodash të thjeshta, qëllimi i të cilave është i qartë nga emrat e tyre dhe nga dokumentacioni. Këto përfshijnë HasRetVal, GetNParams, GetParamDefValue. Unë propozoj të mos i konsiderojmë ato; një shembull është më se i mjaftueshëm. Interesi ynë do të drejtohet drejt zbatimit të drejtpërdrejtë të ngarkesës. Ai zbatohet në metodat CallAsProc dhe CallAsFunc. I pari është përgjegjës për procedurat e thirrjes, i dyti është përgjegjës për thirrjen e funksioneve. Ato ndryshojnë në atë që CallAsFunc ka një parametër shtesë dalës, në të cilin ne do të kalojmë vlerën e kthyer të funksionit në platformë.

Thirrja kryhet si më poshtë: platforma na jep numrin e metodës së thirrur, një grup parametrash aktualë dhe numrin e tyre. Ne duhet të analizojmë numrin e metodës dhe ta ushqejmë atë me parametrat e kaluar. Në rastin e një funksioni, ne gjithashtu duhet të shkruajmë diçka në vlerën e kthimit.

Në shembull, numri i metodës analizohet në switch/case dhe, në varësi të numrit, ekzekutohet logjika e metodës. Për metodat Aktivizo/Çaktivizo, thjesht zgjidhni një kuti zgjedhjeje. Metoda ShowInStatusLine është interesante. Ai tregon se çfarë i është kaluar në shiritin e statusit të dritares 1C:Enterprise. Për ta bërë këtë, ne përdorim objektin e lidhjes së platformës m_iConnect, atë që na është “lëshuar” gjatë regjistrimit të komponentit. Një listë e plotë e aftësive të tij përshkruhet në dokumentacion.

Pika interesante. Këtu, në shembull, lloji i vlerës që vjen nga 1C nuk kontrollohet, por SetStatusLine thjesht thirret me pjesën e vargut Variant. Unë dyshoj se nëse e quani metodën e komponentit nga gjuha 1C, duke kaluar një numër ose datë atje (në vend të një vargu), atëherë asgjë nuk do të funksionojë... Përsëri, le të korrigjojnë gurusët, por duket se treguesi pwstrVal do të tregojë Zoti e di nga ka ardhur nga sipërmarrja le të themi një numër, jo një varg i ndershëm. Kur telefononi SetStatusLine, platforma do të përpiqet të lexojë një rresht nga një adresë e panjohur dhe, ka shumë të ngjarë, do të rrëzohet. Është më mirë të kontrolloni gjithmonë llojin e pritur. Ju kurrë nuk e dini.

Funksioni LoadImage në shembull zbatohet në një mënyrë më interesante; ai shqyrton mundësinë e shkëmbimit të vargjeve dhe të dhënave binare me platformën.

Së pari, këtu kontrollohet numri i parametrave të kaluar. Nëse ata nuk janë të pranishëm, atëherë thirrja konsiderohet e pasuksesshme. Kthen false, e cila interpretohet nga platforma si një gabim thirrjeje.

Më pas, këtu kontrollohet lloji i parametrit të kaluar. Nëse ky është një varg i ngushtë (VTYPE_PSTR), atëherë përdoret pjesa char e variantit. Shembulli thotë paParam->pstrVal, por ju mund të përdorni makro TV_STR, do të jetë njësoj, por do të ruhet edhe uniformiteti i punës me opsionin.

Nëse është një varg i gjerë (VTYPE_PWSTR), atëherë konvertimi bëhet fillimisht në wchar_t dhe më pas në char. Fakti është se shtegu i skedarit kalohet nga gjuha 1C në këtë metodë, e cila më pas përdoret në funksionin fopen(char*). Ky funksion kërkon një lloj char* si hyrje dhe WCHAR_T do të na dërgohet nga platforma. Për funksionimin e saktë, kryhen konvertimet e vargjeve.

Dhe së fundi, nëse kjo nuk është fare një varg, atëherë thirrja konsiderohet e pasuksesshme dhe false kthehet.

Ne ndajmë memorie për të dhënat binare duke përdorur një menaxher memorie. Kjo është logjike; të dhënat binare do të bëhen një objekt i plotë brenda platformës dhe duhet të menaxhohen prej saj. Kujtesa ndahet për variantin pvarRetValue, që është vlera e kthimit të funksionit të komponentit të jashtëm.

I gjithë skedari lexohet në buferin e caktuar; përveç kësaj, Domosdoshmërisht madhësia e bajtit është e specifikuar në vetinë e opsionit strLen dhe lloji i të dhënave të opsionit VTYPE_BLOB. Nëse memoria shpërndahet me sukses, atëherë ne kthehemi true si shenjë e një thirrjeje të suksesshme në të gjithë funksionin.

Kështu, kur në gjuhën 1C shkruhet:

BinaryData = Komponent. NgarkoFoto("C:\pic.jpg");

Metoda CallAsFunc e objektit komponent do të thirret, duke kaluar rrugën dhe duke kthyer të dhënat binare siç përshkruhet më sipër.

Nëse është e suksesshme, ndryshorja BinaryData do të përmbajë një objekt të plotë të gjuhës 1C. Kur të dalë jashtë fushëveprimit, e gjithë memoria që ka zënë do të çlirohet nga platforma. Kjo është arsyeja pse ai u nda përmes menaxherit të kujtesës.

konkluzioni

Historia u shkrua nga një çajnik për dummies, prandaj, ka shumë të ngjarë, ajo është e mbushur me pasaktësi terminologjike. Megjithatë, qëllimi i këtij artikulli është të ofrojë një prezantim të shpejtë të komponentëve të jashtëm. Nëse keni nevojë të bëni shpejt një komponent në një kohë të shkurtër, pa telashe të panevojshme, pa diskutime të gjata, atëherë shpresoj që ky artikull t'ju ndihmojë. Nëse ndonjë nga gabimet e mia ju bën të ndiheni keq, si mësues i C++, ju lutem më njoftoni në komente dhe ne do t'i korrigjojmë.

Faleminderit per vemendjen.

  • Tutorial

Prezantimi

Ky artikull jep një ide se si funksionojnë komponentët e jashtëm në sistemin 1C: Enterprise.
Do të shfaqet procesi i zhvillimit të një komponenti të jashtëm për versionin 8.2 të sistemit 1C: Enterprise, i cili funksionon nën OS Windows me një mënyrë funksionimi skedari. Ky opsion përdoret në shumicën e zgjidhjeve të dizajnuara për bizneset e vogla. VK do të zbatohet në gjuhën e programimit C++.

Komponentët e jashtëm "1C: Ndërmarrja"

"1C: Enterprise" është një sistem i shtrirë. Për të zgjeruar funksionalitetin e sistemit, përdoren komponentë të jashtëm (EC). Nga këndvështrimi i zhvilluesit, një VC është një objekt i jashtëm që ka veti dhe metoda, dhe gjithashtu mund të gjenerojë ngjarje për përpunim nga sistemi 1C: Enterprise.
Komponentët e jashtëm mund të përdoren për të zgjidhur një klasë problemesh që janë të vështira apo edhe të pamundura për t'u zbatuar në gjuhën e programimit të integruar në 1C: Enterprise. Në veçanti, kjo klasë përfshin detyra që kërkojnë ndërveprim të nivelit të ulët me sistemin operativ, për shembull, për të punuar me pajisje specifike.
Sistemi 1C: Enterprise përdor dy teknologji për krijimin e komponentëve të jashtëm:
  • duke përdorur Native API
  • duke përdorur teknologjinë COM
Duke pasur parasysh kufizimet e dhëna, ndryshimi midis dy teknologjive të sipërpërmendura është i parëndësishëm, kështu që ne do të shqyrtojmë zhvillimin e lojërave video duke përdorur API-në vendase. Nëse është e nevojshme, zhvillimet e zbatuara mund të aplikohen në zhvillimin e softuerit kompjuterik duke përdorur teknologjinë COM, dhe gjithashtu, me modifikime të vogla, të aplikohen për përdorim në sistemin 1C: Enterprise me opsione të tjera funksionimi përveç mënyrës së funksionimit të skedarit.
Struktura VK
Komponenti i jashtëm i sistemit 1C: Enterprise paraqitet në formën e një biblioteke DLL. Kodi i bibliotekës përshkruan klasën pasardhëse IComponentBase. Klasa e krijuar duhet të përcaktojë metodat përgjegjëse për zbatimin e funksioneve të komponentit të jashtëm. Metodat e anashkaluara do të përshkruhen më hollësisht më poshtë ndërsa paraqitet materiali.

Nisja e një VK demo

Detyra:
  1. Mblidhni një komponent të jashtëm të furnizuar me një abonim ITS dhe synon të demonstrojë aftësitë kryesore të mekanizmit të komponentit të jashtëm në 1C
  2. Lidhni komponentin demo me konfigurimin 1C
  3. Sigurohuni që funksionet e deklaruara të funksionojnë saktë
Përmbledhje
Demoja VK ndodhet në diskun e abonimit ITS në drejtorinë "/VNCOMP82/shembull/NativeAPI".
Për të ndërtuar VC-në demo, ne do të përdorim Microsoft Visual Studio 2008. Versionet e tjera të këtij produkti nuk e mbështesin formatin e projektit Visual Studio të përdorur.


Hapni projektin AddInNative. Në cilësimet e projektit, ne përfshijmë direktorinë me skedarët e titullit të nevojshëm për të ndërtuar projektin. Si parazgjedhje, ato janë të vendosura në diskun ITS në drejtori /VNCOMP82/përfshi.
Rezultati i ndërtimit është skedari /bind/AddInNative.dll. Kjo është biblioteka e përpiluar për t'u lidhur me konfigurimin 1C.
Lidhja e konfigurimit VK me 1C
Le të krijojmë një konfigurim bosh 1C.
Më poshtë është kodi për modulin e aplikacionit të menaxhuar.
ndryshore DemoComp; Procedura kur fillon sistemi () Lidhni komponentin e jashtëm ("...\bind\AddInNative.dll", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.AddInNativeExtension"); Fundi i procedurës
Nëse nuk u raportua asnjë gabim gjatë fillimit të konfigurimit 1C, atëherë VK u lidh me sukses.
Si rezultat i ekzekutimit të kodit të mësipërm, një objekt shfaqet në dukshmërinë globale të konfigurimit DemoComp, i cili ka veti dhe metoda që përcaktohen në kodin e komponentit të jashtëm.
Demonstrimi i funksionalitetit të integruar
Le të kontrollojmë funksionalitetin e demo VK. Për ta bërë këtë, le të përpiqemi të vendosim dhe lexojmë disa veti, të thërrasim disa metoda VK dhe gjithashtu të marrim dhe përpunojmë mesazhin VK.
Dokumentacioni i dhënë në diskun ITS deklaron funksionalitetin e mëposhtëm të VC-së demo:
  1. Menaxhimi i gjendjes së objektit të komponentit
    Metodat: Ndez, Fikeni
    Vetitë: Të përfshira
  2. Menaxhimi i kohëmatësit
    Çdo sekondë komponenti dërgon një mesazh në sistemin 1C: Enterprise me parametra Komponenti, Timer dhe një linjë numëruesi të orës së sistemit.
    Metodat: StartTimer, StopTimer
    Vetitë: Ka një kohëmatës
  3. Metoda ShowInStatusLine, i cili shfaq tekstin e kaluar në metodë si parametra në shiritin e statusit
  4. Metoda NgarkoFoto. Ngarkon një imazh nga skedari i specifikuar dhe e transferon atë në sistemin 1C: Enterprise në formën e të dhënave binare.
Le të sigurohemi që këto funksione të funksionojnë. Për ta bërë këtë, ekzekutoni kodin e mëposhtëm:
ndryshore DemoComp; Procedura kur fillon sistemi() ConnectExternalComponent(...); DemoComp = I ri ("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Raporti (DemoComp.Enabled); DemoComp.Enable(); Raporti (DemoComp.Enabled); DemoComp.StartTimer(); Procedura e përfundimit të procedurës Përpunimi i ngjarjeve të jashtme (Burimi, Ngjarja, të Dhënat) Raporti (Burimi + " " + Ngjarja + " " + Të dhënat); Fundi i procedurës
Rezultati i ekzekutimit të konfigurimit tregohet në imazh


Paneli "Mesazhet" shfaq rezultatet e thirrjeve të metodës DemoComp.Disable() Dhe Demo.Comp.Enable(). Rreshtat pasues në të njëjtin panel përmbajnë rezultatet e përpunimit të mesazheve të marra nga VK - Burimi, Ngjarje Dhe Të dhënat përkatësisht.

Emri i personalizuar i komponentit të jashtëm

Detyrë: Ndryshoni emrin e komponentit të jashtëm në një arbitrar.
Seksioni i mëparshëm përdori identifikuesin AddInNativeExtension, kuptimi i të cilit nuk u shpjegua. Në këtë rast AddInNativeExtension- ky është emri i shtesës.
Kodi VK përcakton një metodë Register ExtensionAs, duke e kthyer emrin në sistemin 1C: Enterprise, i cili është i nevojshëm për regjistrimin e mëvonshëm të VK në sistem. Rekomandohet të specifikoni një identifikues që zbulon në një farë mase thelbin e komponentit të jashtëm.
Këtu është kodi i plotë i metodës Register ExtensionAs me emrin shtesë të ndryshuar:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* (wsExtension) + 1; ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, wsExtension, iActualSize); kthe e vërtetë; ) kthe false; )
Në shembullin e dhënë, emri VK është ndryshuar në Dikush Emri. Pastaj kur lidhni VK, duhet të specifikoni një emër të ri:
DemoComp = I ri ("AddIn.DemoVK.SomeName");

Zgjerimi i listës së pronave VK

Detyra:
  1. Studioni zbatimin e vetive VK
  2. Shtoni një veçori leximi/shkrimi të llojit të vargut
  3. Shtoni një veçori të vargut të leximit/shkrimit që ruan llojin e të dhënave të grupit të fundit të vetive. Asnjë veprim nuk ndërmerret gjatë vendosjes së vlerës së pronës

Për të përcaktuar vetitë e komponentit që krijohet, zhvilluesi duhet të zbatojë metodat e mëposhtme në kodin e bibliotekës AddInNative.cpp:
GetNProps
Rikthen numrin e vetive të kësaj shtese, 0 nëse nuk ka veçori
FindProp
Kthen numrin serial të pronës, emri i së cilës kalohet në parametrat
GetPropName
Kthen emrin e pronës me numrin e saj serial dhe me identifikuesin e gjuhës së kaluar
GetPropVal
Kthen vlerën e pronës me numrin rendor të specifikuar
SetPropVal
Vendos vlerën e pronës me numrin rendor të specifikuar
IsPropReadable
Kthen flamurin e lexueshmërisë së pronës me numrin e sekuencës së specifikuar
IsPropWritable
Kthen flamurin e shkrueshmërisë së pronës me numrin e sekuencës së specifikuar


Le të shqyrtojmë zbatimin e metodave të klasës së mësipërme CAddInNative.
Në VC-në demo, përcaktohen 2 veti: Të përfshira Dhe Ka një kohëmatës (Është Enabled Dhe IsTimerPresent).
Në shtrirjen globale të kodit të bibliotekës, përcaktohen dy vargje:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Enabled", L"Ka një kohëmatës");
të cilat ruajnë emrat e pronave ruse dhe angleze. Në skedarin e kokës AddInNative.h numërimi është përcaktuar:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Gjithmonë e fundit);
ePropIsEnabled Dhe ePropIsTimerPresent, përkatësisht që kanë vlerat 0 dhe 1, përdoren për të zëvendësuar numrat serialë të pronave me identifikues kuptimplotë. ePropLast, i cili ka vlerën 2, përdoret për të marrë numrin e vetive (duke përdorur metodën GetNProps). Këta emra përdoren vetëm brenda kodit të komponentit dhe nuk janë të disponueshëm nga jashtë.
Metodat FindProp dhe GetPropName kryejnë kërkime në grup g_PropEmrat Dhe g_PropNamesRu.
Për të ruajtur vlerat e fushave në modulin e bibliotekës, klasa CAddInNative ka veti që ruajnë vlerën e vetive të komponentit. Metodat GetPropVal Dhe SetPropVal ktheni dhe vendosni vlerën e këtyre vetive në përputhje me rrethanat.
Metodat IsPropReadable Dhe IsPropWritable dhe kthehu e vërtetë ose i rremë, në varësi të numrit rendor të kaluar të pronës në përputhje me logjikën e aplikimit.
Për të shtuar një pronë të personalizuar ju duhet:

  1. Shtoni emrin e pronës që po shtohet në vargje g_PropEmrat Dhe g_PropNamesRu(skedar AddInNative.cpp)
  2. Për të listuar Props(skedar AddInNative.h) më parë ePropLast shtoni një emër që identifikon në mënyrë unike pronën që po shtohet
  3. Organizoni memorien për ruajtjen e vlerave të vetive (krijoni fusha përbërëse të modulit që ruajnë vlerat përkatëse)
  4. Bëni ndryshime në metoda GetPropVal Dhe SetPropVal për të bashkëvepruar me memorien e alokuar në hapin e mëparshëm
  5. Në përputhje me logjikën e aplikimit, bëni ndryshime në metoda IsPropReadable Dhe IsPropWritable
Pikat 1, 2, 5 nuk kanë nevojë për shpjegim. Detajet e zbatimit të këtyre hapave mund të gjenden duke studiuar shtojcën e artikullit.
Le t'u japim emra vetive të provës Test Dhe Lloji Kontrollo përkatësisht. Pastaj, si rezultat i hapit 1, kemi:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Enabled", L"Ka një kohëmatës", L"Test", L"Kontrollimi i tipit");
Transferimi Props do të duket si:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Gjithmonë e fundit);
Për të thjeshtuar ndjeshëm kodin, ne do të përdorim STL C++. Në veçanti, për të punuar me vargje WCHAR, le të lidhim bibliotekën string.
Për të ruajtur një vlerë të metodës Test, përcaktojmë në klasë CAddInNative në fushën e një fushe private:
testi i vargut1;
Për të transferuar parametrat e vargut midis 1C: Enterprise dhe komponentëve të jashtëm, përdoret menaxheri i kujtesës 1C: Enterprise. Le të hedhim një vështrim më të afërt në punën e tij. Funksionet përdoren për ndarjen dhe lirimin e memories përkatësisht AllocMemory Dhe Memoria e Lirë të përcaktuara në dosje ImemoryManager.h. Nëse është e nevojshme të kaloni një parametër të vargut në sistemin 1C: Enterprise, komponenti i jashtëm duhet të ndajë memorie për të duke thirrur funksionin AllocMemory. Prototipi i tij duket si ky:
virtual bool ADDIN_API AllocMemory (void** pMemory, ulCountByte e gjatë e panënshkruar) = 0;
Ku pKujtesa- adresa e treguesit në të cilin do të vendoset adresa e zonës së caktuar të memories,
ulCountByte- madhësia e zonës së caktuar të memories.
Një shembull i alokimit të memories për një varg:
WCHAR_T *t1 = NULL, *test = L"TEST_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize);
Për lehtësinë e punës me llojet e të dhënave të vargut, ne do të përshkruajmë funksionin wstring_to_p. Ai merr një varg wstring si parametër. Rezultati i funksionit është një strukturë e mbushur tVariant. Kodi i funksionit:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) (char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (rr. gjatësia ()+1) madhësia e(WCHAR_T));memcpy(t1, str.c_str(), (str.gjatësia()+1) * madhësia(WCHAR_T));val -> pstrVal = t1; val -> strLen = str.gjatësia(); kthehu i vërtetë;)
Pastaj seksioni përkatës i rastit të deklaratës switch të metodës GetPropVal do të marrë formën:
rasti ePropTest1: wstring_to_p(test1, pvarPropVal); pushim;
Metoda SetPropVal:
rasti ePropTest1: nëse (TV_VT(varPropVal) != VTYPE_PWSTR) kthen false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); pushim;
Për të zbatuar vetinë e dytë, ne përcaktojmë një fushë të klasës CaddInNative
uint8_t lloji i fundit;
në të cilin do të ruajmë llojin e vlerës së fundit të transferuar. Për ta bërë këtë, shtoni komandën në metodën CaddInNative::SetPropVal:
Lloji_i fundit = TV_VT(varPropVal);
Tani, kur kërkojmë të lexojmë vlerën e pronës së dytë, ne do ta kthejmë vlerën lloji i fundit, çfarë kërkon detyra e caktuar.
Le të kontrollojmë funksionalitetin e ndryshimeve të bëra.
Për ta bërë këtë, le të paraqesim pamjen e konfigurimit 1C si më poshtë:
ndryshore DemoComp; Procedura Kur Sistemi Fillon() Lidh Komponentin e Jashtëm("...", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Raporti(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Raporti(String(DemoComp.Test)); DemoComp.Test = "Petya"; Raporti(String(DemoComp.Test)); Raporti(String(DemoComp.TypeCheck)); Fundi i procedurës
Si rezultat i nisjes, ne do të marrim një sekuencë mesazhesh:
3
Vasya
Pjetri
22

Mesazhi i dytë dhe i tretë janë rezultat i leximit të vetive të vendosura në hapin e mëparshëm. Mesazhi i parë dhe i dytë përmbajnë kodin e tipit të grupit të fundit të vetive. 3 korrespondon me një vlerë të plotë, 22 me një vlerë vargu. Në dosje vendoset korrespondenca e llojeve dhe kodeve të tyre llojet.h, i cili ndodhet në diskun e ITS.

Zgjerimi i listës së metodave

Detyra:
  1. Zgjeroni funksionalitetin e komponentit të jashtëm me funksionalitetin e mëposhtëm:
  2. Eksploroni mënyra për të zbatuar metodat e komponentëve të jashtëm
  3. Shtoni një metodë funksioni Funksioni 1, i cili merr dy vargje (“Parameter1” dhe “Parameter2”) si parametër. Rezultati është një varg si: “Kontrollo. Parametri 1, Parametri 2"
  4. Sigurohuni që ndryshimet që bëni të funksionojnë.

Për të përcaktuar metodat e komponentit që krijohet, zhvilluesi duhet të zbatojë metodat e mëposhtme në kodin e bibliotekës AddInNative:
GetNMethods, FindMethod, GetMethodName
Projektuar për të marrë numrin përkatës të metodave, kërkoni numrin dhe emrin e metodës. Ngjashëm me metodat përkatëse për vetitë
GetNParams
Rikthen numrin e parametrave të metodës me numrin e sekuencës së specifikuar; nëse një metodë me këtë numër mungon ose nuk ka parametra, kthen 0
GetParamDefValue
Kthen vlerën e paracaktuar të parametrit të specifikuar të metodës së specifikuar
HasRetVal
Kthen flamurin nëse metoda me vlerën e specifikuar të kthimit ka një vlerë kthyese: e vërtetë për metodat me një vlerë kthyese dhe i rremë ndryshe
CallAsProc
i rremë, ndodh një gabim në kohën e ekzekutimit dhe ekzekutimi i modulit 1C: Enterprise përfundon. Kujtesa për grupin e parametrave ndahet dhe lëshohet nga 1C: Enterprise.
CallAsFunc
Ekzekuton metodën me numrin e sekuencës së specifikuar. Nëse metoda kthehet i rremë, ndodh një gabim në kohën e ekzekutimit dhe ekzekutimi i modulit 1C: Enterprise përfundon. Kujtesa për grupin e parametrave ndahet nga 1C: Enterprise. Nëse vlera e kthyer është një varg ose tip i të dhënave binar, komponenti alokon memorie me funksionin AllocMemory menaxheri i memories, shkruan aty të dhënat dhe e ruan këtë adresë në fushën përkatëse të strukturës. 1C: Ndërmarrja do ta çlirojë këtë memorie duke telefonuar Memoria e Lirë.
Një përshkrim i plotë i metodave, duke përfshirë një listë të parametrave, përshkruhet në detaje në dokumentacionin e dhënë në diskun ITS.
Le të shqyrtojmë zbatimin e metodave të përshkruara më sipër.
Në kodin e komponentit, përcaktohen dy vargje:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
dhe numërimi:
enum Metodat (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Gjithmonë e fundit );
Ato përdoren në funksione GetNMethods, FindMethod Dhe GetMethodName, në analogji me përshkrimin e vetive.
Metodat GetNParams, GetParamDefValue, HasRetVal ndërprerësi i implementimit, në varësi të parametrave të kaluar dhe logjikës së aplikimit, ktheni vlerën e kërkuar. Metoda HasRetVal në kodin e tij ai ka një listë të metodave të vetme që mund të kthejnë një rezultat. Për ta ai kthehet e vërtetë. Për të gjitha metodat e çelikut kthimet i rremë.
Metodat CallAsProc Dhe CallAsFunc përmbajnë kodin direkt të ekzekutueshëm të metodës.
Për të shtuar një metodë që mund të thirret vetëm si funksion, duhet të bëni ndryshimet e mëposhtme në kodin burimor të komponentit të jashtëm:
  1. Shtoni emrin e metodës në vargje g_Emrat e metodave Dhe g_Emrat e metodësRu(skedar AddInNative.cpp)
  2. Shtoni një identifikues kuptimplotë të metodës në numërimin e metodave (skedari AddInNative.h)
  3. Bëni ndryshime në kodin e funksionit GetNParams sipas logjikës së programit
  4. Nëse është e nevojshme, bëni ndryshime në kodin e metodës GetParamDefValue, nëse dëshironi të përdorni vlerat e paracaktuara të parametrave të metodës.
  5. Bëni ndryshime në funksion HasRetVal
  6. Bëni ndryshime në logjikën e funksioneve CallAsProc ose CallAsFunc, duke vendosur kodin direkt të ekzekutueshëm të metodës atje
Le të paraqesim vargjet g_Emrat e metodave Dhe g_Emrat e metodësRu, si dhe listimi Metodat në formën:
static wchar_t *g_MethodNames = (L"Aktivizo", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Metodat Enum (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Gjithmonë e fundit );
Le të modifikojmë funksionin GetNProps në mënyrë që të kthejë numrin e parametrave të metodës "Test":
i gjatë CAddInNative::GetNParams(konst long lMethodNum) ( switch(lMethodNum) (rasti eMethShowInStatusLine: kthen 1; rasti eMethLoadPicture: kthen 1; rasti eMethTest: kthen 2; parazgjedhje: kthen 0; ) kthen 0; )
Le të bëjmë ndryshime në funksion:
bool CAddInNative::GetParamDefValue(konst i gjatë lMethodNum, konst i gjatë lParamNum, tVariant *pvarParamDefValue) (TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) (Numri i metodës në rast: në rast të rastit:L rasti i rastit e meth) MethStartTimer: rasti eMethStopTimer: rasti eMethTest : / / Nuk ka vlera parametrash sipas parazgjedhjes; default: kthe false; ) kthe false; )
Falë linjës së shtuar
rasti eMethTest:
nëse një ose më shumë argumente mungojnë, parametrat përkatës do të kenë një vlerë boshe ( VTYPE_EMPTY). Nëse keni nevojë për një vlerë të paracaktuar për një parametër, duhet ta vendosni atë në seksion eMethTest deklarata e ndërruesit të funksionit CAddInNative::GetParamDefValue.
Meqenëse metoda e Testit mund të kthejë një vlerë, duhet të bëni ndryshime në kodin e funksionit HasRetVal:
bool CAddInNative::HasRetVal(konst long lMethodNum) ( switch(lMethodNum) (rasti eMethLoadPicture: rasti eMethTest: kthen true; default: kthen false; ) kthen false; )
Dhe shtoni kodin e ekzekutueshëm të metodës në funksion CallAsFunc:
bool CAddInNative::CallAsFunc(konst long lMethodNum, tVariant* pvarRetValue, tVariant* paparams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) (rasti eMethLoadT;P nëse (!lSizeArray || !paParams) kthen false; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstrVal; wstring_to_p(std::wstring(s1+s2), pvarRetValue); ret = true ; pushim; ) kthim ret;)
Le të përpilojmë komponentin dhe të sjellim kodin e konfigurimit në formën:
ndryshore DemoComp; Procedura Kur Sistemi Fillon() Lidh Komponentin e Jashtëm("...", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.SomeName"); korsi = DemoComp.Test ("Përshëndetje", "Botë!"); Raporti (për); Fundi i procedurës
Pas nisjes së konfigurimit, do të marrim mesazhin: "Përshëndetje, Botë!", që tregon se metoda funksionoi me sukses.

Timer

Detyra:
  1. Studioni zbatimin e kohëmatësit në demo VK
  2. Modifikoni metodën "StartTimer" duke shtuar aftësinë për të kaluar në parametra intervalin e përgjigjes së kohëmatësit (në milisekonda)
  3. Sigurohuni që ndryshimet që bëni të funksionojnë.

Në WinAPI, ju mund të përdorni mesazhin për të punuar me kohën WM_TIMER. Ky mesazh do t'i dërgohet programit tuaj në intervalin kohor që keni vendosur kur krijoni kohëmatësin.
Për të krijuar një kohëmatës, përdorni funksionin SetTimer:
UINT SetTimer(HWND hWnd, // përshkruesi i dritares UINT nIDevent, // identifikuesi i kohëmatësit (numri) UINT nElapse, // vonesa TIMERPROC lpTimerFunc); // tregues për të funksionuar
Sistemi operativ do të dërgojë një mesazh WM_TIMER në program me intervalin e specifikuar në argument nKalimi(në milisekonda). Në parametrin e fundit mund të specifikoni një funksion që do të ekzekutohet sa herë që ndizet kohëmatësi. Kreu i këtij funksioni duhet të duket kështu (emri mund të jetë çdo gjë):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Le të shqyrtojmë zbatimin e një kohëmatës në demo VC.
Meqenëse po shqyrtojmë procesin e zhvillimit të një komponenti të jashtëm për familjen Windows OS, nuk do të shqyrtojmë zbatimin e kohëmatësit në sistemet e tjera operative. Për GNU/Linux OS, në veçanti, zbatimi do të ndryshojë në sintaksën e funksionit SetTimer Dhe TimerProc.
Kodi i ekzekutueshëm thërret metodën SetTimer, të cilit i kalon funksioni MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
ID-ja e kohëmatësit të krijuar vendoset në një variabël m_uiTimer në mënyrë që të mund të çaktivizohet më vonë.
Funksioni MyTimerProc si në vazhdim:
BANKËSHTJA E Thirrjes VOID MyTimerProc(HWND hwnd, // doreza e dritares për mesazhet e kohëmatësit UINT uMsg, // mesazhi WM_TIMER UINT idEvent, // identifikuesi i kohëmatësit DWORD dwTime // koha aktuale e sistemit) ( nëse (!pAsyncEvent) *who = wchar "ComponentNative", *what = L"Timer"; wchar_t *wstime = new wchar_t; if (wstime) ( wmemset(wstime, 0, TIME_LEN); ::_ultow(dwTime, wstime, 10); pAsyncEvent->ExternalEvent(who , çfarë, wstime); fshi wstime; ))
Thelbi i funksionit është se thirret metoda Ngjarje e jashtme, i cili dërgon një mesazh në sistemin 1C: Enterprise.
Për të zgjeruar funksionalitetin e metodës StartTimer Le të bëjmë sa vijon:
Modifikimi i kodit të metodës GetNParams në mënyrë që të jetë për metodën eMethStartTimer vlera e kthyer 1:
rasti eMethStartTimer: kthimi 1;
Këtu është kodi i metodës CallAsProc në formën:
rasti eMethStartTimer: nëse (!lSizeArray || TV_VT(paParams) != VTYPE_I4 || TV_I4(paParams)<= 0) return false; pAsyncEvent = m_iConnect; #ifndef __linux__ m_uiTimer = ::SetTimer(NULL,0,TV_I4(paParams),(TIMERPROC)MyTimerProc); #else // код для GNU/Linux #endif break;
Tani le të kontrollojmë funksionalitetin. Për ta bërë këtë, ne do të shkruajmë kodin në modulin e aplikacionit të menaxhuar të konfigurimit:
ndryshore DemoComp; Procedura Kur Sistemi Fillon() Lidh Komponentin e Jashtëm("...", "DemoVK", Lloji i Komponentit të Jashtëm.Native); DemoComp = I ri ("AddIn.DemoVK.SomeName"); DemoComp.StartTimer (2000); Fundi i procedurës
Pas fillimit të konfigurimit, programi do të marrë mesazhe në intervale prej 2 sekondash, gjë që tregon se kohëmatësi po funksionon siç duhet.

Ndërveprimi me sistemin 1C: Enterprise

Për të bashkëvepruar midis komponentit të jashtëm dhe sistemit 1C: Enterprise, metodat e klasës IAddInDefBase, të përshkruara në skedar AddInDefBase.h. Ne rendisim ato më të përdorurat:
Gjenerimi i një mesazhi gabimi
virtual bool ADDIN_API AddError (kodi i shkurtër i panënshkruar, burimi konst WCHAR_T*, përshkrimi WCHAR_T* konst, kodi i gjatë)
wcode, kodi- kodet e gabimit (një listë e kodeve të gabimit me përshkrime mund të gjendet në diskun ITS)
burimi- burimi i gabimit
përshkruaj- përshkrimi i gabimit
Dërgimi i një mesazhi në sistemin 1C: Enterprise
virtual bool ADDIN_API Ngjarje e jashtme (WCHAR_T* wszBurimi, WCHAR_T* wszMesazh, WCHAR_T* wszData) = 0;
wszBurimi- burimi i mesazhit
wszMesazhi- Teksti i mesazhit
wszTë dhënat- të dhënat e transmetuara
Përgjimi i mesazheve kryhet nga procedura e Përpunimit të Ngjarjeve të Jashtme
Regjistrimi i një komponenti të jashtëm në sistemin 1C: Enterprise
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszEmri i profilit- emri i komponentit.
Këto metoda janë të mjaftueshme për ndërveprim të plotë midis VK dhe 1C. Për të marrë të dhëna nga një komponent i jashtëm nga sistemi 1C: Enterprise dhe anasjelltas, komponenti i jashtëm dërgon një mesazh të veçantë, i cili nga ana tjetër kapet nga sistemi 1C dhe, nëse është e nevojshme, thërret metodat e komponentit të jashtëm për të transmetuar të dhënat prapa. .

Lloji i të dhënave tVariant

Kur shkëmbeni të dhëna midis komponentit të jashtëm dhe sistemit 1C: Enterprise, përdoret lloji i të dhënave tVariant. Ai përshkruhet në skedarin type.h, i cili mund të gjendet në diskun ITS:
struct _tVariant ( _ANONYMOUS_UNION union ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; i panënshkruar int uintVal; int64_t llVal; uint8_t ui8Val; uint16_t ui8Valt; uint32_t lVal; int intVal; i panënshkruar int uintVal; int64_t llVal; uint8_t ui8Val; uint32Vintalt; ; int32_t errCode; hRes të gjata; float fltVal; dyfishtë dblVal; bool bVal; char chVal; wchar_t wchVal; DATE data; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; _ANONYMOUS_STRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NAMEY_2/UST int3 2_t strLen ; //numri i bajteve ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //numërimi i simboleve ) __VARIANT_NAME_4/*wstr*/; ) _2_VARIANT_NAME_4/*wstr*/; ) _2_VARIANT;) _2_VARIAN; - grupi dimensional në pvarVal TYPEVAR vt; );
Lloji tVariantështë një strukturë që përfshin:
  • përzierje (bashkim) i destinuar drejtpërdrejt për ruajtjen e të dhënave
  • identifikues i llojit të të dhënave
Në përgjithësi, puna me variabla të llojit tVariant ndodh sipas algoritmit të mëposhtëm:
  1. Përcaktimi i llojit të të dhënave të ruajtura aktualisht në një variabël
  2. Hyni në fushën përkatëse të përzierjes për të hyrë drejtpërdrejt në të dhënat
Duke përdorur llojin tVariant thjeshton ndjeshëm ndërveprimin e sistemit 1C: Enterprise dhe komponentëve të jashtëm

Aplikacion

Drejtoria "shembuj" përmban shembuj për artikullin
shembuj/1 - nisni komponentin demo
shembuj/2 - demonstrim i zgjerimit të listës pronësore
shembuj/3 - demonstrim i zgjerimit të listës së metodave
Çdo direktori përmban një projekt VS 2008 dhe një konfigurim të gatshëm 1C.

Ky artikull i kushtohet punës me komponentë të jashtëm, përkatësisht lidhjen e tyre. Për momentin, për të zgjeruar aftësitë e 1C Enterprise, përdoren dy teknologji të përbërësve të jashtëm:

  • 1 Duke përdorur API-në vendase
  • 2 Përdorimi i teknologjisë COM
Në këtë artikull, vendosa të theksoj punën me komponentët Native API.
Pra, le të fillojmë, nga e thjeshta në komplekse:
Fragment nga ITS

1. Le të themi se VK-ja jonë ndodhet në një drejtori specifike në disk:

Mund të përdoret në "Thick Client (aplikacion i rregullt)";

Ky është shembulli më i thjeshtë i punës me komponentin Native. Ju lutemi vini re se ky lloj komponenti nuk kërkon regjistrim në sistem, gjë që thjeshton shumë administrimin.

2. Shembulli i diskutuar më sipër nuk është aspak realist. Më shpesh, komponenti vendoset në një plan urbanistik. Paraqitja duhet të përmbajë një arkiv zip me skedarë përbërës dhe një skedar MANIFEST.xml
Shembull i skedarit të manifestit:

3. Kur punoni në një klient të hollë dhe në internet, sigurohuni që të përdorni metodën.
Citim nga ITS:

Shpjegim:
%APPDATA%\1C\1Cv82\ExtCompT- direktori për instalimin e komponentëve për klientët e trashë dhe të hollë.
%APPDATA%\Roaming\Mozilla\Extensions- shtesat e drejtorisë (në rastin tim) për Mozilla FF/
Kur përdorni metodën SetExternalComponent(), në varësi të klientit të përdorur, shtesat do të shpaketohen në drejtorinë e duhur.

Një shembull i procedurës së instalimit të komponentit të jashtëm:

InstallExternalComponent- metoda duhet të thirret vetëm gjatë instalimit fillestar të komponentit dhe në rastin kur është e nevojshme të përditësohet versioni i instaluar i komponentit.

Në rastin e klientëve të hollë dhe të trashë:
Mjafton të riekzekutoni funksionimin e instalimit të komponentit të jashtëm duke përdorur metodën InstallExternalComponent().

Në rastin e një klienti në internet për të përditësuar një komponent:

  • Është e nevojshme të hiqni shtojcën përmes mekanizmit të punës me shtesat e shfletuesit të internetit (Mozilla FF)
  • Përdorni metodën InstallExternalComponent
Për të lidhur një VK, mund të përdorni procedurën e mëposhtme:

Nëse komponenti nuk është instaluar, do të bëhet një përjashtim.

2. Ka raste kur një komponent duhet të instalohet nga ruajtja e përkohshme (skedari është marrë nga një burim i palës së tretë, përpunim i jashtëm), në këtë rast, parametrat e parë në metodat Connect External Component dhe Install External Component janë adresa e arkivit në ruajtje të përkohshme. Më poshtë është një shembull i mundshëm se si funksionon:

&OnClient VariableAddressArchiveComponent; Komponenti i ndryshueshëm &OnClient; &OnClient Procedura OnOpen(Dështim) // adresa, përmban një varg (lidhje navigimi me të dhënat binare të arkivit zip në // ruajtjen e përkohshme) ComponentArchiveAddress = GetArchiveAddressInTemporaryStorage(); EndProcedure // WhenOpen() &OnServer // metodat ConnectExternalComponent, SetExternalComponent mund të marrë si // si parametër të parë një varg në formatin "navigation link" // (URL në një komponent të jashtëm të paketuar në një arkiv ZIP, në një format të ngjashëm me // GetNavigationLink). Funksioni GetArchiveAddressInTemporaryStorage()ProcessingObject = FormAttributesValue("ProcessingObject"); Lidhja e arkivit = PlaceInTemporaryStorage(ProcessingObject.GetLayout("MIKO_phone_IP"), Identifikuesi i ri unik); ReturnLinkToArchive; EndFunction // GetArchiveAddressInTemporaryStorage() &OnClient // Procedura duhet të thirret vetëm një herë, nëse komponenti nuk është instaluar ende // ose duhet të përditësohet Procedura InstallComponent(Command) Përpjekje për të InstallExternalComponent(ArchiveComponentAddress); Raporti i përjashtimit ("Instalimi i komponentit të jashtëm dështoi."); Përpjekja e Fundit; Fundi i procedurës // InstallComponent() &OnClient // Procedura kryesore për inicializimin e një komponenti. Komponenti = I ri ("AddIn.Comp.MIKO_phone_IP"); Raporti i përjashtimit ("Përjashtimi i fillimit. Komponenti mund të mos jetë instaluar ende."); Përpjekja e Fundit; Fundi i procedurës