การเขียนส่วนประกอบดั้งเดิม 1c บน c เทคโนโลยีส่วนประกอบภายนอก () ส่วนประกอบภายนอก "1C: องค์กร"

อันสเมียร์นอฟ 22 สิงหาคม 2556 เวลา 14:12 น

ส่วนประกอบภายนอกใน 1C 8.2

  • การเขียนโปรแกรม,
  • ซี++
  • บทช่วยสอน

การแนะนำ

บทความนี้ให้แนวคิดเกี่ยวกับการทำงานของส่วนประกอบภายนอกในระบบ 1C: Enterprise
กระบวนการพัฒนาส่วนประกอบภายนอกสำหรับ 1C: ระบบ Enterprise เวอร์ชัน 8.2 ที่ทำงานภายใต้ Windows OS พร้อมโหมดการทำงานไฟล์จะปรากฏขึ้น ตัวเลือกนี้ใช้ในโซลูชันส่วนใหญ่ที่ออกแบบมาสำหรับธุรกิจขนาดเล็ก VK จะถูกนำไปใช้ในภาษาการเขียนโปรแกรม C++

ส่วนประกอบภายนอก "1C: องค์กร"

"1C: Enterprise" เป็นระบบที่ขยายได้ เพื่อขยายฟังก์ชันการทำงานของระบบ จึงมีการใช้ส่วนประกอบภายนอก (EC) จากมุมมองของนักพัฒนา VC เป็นวัตถุภายนอกที่มีคุณสมบัติและวิธีการ และยังสามารถสร้างเหตุการณ์สำหรับการประมวลผลโดยระบบ 1C: Enterprise
ส่วนประกอบภายนอกสามารถใช้เพื่อแก้ไขปัญหาระดับหนึ่งที่ยากหรือเป็นไปไม่ได้เลยที่จะนำไปใช้ในภาษาการเขียนโปรแกรมที่สร้างใน 1C: Enterprise โดยเฉพาะอย่างยิ่ง คลาสนี้ประกอบด้วยงานที่ต้องมีการโต้ตอบระดับต่ำกับระบบปฏิบัติการ เช่น เพื่อทำงานกับอุปกรณ์เฉพาะ
1C: ระบบองค์กรใช้เทคโนโลยีสองอย่างในการสร้างส่วนประกอบภายนอก:
  • โดยใช้ Native API
  • โดยใช้เทคโนโลยีคอม
ด้วยข้อจำกัดที่กำหนด ความแตกต่างระหว่างเทคโนโลยีทั้งสองที่กล่าวมาข้างต้นจึงไม่มีนัยสำคัญ ดังนั้นเราจะพิจารณาการพัฒนาวิดีโอเกมโดยใช้ Native API หากจำเป็น การพัฒนาที่นำไปใช้สามารถนำไปใช้กับการพัฒนาซอฟต์แวร์คอมพิวเตอร์โดยใช้เทคโนโลยี COM และยังมีการปรับเปลี่ยนเล็กน้อยเพื่อใช้ในระบบ 1C: Enterprise พร้อมตัวเลือกการทำงานอื่น ๆ นอกเหนือจากโหมดการทำงานของไฟล์
โครงสร้างวีเค
ส่วนประกอบภายนอกของระบบ 1C: Enterprise นำเสนอในรูปแบบของไลบรารี DLL รหัสไลบรารีอธิบายคลาสสืบทอด IComponentBase คลาสที่สร้างขึ้นจะต้องกำหนดวิธีการที่รับผิดชอบในการใช้งานฟังก์ชันของส่วนประกอบภายนอก วิธีการแทนที่จะมีการอธิบายโดยละเอียดด้านล่างเมื่อมีการนำเสนอเนื้อหา

เปิดตัวการสาธิต VK

งาน:
  1. ประกอบส่วนประกอบภายนอกที่มาพร้อมกับการสมัครสมาชิก ITS และมีวัตถุประสงค์เพื่อแสดงความสามารถหลักของกลไกส่วนประกอบภายนอกใน 1C
  2. เชื่อมต่อส่วนประกอบสาธิตกับการกำหนดค่า 1C
  3. ตรวจสอบให้แน่ใจว่าฟังก์ชันที่ประกาศไว้ทำงานอย่างถูกต้อง
การรวบรวม
VK สาธิตอยู่ในดิสก์การสมัครสมาชิก ITS ในไดเร็กทอรี “/VNCOPP82/example/NativeAPI”
ในการสร้าง VC สาธิต เราจะใช้ Microsoft Visual Studio 2008 เวอร์ชันอื่นของผลิตภัณฑ์นี้ไม่รองรับรูปแบบโครงการ Visual Studio ที่ใช้


เปิดโครงการ AddInNative ในการตั้งค่าโปรเจ็กต์ เราจะรวมไดเร็กทอรีพร้อมกับไฟล์ส่วนหัวที่จำเป็นในการสร้างโปรเจ็กต์ โดยค่าเริ่มต้น จะอยู่บนดิสก์ ITS ในไดเร็กทอรี /VNCOP82/รวม.
ผลลัพธ์ของบิลด์คือไฟล์ /bind/AddInNative.dll- นี่คือไลบรารีที่คอมไพล์สำหรับเชื่อมต่อกับการกำหนดค่า 1C
การเชื่อมต่อการกำหนดค่า VK กับ 1C
มาสร้างการกำหนดค่า 1C ที่ว่างเปล่ากัน
ด้านล่างนี้คือโค้ดสำหรับโมดูลแอปพลิเคชันที่ได้รับการจัดการ
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...\bind\AddInNative.dll", "DemoVK", ส่วนประกอบภายนอก Type.Native);
DemoComp = ใหม่ ("AddIn.DemoVK.AddInNativeExtension"); สิ้นสุดขั้นตอน
หากไม่มีรายงานข้อผิดพลาดเมื่อเริ่มการกำหนดค่า 1C แสดงว่าเชื่อมต่อ VK ได้สำเร็จ อันเป็นผลมาจากการรันโค้ดข้างต้น ออบเจ็กต์จะปรากฏขึ้นในการมองเห็นการกำหนดค่าทั่วโลกเดโมคอม
ซึ่งมีคุณสมบัติและเมธอดที่กำหนดไว้ในโค้ดของส่วนประกอบภายนอก
การสาธิตฟังก์ชันการทำงานในตัว
เรามาตรวจสอบการทำงานของการสาธิต VK กัน ในการดำเนินการนี้ ให้ลองตั้งค่าและอ่านคุณสมบัติบางอย่าง เรียกใช้วิธี VK บางอย่าง รวมถึงรับและประมวลผลข้อความ VK ด้วย
  1. เอกสารประกอบที่ให้มาบนดิสก์ ITS ระบุฟังก์ชันการทำงานของ VC สาธิตต่อไปนี้:
    การจัดการสถานะวัตถุส่วนประกอบ วิธีการ:, เปิดเครื่อง
    ปิดเครื่อง คุณสมบัติ:
  2. เปิดใช้งานแล้ว
    การจัดการตัวจับเวลา ทุกวินาทีส่วนประกอบจะส่งข้อความไปยังระบบ 1C: Enterprise พร้อมพารามิเตอร์, ส่วนประกอบตัวจับเวลา
    การจัดการสถานะวัตถุส่วนประกอบ และสายนับนาฬิกาของระบบ, เริ่มจับเวลา
    ปิดเครื่อง ตัวจับเวลา
  3. มีตัวจับเวลา วิธี ShowInStatusLine
  4. มีตัวจับเวลา ซึ่งจะแสดงข้อความที่ส่งไปยังเมธอดเป็นพารามิเตอร์ในบรรทัดสถานะอัพโหลดรูปภาพ
- โหลดรูปภาพจากไฟล์ที่ระบุและถ่ายโอนไปยังระบบ 1C: Enterprise ในรูปแบบของข้อมูลไบนารี
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() ConnectExternalComponent(...);
DemoComp = ใหม่ ("AddIn.DemoVK.AddInNativeExtension");


สาธิตคอม.ปิดการใช้งาน(); รายงาน (DemoComp.Enabled);สาธิตคอม.เปิดใช้งาน(); รายงาน (DemoComp.Enabled); DemoComp.StartTimer(); สิ้นสุดขั้นตอน ขั้นตอน การประมวลผลเหตุการณ์ภายนอก (แหล่งที่มา เหตุการณ์ ข้อมูล) รายงาน (แหล่งที่มา + " " + เหตุการณ์ + " " + ข้อมูล); สิ้นสุดขั้นตอน ผลลัพธ์ของการรันการกำหนดค่าจะแสดงในภาพ, แผง "ข้อความ" จะแสดงผลลัพธ์ของการเรียกเมธอดสาธิตคอม.เปิดใช้งาน(); DemoComp.ปิดการใช้งาน()และ

Demo.Comp.เปิดใช้งาน()

- บรรทัดต่อมาในแผงเดียวกันประกอบด้วยผลลัพธ์การประมวลผลข้อความที่ได้รับจาก VK -
แหล่งที่มา เหตุการณ์ข้อมูล เหตุการณ์ตามลำดับ
ชื่อส่วนประกอบภายนอกที่กำหนดเอง ภารกิจ: เปลี่ยนชื่อของส่วนประกอบภายนอกเป็นชื่อที่กำหนดเองส่วนก่อนหน้านี้ใช้ตัวระบุ
AddInNativeExtension ภารกิจ: เปลี่ยนชื่อของส่วนประกอบภายนอกเป็นชื่อที่กำหนดเองซึ่งไม่ได้อธิบายความหมายไว้ ในกรณีนี้
- นี่คือชื่อของส่วนขยาย
รหัส VK กำหนดวิธีการ ลงทะเบียนส่วนขยายเป็นซึ่งส่งคืนชื่อให้กับระบบ 1C: Enterprise ซึ่งจำเป็นสำหรับการลงทะเบียน VK ในระบบในภายหลัง ขอแนะนำให้ระบุตัวระบุที่เปิดเผยสาระสำคัญของส่วนประกอบภายนอกในระดับหนึ่ง
นี่คือรหัสที่สมบูรณ์ของวิธีการ

เมื่อเปลี่ยนชื่อนามสกุลแล้ว:

