การเขียนโปรแกรมโครงสร้างปลั๊กอินต้องใช้คอนเทนเนอร์ปลั๊กอินเพื่อควบคุมการทำงานของ DLL แต่ละตัว และจัดเรียงระบบย่อยแต่ละระบบที่ถูกแบ่งให้เป็นไฟล์ไลบรารี DLL สำหรับแต่ละโปรแกรม DLL ฟังก์ชันอินเทอร์เฟซจำเป็นต้องสงวนไว้สำหรับคอนเทนเนอร์ โดยทั่วไป ฟังก์ชันอินเทอร์เฟซจะประกอบด้วย: ฟังก์ชันที่เริ่มเรียกใช้ไลบรารี DLL และฟังก์ชันที่ปิดไลบรารี DLL ผ่านฟังก์ชันอินเทอร์เฟซ คอนเทนเนอร์ปลั๊กอินสามารถส่งพารามิเตอร์ไปยังโมดูล DLL เพื่อให้เกิดการควบคุมแบบไดนามิก ฉันจะอธิบายรายละเอียดการใช้งานเฉพาะและให้โค้ดตอบกลับด้านล่าง
คุณอาจต้องเข้าใจโครงสร้างของ UNIT และโครงสร้างของโครงการใน DELPHI ก่อน บทความนี้ไม่ได้กล่าวถึงรายละเอียดทางทฤษฎีของการเขียนโปรแกรม DLL ในเชิงลึก แต่สาธิตเฉพาะโค้ดที่ใช้งานได้จริงบางส่วนเท่านั้น ฉันกำลังศึกษาหนังสือ "DELPHI In- allowance of Programming" โดย Liu Yi
ฉันยังอยู่ในช่วงเริ่มต้นของ DELPHI ฉันรู้สึกว่ามีบางสิ่งที่ควรค่าแก่การพูดคุยในการพัฒนา DLL นี้ ฉันจึงเขียนบทความนี้ ฉันหวังว่าคุณจะสามารถให้คำแนะนำที่ดีเกี่ยวกับสิ่งที่ฉันทำได้ไม่ดี
ความรู้เบื้องต้นเกี่ยวกับโปรแกรมตัวอย่าง
เพื่ออำนวยความสะดวกในการอ่าน ฉันจะใช้ส่วนหนึ่งของโค้ดโปรแกรมของระบบ MIS เพื่อสาธิตวิธีการเขียนโปรแกรมปลั๊กอินบางอย่าง โปรแกรมตัวอย่างเป็นแอปพลิเคชัน DBMS โครงสร้าง C/S ทั่วไป เราจะเน้นที่คำสั่งควบคุมของโปรแกรมกรอบงาน (ต่อไปนี้จะเรียกว่า Hall) และการควบคุมการตอบสนองของโปรแกรมปลั๊กอิน dll
1. โครงสร้างโปรแกรม
ปลั๊กอินคอนเทนเนอร์ฮอลล์ถูกสร้างขึ้นโดยใช้โครงการอิสระ หน้าต่างหลักของฮอลล์เทียบเท่ากับฟอร์มคอนเทนเนอร์ MDI ในโปรแกรม MDI ฟังก์ชันอินเทอร์เฟซใน Dll จะถูกเรียกอย่างชัดเจนในฮอลล์
โปรแกรมปลั๊กอินแต่ละตัวใช้โปรเจ็กต์ของตัวเองอย่างอิสระ โปรเจ็กต์ DLL จะสร้าง Dll Wizard แตกต่างจากโปรเจ็กต์ทั่วไป และไฟล์ที่สร้างโดยการคอมไพล์ที่เกี่ยวข้องจะมี DLL ต่อท้าย
=550) window.open('/upload/20080315181507424.jpg');" src="http://files.VeVB.COm/upload/20080315181507424.jpg" onload="if(this.width>'550')this.width='550';if(this.height>'1000')this.height='1000';" เส้นขอบ = 0>
2. การออกแบบส่วนต่อประสาน
ในตัวอย่างโปรแกรม Narcissus เราสงวนฟังก์ชันอินเทอร์เฟซไว้ 2 ฟังก์ชัน:
แสดง DLLForm
ฟังก์ชันนี้ส่งผ่านหมายเลขอ้างอิงของแอปพลิเคชันไปยังหน้าต่างลูก DLL และโปรแกรม DLL จะสร้างอินสแตนซ์ของแบบฟอร์ม DLL แบบไดนามิก คุณยังสามารถส่งตรรกะทางธุรกิจบางอย่างไปยังหน้าต่างย่อย DLL ในรูปแบบของพารามิเตอร์ เช่น ชื่อแบบฟอร์ม ชื่อผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน เป็นต้น ใช้ฟังก์ชันนี้เพื่อสร้างอินสแตนซ์ของฟอร์ม DLL เมื่อมีการเรียกเป็นครั้งแรก
FreeDLLForm.dll
ฟังก์ชันนี้จะแสดงการเปิดตัวอินสแตนซ์หน้าต่าง DLL และเรียกใช้เมธอด FreeDLLForm ของแบบฟอร์ม DLL แต่ละฟอร์มเพื่อปล่อยอินสแตนซ์ที่สร้างขึ้นเมื่อออกจากแอปพลิเคชัน มิฉะนั้น จะทำให้เกิดข้อผิดพลาดแบบอ่านอย่างเดียวของหน่วยความจำ ในทำนองเดียวกัน คุณยังสามารถส่งผ่านตรรกะทางธุรกิจบางอย่างที่จำเป็นต้องดำเนินการเมื่อปล่อยแบบฟอร์มไปยังแบบฟอร์ม DLL ในรูปแบบของพารามิเตอร์
3. วิธีการแก้ไขจุดบกพร่อง
โปรแกรมฟอร์ม DLL ไม่สามารถดำเนินการได้โดยตรง และต้องมีคอนเทนเนอร์ปลั๊กอินจึงจะเรียกใช้ได้ ดังนั้นเราจึงจำเป็นต้องติดตั้งโปรแกรม Hall พื้นฐานก่อน จากนั้นจึงบันทึก Hall.exe ลงในไดเร็กทอรีคงที่ ทำการตั้งค่าต่อไปนี้สำหรับแต่ละโครงการ DLL:
1) เปิดโครงการ DLL
2) เลือกเมนู เรียกใช้พารามิเตอร์
3) เรียกดูคอนเทนเนอร์ Hall.exe ของเราในหน้าต่างป๊อปอัป
ด้วยวิธีนี้ โปรแกรม Hall จะถูกเรียกโดยอัตโนมัติเมื่อทำการดีบั๊กโปรแกรม DLL และโปรแกรม DLL จะถูกดีบั๊กโดยใช้อินเทอร์เฟซการเรียกที่สงวนไว้ใน Hall
การใช้งานโปรแกรมปลั๊กอินขั้นพื้นฐาน
วิธีการออกแบบของโปรแกรม DLL ไม่แตกต่างจาก WINAPP ทั่วไปมากนัก ยกเว้นว่าหน้าต่างทั้งหมดจะถูกบันทึกในไลบรารี DLL เป็น "ทรัพยากร" พิเศษ และจำเป็นต้องเรียกใช้ด้วยตนเอง ไม่เหมือนใน WINAPP ที่โปรเจ็กต์จะถูกสร้างขึ้นโดยอัตโนมัติ วิธีการประกาศฟังก์ชันอินเทอร์เฟซนั้นง่ายมาก
1) ประกาศฟังก์ชันในส่วนการดำเนินการของหน่วย
2) เพิ่มเครื่องหมาย stdcall ที่ส่วนท้ายของคำสั่งประกาศฟังก์ชัน
3) ก่อนคำสั่งเริ่มต้นของรหัสโครงการ (Project View Source) ให้ใช้คำสั่งส่งออกเพื่อประกาศอินเทอร์เฟซฟังก์ชัน
เพื่อให้โค้ดกระชับ โดยส่วนตัวแล้วฉันชอบที่จะเพิ่มหน่วยหน่วย (ไฟล์ใหม่ - หน่วย) อย่างอิสระในโปรเจ็กต์ จากนั้นจึงกำหนดส่วนของฟังก์ชันทั้งหมดที่จะส่งออกในหน่วยนี้ อย่าลืมใช้ the ด้วย หน่วยของแบบฟอร์มที่อ้างอิงเข้ามา ฉันตั้งชื่อหน่วยนี้ว่า UnitEntrance เริ่มต้นหน้าต่างที่จะแสดงในฟังก์ชัน ShowDLLForm และเรียกวิธีการแสดงเพื่อแสดง HALL จะส่งชื่อผู้ใช้ที่เข้าสู่ระบบเป็นพารามิเตอร์ หลังจากได้รับชื่อผู้ใช้แล้ว การควบคุมสิทธิ์บางอย่างก็สามารถทำได้ สะท้อนให้เห็นในการเริ่มต้นอินเทอร์เฟซที่เหนือกว่า
รหัสมีดังนี้
หน่วย หน่วยสำนักงานทางเข้า;
อินเตอร์เฟซ
การใช้งาน
Windows, ข้อความ, SysUtils, ตัวแปร, คลาส, กราฟิก, การควบคุม, แบบฟอร์ม;
ฟังก์ชัน ShowDLLForm (AHandle: THandle; ACaption: string; AUserID: string): บูลีน; stdcall;
ฟังก์ชัน FreeDLLForm (AHandle: THandle; ACaption: string; AUserID: string): บูลีน; stdcall;
การดำเนินการ
ใช้ UnitOfficialMainForm; // เปลี่ยนเป็นหน่วยของ MAINFORM
var
DLL_Form:TFormOfficialMain; //เปลี่ยนชื่อเป็น MAINFORM
-
//ชื่อ: ShowDLLForm
//Func: ปลั๊กอิน DLL เรียกใช้ฟังก์ชันรายการ
//Para: AHandle แนบชื่อโปรแกรม ACaption ของแบบฟอร์มนี้
//รายงาน: N/A
//รับรองความถูกต้อง: CST
//วันที่: 2548-6-3
-
ฟังก์ชัน ShowDLLForm (AHandle: THandle; ACaption: string; AUserID: string): บูลีน;
เริ่ม
ผลลัพธ์:=จริง;
พยายาม
Application.Handle:=AHandle; //Anched ไปยังคอนเทนเนอร์โปรแกรมหลัก
DLL_Form:=TFormOfficialMain.Create(Application); //เปลี่ยนเป็น NAME ของ MAINFORM
พยายาม
ด้วย DLL_Form ทำ
เริ่ม
คำบรรยายภาพ := ACaption;
StatusBar.Panels.Items[0].ข้อความ := AUserID;
//กำหนดค่า UI
แสดง ;
จบ;
ยกเว้น
บน e: ข้อยกเว้นทำ
เริ่ม
dll_form.ฟรี;
จบ;
จบ;
ยกเว้น
ผลลัพธ์:=เท็จ;
จบ;
จบ;
-
//ชื่อ: FreeDLLForm
//Func: ปลั๊กอิน DLL เรียกใช้ฟังก์ชันส่งออก
//Para: AHandle แนบตัวจัดการโปรแกรม
//Rtrn: จริง/เท็จ
//รับรองความถูกต้อง: CST
//วันที่: 11-6-2548
-
ฟังก์ชัน FreeDLLForm (AHandle: THandle; ACaption: string; AUserID: string): บูลีน;
เริ่ม
Application.Handle:=AHandle; //Anched ไปยังคอนเทนเนอร์โปรแกรมหลัก
ถ้า DLL_Form.Showing แล้ว DLL_Form.Close; //ถ้าหน้าต่างถูกเปิดและปิดก่อน การเรียกใช้ FORM.CLOSEQUERY สามารถยกเลิกกระบวนการปิดได้
ถ้าไม่ใช่ DLL_Form. กำลังแสดงอยู่
เริ่ม
DLL_Form.ฟรี;
ผลลัพธ์:=จริง;
end //ยังคงเปิดอยู่ โดยระบุ CLOSEQUERY.CANCLOSE=FALSE
อื่น
เริ่ม
ผลลัพธ์:=เท็จ;
จบ;
จบ;
จบ.
รหัสไฟล์โครงการ DLL เป็นดังนี้:
เจ้าหน้าที่ห้องสมุด;
{ หมายเหตุสำคัญเกี่ยวกับการจัดการหน่วยความจำ DLL: ShareMem ต้องเป็น
หน่วยแรกในส่วนคำสั่ง USES ของห้องสมุดและโครงการของคุณ (เลือก
Project-View Source) ใช้ส่วนคำสั่งหาก DLL ของคุณส่งออกขั้นตอนใดๆ หรือ
ฟังก์ชันที่ส่งผ่านสตริงเป็นพารามิเตอร์หรือผลลัพธ์ของฟังก์ชัน
ใช้กับสตริงทั้งหมดที่ส่งผ่านไปยังและจาก DLL ของคุณ แม้แต่สตริงนั้นก็ตาม
ซ้อนอยู่ในบันทึกและคลาส ShareMem เป็นหน่วยอินเทอร์เฟซสำหรับ
ตัวจัดการหน่วยความจำที่ใช้ร่วมกัน BORLNDMM.DLL ซึ่งจะต้องปรับใช้พร้อมกัน
ด้วย DLL ของคุณ หากต้องการหลีกเลี่ยงการใช้ BORLNDMM.DLL ให้ส่งผ่านข้อมูลสตริง
โดยใช้พารามิเตอร์ PChar หรือ ShortString }
การใช้งาน
SysUtils,
ชั้นเรียน
UnitOfficialDetailForm ใน 'UnitOfficialDetailForm.pas' {FormOfficialDetail}
UnitOfficialMainForm ใน 'UnitOfficialMainForm.pas' {FormOfficialMain}
UnitOfficeEntrance ใน 'UnitOfficeEntrance.pas'
UnitOfficialClass ใน '../../Public/Library/UnitOfficialClass.pas',
UnitMyDataAdatper ใน '../../Public/Library/UnitMyDataAdatper.pas',
UnitMyHeaders ใน '../../Public/Library/UnitMyHeaders.pas';
{$R *.เรส}
ส่งออก ShowDLLForm, FreeDLLForm; // ฟังก์ชันอินเทอร์เฟซ
เริ่ม
จบ.
เมื่อโปรแกรมปลั๊กอินเรียกหน้าต่าง DLL อินสแตนซ์หน้าต่างจะยังคงอยู่ด้านบนของหน้าต่าง HALL ดังนั้นจึงไม่จำเป็นต้องกังวลเกี่ยวกับการบดบัง
การใช้งานโปรแกรมคอนเทนเนอร์
1. การแนะนำฟังก์ชันอินเทอร์เฟซ
มีสองวิธีในการเรียกใช้ฟังก์ชันในไลบรารี DLL: การเรียกที่ชัดเจนและโดยนัยมีความยืดหยุ่นมากกว่า ดังนั้นเราจึงใช้การเรียกที่ชัดเจน ใน Delphi คุณต้องประกาศประเภทฟังก์ชันสำหรับฟังก์ชันอินเทอร์เฟซ จากนั้นสร้างอินสแตนซ์ของประเภทฟังก์ชัน จริงๆ แล้วอินสแตนซ์เป็นตัวชี้ไปยังฟังก์ชัน เราสามารถเข้าถึงฟังก์ชัน ส่งผ่านพารามิเตอร์ และรับได้ ค่าส่งคืน เพิ่มการประกาศคลาสฟังก์ชันในส่วนอินเทอร์เฟซของไฟล์หน่วย:
พิมพ์
//กำหนดประเภทฟังก์ชันอินเทอร์เฟซ ฟังก์ชันอินเทอร์เฟซมาจากอินเทอร์เฟซ DLL
TShowDLLForm = Function(AHandle:THandle; ACaption: String; AUserID:string):บูลีน;stdcall;
TFreeDLLForm = Function(AHandle:THandle; ACaption: String; AUserID:string):boolean;stdcall;
ฟังก์ชั่นไลบรารีการโทรแสดงต้องมีขั้นตอนต่อไปนี้:
1) โหลดไฟล์ไลบรารี DLL
2) รับที่อยู่ของฟังก์ชัน
3) ดำเนินการฟังก์ชัน
4) ปล่อยไลบรารี DLL
ต่อไปเราจะพูดถึงขั้นตอนเหล่านี้โดยละเอียด
2. โหลดไฟล์ไลบรารี DLL
ไลบรารี DLL สามารถโหลดลงในหน่วยความจำได้โดยการเรียกใช้ฟังก์ชัน API LoadLibrary เราจะไม่กล่าวถึงผลกระทบของ DLL ในการจัดการหน่วยความจำที่นี่ พารามิเตอร์ของ LoadLibrary คือเส้นทางที่อยู่ของไฟล์ DLL หากการโหลดสำเร็จ ตัวแปรประเภท CARDINAL จะถูกส่งกลับเป็นตัวจัดการของไลบรารี DLL หากไม่มีไฟล์เป้าหมายหรือสาเหตุอื่นที่ทำให้โหลด DLL ไฟล์ล้มเหลว 0 จะถูกส่งกลับ
3. สร้างอินสแตนซ์ฟังก์ชันอินเทอร์เฟซ
ฟังก์ชัน API เพื่อรับตัวชี้ฟังก์ชันอินเทอร์เฟซคือ GetProcAddress (ตัวจัดการไฟล์ไลบรารี ชื่อฟังก์ชัน) หากพบฟังก์ชัน ตัวชี้ของฟังก์ชันจะถูกส่งกลับ หากล้มเหลว NIL จะถูกส่งกลับ
กำหนดตัวแปรตัวชี้ฟังก์ชันโดยใช้ประเภทฟังก์ชันที่กำหนดไว้ด้านบน จากนั้นใช้ตัวดำเนินการ @ เพื่อรับที่อยู่ฟังก์ชัน เพื่อให้คุณสามารถใช้ตัวแปรตัวชี้เพื่อเข้าถึงฟังก์ชันได้ รหัสหลักมีดังนี้:
-
var
ShowDLLForm: TShowDLLForm; //อินสแตนซ์ของฟังก์ชันอินเทอร์เฟซ DLL
FreeDLLForm: TFreeDLLForm;
เริ่ม
พยายาม
เริ่ม
APlugin.ProcAddr := LoadLibrary(PCar(sPath));
APlugin.FuncFreeAddr := GetProcAddress(APlugin.ProcAddr,'FreeDLLForm');
APlugin.FuncAddr := GetProcAddress(APlugin.ProcAddr ,'ShowDLLForm');
@ShowDLLForm:=APlugin.FuncAddr;
@FreeDLLForm:=APlugin.FuncFreeAddr;
ถ้า ShowDllForm(Self.Handle, APlugin.Caption, APlugin.UserID) แล้ว
ผลลัพธ์:=จริง
-
4. วิธีการดำเนินการเฉพาะ
เพื่อที่จะจัดการปลั๊กอินในลักษณะที่มีโครงสร้างและอำนวยความสะดวกในการขยายระบบในอนาคต เราสามารถรวมข้อมูล DLL ที่มีอยู่ซึ่งบันทึกไว้ในฐานข้อมูล จากนั้นจึงเข้าถึงโปรแกรม DLL แบบไดนามิกโดยการสืบค้นบันทึกฐานข้อมูล
1) การออกแบบตารางโมดูลระบบ
สำหรับระบบ MIS คุณสามารถใช้เงื่อนไข DBS ที่มีอยู่เพื่อสร้างตารางโมดูลระบบเพื่อบันทึกไฟล์ DLL และข้อมูลที่เกี่ยวข้องซึ่งแมปกับโมดูลระบบ
ประเภทบทบาทของชื่อฟิลด์
ดัชนี AutoIDINT
modAlias นามแฝงโมดูล VARCHAR
ชื่อโมดูล modName VARCHAR
modWndClass สร้างตัวระบุเฉพาะ VARCHAR
เส้นทาง modFile DLL VARCHAR
ข้อความข้อความ modMemo
・นามแฝงของโมดูลใช้เพื่อรวมกฎการตั้งชื่อในระหว่างขั้นตอนการออกแบบการเขียนโปรแกรม โดยเฉพาะอย่างยิ่งสำหรับการอ้างอิงของสมาชิกในทีมในระหว่างการพัฒนาทีม
・ชื่อโมดูลจะถูกส่งผ่านเป็นพารามิเตอร์ ACAPTION ไปยังฟังก์ชัน SHOWDLLFORM เป็นชื่อของหน้าต่าง DLL
・ตัวระบุเฉพาะของแบบฟอร์มคือ CLASSNAME ของหน้าต่างหลักในโมดูลย่อย DLL ซึ่งใช้เพื่อกำหนดหน้าต่างที่จะควบคุมขณะรันไทม์
・เส้นทาง DLL จะบันทึกชื่อไฟล์ DLL ซึ่งจะถูกแปลงเป็นเส้นทางสัมบูรณ์ในโปรแกรม
2) โครงสร้างข้อมูลข้อมูลปลั๊กอิน
การกำหนดอินเทอร์เฟซข้อมูลที่บันทึกข้อมูลที่เกี่ยวข้องกับปลั๊กอินสามารถควบคุมปลั๊กอิน DLL จากส่วนกลางได้ เพิ่มรหัสต่อไปนี้ลงในส่วนของอินเทอร์เฟซ:
พิมพ์
//กำหนดคลาสข้อมูลปลั๊กอิน
TMyPlugins = คลาส
คำอธิบายภาพ:String; //ชื่อแบบฟอร์ม DLL
DllFileName:String; //เส้นทางไฟล์ DLL
WndClass:String; //ระบุแบบฟอร์ม
UserID:string; //ชื่อผู้ใช้
ProcAddr: THandle; // ตัวจัดการไลบรารีที่โหลดโดย LOADLIBRARY
FuncAddr:Pointer; //SHOWDLLFORM ตัวชี้ฟังก์ชัน
FuncFreeAddr:Pointer; //ตัวชี้ฟังก์ชัน FREEDLLFORM
จบ;
-
สร้างอินสแตนซ์ของ TMyPlugins สำหรับแต่ละปลั๊กอิน วิธีการเริ่มต้นสำหรับอินสแตนซ์เหล่านี้จะกล่าวถึงด้านล่าง
3) ฟังก์ชั่นการโหลดปลั๊กอิน
ในตัวอย่างนี้ หน้าต่าง DLL จะถูกโหลดและแสดงในกรณีที่ทริกเกอร์การเปิดหน้าต่างลูกใน HALL หลังจากเหตุการณ์ปุ่มถูกทริกเกอร์ ขั้นแรกให้ตรวจสอบว่า DLL ถูกโหลดตามอินสแตนซ์โครงสร้างปลั๊กอินหรือไม่ หากมีการโหลดแล้ว ให้ควบคุมการแสดงผลหรือการปิดหน้าต่าง หากไม่ได้โหลด ให้เข้าถึงตารางข้อมูลและ กำหนดฟิลด์ให้กับโครงสร้างปลั๊กอิน จากนั้นดำเนินการโหลด
รหัสบางส่วนมีดังนี้
-
-
//ชื่อ: OpenPlugin
//Func: กระบวนการควบคุมข้อมูลปลั๊กอิน: การเริ่มต้น==》ตั้งค่าการอนุญาต==》โหลดหน้าต่าง DLL
// Para: APlugin-TMyPlugins; sAlias นามแฝง;
//รายงาน: N/A
//รับรองความถูกต้อง: CST
//วันที่: 2548-6-2
-
ขั้นตอน TFormHall.OpenPlugin (AFromActn: TAction ; APlugin: TMyPlugins; sAlias: string; sUserID: string);
var hWndPlugin:HWnd;
เริ่ม
//ตรวจสอบว่าหน้าต่างปลั๊กอินโหลด hWndPlugin:=FindWindow(PChar(APlugin.WndClass),nil);
ถ้า hWndPlugin <> 0 ดังนั้น // โหลดหน้าต่างปลั๊กอินแล้ว
เริ่ม
ถ้าไม่ใช่ IsWindowVisible(hWndPlugin) แล้ว
เริ่ม
AFromActn.Checked := จริง;
ShowWindow(hWndPlugin,SW_SHOWDEFAULT); //Display
จบ
อื่น
เริ่ม
AFromActn.checked := เท็จ;
ShowWindow(hWndPlugin,SW_HIDE);
จบ;
ออก; //ออกจากกระบวนการสร้างปลั๊กอิน
จบ;
//เตรียมใช้งานอินสแตนซ์คลาสปลั๊กอิน
ถ้าไม่ใช่ InitializeMyPlugins(APlugin,sAlias) แล้ว
เริ่ม
showmessage('เกิดข้อผิดพลาดในการเริ่มต้นคลาสปลั๊กอิน');
ออก;
จบ;
// รับค่าสิทธิ์ปัจจุบัน
APlugin.UserID := sUserID;
//โหลดหน้าต่าง DLL
ถ้าไม่ใช่ LoadShowPluginForm(APlugin) แล้ว
เริ่ม
showmessage('เกิดข้อผิดพลาดในการโหลดปลั๊กอินศูนย์');
ออก;
จบ;
จบ;
-
//ชื่อ: InitializeMyPlugins
//Func: เริ่มต้นอินสแตนซ์ MYPLUGIN (คำบรรยาย | DllFileName | IsLoaded)
//สำหรับ: APlugin-TMyPlugins
//รายงาน: N/A
//รับรองความถูกต้อง: CST
//วันที่: 2548-6-2
-
ฟังก์ชัน TFormHall.InitializeMyPlugins(APlugin:TMyPlugins; sAlias:String):บูลีน;
var
strSQL:สตริง;
myDA:TMyDataAdapter;
เริ่ม
ผลลัพธ์:=เท็จ;
myDA:=TMyDataAdapter.Create;
strSQL:='SELECT * FROM SystemModuleList โดยที่ modAlias='+QuotedStr(sAlias);
พยายาม
myDA.ดึงข้อมูล(strSQL);
ยกเว้น
บน E: ข้อยกเว้นทำ
เริ่ม
ผลลัพธ์:=เท็จ;
myDA.ฟรี;
ออก;
จบ;
จบ;
พยายาม
เริ่ม
ด้วย myDA.MyDataSet ทำ
เริ่ม
ถ้าไม่ใช่ IsEmpty แล้ว
เริ่ม
APlugin.Caption:= FieldByName('modName').Value;
APlugin.DllFileName := FieldByName('modFile').Value;
APlugin.WndClass := FieldByName('modWndClass').Value;
ผลลัพธ์:=จริง;
จบ;
ปิด;
จบ; //จบด้วย...ทำ...
สิ้นสุด; //สิ้นสุดความพยายาม
ยกเว้น
บน E: ข้อยกเว้นทำ
เริ่ม
ผลลัพธ์:=เท็จ;
myDA.ฟรี;
ออก;
สิ้นสุด; //สิ้นสุดข้อยกเว้น
end; //สิ้นสุดการลอง...ยกเว้น
myDA.ฟรี;
จบ;
-
//ชื่อ: LoadShowPluginForm
//Func: โหลดปลั๊กอิน DLL และแสดงหน้าต่าง
//สำหรับ: APlugin-TMyPlugins
//Rtrn: สร้างจริงสำเร็จแล้ว
//รับรองความถูกต้อง: CST
//วันที่: 2548-6-2
-
ฟังก์ชัน TFormHall.LoadShowPluginForm (const APlugin:TMyPlugins):บูลีน;
var
ShowDLLForm: TShowDLLForm; //อินสแตนซ์ของฟังก์ชันอินเทอร์เฟซ DLL
FreeDLLForm: TFreeDLLForm;
sPath:string; //เส้นทางแบบเต็มของไฟล์ DLL
เริ่ม
พยายาม
เริ่ม
sPath:=ExtractFilepath(Application.ExeName)+ 'ปลั๊กอิน/' + APlugin.DllFileName;
APlugin.ProcAddr := LoadLibrary(PCar(sPath));
APlugin.FuncFreeAddr := GetProcAddress(APlugin.ProcAddr,'FreeDLLForm');
APlugin.FuncAddr := GetProcAddress(APlugin.ProcAddr ,'ShowDLLForm');
@ShowDLLForm:=APlugin.FuncAddr;
@FreeDLLForm:=APlugin.FuncFreeAddr;
ถ้า ShowDllForm(Self.Handle, APlugin.Caption, APlugin.UserID) แล้ว
ผลลัพธ์:=จริง
อื่น
ผลลัพธ์:=เท็จ;
จบ;
ยกเว้น
บน E: ข้อยกเว้นทำ
เริ่ม
ผลลัพธ์:=เท็จ;
ShowMessage('เกิดข้อผิดพลาดในการโหลดโมดูลปลั๊กอิน โปรดตรวจสอบว่าไฟล์ในไดเร็กทอรี PLUGINS เสร็จสมบูรณ์หรือไม่');
จบ;
จบ;
จบ;
-
4) การควบคุมหน้าต่าง DLL
ดังที่โค้ดใน 3) แสดงให้เห็น การเปิดและปิดหน้าต่าง DLL อยู่ที่เลเยอร์การนำเสนอเท่านั้น การปิดหน้าต่างไม่ได้ปล่อยหน้าต่าง DLL จริงๆ เพียงเรียกฟังก์ชัน API FindWindow เพื่อรับตัวจัดการแบบฟอร์มตามหน้าต่าง ตัวระบุ (นั่นคือ Form.name) ใช้พารามิเตอร์ nCmdShow ของฟังก์ชัน SHOWWINDOW ควบคุมการแสดงผล/การซ่อนของหน้าต่าง
นี่เป็นจุดอ่อนในการใช้งานโปรแกรมของฉัน หากใช้วิธี Self.close ในหน้าต่าง DLL จะทำให้เกิดข้อผิดพลาดของหน่วยความจำ ไม่มีทางแก้ไขได้เนื่องจากความสามารถที่จำกัด ดังนั้นจึงเป็นเช่นนั้น ทางเลือกสุดท้าย ดังนั้นจึงต้องซ่อนปุ่มปิดของหน้าต่างหลักของแต่ละโปรแกรม DLL :-ป
5) การเปิดตัวไลบรารี DLL
เมื่อโปรแกรมออก ไลบรารี DLL จะต้องออกทีละรายการตามอินสแตนซ์ข้อมูลปลั๊กอิน ฟังก์ชันในการเผยแพร่ไลบรารี DLL มีดังนี้:
ขั้นตอน TFormHall.ClosePlugin (aPLG: TMyPlugins);
var
FreeDLLForm:TFreeDLLForm;
เริ่ม
ถ้า aPLG.ProcAddr = 0 ให้ออก;
ถ้า aPLG.FuncFreeAddr = ไม่มี ให้ออก;
@FreeDLLForm:=aPLG.FuncFreeAddr;
ถ้าไม่ใช่ FreeDLLForm(Application.Handle,'','') แล้ว
showMessage('ผิดพลาด');
จบ;
สรุป
ผลการรันของโปรแกรมตัวอย่างนี้เป็นดังนี้:
=550) window.open('/upload/20080315181507979.jpg');" src="http://files.VeVB.COm/upload/20080315181507979.jpg" onload="if(this.width>'550')this.width='550';if(this.height>'1000')this.height='1000';" เส้นขอบ = 0>
ในบรรดาวิธีการข้างต้น เนื่องจากมีปัญหามากมายที่ยังไม่ได้รับการแก้ไขเนื่องจากความสามารถที่จำกัด ฉันจึงได้นำวิธีการปกปิดบางอย่างที่ดูไม่สมเหตุสมผลมาใช้ ฉันหวังว่าทุกคนจะสามารถออกแบบวิธีแก้ปัญหาที่ดีขึ้นได้หลังจากลองสักหน่อยแล้ว วิธีที่ดีในการเรียนรู้เพิ่มเติม