บูล CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; if (m_iMemory) ( if(m_iMemory->AllocMemory ((เป็นโมฆะ**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) ส่งคืนค่าเท็จ;
  1. ในตัวอย่างที่กำหนด ชื่อ VK จะถูกเปลี่ยนเป็น
  2. ชื่อบางคน
  3. - จากนั้นเมื่อเชื่อมต่อ VK คุณต้องระบุชื่อใหม่:

DemoComp = ใหม่ ("AddIn.DemoVK.SomeName");
ขยายรายการคุณสมบัติ VK
งาน:
ศึกษาการใช้งานคุณสมบัติ VK
เพิ่มคุณสมบัติการอ่าน/เขียนประเภทสตริง
เพิ่มคุณสมบัติสตริงการอ่าน/เขียนที่เก็บชนิดข้อมูลของชุดคุณสมบัติสุดท้าย ไม่มีการดำเนินการใด ๆ เมื่อตั้งค่าคุณสมบัติ
ส่งกลับชื่อของคุณสมบัติตามหมายเลขลำดับและตามตัวระบุภาษาที่ส่งผ่าน
รับ PropVal
ส่งกลับค่าของคุณสมบัติที่มีเลขลำดับที่ระบุ
SetPropVal
ตั้งค่าของคุณสมบัติด้วยเลขลำดับที่ระบุ
เป็น PropReadable
ส่งกลับค่าสถานะความสามารถในการอ่านของคุณสมบัติที่มีหมายเลขลำดับที่ระบุ
สามารถเขียน Prop ได้
ส่งกลับค่าสถานะความสามารถในการเขียนของคุณสมบัติที่มีหมายเลขลำดับที่ระบุ


ลองพิจารณาการใช้งานวิธีการเรียนข้างต้น CAddInNative.
ในการสาธิต VC มีการกำหนดคุณสมบัติ 2 รายการ: คุณสมบัติ:สาธิตคอม.เปิดใช้งาน(); ตัวจับเวลา (เปิดใช้งานแล้วสาธิตคอม.เปิดใช้งาน(); อิสไทม์เมอร์ปัจจุบัน).
ในขอบเขตสากลของโค้ดไลบรารี จะมีการกำหนดอาร์เรย์สองตัว:
wchar_t แบบคงที่ *g_PropNames = (L "IsEnabled", L "IsTimerPresent"); wchar_t แบบคงที่ *g_PropNamesRu = (L "เปิดใช้งาน", L "มีตัวจับเวลา");
ซึ่งเก็บชื่อทรัพย์สินภาษารัสเซียและอังกฤษ ในไฟล์ส่วนหัว AddInNative.hการแจกแจงถูกกำหนดไว้:
อุปกรณ์ประกอบฉาก enum ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // เสมอ);
เปิดใช้งาน eProp แล้วสาธิตคอม.เปิดใช้งาน(); ePropIsTimerPresentตามลำดับที่มีค่า 0 และ 1 ใช้เพื่อแทนที่หมายเลขซีเรียลของคุณสมบัติด้วยตัวระบุที่มีความหมาย ePropLast ซึ่งมีค่าเป็น 2 ถูกใช้เพื่อรับจำนวนคุณสมบัติ (โดยใช้วิธี GetNProps) ชื่อเหล่านี้ใช้ภายในโค้ดส่วนประกอบเท่านั้น และไม่สามารถใช้ได้จากภายนอก
วิธีการFindPropและGetPropNameทำการค้นหาอาร์เรย์ g_PropNamesสาธิตคอม.เปิดใช้งาน(); g_PropNamesRu.
ในการจัดเก็บค่าของฟิลด์ในโมดูลไลบรารีคลาส CAddInNative มีคุณสมบัติที่เก็บค่าของคุณสมบัติส่วนประกอบ วิธีการ รับ PropValสาธิตคอม.เปิดใช้งาน(); SetPropValกลับและตั้งค่าของคุณสมบัติเหล่านี้ตามลำดับ
วิธีการ เป็น PropReadableสาธิตคอม.เปิดใช้งาน(); สามารถเขียน Prop ได้และกลับมา จริงหรือ เท็จขึ้นอยู่กับหมายเลขลำดับที่ส่งผ่านของคุณสมบัติตามตรรกะของแอปพลิเคชัน
ในการเพิ่มคุณสมบัติแบบกำหนดเอง คุณต้อง:

  1. เพิ่มชื่อของคุณสมบัติที่จะเพิ่มลงในอาร์เรย์ g_PropNamesสาธิตคอม.เปิดใช้งาน(); g_PropNamesRu(ไฟล์ AddInNative.cpp)
  2. เพื่อแสดงรายการ อุปกรณ์ประกอบฉาก(ไฟล์ AddInNative.h) ก่อน ePropLastเพิ่มชื่อที่ระบุคุณสมบัติที่กำลังเพิ่มโดยไม่ซ้ำกัน
  3. จัดระเบียบหน่วยความจำสำหรับจัดเก็บค่าคุณสมบัติ (สร้างฟิลด์ส่วนประกอบโมดูลที่เก็บค่าที่สอดคล้องกัน)
  4. ทำการเปลี่ยนแปลงวิธีการ รับ PropValสาธิตคอม.เปิดใช้งาน(); SetPropValเพื่อโต้ตอบกับหน่วยความจำที่จัดสรรไว้ในขั้นตอนก่อนหน้า
  5. ให้สอดคล้องกับตรรกะของแอปพลิเคชัน ให้ทำการเปลี่ยนแปลงวิธีการ เป็น PropReadableสาธิตคอม.เปิดใช้งาน(); สามารถเขียน Prop ได้
จุดที่ 1, 2, 5 ไม่ต้องการคำอธิบาย รายละเอียดของการดำเนินการตามขั้นตอนเหล่านี้สามารถดูได้จากการศึกษาภาคผนวกของบทความ
มาตั้งชื่อให้กับคุณสมบัติการทดสอบกัน ทดสอบสาธิตคอม.เปิดใช้งาน(); พิมพ์เช็คตามลำดับ จากขั้นตอนที่ 1 เราได้:
wchar_t แบบคงที่ *g_PropNames = (L "IsEnabled", L "IsTimerPresent", L "ทดสอบ", L "TestType"); wchar_t แบบคงที่ *g_PropNamesRu = (L "เปิดใช้งาน", L "มีตัวจับเวลา", L "ทดสอบ", L "ตรวจสอบประเภท");
โอนย้าย อุปกรณ์ประกอบฉากจะมีลักษณะดังนี้:
อุปกรณ์ประกอบฉาก enum ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // เสมอ);
เพื่อให้โค้ดง่ายขึ้นอย่างมาก เราจะใช้ STL C++ โดยเฉพาะอย่างยิ่งสำหรับการทำงานกับสตริง วชารเรามาเชื่อมต่อห้องสมุดกันเถอะ wstring.
เพื่อบันทึกค่าวิธีการ ทดสอบ, เรากำหนดไว้ในชั้นเรียน CAddInNativeในขอบเขตของเขตส่วนตัว:
สตริงทดสอบ 1;
ในการถ่ายโอนพารามิเตอร์สตริงระหว่าง 1C: Enterprise และส่วนประกอบภายนอก 1C: Enterprise memory manager จะถูกนำมาใช้ มาดูผลงานของเขากันดีกว่า ฟังก์ชันนี้ใช้เพื่อจัดสรรและเพิ่มหน่วยความจำตามลำดับ AllocMemoryสาธิตคอม.เปิดใช้งาน(); ฟรีหน่วยความจำกำหนดไว้ในไฟล์ ImemoryManager.h- หากจำเป็นต้องส่งพารามิเตอร์สตริงไปยังระบบ 1C: Enterprise ส่วนประกอบภายนอกจะต้องจัดสรรหน่วยความจำโดยการเรียกใช้ฟังก์ชัน AllocMemory- ต้นแบบของมันมีลักษณะดังนี้:
บูลเสมือน ADDIN_API AllocMemory (โมฆะ ** pMemory, ulCountByte แบบยาวที่ไม่ได้ลงนาม) = 0;
ที่ไหน pหน่วยความจำ- ที่อยู่ของตัวชี้ที่จะวางที่อยู่ของพื้นที่หน่วยความจำที่จัดสรรไว้
ulCountByte- ขนาดของพื้นที่หน่วยความจำที่จัดสรร
ตัวอย่างของการจัดสรรหน่วยความจำสำหรับสตริง:
WCHAR_T *t1 = โมฆะ, *ทดสอบ = L"TEST_STRING"; int iActualSize = wcslen(ทดสอบ1)+1; m_iMemory->AllocMemory((เป็นโมฆะ**)&t1, iActualSize * ขนาดของ(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize); ::convToShortWchar(&t1, test1, iActualSize);
เพื่อความสะดวกในการทำงานกับชนิดข้อมูลสตริง เราจะอธิบายฟังก์ชันนี้ wstring_to_p- ได้รับสตริง wstring เป็นพารามิเตอร์ ผลลัพธ์ของฟังก์ชันคือโครงสร้างที่เต็มไป tตัวแปร- รหัสฟังก์ชัน:
บูล CAddInNative::wstring_to_p(std::wstring str, tVariant* val) ( char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (str.length()+1) * ขนาดของ(WCHAR_T)); memcpy(t1, str.c_str(), (str.length()+1) * ขนาดของ(WCHAR_T)); val -> pstrVal = t1; val -> strLen = str.length(); กลับเป็นจริง)
จากนั้นส่วนกรณีที่สอดคล้องกันของคำสั่งสวิตช์ของวิธีการ รับ PropValจะอยู่ในรูปแบบ:
กรณี ePropTest1: wstring_to_p (test1, pvarPropVal);
หยุดพัก; SetPropVal:
วิธี
กรณี ePropTest1: ถ้า (TV_VT(varPropVal) != VTYPE_PWSTR) ส่งคืนค่าเท็จ; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal));
หยุดพัก;
ในการใช้คุณสมบัติที่สอง เรากำหนดฟิลด์คลาส
Last_type = TV_VT(varPropVal);
ตอนนี้เมื่อร้องขอให้อ่านค่าของคุณสมบัติที่สอง เราจะส่งคืนค่า Last_type, สิ่งที่งานที่ได้รับมอบหมายต้องการ
เรามาตรวจสอบการทำงานของการเปลี่ยนแปลงที่ทำกัน
ในการทำเช่นนี้ให้เรานำเสนอลักษณะที่ปรากฏของการกำหนดค่า 1C ดังนี้:
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...", "DemoVK", ประเภทส่วนประกอบภายนอก.เนทิฟ);
DemoComp = ใหม่ ("AddIn.DemoVK.SomeName");
3
DemoComp.TypeCheck = 1;
รายงาน (สตริง (DemoComp.TypeCheck));
22

DemoComp.Test = "วาสยา"; รายงาน (สตริง (DemoComp.Test)); DemoComp.Test = "เพชร";

รายงาน (สตริง (DemoComp.Test));

งาน:
  1. รายงาน (สตริง (DemoComp.TypeCheck)); สิ้นสุดขั้นตอน
  2. จากการเปิดตัว เราจะได้รับข้อความตามลำดับ:
  3. วาสยา เพ็ตยาข้อความที่สองและสามเป็นผลมาจากการอ่านชุดคุณสมบัติในขั้นตอนก่อนหน้า ข้อความแรกและข้อความที่สองประกอบด้วยรหัสประเภทของชุดคุณสมบัติสุดท้าย 3 สอดคล้องกับค่าจำนวนเต็ม 22 สอดคล้องกับค่าสตริง ความสอดคล้องของประเภทและรหัสถูกสร้างขึ้นในไฟล์
  4. ประเภท.h

ซึ่งอยู่บนดิสก์ ITS
ขยายรายการวิธีการ, ขยายฟังก์ชันการทำงานของส่วนประกอบภายนอกด้วยฟังก์ชันต่อไปนี้:, สำรวจวิธีการนำวิธีส่วนประกอบภายนอกไปใช้
เพิ่มวิธีการทำงาน
ฟังก์ชั่น1
ซึ่งรับสองสตริง (“Parameter1” และ “Parameter2”) เป็นพารามิเตอร์ ผลลัพธ์จะเป็นสตริงเช่น: “กำลังตรวจสอบ พารามิเตอร์1, พารามิเตอร์2"
ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงที่คุณทำใช้งานได้
เพื่อกำหนดวิธีการสร้างส่วนประกอบ นักพัฒนาจะต้องใช้วิธีการต่อไปนี้ในโค้ดไลบรารี AddInNative:
รับวิธีการ
ค้นหาวิธีการ เท็จรับMethodName
ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติ
เท็จรับ NParams
ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0
รับ ParamDefValue เท็จเกิดข้อผิดพลาดรันไทม์และการดำเนินการของโมดูล 1C: Enterprise สิ้นสุดลง หน่วยความจำสำหรับอาร์เรย์ของพารามิเตอร์ได้รับการจัดสรรโดย 1C: Enterprise หากค่าที่ส่งคืนเป็นชนิดข้อมูลสตริงหรือไบนารี ส่วนประกอบจะจัดสรรหน่วยความจำด้วยฟังก์ชัน AllocMemoryผู้จัดการหน่วยความจำ เขียนข้อมูลที่นั่นและจัดเก็บที่อยู่นี้ในช่องที่เกี่ยวข้องของโครงสร้าง 1C: องค์กรจะเพิ่มหน่วยความจำนี้โดยการโทร ฟรีหน่วยความจำ.
คำอธิบายวิธีการโดยสมบูรณ์ รวมถึงรายการพารามิเตอร์ มีการอธิบายโดยละเอียดในเอกสารประกอบที่ให้มาในดิสก์ ITS
พิจารณาการนำวิธีการที่อธิบายไว้ข้างต้นไปใช้
ในโค้ดส่วนประกอบ มีการกำหนดอาร์เรย์สองตัว:
wchar_t แบบคงที่ *g_MethodNames = (L "เปิดใช้งาน", L "ปิดการใช้งาน", L "ShowInStatusLine", L "StartTimer", L "StopTimer", L "LoadPicture"); wchar_t แบบคงที่ *g_MethodNamesRu = (L"เปิดใช้งาน", L"ปิดการใช้งาน", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
และการแจงนับ:
วิธีการแจงนับ ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // เสมอ);
พวกมันถูกใช้ในฟังก์ชั่น ขยายรายการวิธีการ, ขยายฟังก์ชันการทำงานของส่วนประกอบภายนอกด้วยฟังก์ชันต่อไปนี้:สาธิตคอม.เปิดใช้งาน(); สำรวจวิธีการนำวิธีส่วนประกอบภายนอกไปใช้โดยการเปรียบเทียบกับคำอธิบายคุณสมบัติ
วิธีการ ฟังก์ชั่น1, ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงที่คุณทำใช้งานได้, รับวิธีการใช้สวิตช์ ขึ้นอยู่กับพารามิเตอร์ที่ส่งผ่านและตรรกะของแอปพลิเคชัน ให้ส่งคืนค่าที่ต้องการ วิธี รับวิธีการในโค้ดจะมีรายการวิธีการเดียวที่สามารถส่งคืนผลลัพธ์ได้ เขากลับมาเพื่อพวกเขา จริง- สำหรับผลตอบแทนจากวิธีเหล็กทั้งหมด เท็จ.
วิธีการ ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติสาธิตคอม.เปิดใช้งาน(); ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0มีโค้ดที่ปฏิบัติการได้โดยตรงของวิธีการ
หากต้องการเพิ่มเมธอดที่สามารถเรียกว่าเป็นฟังก์ชันได้เท่านั้น คุณต้องทำการเปลี่ยนแปลงต่อไปนี้กับซอร์สโค้ดของส่วนประกอบภายนอก:
  1. เพิ่มชื่อวิธีการให้กับอาร์เรย์ g_MethodNamesสาธิตคอม.เปิดใช้งาน(); g_MethodNamesRu(ไฟล์ AddInNative.cpp)
  2. เพิ่มตัวระบุวิธีการที่มีความหมายในการแจงนับวิธีการ (file AddInNative.h)
  3. ทำการเปลี่ยนแปลงโค้ดฟังก์ชัน ฟังก์ชั่น1ตามลอจิกของโปรแกรม
  4. หากจำเป็น ให้ทำการเปลี่ยนแปลงรหัสวิธีการ ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงที่คุณทำใช้งานได้หากคุณต้องการใช้ค่าเริ่มต้นของพารามิเตอร์วิธีการ
  5. ทำการเปลี่ยนแปลงฟังก์ชัน รับวิธีการ
  6. ทำการเปลี่ยนแปลงตรรกะของฟังก์ชัน ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติหรือ ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0โดยวางโค้ดที่ปฏิบัติการได้โดยตรงของวิธีการไว้ที่นั่น
มานำเสนออาร์เรย์กัน g_MethodNamesสาธิตคอม.เปิดใช้งาน(); g_MethodNamesRuตลอดจนรายการ วิธีการไปที่แบบฟอร์ม:
wchar_t แบบคงที่ *g_MethodNames = (L "เปิดใช้งาน", L "ปิดการใช้งาน", L "ShowInStatusLine", L "StartTimer", L "StopTimer", L "LoadPicture", L "ทดสอบ"); wchar_t แบบคงที่ *g_MethodNamesRu = (L"เปิดใช้งาน", L"ปิดการใช้งาน", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"โหลดภาพ", L"ทดสอบ");

วิธีการแจงนับ ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // เสมอ);
มาแก้ไขฟังก์ชั่นกันดีกว่า ขยายรายการคุณสมบัติ VKเพื่อให้ส่งกลับจำนวนพารามิเตอร์ของวิธี "ทดสอบ":
ยาว CAddInNative::GetNParams (const ยาว lMethodNum) ( สวิตช์ (lMethodNum) ( กรณี eMethShowInStatusLine: กลับ 1; กรณี eMethLoadPicture: กลับ 1; กรณี eMethTest: กลับ 2; ค่าเริ่มต้น: กลับ 0; ) กลับ 0; )
มาทำการเปลี่ยนแปลงฟังก์ชั่นกัน:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( ​​TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( case eMethEnable: case eMethDisable: case eMethShowInStatusLine: case eMethStartTimer : case e MethStopTimer: กรณี eMethTest : / / ไม่มีค่าพารามิเตอร์ตามค่าเริ่มต้น ตัวแบ่ง ค่าเริ่มต้น: return false;
ขอบคุณที่เพิ่มบรรทัด
กรณี eMethTest:
หากไม่มีอาร์กิวเมนต์อย่างน้อยหนึ่งรายการ พารามิเตอร์ที่เกี่ยวข้องจะมีค่าว่าง ( VTYPE_EMPTY- หากคุณต้องการค่าเริ่มต้นสำหรับพารามิเตอร์ คุณควรตั้งค่าในส่วนนี้ eMethTestคำสั่งสวิตช์ฟังก์ชัน CAddInNative::GetParamDefValue.
เนื่องจากวิธีทดสอบสามารถคืนค่าได้ คุณจึงต้องทำการเปลี่ยนแปลงโค้ดฟังก์ชัน รับวิธีการ:
bool CAddInNative::HasRetVal(const long lMethodNum) ( สวิตช์(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; default: return false; ) return false; )
และเพิ่มรหัสปฏิบัติการของวิธีการให้กับฟังก์ชัน ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0:
บูล CAddInNative::CallAsFunc (const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch (lMethodNum) ( case eMethLoadPicture: ... break; case eMethTest: if (!lSizeArray || !paParams) ส่งคืน false; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstring_to_p(std::wstring(s1+s2), pvarRetValue); ;
มาคอมไพล์ส่วนประกอบและนำโค้ดการกำหนดค่ามาไว้ในแบบฟอร์ม:
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...", "DemoVK", ประเภทส่วนประกอบภายนอก.เนทิฟ);
DemoComp = ใหม่ ("AddIn.DemoVK.SomeName");

lane = DemoComp.Test("สวัสดี" "โลก!");

บูล CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; if (m_iMemory) ( if(m_iMemory->AllocMemory ((เป็นโมฆะ**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) ส่งคืนค่าเท็จ;
  1. รายงาน(ต่อ); สิ้นสุดขั้นตอน
  2. หลังจากเปิดตัวการกำหนดค่า เราจะได้รับข้อความ: “Hello, World!” ซึ่งระบุว่าวิธีนี้ใช้ได้ผลสำเร็จ
  3. ประเภท.h

ตัวจับเวลา ศึกษาการใช้งานตัวจับเวลาในการสาธิต VK- ข้อความนี้จะถูกส่งไปยังโปรแกรมของคุณตามช่วงเวลาที่คุณกำหนดไว้เมื่อสร้างตัวจับเวลา
หากต้องการสร้างตัวจับเวลา ให้ใช้ฟังก์ชัน ตั้งเวลา:
UINT SetTimer(HWND hWnd, // ตัวอธิบายหน้าต่าง UINT nIDevent, // ตัวระบุตัวจับเวลา (หมายเลข) UINT nElapse, // หน่วงเวลา TIMERPROC lpTimerFunc); // ตัวชี้ไปยังฟังก์ชัน
ระบบปฏิบัติการจะส่งข้อความ ศึกษาการใช้งานตัวจับเวลาในการสาธิต VKเข้าสู่โปรแกรมตามช่วงเวลาที่ระบุในอาร์กิวเมนต์ nElapse(เป็นมิลลิวินาที) ในพารามิเตอร์สุดท้าย คุณสามารถระบุฟังก์ชันที่จะดำเนินการในแต่ละครั้งที่ตัวจับเวลาเริ่มทำงาน ส่วนหัวของฟังก์ชันนี้ควรมีลักษณะดังนี้ (ชื่ออาจเป็นอะไรก็ได้):
เป็นโมฆะ __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
ลองพิจารณาการใช้งานตัวจับเวลาใน VC สาธิต
เนื่องจากเรากำลังพิจารณากระบวนการพัฒนาส่วนประกอบภายนอกสำหรับตระกูล Windows OS เราจะไม่พิจารณาการใช้งานตัวจับเวลาในระบบปฏิบัติการอื่น โดยเฉพาะสำหรับ GNU/Linux OS การใช้งานจะแตกต่างกันในรูปแบบไวยากรณ์ของฟังก์ชัน ตั้งเวลาสาธิตคอม.เปิดใช้งาน(); จับเวลาProc.
รหัสปฏิบัติการเรียกวิธีการ ตั้งเวลาซึ่งฟังก์ชันถูกส่งผ่านไป MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
ID ของตัวจับเวลาที่สร้างขึ้นจะถูกวางไว้ในตัวแปร m_uiTimerเพื่อที่จะสามารถปิดการใช้งานได้ในภายหลัง
การทำงาน MyTimerProcดูเหมือนว่านี้:
VOID CALLBACK MyTimerProc (HWND hwnd, // หมายเลขอ้างอิงของหน้าต่างสำหรับข้อความจับเวลา UINT uMsg, // WM_TIMER ข้อความ UINT idEvent, // ตัวระบุตัวจับเวลา DWORD dwTime // เวลาของระบบปัจจุบัน) ( if (!pAsyncEvent) return; wchar_t *who = L "ComponentNative", *อะไร = L"ตัวจับเวลา"; , อะไร, wstime); ลบ wstime;
สาระสำคัญของฟังก์ชันคือการเรียกเมธอด เหตุการณ์ภายนอกซึ่งส่งข้อความไปยังระบบ 1C: Enterprise
เพื่อขยายการทำงานของวิธีการ และสายนับนาฬิกาของระบบมาทำสิ่งต่อไปนี้:
การปรับเปลี่ยนรหัสวิธีการ ฟังก์ชั่น1เพื่อให้เป็นวิธีการ eMethStartTimerค่าที่ส่งคืน 1:
กรณี eMethStartTimer: ส่งคืน 1;
นี่คือรหัสวิธีการ ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติไปที่แบบฟอร์ม:
กรณี eMethStartTimer: ถ้า (!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;
ตอนนี้เรามาตรวจสอบฟังก์ชันการทำงานกัน เมื่อต้องการทำเช่นนี้ เราจะเขียนโค้ดในโมดูลแอปพลิเคชันที่ได้รับการจัดการของการกำหนดค่า:
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...", "DemoVK", ประเภทส่วนประกอบภายนอก.เนทิฟ);
หลังจากเริ่มการกำหนดค่าโปรแกรมจะได้รับข้อความในช่วงเวลา 2 วินาทีซึ่งแสดงว่าตัวจับเวลาทำงานถูกต้อง

การโต้ตอบกับระบบ 1C: Enterprise

ในการโต้ตอบระหว่างส่วนประกอบภายนอกและระบบ 1C: Enterprise วิธีการของคลาส IAddInDefBase ที่อธิบายไว้ในไฟล์ AddInDefBase.h- เราแสดงรายการที่ใช้บ่อยที่สุด:
การสร้างข้อความแสดงข้อผิดพลาด
บูลเสมือน ADDIN_API AddError (wcode สั้นที่ไม่ได้ลงนาม, แหล่งที่มา const WCHAR_T*, const WCHAR_T* descr, scode แบบยาว)
wcode, รหัส- รหัสข้อผิดพลาด (รายการรหัสข้อผิดพลาดพร้อมคำอธิบายสามารถพบได้ในดิสก์ ITS)
แหล่งที่มา- แหล่งที่มาของข้อผิดพลาด
คำอธิบาย- คำอธิบายข้อผิดพลาด
ส่งข้อความไปยังระบบ 1C: Enterprise
บูลเสมือน ADDIN_API ExternalEvent (WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- แหล่งที่มาของข้อความ
wszMessage- ข้อความ
wszData- ข้อมูลที่ส่ง
การสกัดกั้นข้อความดำเนินการโดยขั้นตอนการประมวลผลเหตุการณ์ภายนอก
การลงทะเบียนส่วนประกอบภายนอกในระบบ 1C: Enterprise
บูลเสมือน ADDIN_API RegisterProfileAs (WCHAR_T* wszProfileName)
wszProfileName- ชื่อส่วนประกอบ
วิธีการเหล่านี้เพียงพอสำหรับการโต้ตอบอย่างสมบูรณ์ระหว่าง VK และ 1C ในการรับข้อมูลโดยส่วนประกอบภายนอกจากระบบ 1C: Enterprise และในทางกลับกัน ส่วนประกอบภายนอกจะส่งข้อความพิเศษซึ่งจะถูกดักโดยระบบ 1C และหากจำเป็น ให้เรียกวิธีการของส่วนประกอบภายนอกเพื่อส่งข้อมูลกลับ .

ชนิดข้อมูล tVariant

เมื่อแลกเปลี่ยนข้อมูลระหว่างส่วนประกอบภายนอกและระบบ 1C: Enterprise จะใช้ประเภทข้อมูล tVariant มีการอธิบายไว้ในไฟล์ types.h ซึ่งสามารถพบได้บนดิสก์ ITS:
struct _tVariant ( _ANONYMOUS_UNION ยูเนี่ยน ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; ไม่ได้ลงนาม int uintVal; int64_t llVal; uint8_t ui8Val; uint16_t ushortVal; uint32_t ulVal; t ; int32_t errCode; float fltVal; struct tm tmVal; // VARIANT_NAME_3/*str*/; _VARIANT_NAME_2/*iface*/; pstrVal; uint32_t strLen ; // จำนวนไบต์ ) __VARIANT_NAME_3/*str*/; ) __VARIANT_NAME_1 ; อาร์เรย์มิติใน pvarVal TYPEVAR vt);
พิมพ์ tตัวแปรเป็นโครงสร้างที่ประกอบด้วย:
  • ส่วนผสม (ยูเนี่ยน) มีไว้สำหรับการจัดเก็บข้อมูลโดยตรง
  • ตัวระบุชนิดข้อมูล
โดยทั่วไปการทำงานกับตัวแปรประเภท tตัวแปรเกิดขึ้นตามอัลกอริทึมต่อไปนี้:
  1. การกำหนดประเภทของข้อมูลที่จัดเก็บไว้ในตัวแปรในปัจจุบัน
  2. เข้าถึงฟิลด์ส่วนผสมที่เกี่ยวข้องเพื่อเข้าถึงข้อมูลโดยตรง
โดยใช้ชนิด tตัวแปรลดความซับซ้อนของการโต้ตอบของ 1C: ระบบองค์กรและส่วนประกอบภายนอกได้ง่ายขึ้นอย่างมาก

แอปพลิเคชัน

ไดเรกทอรี “ตัวอย่าง” มีตัวอย่างสำหรับบทความ
ตัวอย่าง/1 - เปิดส่วนประกอบสาธิต
ตัวอย่าง/2 - การสาธิตการขยายรายการทรัพย์สิน
ตัวอย่าง/3 - การสาธิตการขยายรายการวิธีการ
แต่ละไดเร็กทอรีประกอบด้วยโปรเจ็กต์ VS 2008 และการกำหนดค่า 1C สำเร็จรูป

โอเลก ฟิลิปโปฟ, แอนท์อินฟอร์ม รองหัวหน้าฝ่ายพัฒนา [ป้องกันอีเมล]

ขยายฟังก์ชันการทำงานของ 1C:Enterprise
ส่วนที่ 1: ส่วนประกอบ COM ภายนอก

ในชีวิตของนักพัฒนา 1C ทุกคนมาถึงเมื่องานที่มอบหมายให้เขาเกินความสามารถของแพลตฟอร์ม 1C มาดูวิธี “เอาชนะขอบเขตที่เป็นไปได้” กัน

นักพัฒนา 1C ที่มีประสบการณ์อาจเดาได้จากสามคำแรกของชื่อบทความว่าเราจะพูดถึงส่วนประกอบภายนอกสำหรับ 1C:Enterprise เทคโนโลยีนี้มีมาตั้งแต่สมัยของแพลตฟอร์ม 1C:Enterprise 7.7 (หรือก่อนหน้า) ในอดีต ดูเหมือนว่าส่วนใหญ่จะแก้ปัญหาการโต้ตอบกับอุปกรณ์ขายปลีก (เครื่องสแกนบาร์โค้ด เครื่องชั่งอิเล็กทรอนิกส์ เครื่องบันทึกเงินสด) ในระหว่างนี้แพลตฟอร์ม 1C จำเป็นต้องประมวลผลเหตุการณ์บางอย่างที่เริ่มต้นโดยอุปกรณ์ เหตุการณ์ดังกล่าวไม่มีอะไรมากไปกว่าลำดับไบต์ที่มาถึงพอร์ต COM/LPT แน่นอนว่าการปรับแพลตฟอร์ม 1C ให้ทำงานกับกลไกระดับต่ำดังกล่าวนั้นไม่ถูกต้องนัก ดังนั้นเราจึงคิดเทคโนโลยีของส่วนประกอบภายนอกสำหรับ 1C: Enterprise

ในบทความชุดนี้ เราจะไม่เพียงแต่พูดถึงส่วนประกอบภายนอกเท่านั้น แต่ส่วนประกอบภายนอกเป็นกลไกที่ค่อนข้างทรงพลังและซับซ้อน ดังนั้นการใช้พวกมันเพื่อแก้ไขปัญหาบางอย่างจึงถูกมองว่าเป็น "การยิงนกกระจอกด้วยปืนใหญ่" อย่างไรก็ตาม ส่วนประกอบภายนอกเป็นเครื่องมือที่เป็นสากลที่สุดในการแก้ปัญหาทุกประเภทที่อยู่นอกเหนือขอบเขตของแพลตฟอร์ม 1C:Enterprise ดังนั้นเราจะเริ่มต้นด้วยส่วนประกอบเหล่านั้น บทความนี้จะกล่าวถึงเทคโนโลยีที่เก่าแก่ ใช้บ่อยที่สุด และผ่านการทดสอบตามเวลาสำหรับการสร้างส่วนประกอบภายนอกโดยใช้ COM

ส่วนประกอบภายนอกคืออะไร

ส่วนประกอบภายนอกตามที่กล่าวไว้ข้างต้นปรากฏใน 1C:Enterprise ตั้งแต่เวอร์ชัน 7.7 ในขั้นต้นตามประเพณีนักพัฒนาแพลตฟอร์ม 1C "ไม่สนใจ" และส่วนประกอบภายนอกเป็นวัตถุที่มีคุณสมบัติและวิธีการบังคับบางอย่าง ส่วนประกอบยังคงมีอยู่ในรูปแบบเดียวกันจนถึงทุกวันนี้ นั่นคือส่วนประกอบที่เขียนขึ้นสำหรับ 1C:Enterprise 7.7 (ในทางทฤษฎี) จะทำงานร่วมกับ 1C:Enterprise 8.3 ได้ด้วย

ในทางปฏิบัติ มีรายละเอียดปลีกย่อยหลายประการ: หากส่วนประกอบภายนอกโต้ตอบกับแพลตฟอร์มอย่างแข็งขัน ฟังก์ชันของส่วนประกอบนั้นก็จะมีความเฉพาะเจาะจงสำหรับเวอร์ชันเฉพาะ

ตั้งแต่เวอร์ชัน 8.2 เป็นต้นมา 1C:Enterprise ได้เปิดตัวเทคโนโลยีใหม่สำหรับการพัฒนาส่วนประกอบภายนอกที่เรียกว่า NativeAPI ส่วนประกอบที่เขียนโดยใช้เทคโนโลยีนี้ไม่ใช่วัตถุ COM อีกต่อไป ในอีกด้านหนึ่ง นี่เป็นข้อดี - ส่วนประกอบเหล่านี้ไม่จำเป็นต้องลงทะเบียน ในทางกลับกัน การใช้งานที่อื่นยกเว้นแพลตฟอร์ม 1C:Enterprise นั้นเป็นไปไม่ได้ การพัฒนาส่วนประกอบภายนอกค่อนข้างซับซ้อนมากขึ้น โดยจะต้องรองรับอินเทอร์เฟซที่จำเป็นจำนวนมากขึ้นเล็กน้อย แต่เราจะพูดถึงเรื่องนี้ในบทความถัดไป

ส่วนประกอบภายนอกและเทคโนโลยี COM

ฉันจะไม่อธิบายรายละเอียดเทคโนโลยี COM อย่างละเอียดเนื่องจากมีวรรณกรรมมากมายในหัวข้อนี้ เราควรพูดว่าหลาย ๆ คน "สับสน" ในการสร้างเซิร์ฟเวอร์ที่ไม่เหมาะสมปกติด้วยการสร้างส่วนประกอบภายนอกสำหรับ 1C:Enterprise แต่นี่ก็ไม่ไกลจากความจริง บ่อยครั้งคุณสามารถใช้ฟังก์ชันนี้ได้ วิธีการสร้างวัตถุ COM ใน Visual Studio ได้อธิบายไว้ในแหล่งต่างๆ มากมาย โดยเฉพาะอย่างยิ่งบุคคลนั้นเขียนรายละเอียดวิธีการดำเนินการนี้ พร้อมตัวอย่างการโทรจาก 1C:Enterprise

หากคุณยังคงต้องการสร้างส่วนประกอบภายนอก COM เต็มรูปแบบสำหรับ 1C:Enterprise (ตัวเลือกว่าทำไมจึงจำเป็น ฉันคิดได้เพียงรายการเดียว - ส่วนประกอบจะต้องโต้ตอบกับระบบบนแพลตฟอร์ม 1C อย่างแข็งขัน แจ้งให้ผู้ใช้ทราบ เปลี่ยนบรรทัดสถานะ แสดงกล่องโต้ตอบ ฯลฯ) จากนั้นคุณจะต้องใช้เทคโนโลยีของส่วนประกอบภายนอกโดยตรง มาเริ่มกันเลย

  • บทช่วยสอน

การแนะนำ

บทความนี้ให้แนวคิดเกี่ยวกับการทำงานของส่วนประกอบภายนอกในระบบ 1C: Enterprise
กระบวนการพัฒนาส่วนประกอบภายนอกสำหรับ 1C: ระบบ Enterprise เวอร์ชัน 8.2 ที่ทำงานภายใต้ Windows OS พร้อมโหมดการทำงานไฟล์จะปรากฏขึ้น ตัวเลือกนี้ใช้ในโซลูชันส่วนใหญ่ที่ออกแบบมาสำหรับธุรกิจขนาดเล็ก VK จะถูกนำไปใช้ในภาษาการเขียนโปรแกรม C++

ส่วนประกอบภายนอก "1C: องค์กร"

"1C: Enterprise" เป็นระบบที่ขยายได้ เพื่อขยายฟังก์ชันการทำงานของระบบ จึงมีการใช้ส่วนประกอบภายนอก (EC) จากมุมมองของนักพัฒนา VC เป็นวัตถุภายนอกที่มีคุณสมบัติและวิธีการ และยังสามารถสร้างเหตุการณ์สำหรับการประมวลผลโดยระบบ 1C: Enterprise
ส่วนประกอบภายนอกสามารถใช้เพื่อแก้ไขปัญหาระดับหนึ่งที่ยากหรือเป็นไปไม่ได้เลยที่จะนำไปใช้ในภาษาการเขียนโปรแกรมที่สร้างใน 1C: Enterprise โดยเฉพาะอย่างยิ่ง คลาสนี้ประกอบด้วยงานที่ต้องมีการโต้ตอบระดับต่ำกับระบบปฏิบัติการ เช่น เพื่อทำงานกับอุปกรณ์เฉพาะ
1C: ระบบองค์กรใช้เทคโนโลยีสองอย่างในการสร้างส่วนประกอบภายนอก:
  • โดยใช้ Native API
  • โดยใช้เทคโนโลยีคอม
ด้วยข้อจำกัดที่กำหนด ความแตกต่างระหว่างเทคโนโลยีทั้งสองที่กล่าวมาข้างต้นจึงไม่มีนัยสำคัญ ดังนั้นเราจะพิจารณาการพัฒนาวิดีโอเกมโดยใช้ Native API หากจำเป็น การพัฒนาที่นำไปใช้สามารถนำไปใช้กับการพัฒนาซอฟต์แวร์คอมพิวเตอร์โดยใช้เทคโนโลยี COM และยังมีการปรับเปลี่ยนเล็กน้อยเพื่อใช้ในระบบ 1C: Enterprise พร้อมตัวเลือกการทำงานอื่น ๆ นอกเหนือจากโหมดการทำงานของไฟล์
โครงสร้างวีเค
ส่วนประกอบภายนอกของระบบ 1C: Enterprise นำเสนอในรูปแบบของไลบรารี DLL รหัสไลบรารีอธิบายคลาสสืบทอด IComponentBase คลาสที่สร้างขึ้นจะต้องกำหนดวิธีการที่รับผิดชอบในการใช้งานฟังก์ชันของส่วนประกอบภายนอก วิธีการแทนที่จะมีการอธิบายโดยละเอียดด้านล่างเมื่อมีการนำเสนอเนื้อหา

เปิดตัวการสาธิต VK

งาน:
  1. ประกอบส่วนประกอบภายนอกที่มาพร้อมกับการสมัครสมาชิก ITS และมีวัตถุประสงค์เพื่อแสดงความสามารถหลักของกลไกส่วนประกอบภายนอกใน 1C
  2. เชื่อมต่อส่วนประกอบสาธิตกับการกำหนดค่า 1C
  3. ตรวจสอบให้แน่ใจว่าฟังก์ชันที่ประกาศไว้ทำงานอย่างถูกต้อง
การรวบรวม
VK สาธิตอยู่ในดิสก์การสมัครสมาชิก ITS ในไดเร็กทอรี “/VNCOPP82/example/NativeAPI”
ในการสร้าง VC สาธิต เราจะใช้ Microsoft Visual Studio 2008 เวอร์ชันอื่นของผลิตภัณฑ์นี้ไม่รองรับรูปแบบโครงการ Visual Studio ที่ใช้


เปิดโครงการ AddInNative ในการตั้งค่าโปรเจ็กต์ เราจะรวมไดเร็กทอรีพร้อมกับไฟล์ส่วนหัวที่จำเป็นในการสร้างโปรเจ็กต์ โดยค่าเริ่มต้น จะอยู่บนดิสก์ ITS ในไดเร็กทอรี /VNCOP82/รวม.
ผลลัพธ์ของบิลด์คือไฟล์ /bind/AddInNative.dll- นี่คือไลบรารีที่คอมไพล์สำหรับเชื่อมต่อกับการกำหนดค่า 1C
การเชื่อมต่อการกำหนดค่า VK กับ 1C
มาสร้างการกำหนดค่า 1C ที่ว่างเปล่ากัน
ด้านล่างนี้คือโค้ดสำหรับโมดูลแอปพลิเคชันที่ได้รับการจัดการ
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...\bind\AddInNative.dll", "DemoVK", ส่วนประกอบภายนอก Type.Native);
DemoComp = ใหม่ ("AddIn.DemoVK.AddInNativeExtension"); สิ้นสุดขั้นตอน
หากไม่มีรายงานข้อผิดพลาดเมื่อเริ่มการกำหนดค่า 1C แสดงว่าเชื่อมต่อ VK ได้สำเร็จ อันเป็นผลมาจากการรันโค้ดข้างต้น ออบเจ็กต์จะปรากฏขึ้นในการมองเห็นการกำหนดค่าทั่วโลกเดโมคอม
ซึ่งมีคุณสมบัติและเมธอดที่กำหนดไว้ในโค้ดของส่วนประกอบภายนอก
การสาธิตฟังก์ชันการทำงานในตัว
เรามาตรวจสอบการทำงานของการสาธิต VK กัน ในการดำเนินการนี้ ให้ลองตั้งค่าและอ่านคุณสมบัติบางอย่าง เรียกใช้วิธี VK บางอย่าง รวมถึงรับและประมวลผลข้อความ VK ด้วย
  1. เอกสารประกอบที่ให้มาบนดิสก์ ITS ระบุฟังก์ชันการทำงานของ VC สาธิตต่อไปนี้:
    การจัดการสถานะวัตถุส่วนประกอบ วิธีการ:, เปิดเครื่อง
    ปิดเครื่อง คุณสมบัติ:
  2. เปิดใช้งานแล้ว
    การจัดการตัวจับเวลา ทุกวินาทีส่วนประกอบจะส่งข้อความไปยังระบบ 1C: Enterprise พร้อมพารามิเตอร์, ส่วนประกอบตัวจับเวลา
    การจัดการสถานะวัตถุส่วนประกอบ และสายนับนาฬิกาของระบบ, เริ่มจับเวลา
    ปิดเครื่อง ตัวจับเวลา
  3. มีตัวจับเวลา วิธี ShowInStatusLine
  4. มีตัวจับเวลา ซึ่งจะแสดงข้อความที่ส่งไปยังเมธอดเป็นพารามิเตอร์ในบรรทัดสถานะอัพโหลดรูปภาพ
- โหลดรูปภาพจากไฟล์ที่ระบุและถ่ายโอนไปยังระบบ 1C: Enterprise ในรูปแบบของข้อมูลไบนารี
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() ConnectExternalComponent(...);
DemoComp = ใหม่ ("AddIn.DemoVK.AddInNativeExtension");


สาธิตคอม.ปิดการใช้งาน(); รายงาน (DemoComp.Enabled);สาธิตคอม.เปิดใช้งาน(); รายงาน (DemoComp.Enabled); DemoComp.StartTimer(); สิ้นสุดขั้นตอน ขั้นตอน การประมวลผลเหตุการณ์ภายนอก (แหล่งที่มา เหตุการณ์ ข้อมูล) รายงาน (แหล่งที่มา + " " + เหตุการณ์ + " " + ข้อมูล); สิ้นสุดขั้นตอน ผลลัพธ์ของการรันการกำหนดค่าจะแสดงในภาพ, แผง "ข้อความ" จะแสดงผลลัพธ์ของการเรียกเมธอดสาธิตคอม.เปิดใช้งาน(); DemoComp.ปิดการใช้งาน()และ

Demo.Comp.เปิดใช้งาน()

- บรรทัดต่อมาในแผงเดียวกันประกอบด้วยผลลัพธ์การประมวลผลข้อความที่ได้รับจาก VK -
แหล่งที่มา เหตุการณ์ข้อมูล เหตุการณ์ตามลำดับ
ชื่อส่วนประกอบภายนอกที่กำหนดเอง ภารกิจ: เปลี่ยนชื่อของส่วนประกอบภายนอกเป็นชื่อที่กำหนดเองส่วนก่อนหน้านี้ใช้ตัวระบุ
AddInNativeExtension ภารกิจ: เปลี่ยนชื่อของส่วนประกอบภายนอกเป็นชื่อที่กำหนดเองซึ่งไม่ได้อธิบายความหมายไว้ ในกรณีนี้
- นี่คือชื่อของส่วนขยาย
รหัส VK กำหนดวิธีการ ลงทะเบียนส่วนขยายเป็นซึ่งส่งคืนชื่อให้กับระบบ 1C: Enterprise ซึ่งจำเป็นสำหรับการลงทะเบียน VK ในระบบในภายหลัง ขอแนะนำให้ระบุตัวระบุที่เปิดเผยสาระสำคัญของส่วนประกอบภายนอกในระดับหนึ่ง
นี่คือรหัสที่สมบูรณ์ของวิธีการ

เมื่อเปลี่ยนชื่อนามสกุลแล้ว:

บูล CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; if (m_iMemory) ( if(m_iMemory->AllocMemory ((เป็นโมฆะ**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) ส่งคืนค่าเท็จ;
  1. ในตัวอย่างที่กำหนด ชื่อ VK จะถูกเปลี่ยนเป็น
  2. ชื่อบางคน
  3. - จากนั้นเมื่อเชื่อมต่อ VK คุณต้องระบุชื่อใหม่:

DemoComp = ใหม่ ("AddIn.DemoVK.SomeName");
ขยายรายการคุณสมบัติ VK
งาน:
ศึกษาการใช้งานคุณสมบัติ VK
เพิ่มคุณสมบัติการอ่าน/เขียนประเภทสตริง
เพิ่มคุณสมบัติสตริงการอ่าน/เขียนที่เก็บชนิดข้อมูลของชุดคุณสมบัติสุดท้าย ไม่มีการดำเนินการใด ๆ เมื่อตั้งค่าคุณสมบัติ
ส่งกลับชื่อของคุณสมบัติตามหมายเลขลำดับและตามตัวระบุภาษาที่ส่งผ่าน
รับ PropVal
ส่งกลับค่าของคุณสมบัติที่มีเลขลำดับที่ระบุ
SetPropVal
ตั้งค่าของคุณสมบัติด้วยเลขลำดับที่ระบุ
เป็น PropReadable
ส่งกลับค่าสถานะความสามารถในการอ่านของคุณสมบัติที่มีหมายเลขลำดับที่ระบุ
สามารถเขียน Prop ได้
ส่งกลับค่าสถานะความสามารถในการเขียนของคุณสมบัติที่มีหมายเลขลำดับที่ระบุ


ลองพิจารณาการใช้งานวิธีการเรียนข้างต้น CAddInNative.
ในการสาธิต VC มีการกำหนดคุณสมบัติ 2 รายการ: คุณสมบัติ:สาธิตคอม.เปิดใช้งาน(); ตัวจับเวลา (เปิดใช้งานแล้วสาธิตคอม.เปิดใช้งาน(); อิสไทม์เมอร์ปัจจุบัน).
ในขอบเขตสากลของโค้ดไลบรารี จะมีการกำหนดอาร์เรย์สองตัว:
wchar_t แบบคงที่ *g_PropNames = (L "IsEnabled", L "IsTimerPresent"); wchar_t แบบคงที่ *g_PropNamesRu = (L "เปิดใช้งาน", L "มีตัวจับเวลา");
ซึ่งเก็บชื่อทรัพย์สินภาษารัสเซียและอังกฤษ ในไฟล์ส่วนหัว AddInNative.hการแจกแจงถูกกำหนดไว้:
อุปกรณ์ประกอบฉาก enum ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // เสมอ);
เปิดใช้งาน eProp แล้วสาธิตคอม.เปิดใช้งาน(); ePropIsTimerPresentตามลำดับที่มีค่า 0 และ 1 ใช้เพื่อแทนที่หมายเลขซีเรียลของคุณสมบัติด้วยตัวระบุที่มีความหมาย ePropLast ซึ่งมีค่าเป็น 2 ถูกใช้เพื่อรับจำนวนคุณสมบัติ (โดยใช้วิธี GetNProps) ชื่อเหล่านี้ใช้ภายในโค้ดส่วนประกอบเท่านั้น และไม่สามารถใช้ได้จากภายนอก
วิธีการFindPropและGetPropNameทำการค้นหาอาร์เรย์ g_PropNamesสาธิตคอม.เปิดใช้งาน(); g_PropNamesRu.
ในการจัดเก็บค่าของฟิลด์ในโมดูลไลบรารีคลาส CAddInNative มีคุณสมบัติที่เก็บค่าของคุณสมบัติส่วนประกอบ วิธีการ รับ PropValสาธิตคอม.เปิดใช้งาน(); SetPropValกลับและตั้งค่าของคุณสมบัติเหล่านี้ตามลำดับ
วิธีการ เป็น PropReadableสาธิตคอม.เปิดใช้งาน(); สามารถเขียน Prop ได้และกลับมา จริงหรือ เท็จขึ้นอยู่กับหมายเลขลำดับที่ส่งผ่านของคุณสมบัติตามตรรกะของแอปพลิเคชัน
ในการเพิ่มคุณสมบัติแบบกำหนดเอง คุณต้อง:

  1. เพิ่มชื่อของคุณสมบัติที่จะเพิ่มลงในอาร์เรย์ g_PropNamesสาธิตคอม.เปิดใช้งาน(); g_PropNamesRu(ไฟล์ AddInNative.cpp)
  2. เพื่อแสดงรายการ อุปกรณ์ประกอบฉาก(ไฟล์ AddInNative.h) ก่อน ePropLastเพิ่มชื่อที่ระบุคุณสมบัติที่กำลังเพิ่มโดยไม่ซ้ำกัน
  3. จัดระเบียบหน่วยความจำสำหรับจัดเก็บค่าคุณสมบัติ (สร้างฟิลด์ส่วนประกอบโมดูลที่เก็บค่าที่สอดคล้องกัน)
  4. ทำการเปลี่ยนแปลงวิธีการ รับ PropValสาธิตคอม.เปิดใช้งาน(); SetPropValเพื่อโต้ตอบกับหน่วยความจำที่จัดสรรไว้ในขั้นตอนก่อนหน้า
  5. ให้สอดคล้องกับตรรกะของแอปพลิเคชัน ให้ทำการเปลี่ยนแปลงวิธีการ เป็น PropReadableสาธิตคอม.เปิดใช้งาน(); สามารถเขียน Prop ได้
จุดที่ 1, 2, 5 ไม่ต้องการคำอธิบาย รายละเอียดของการดำเนินการตามขั้นตอนเหล่านี้สามารถดูได้จากการศึกษาภาคผนวกของบทความ
มาตั้งชื่อให้กับคุณสมบัติการทดสอบกัน ทดสอบสาธิตคอม.เปิดใช้งาน(); พิมพ์เช็คตามลำดับ จากขั้นตอนที่ 1 เราได้:
wchar_t แบบคงที่ *g_PropNames = (L "IsEnabled", L "IsTimerPresent", L "ทดสอบ", L "TestType"); wchar_t แบบคงที่ *g_PropNamesRu = (L "เปิดใช้งาน", L "มีตัวจับเวลา", L "ทดสอบ", L "ตรวจสอบประเภท");
โอนย้าย อุปกรณ์ประกอบฉากจะมีลักษณะดังนี้:
อุปกรณ์ประกอบฉาก enum ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // เสมอ);
เพื่อให้โค้ดง่ายขึ้นอย่างมาก เราจะใช้ STL C++ โดยเฉพาะอย่างยิ่งสำหรับการทำงานกับสตริง วชารเรามาเชื่อมต่อห้องสมุดกันเถอะ wstring.
เพื่อบันทึกค่าวิธีการ ทดสอบ, เรากำหนดไว้ในชั้นเรียน CAddInNativeในขอบเขตของเขตส่วนตัว:
สตริงทดสอบ 1;
ในการถ่ายโอนพารามิเตอร์สตริงระหว่าง 1C: Enterprise และส่วนประกอบภายนอก 1C: Enterprise memory manager จะถูกนำมาใช้ มาดูผลงานของเขากันดีกว่า ฟังก์ชันนี้ใช้เพื่อจัดสรรและเพิ่มหน่วยความจำตามลำดับ AllocMemoryสาธิตคอม.เปิดใช้งาน(); ฟรีหน่วยความจำกำหนดไว้ในไฟล์ ImemoryManager.h- หากจำเป็นต้องส่งพารามิเตอร์สตริงไปยังระบบ 1C: Enterprise ส่วนประกอบภายนอกจะต้องจัดสรรหน่วยความจำโดยการเรียกใช้ฟังก์ชัน AllocMemory- ต้นแบบของมันมีลักษณะดังนี้:
บูลเสมือน ADDIN_API AllocMemory (โมฆะ ** pMemory, ulCountByte แบบยาวที่ไม่ได้ลงนาม) = 0;
ที่ไหน pหน่วยความจำ- ที่อยู่ของตัวชี้ที่จะวางที่อยู่ของพื้นที่หน่วยความจำที่จัดสรรไว้
ulCountByte- ขนาดของพื้นที่หน่วยความจำที่จัดสรร
ตัวอย่างของการจัดสรรหน่วยความจำสำหรับสตริง:
WCHAR_T *t1 = โมฆะ, *ทดสอบ = L"TEST_STRING"; int iActualSize = wcslen(ทดสอบ1)+1; m_iMemory->AllocMemory((เป็นโมฆะ**)&t1, iActualSize * ขนาดของ(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize); ::convToShortWchar(&t1, test1, iActualSize);
เพื่อความสะดวกในการทำงานกับชนิดข้อมูลสตริง เราจะอธิบายฟังก์ชันนี้ wstring_to_p- ได้รับสตริง wstring เป็นพารามิเตอร์ ผลลัพธ์ของฟังก์ชันคือโครงสร้างที่เต็มไป tตัวแปร- รหัสฟังก์ชัน:
บูล CAddInNative::wstring_to_p(std::wstring str, tVariant* val) ( char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (str.length()+1) * ขนาดของ(WCHAR_T)); memcpy(t1, str.c_str(), (str.length()+1) * ขนาดของ(WCHAR_T)); val -> pstrVal = t1; val -> strLen = str.length(); กลับเป็นจริง)
จากนั้นส่วนกรณีที่สอดคล้องกันของคำสั่งสวิตช์ของวิธีการ รับ PropValจะอยู่ในรูปแบบ:
กรณี ePropTest1: wstring_to_p (test1, pvarPropVal);
หยุดพัก; SetPropVal:
วิธี
กรณี ePropTest1: ถ้า (TV_VT(varPropVal) != VTYPE_PWSTR) ส่งคืนค่าเท็จ; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal));
หยุดพัก;
ในการใช้คุณสมบัติที่สอง เรากำหนดฟิลด์คลาส
Last_type = TV_VT(varPropVal);
ตอนนี้เมื่อร้องขอให้อ่านค่าของคุณสมบัติที่สอง เราจะส่งคืนค่า Last_type, สิ่งที่งานที่ได้รับมอบหมายต้องการ
เรามาตรวจสอบการทำงานของการเปลี่ยนแปลงที่ทำกัน
ในการทำเช่นนี้ให้เรานำเสนอลักษณะที่ปรากฏของการกำหนดค่า 1C ดังนี้:
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...", "DemoVK", ประเภทส่วนประกอบภายนอก.เนทิฟ);
DemoComp = ใหม่ ("AddIn.DemoVK.SomeName");
3
DemoComp.TypeCheck = 1;
รายงาน (สตริง (DemoComp.TypeCheck));
22

DemoComp.Test = "วาสยา"; รายงาน (สตริง (DemoComp.Test)); DemoComp.Test = "เพชร";

รายงาน (สตริง (DemoComp.Test));

งาน:
  1. รายงาน (สตริง (DemoComp.TypeCheck)); สิ้นสุดขั้นตอน
  2. จากการเปิดตัว เราจะได้รับข้อความตามลำดับ:
  3. วาสยา เพ็ตยาข้อความที่สองและสามเป็นผลมาจากการอ่านชุดคุณสมบัติในขั้นตอนก่อนหน้า ข้อความแรกและข้อความที่สองประกอบด้วยรหัสประเภทของชุดคุณสมบัติสุดท้าย 3 สอดคล้องกับค่าจำนวนเต็ม 22 สอดคล้องกับค่าสตริง ความสอดคล้องของประเภทและรหัสถูกสร้างขึ้นในไฟล์
  4. ประเภท.h

ซึ่งอยู่บนดิสก์ ITS
ขยายรายการวิธีการ, ขยายฟังก์ชันการทำงานของส่วนประกอบภายนอกด้วยฟังก์ชันต่อไปนี้:, สำรวจวิธีการนำวิธีส่วนประกอบภายนอกไปใช้
เพิ่มวิธีการทำงาน
ฟังก์ชั่น1
ซึ่งรับสองสตริง (“Parameter1” และ “Parameter2”) เป็นพารามิเตอร์ ผลลัพธ์จะเป็นสตริงเช่น: “กำลังตรวจสอบ พารามิเตอร์1, พารามิเตอร์2"
ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงที่คุณทำใช้งานได้
เพื่อกำหนดวิธีการสร้างส่วนประกอบ นักพัฒนาจะต้องใช้วิธีการต่อไปนี้ในโค้ดไลบรารี AddInNative:
รับวิธีการ
ค้นหาวิธีการ เท็จรับMethodName
ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติ
เท็จรับ NParams
ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0
รับ ParamDefValue เท็จเกิดข้อผิดพลาดรันไทม์และการดำเนินการของโมดูล 1C: Enterprise สิ้นสุดลง หน่วยความจำสำหรับอาร์เรย์ของพารามิเตอร์ได้รับการจัดสรรโดย 1C: Enterprise หากค่าที่ส่งคืนเป็นชนิดข้อมูลสตริงหรือไบนารี ส่วนประกอบจะจัดสรรหน่วยความจำด้วยฟังก์ชัน AllocMemoryผู้จัดการหน่วยความจำ เขียนข้อมูลที่นั่นและจัดเก็บที่อยู่นี้ในช่องที่เกี่ยวข้องของโครงสร้าง 1C: องค์กรจะเพิ่มหน่วยความจำนี้โดยการโทร ฟรีหน่วยความจำ.
คำอธิบายวิธีการโดยสมบูรณ์ รวมถึงรายการพารามิเตอร์ มีการอธิบายโดยละเอียดในเอกสารประกอบที่ให้มาในดิสก์ ITS
พิจารณาการนำวิธีการที่อธิบายไว้ข้างต้นไปใช้
ในโค้ดส่วนประกอบ มีการกำหนดอาร์เรย์สองตัว:
wchar_t แบบคงที่ *g_MethodNames = (L "เปิดใช้งาน", L "ปิดการใช้งาน", L "ShowInStatusLine", L "StartTimer", L "StopTimer", L "LoadPicture"); wchar_t แบบคงที่ *g_MethodNamesRu = (L"เปิดใช้งาน", L"ปิดการใช้งาน", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
และการแจงนับ:
วิธีการแจงนับ ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // เสมอ);
พวกมันถูกใช้ในฟังก์ชั่น ขยายรายการวิธีการ, ขยายฟังก์ชันการทำงานของส่วนประกอบภายนอกด้วยฟังก์ชันต่อไปนี้:สาธิตคอม.เปิดใช้งาน(); สำรวจวิธีการนำวิธีส่วนประกอบภายนอกไปใช้โดยการเปรียบเทียบกับคำอธิบายคุณสมบัติ
วิธีการ ฟังก์ชั่น1, ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงที่คุณทำใช้งานได้, รับวิธีการใช้สวิตช์ ขึ้นอยู่กับพารามิเตอร์ที่ส่งผ่านและตรรกะของแอปพลิเคชัน ให้ส่งคืนค่าที่ต้องการ วิธี รับวิธีการในโค้ดจะมีรายการวิธีการเดียวที่สามารถส่งคืนผลลัพธ์ได้ เขากลับมาเพื่อพวกเขา จริง- สำหรับผลตอบแทนจากวิธีเหล็กทั้งหมด เท็จ.
วิธีการ ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติสาธิตคอม.เปิดใช้งาน(); ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0มีโค้ดที่ปฏิบัติการได้โดยตรงของวิธีการ
หากต้องการเพิ่มเมธอดที่สามารถเรียกว่าเป็นฟังก์ชันได้เท่านั้น คุณต้องทำการเปลี่ยนแปลงต่อไปนี้กับซอร์สโค้ดของส่วนประกอบภายนอก:
  1. เพิ่มชื่อวิธีการให้กับอาร์เรย์ g_MethodNamesสาธิตคอม.เปิดใช้งาน(); g_MethodNamesRu(ไฟล์ AddInNative.cpp)
  2. เพิ่มตัวระบุวิธีการที่มีความหมายในการแจงนับวิธีการ (file AddInNative.h)
  3. ทำการเปลี่ยนแปลงโค้ดฟังก์ชัน ฟังก์ชั่น1ตามลอจิกของโปรแกรม
  4. หากจำเป็น ให้ทำการเปลี่ยนแปลงรหัสวิธีการ ตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงที่คุณทำใช้งานได้หากคุณต้องการใช้ค่าเริ่มต้นของพารามิเตอร์วิธีการ
  5. ทำการเปลี่ยนแปลงฟังก์ชัน รับวิธีการ
  6. ทำการเปลี่ยนแปลงตรรกะของฟังก์ชัน ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติหรือ ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0โดยวางโค้ดที่ปฏิบัติการได้โดยตรงของวิธีการไว้ที่นั่น
มานำเสนออาร์เรย์กัน g_MethodNamesสาธิตคอม.เปิดใช้งาน(); g_MethodNamesRuตลอดจนรายการ วิธีการไปที่แบบฟอร์ม:
wchar_t แบบคงที่ *g_MethodNames = (L "เปิดใช้งาน", L "ปิดการใช้งาน", L "ShowInStatusLine", L "StartTimer", L "StopTimer", L "LoadPicture", L "ทดสอบ"); wchar_t แบบคงที่ *g_MethodNamesRu = (L"เปิดใช้งาน", L"ปิดการใช้งาน", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"โหลดภาพ", L"ทดสอบ");

วิธีการแจงนับ ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // เสมอ);
มาแก้ไขฟังก์ชั่นกันดีกว่า ขยายรายการคุณสมบัติ VKเพื่อให้ส่งกลับจำนวนพารามิเตอร์ของวิธี "ทดสอบ":
ยาว CAddInNative::GetNParams (const ยาว lMethodNum) ( สวิตช์ (lMethodNum) ( กรณี eMethShowInStatusLine: กลับ 1; กรณี eMethLoadPicture: กลับ 1; กรณี eMethTest: กลับ 2; ค่าเริ่มต้น: กลับ 0; ) กลับ 0; )
มาทำการเปลี่ยนแปลงฟังก์ชั่นกัน:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( ​​TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( case eMethEnable: case eMethDisable: case eMethShowInStatusLine: case eMethStartTimer : case e MethStopTimer: กรณี eMethTest : / / ไม่มีค่าพารามิเตอร์ตามค่าเริ่มต้น ตัวแบ่ง ค่าเริ่มต้น: return false;
ขอบคุณที่เพิ่มบรรทัด
กรณี eMethTest:
หากไม่มีอาร์กิวเมนต์อย่างน้อยหนึ่งรายการ พารามิเตอร์ที่เกี่ยวข้องจะมีค่าว่าง ( VTYPE_EMPTY- หากคุณต้องการค่าเริ่มต้นสำหรับพารามิเตอร์ คุณควรตั้งค่าในส่วนนี้ eMethTestคำสั่งสวิตช์ฟังก์ชัน CAddInNative::GetParamDefValue.
เนื่องจากวิธีทดสอบสามารถคืนค่าได้ คุณจึงต้องทำการเปลี่ยนแปลงโค้ดฟังก์ชัน รับวิธีการ:
bool CAddInNative::HasRetVal(const long lMethodNum) ( สวิตช์(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; default: return false; ) return false; )
และเพิ่มรหัสปฏิบัติการของวิธีการให้กับฟังก์ชัน ส่งกลับจำนวนพารามิเตอร์วิธีการที่มีหมายเลขลำดับที่ระบุ ถ้าไม่มีวิธีการที่มีตัวเลขนี้หรือไม่มีพารามิเตอร์ จะส่งคืนค่า 0:
บูล CAddInNative::CallAsFunc (const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch (lMethodNum) ( case eMethLoadPicture: ... break; case eMethTest: if (!lSizeArray || !paParams) ส่งคืน false; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstring_to_p(std::wstring(s1+s2), pvarRetValue); ;
มาคอมไพล์ส่วนประกอบและนำโค้ดการกำหนดค่ามาไว้ในแบบฟอร์ม:
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...", "DemoVK", ประเภทส่วนประกอบภายนอก.เนทิฟ);
DemoComp = ใหม่ ("AddIn.DemoVK.SomeName");

lane = DemoComp.Test("สวัสดี" "โลก!");

บูล CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; if (m_iMemory) ( if(m_iMemory->AllocMemory ((เป็นโมฆะ**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) ส่งคืนค่าเท็จ;
  1. รายงาน(ต่อ); สิ้นสุดขั้นตอน
  2. หลังจากเปิดตัวการกำหนดค่า เราจะได้รับข้อความ: “Hello, World!” ซึ่งระบุว่าวิธีนี้ใช้ได้ผลสำเร็จ
  3. ประเภท.h

ตัวจับเวลา ศึกษาการใช้งานตัวจับเวลาในการสาธิต VK- ข้อความนี้จะถูกส่งไปยังโปรแกรมของคุณตามช่วงเวลาที่คุณกำหนดไว้เมื่อสร้างตัวจับเวลา
หากต้องการสร้างตัวจับเวลา ให้ใช้ฟังก์ชัน ตั้งเวลา:
UINT SetTimer(HWND hWnd, // ตัวอธิบายหน้าต่าง UINT nIDevent, // ตัวระบุตัวจับเวลา (หมายเลข) UINT nElapse, // หน่วงเวลา TIMERPROC lpTimerFunc); // ตัวชี้ไปยังฟังก์ชัน
ระบบปฏิบัติการจะส่งข้อความ ศึกษาการใช้งานตัวจับเวลาในการสาธิต VKเข้าสู่โปรแกรมตามช่วงเวลาที่ระบุในอาร์กิวเมนต์ nElapse(เป็นมิลลิวินาที) ในพารามิเตอร์สุดท้าย คุณสามารถระบุฟังก์ชันที่จะดำเนินการในแต่ละครั้งที่ตัวจับเวลาเริ่มทำงาน ส่วนหัวของฟังก์ชันนี้ควรมีลักษณะดังนี้ (ชื่ออาจเป็นอะไรก็ได้):
เป็นโมฆะ __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
ลองพิจารณาการใช้งานตัวจับเวลาใน VC สาธิต
เนื่องจากเรากำลังพิจารณากระบวนการพัฒนาส่วนประกอบภายนอกสำหรับตระกูล Windows OS เราจะไม่พิจารณาการใช้งานตัวจับเวลาในระบบปฏิบัติการอื่น โดยเฉพาะสำหรับ GNU/Linux OS การใช้งานจะแตกต่างกันในรูปแบบไวยากรณ์ของฟังก์ชัน ตั้งเวลาสาธิตคอม.เปิดใช้งาน(); จับเวลาProc.
รหัสปฏิบัติการเรียกวิธีการ ตั้งเวลาซึ่งฟังก์ชันถูกส่งผ่านไป MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
ID ของตัวจับเวลาที่สร้างขึ้นจะถูกวางไว้ในตัวแปร m_uiTimerเพื่อที่จะสามารถปิดการใช้งานได้ในภายหลัง
การทำงาน MyTimerProcดูเหมือนว่านี้:
VOID CALLBACK MyTimerProc (HWND hwnd, // หมายเลขอ้างอิงของหน้าต่างสำหรับข้อความจับเวลา UINT uMsg, // WM_TIMER ข้อความ UINT idEvent, // ตัวระบุตัวจับเวลา DWORD dwTime // เวลาของระบบปัจจุบัน) ( if (!pAsyncEvent) return; wchar_t *who = L "ComponentNative", *อะไร = L"ตัวจับเวลา"; , อะไร, wstime); ลบ wstime;
สาระสำคัญของฟังก์ชันคือการเรียกเมธอด เหตุการณ์ภายนอกซึ่งส่งข้อความไปยังระบบ 1C: Enterprise
เพื่อขยายการทำงานของวิธีการ และสายนับนาฬิกาของระบบมาทำสิ่งต่อไปนี้:
การปรับเปลี่ยนรหัสวิธีการ ฟังก์ชั่น1เพื่อให้เป็นวิธีการ eMethStartTimerค่าที่ส่งคืน 1:
กรณี eMethStartTimer: ส่งคืน 1;
นี่คือรหัสวิธีการ ออกแบบมาเพื่อให้ได้จำนวนวิธีที่สอดคล้องกัน ค้นหาหมายเลขและชื่อของวิธี คล้ายกับวิธีการที่สอดคล้องกันสำหรับคุณสมบัติไปที่แบบฟอร์ม:
กรณี eMethStartTimer: ถ้า (!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;
ตอนนี้เรามาตรวจสอบฟังก์ชันการทำงานกัน เมื่อต้องการทำเช่นนี้ เราจะเขียนโค้ดในโมดูลแอปพลิเคชันที่ได้รับการจัดการของการกำหนดค่า:
ตัวแปร DemoComp; ขั้นตอนที่เมื่อระบบเริ่มทำงาน() เชื่อมต่อส่วนประกอบภายนอก ("...", "DemoVK", ประเภทส่วนประกอบภายนอก.เนทิฟ);
หลังจากเริ่มการกำหนดค่าโปรแกรมจะได้รับข้อความในช่วงเวลา 2 วินาทีซึ่งแสดงว่าตัวจับเวลาทำงานถูกต้อง

การโต้ตอบกับระบบ 1C: Enterprise

ในการโต้ตอบระหว่างส่วนประกอบภายนอกและระบบ 1C: Enterprise วิธีการของคลาส IAddInDefBase ที่อธิบายไว้ในไฟล์ AddInDefBase.h- เราแสดงรายการที่ใช้บ่อยที่สุด:
การสร้างข้อความแสดงข้อผิดพลาด
บูลเสมือน ADDIN_API AddError (wcode สั้นที่ไม่ได้ลงนาม, แหล่งที่มา const WCHAR_T*, const WCHAR_T* descr, scode แบบยาว)
wcode, รหัส- รหัสข้อผิดพลาด (รายการรหัสข้อผิดพลาดพร้อมคำอธิบายสามารถพบได้ในดิสก์ ITS)
แหล่งที่มา- แหล่งที่มาของข้อผิดพลาด
คำอธิบาย- คำอธิบายข้อผิดพลาด
ส่งข้อความไปยังระบบ 1C: Enterprise
บูลเสมือน ADDIN_API ExternalEvent (WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- แหล่งที่มาของข้อความ
wszMessage- ข้อความ
wszData- ข้อมูลที่ส่ง
การสกัดกั้นข้อความดำเนินการโดยขั้นตอนการประมวลผลเหตุการณ์ภายนอก
การลงทะเบียนส่วนประกอบภายนอกในระบบ 1C: Enterprise
บูลเสมือน ADDIN_API RegisterProfileAs (WCHAR_T* wszProfileName)
wszProfileName- ชื่อส่วนประกอบ
วิธีการเหล่านี้เพียงพอสำหรับการโต้ตอบอย่างสมบูรณ์ระหว่าง VK และ 1C ในการรับข้อมูลโดยส่วนประกอบภายนอกจากระบบ 1C: Enterprise และในทางกลับกัน ส่วนประกอบภายนอกจะส่งข้อความพิเศษซึ่งจะถูกดักโดยระบบ 1C และหากจำเป็น ให้เรียกวิธีการของส่วนประกอบภายนอกเพื่อส่งข้อมูลกลับ .

ชนิดข้อมูล tVariant

เมื่อแลกเปลี่ยนข้อมูลระหว่างส่วนประกอบภายนอกและระบบ 1C: Enterprise จะใช้ประเภทข้อมูล tVariant มีการอธิบายไว้ในไฟล์ types.h ซึ่งสามารถพบได้บนดิสก์ ITS:
struct _tVariant ( _ANONYMOUS_UNION ยูเนี่ยน ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; ไม่ได้ลงนาม int uintVal; int64_t llVal; uint8_t ui8Val; uint16_t ushortVal; uint32_t ulVal; t ; int32_t errCode; float fltVal; struct tm tmVal; // VARIANT_NAME_3/*str*/; _VARIANT_NAME_2/*iface*/; pstrVal; uint32_t strLen ; // จำนวนไบต์ ) __VARIANT_NAME_3/*str*/; ) __VARIANT_NAME_1 ; อาร์เรย์มิติใน pvarVal TYPEVAR vt);
พิมพ์ tตัวแปรเป็นโครงสร้างที่ประกอบด้วย:
  • ส่วนผสม (ยูเนี่ยน) มีไว้สำหรับการจัดเก็บข้อมูลโดยตรง
  • ตัวระบุชนิดข้อมูล
โดยทั่วไปการทำงานกับตัวแปรประเภท tตัวแปรเกิดขึ้นตามอัลกอริทึมต่อไปนี้:
  1. การกำหนดประเภทของข้อมูลที่จัดเก็บไว้ในตัวแปรในปัจจุบัน
  2. เข้าถึงฟิลด์ส่วนผสมที่เกี่ยวข้องเพื่อเข้าถึงข้อมูลโดยตรง
โดยใช้ชนิด tตัวแปรลดความซับซ้อนของการโต้ตอบของ 1C: ระบบองค์กรและส่วนประกอบภายนอกได้ง่ายขึ้นอย่างมาก

แอปพลิเคชัน

ไดเรกทอรี “ตัวอย่าง” มีตัวอย่างสำหรับบทความ
ตัวอย่าง/1 - เปิดส่วนประกอบสาธิต
ตัวอย่าง/2 - การสาธิตการขยายรายการทรัพย์สิน
ตัวอย่าง/3 - การสาธิตการขยายรายการวิธีการ
แต่ละไดเร็กทอรีประกอบด้วยโปรเจ็กต์ VS 2008 และการกำหนดค่า 1C สำเร็จรูป

เทคโนโลยีของส่วนประกอบภายนอกช่วยให้คุณสร้างโปรแกรม (ส่วนประกอบภายนอก) ที่จะเชื่อมต่อแบบไดนามิกและโต้ตอบอย่างใกล้ชิดกับระบบ 1C:Enterprise 8 เพื่อขยายขีดความสามารถ เทคโนโลยีนี้ช่วยให้คุณเชื่อมต่ออุปกรณ์ค้าปลีกต่างๆ เข้ากับระบบ 1C:Enterprise 8: เครื่องสแกนบาร์โค้ด เครื่องพิมพ์ฉลาก ฯลฯ

API ดั้งเดิม

เทคโนโลยีถูกนำมาใช้เพื่อสร้างส่วนประกอบภายนอก API ดั้งเดิม– อินเทอร์เฟซการเขียนโปรแกรมระบบของตัวเอง 1C:Enterprise 8 รองรับระบบปฏิบัติการ Windows และ Linux และทำให้สามารถสร้างส่วนประกอบภายนอกที่ทำงานภายใต้ระบบปฏิบัติการทั้งสองระบบได้ ส่วนประกอบที่สร้างขึ้นโดยใช้เทคโนโลยี Native API สามารถเชื่อมต่อในไคลเอ็นต์แบบหนา ในไคลเอ็นต์แบบบาง ในเว็บไคลเอ็นต์ ในการเชื่อมต่อภายนอก และในแอปพลิเคชันเซิร์ฟเวอร์

ส่วนขยายภาษาในตัว

ส่วนประกอบภายนอกช่วยให้คุณสามารถขยายภาษาในตัวด้วยออบเจ็กต์ใหม่ โครงสร้างของกลไกของส่วนประกอบภายนอกนั้นใกล้เคียงกับโครงสร้างภายในของระบบ 1C:Enterprise 8 มากที่สุดซึ่งจะช่วยเพิ่มประสิทธิภาพในการดำเนินงาน

การเรียกขั้นตอนเพื่อจัดการกับเหตุการณ์ที่ควบคุมโดยส่วนประกอบภายนอก

ส่วนประกอบภายนอกสามารถทำให้เกิดเหตุการณ์ที่ถูกประมวลผลในขั้นตอนภาษาที่กำหนดไว้ล่วงหน้า การจัดการเหตุการณ์ภายนอก- สิ่งนี้ช่วยให้คุณเชื่อมต่อเครื่องสแกนและอุปกรณ์อื่น ๆ ที่ต้องมีการแลกเปลี่ยนข้อมูลแบบอะซิงโครนัสกับระบบ 1C:Enterprise 8

การเพิ่มหน้าคุณสมบัติให้กับพารามิเตอร์ 1C:Enterprise 8

ส่วนประกอบภายนอกสามารถเพิ่มหน้าคุณสมบัติของตนลงในกล่องโต้ตอบพารามิเตอร์ระบบ 1C:Enterprise 8 ได้ ดังนั้น อุปกรณ์การขายปลีกจึงสามารถรวมไว้ในระบบและจัดการด้วยวิธีมาตรฐานสำหรับระบบ 1C:Enterprise 8

บันทึกพารามิเตอร์ส่วนประกอบผ่านกลไกการบันทึกพารามิเตอร์ “1C:Enterprise 8”

ในขณะที่บันทึกพารามิเตอร์ ส่วนประกอบภายนอกสามารถใช้กลไกของระบบ 1C:Enterprise 8 ได้

การเข้าถึงแถบสถานะ

ในระหว่างการดำเนินการ สถานะของส่วนประกอบภายนอกสามารถสะท้อนให้เห็นได้ในแผงสถานะของระบบ 1C:Enterprise 8