ASP (Active Server Page) เป็นผลิตภัณฑ์ของ Microsoft เนื่องจากง่ายต่อการเขียนโปรแกรมและสามารถพัฒนาเว็บไซต์ไดนามิกได้อย่างรวดเร็วด้วยฟังก์ชันที่มีประสิทธิภาพ เว็บไซต์จำนวนมาก (โดยเฉพาะอินทราเน็ต/เอ็กซ์ทราเน็ต) จึงนำโมเดล NT+IIS+ASP มาใช้ ทำให้ ASP เป็น ปัจจุบัน ภาษาสคริปต์ยอดนิยมสำหรับการพัฒนาเว็บไซต์ ในบริการเว็บ บริการอัพโหลดไฟล์เป็นฟังก์ชันทั่วไป แต่ PWS ภายใต้ WIN9X ไม่มีส่วนประกอบที่เกี่ยวข้อง แต่ IIS ภายใต้ NT จัดให้มีโพสต์ ส่วนประกอบตัวรับ แต่ไม่ใช่เรื่องง่ายที่จะใช้เนื่องจากจะตรวจสอบสิทธิ์การเข้าถึง WWW ของผู้ใช้ คุณยังสามารถดาวน์โหลดส่วนประกอบที่เกี่ยวข้องได้จากอินเทอร์เน็ต แต่ส่วนใหญ่เป็นส่วนประกอบเชิงพาณิชย์และส่วนประกอบที่ใช้ในการดาวน์โหลดเป็นเวอร์ชันทดลองระหว่างการใช้งาน เวลาหรือมีข้อจำกัดในการใช้งาน เนื่องจาก ASP สามารถเรียกส่วนประกอบมาตรฐาน OLE/COM ได้ เราจึงสามารถใช้เครื่องมือการเขียนโปรแกรมขั้นสูง เช่น VB/VC/DELPHI เพื่อปรับแต่งส่วนประกอบการอัปโหลดไฟล์ ASP ของเราเองตามความต้องการของเราเอง เพื่อให้ตรงตามข้อกำหนดระบบแอปพลิเคชันของเราเอง
ต่อไปนี้จะกล่าวถึงหลักการและขั้นตอนการใช้งานเฉพาะของการใช้ DELPHI เพื่อพัฒนาส่วนประกอบการอัพโหลดไฟล์สำหรับ ASP
1. หลักการดำเนินการอัพโหลดไฟล์
การอัปโหลดข้อมูลบนเว็บจะต้องเป็นไปตามมาตรฐาน RFC1867 และข้อมูลไฟล์ที่อัปโหลดก็ไม่มีข้อยกเว้น ตัวอย่างเช่น ใช้ไฟล์เพจ HTML ต่อไปนี้ (delphiup.htm) เพื่อเลือกไฟล์อัพโหลด:
<!-- DelphiUp.htm: อินเทอร์เฟซการอัพโหลดไฟล์ -->
<html><head><title>อัพโหลดไฟล์</title></head><body>
ใช้งานการอัพโหลดไฟล์โดยใช้องค์ประกอบการอัพโหลดไฟล์ที่เขียนด้วย DELPHI
<form NAME = "UploadForm" ACTION = "delphiup.asp" METHOD = "POST" ENCTYPE = "หลายส่วน/แบบฟอร์มข้อมูล">
<p>บันทึกไฟล์เป็น: <input TYPE=text NAME="SaveAs">
<p>โปรดเลือกไฟล์ที่จะอัปโหลด: <input TYPE=file NAME="FileData">
<input type="submit" name="b1" value="ยืนยันการอัปโหลด"> </p>
</แบบฟอร์ม>
</body></html>
เมื่อไคลเอนต์เลือกไฟล์ (เช่น Test.TXT ซึ่งมีเนื้อหาเป็น "นี่คือเนื้อหาของไฟล์สำหรับการอัปโหลด") แล้วกด
หลังจากที่ปุ่ม "ยืนยันการอัปโหลด" ส่งข้อมูลแล้ว ข้อมูลที่ได้รับจากโปรแกรมฝั่งเซิร์ฟเวอร์จะมีแบบฟอร์มดังต่อไปนี้:
--------------------------7cf1d6c47c#13#10
การจัดการเนื้อหา: form-data; name="SaveAs"#13#10#13#10
ใหม่ชื่อไฟล์#13#10
--------------------------7cf1d6c47c#13#10
การจัดการเนื้อหา: form-data; name = "FileData"; filename = "D: est.txt"
ประเภทเนื้อหา: ข้อความ/ธรรมดา#13#10#13#10
นี่คือเนื้อหาของไฟล์ที่จะอัปโหลด #13#10
--------------------------7cf1d6c47c#13#10
การจัดการเนื้อหา: form-data; name="b1"#13#10#13#10
ยืนยันการอัปโหลด#13#10
-------------------------------7cf1d6c47c--
ในหมู่พวกเขา "--------------------------------7cf1d6c47c" เป็นตัวคั่นที่ใช้แยกแต่ละฟิลด์ในรูปแบบ ( รูปร่าง);
#13#10 คือการแสดง DELPHI ของการขึ้นบรรทัดใหม่และการป้อนบรรทัด เราคิดได้เช่นนี้ คำอธิบายข้อมูลของแต่ละฟิลด์ในแบบฟอร์มจะเริ่มต้นด้วยตัวคั่น บวกคู่การขึ้นบรรทัดใหม่และการป้อนบรรทัด #13#10; ชื่อโดเมนของแบบฟอร์มเริ่มต้นด้วย "name="" และลงท้ายด้วย """ ; ฟิลด์แบบฟอร์ม ค่าจะเริ่มต้นด้วยอักขระขึ้นบรรทัดใหม่สองคู่และอักขระป้อนบรรทัด #13#10#13#10 และลงท้ายด้วยอักขระขึ้นบรรทัดใหม่และการป้อนบรรทัด #13#10# บวกกับชื่อไฟล์ ขึ้นต้นด้วย "filename="" และลงท้ายด้วย """ ต่อท้าย ด้วยแฟล็กเหล่านี้ เราจะได้รับชื่อและค่าของฟิลด์แบบฟอร์มและชื่อของไฟล์ที่จะอัปโหลด เพื่อให้สามารถอ่านและจัดเก็บข้อมูลไฟล์ได้
2. ขั้นตอนการดำเนินการอัพโหลดไฟล์
หลังจากทำความเข้าใจรูปแบบข้อมูลที่กล่าวถึงข้างต้นแล้ว การเขียนองค์ประกอบการอัปโหลดไฟล์ด้วยตนเองก็ไม่ใช่เรื่องยากอีกต่อไป
(1) เริ่มต้นโครงการเพื่อสร้างส่วนประกอบ ASP
หากคุณไม่คุ้นเคยกับขั้นตอนการใช้ DELPHI ในการพัฒนา OLE Automation Server โปรดดูบทความ "การใช้ DELPHI เพื่อพัฒนา OLE Automation Server สำหรับ ASP" ใน "Electronics and Computers", ฉบับที่ 06, 1999
ในที่นี้เราจะแนะนำขั้นตอนต่างๆ สั้นๆ เท่านั้น
1. สร้างโครงการไลบรารี ActiveX
ใน DELPHI เลือกเมนู File="New... เลือก "ActiveX Library" ในแท็บ ActiveX ของกล่องโต้ตอบ "New Item" และ DELPHI จะสร้างโปรเจ็กต์ DLL โดยอัตโนมัติ PRoject1
2. สร้างส่วนประกอบระบบอัตโนมัติ
ใน DELPHI เลือกเมนู File="New... เลือก "Automation Object" ในแท็บ ActiveX ของกล่องโต้ตอบ "New Item" จากนั้นป้อนชื่อคลาส (เช่น "UploadFile") ใน "Automation Object Wizard กล่องโต้ตอบ " ให้เลือก "หลายรายการ" อินสแตนซ์" หลังจากคลิก "ตกลง" DELPHI จะสร้างไฟล์ TLB (Type Library) Project1_TLB.PAS และไฟล์ PAS (Unit) Unit1.PAS โดยอัตโนมัติ ในหน้าต่างการออกแบบไลบรารีชนิด ให้เปลี่ยนชื่อ Project1 เป็น MyUpload จากนั้นรหัสการลงทะเบียน OLE ของส่วนประกอบการอัพโหลดไฟล์คือ "MyUpload.UploadFile"
3. แนะนำไลบรารีประเภท ASP
เพื่อที่จะใช้ออบเจ็กต์ในตัวทั้งห้าของ ASP (คำขอ, การตอบสนอง, เซิร์ฟเวอร์, แอปพลิเคชัน, เซสชัน) จำเป็นต้องแนะนำไลบรารีประเภท ASP เราใช้อ็อบเจ็กต์ Request เพื่ออ่านข้อมูลที่ส่งผ่านจากไคลเอนต์ไปยังเซิร์ฟเวอร์เป็นหลัก
เลือก "ไลบรารีประเภทการนำเข้า" ในเมนูโครงการ และเลือก "ไลบรารีวัตถุ Microsoft Active Server Pages (เวอร์ชัน)" ในรายการ "ประเภทไลบรารี" ของกล่องโต้ตอบ "ไลบรารีประเภทการนำเข้า" 2.0)" (หากไม่มีตัวเลือกนี้ โปรดตรวจสอบให้แน่ใจว่าได้ติดตั้ง IIS3 หรือสูงกว่า หรือ PWS4 หรือสูงกว่าบนคอมพิวเตอร์ของคุณและ ASP.DLL ได้รับการลงทะเบียนอย่างถูกต้อง) D ELPHI จะสร้างไฟล์ TLB ASPTypeLibrary_TLB.PAS โดยอัตโนมัติ ซึ่งมีการประกาศประเภทอ็อบเจ็กต์ ASP ที่เราต้องการ
4. กำหนดกระบวนการ OnStartPage และ OnEndPage
เมื่อใช้ Server.CreateObject เพื่อสร้างอินสแตนซ์วัตถุ OLE บนเพจ ASP เซิร์ฟเวอร์เว็บจะเรียกเมธอดของมัน OnStartPage และส่งข้อมูลสภาพแวดล้อมแอปพลิเคชัน ASP ไปยังวัตถุ เราสามารถรับข้อมูลไคลเอนต์ในระหว่างกระบวนการนี้ เมื่อมีการเผยแพร่อินสแตนซ์วัตถุ OLE ในเพจ ASP เซิร์ฟเวอร์เว็บจะเรียกใช้เมธอด OnEndPage และเราสามารถดำเนินการสิ้นสุดได้ เช่น การปล่อยหน่วยความจำในระหว่างกระบวนการนี้ ในองค์ประกอบของเรา เราจำเป็นต้องใช้วิธี OnStartPage
ควรกำหนดวิธี OnStartPage ใน Unit1.PAS ต้นแบบฟังก์ชันของ OnStartPage คือ:
ขั้นตอน OnStartPage (AScriptingContext: IUnknown);
พารามิเตอร์ AScriptingContext คือตัวแปรประเภท IScriptingContext ซึ่งประกอบด้วยแอตทริบิวต์ 5 รายการ (คำขอ การตอบกลับ เซิร์ฟเวอร์ แอปพลิเคชัน เซสชัน) ที่สอดคล้องกับออบเจ็กต์บิวท์อิน 5 รายการที่มีชื่อเดียวกันใน ASP
เราจำเป็นต้องเพิ่มเมธอด OnStartPage ให้กับ IUploadFile ในหน้าต่างคำจำกัดความ TLB (View = "Type Library) และคำสั่ง Declaration คือ "procedure OnStartPage (AScriptingContext: IUnknown);"
(2) แยกข้อมูลที่อัพโหลดโดยไคลเอนต์
งานนี้สามารถทำได้ในกระบวนการ OnStartPage
การใช้คุณสมบัติ TotalBytes (ความยาวเนื้อหาข้อมูลคำขอ) และวิธี BinaryRead ในคุณสมบัติคำขอ (ประเภท IRequest) ของ AScriptingContext ข้อมูลข้อมูลคำขอที่อัปโหลดโดยไคลเอ็นต์สามารถอ่านลงในอาร์เรย์ประเภทไบต์ จากนั้นจึงใช้รูปแบบข้อมูลที่กำหนดโดย RFC1867 มาตรฐานในการวิเคราะห์และดึงข้อมูล
1. ขั้นแรกให้กำหนดตัวแปรส่วนตัวหลายตัวของ TUploadFile
เพิ่มการอ้างอิงถึง ASPTypeLibrary_TLB.PAS (การใช้งาน) ในไฟล์หน่วย UP01.PAS (บันทึกโดย Unit1.PAS)
จากนั้นเข้าร่วม
ส่วนตัว
FContentLength: LongInt; // ขอความยาวเนื้อหาข้อมูล
FContentData: Variant;//ข้อมูลเนื้อหา เก็บเนื้อหาข้อมูลคำขอในรูปแบบของอาร์เรย์
FFileName, //ชื่อของไฟล์ที่จะอัพโหลด
FDelimeter: string; //ตัวคั่นฟิลด์แบบฟอร์ม
FScriptingContext: IScriptingContext;//ASP ประมวลผลเนื้อหาบริบท
FFileDataStart //ตำแหน่งเริ่มต้นของข้อมูลไฟล์
FFileDataEnd: LongInt; //ตำแหน่งสิ้นสุดของข้อมูลไฟล์
2. แยกข้อมูลคำขอที่อัพโหลดโดยไคลเอนต์
//ในเหตุการณ์ OnStartPage รับข้อมูลบริบท ASP ขอเนื้อหาข้อมูล ตัวคั่นฟิลด์แบบฟอร์ม และข้อมูลไฟล์
ขั้นตอน TUploadFile.OnStartPage (AScriptingContext: IUnknown);
var
ARequest: IRequest; //WWW ร้องขอวัตถุ
AOleVariant: OleVariant; //บันทึกความยาวของเนื้อหาข้อมูลคำขอ
intDelimterLength: จำนวนเต็ม;//ความยาวตัวคั่น
longIndex, ALongInt, longPos : LongInt;
ContentData: AnsiString;//การแสดงสตริงของเนื้อหาข้อมูลคำขอ
strTemp: สตริง;
FindEndOfFileData: boolean;//ไม่ว่าจะพบตำแหน่งสิ้นสุดของข้อมูลไฟล์หรือไม่
เริ่ม
//แยกข้อมูลคำขอที่อัพโหลดโดยไคลเอนต์
FScriptingContext := AScriptingContext เป็น IScriptingContext;//รับข้อมูลบริบท ASP
ARequest := FScriptingContext.Request;//รับข้อมูลคำขอ WWW
FContentLength := ARequest.TotalBytes;//ขอความยาวเนื้อหาข้อมูล
//สร้างอาร์เรย์แบบไดนามิกเพื่อจัดเก็บเนื้อหาข้อมูลคำขอในรูปแบบของอาร์เรย์
FContentData := VarArrayCreate( [0,FContentLength], varByte );
//จัดเก็บเนื้อหาข้อมูลคำขอลงในอาร์เรย์
AOleVariant := FContentLength;
FContentData := ARequest.BinaryRead(AOleVariant);//อ่านเนื้อหาข้อมูลคำขอ
//แปลงเนื้อหาข้อมูลคำขอให้เป็นสตริงเพื่อให้จัดตำแหน่งได้ง่าย
ข้อมูลเนื้อหา := ';
สำหรับ longIndex := 0 ถึง FContentLength - 1 ทำ
เริ่ม
ContentData := ContentData + chr( ไบต์ ( FContentData[ longIndex ] ));
ถ้า FContentData[ longIndex ] = 0 จะแตก;//0 หมายถึงจุดสิ้นสุดของเนื้อหา
จบ;
3. รับตัวคั่นและอัพโหลดชื่อไฟล์
//รับตัวคั่นของฟิลด์แบบฟอร์ม
longPos := pos( #13#10,ContentData );//ตำแหน่งของการขึ้นบรรทัดใหม่และการป้อนบรรทัด
FDelimeter := Copy( ContentData,1,longPos-1);//เนื้อหาก่อนตำแหน่งนี้เป็นตัวคั่น
//รับชื่อไฟล์พร้อมพาธต้นทาง ในเนื้อหาข้อมูลคำขอ ชื่อไฟล์จะขึ้นต้นด้วย
//การจัดเก็บในรูปแบบ filename="path/filename"
strTemp := 'filename="';//ชื่อไฟล์อยู่หลัง "filename=""
longPos := pos( strTemp, ContentData );//รับตำแหน่ง "filename=""
ถ้า longPos <= 0 แล้ว
เริ่ม
FFileName := ';
FFileDataStart := -1;
FFileDataEnd := -2;
ออก;
จบ;
// รับเนื้อหาก่อนเครื่องหมายคำพูดคู่ถัดไป """ นั่นคือชื่อไฟล์พร้อมเส้นทางต้นทาง
longPos := longPos + ความยาว ( strTemp );
strTemp := ';
สำหรับ longIndex := longPos ถึง FContentLength - 1 ทำ
ถ้า ContentData[ longIndex ] <> '"' แล้ว
strTemp := strTemp + ข้อมูลเนื้อหา [ longIndex ]
อย่างอื่นพัง;
FFileName := strTemp;
4. รับตำแหน่งเริ่มต้นและสิ้นสุดของข้อมูลไฟล์ในเนื้อหาข้อมูลคำขอ
//ตำแหน่งเริ่มต้นของข้อมูลไฟล์อยู่หลัง #13#10#13#10 แรกหลังชื่อไฟล์
ลบ( ContentData, 1, longIndex );
strTemp := #13#10#13#10;
FFileDataStart := longIndex + pos(strTemp, ContentData) + ความยาว(strTemp) - 1;
//ตำแหน่งสิ้นสุดของข้อมูลไฟล์อยู่ก่อน #13#10 ถัดไปและตัวคั่น
//เนื่องจากข้อมูลไฟล์อาจมีอักขระที่ไม่ถูกต้อง ฟังก์ชันการวางตำแหน่งสตริง POS ไม่สามารถใช้งานได้อีกต่อไป
//ค้นหาตำแหน่งของตัวคั่นถัดไป
FFileDataEnd := FFileDataStart;
intDelimterLength := ความยาว ( FDelimeter );
FindEndOfFileData := เท็จ;
ในขณะที่ FFileDataEnd <= FContentLength - intDelimterLength ทำ
เริ่ม
FindEndOfFileData := จริง;
สำหรับ ALongInt := 0 ถึง intDelimterLength - 1 ทำ
ถ้าไบต์( FDelimeter[ ALongInt + 1 ] ) <>
จากนั้น FContentData[FFileDataEnd + ALongInt]
เริ่ม
FindEndOfFileData := เท็จ;
หยุดพัก;
จบ;
ถ้า FindEndOfFileData ก็พัง;
FFileDataEnd := FFileDataEnd + 1;
จบ;
ถ้าไม่ใช่ FindEndOfFileData ดังนั้น FFileDataEnd := FFileDataStart - 1//ไม่พบตัวคั่น
อื่น FFileDataEnd := FFileDataEnd - 3;//ตัวคั่น ข้ามไปข้างหน้า #13#10
จบ;
(3) ส่งข้อมูลไปยังโปรแกรม ASP
หลังจากดำเนินการ (2) องค์ประกอบการอัปโหลดของเราสามารถส่งข้อมูลไปยังโปรแกรม ASP ตามความต้องการได้ ข้อมูลที่มีอยู่ในปัจจุบัน ได้แก่ ชื่อไฟล์ต้นฉบับของไคลเอ็นต์ (FFileName รวมถึงเส้นทาง) ขนาดไฟล์ (FFileDataEnd-FFileDataStart+1)
ขั้นแรก ควรประกาศสองวิธีต่อไปนี้ GetFileName และ GetFileSize ในหน้าต่างการออกแบบ TLB
1. ส่งคืนชื่อไฟล์ต้นฉบับไคลเอนต์ (รวมถึงเส้นทาง)
//ส่งคืนชื่อไฟล์ต้นฉบับของไคลเอ็นต์ (รวมถึงเส้นทาง)
ฟังก์ชัน TUploadFile.GetFileName: OleVariant;
เริ่ม
ผลลัพธ์ := FFileName;//ชื่อไฟล์ต้นฉบับของไคลเอ็นต์ (รวมถึงพาธ)
จบ;
2. ส่งคืนขนาดไฟล์
//ส่งคืนขนาดไฟล์ (ไบต์)
ฟังก์ชัน TUploadFile.GetFileSize: OleVariant;
เริ่ม
ผลลัพธ์ := FFileDataEnd - FFileDataStart + 1;
จบ;
(4) บันทึกไฟล์
หลังจากดำเนินการ (2) องค์ประกอบการอัพโหลดของเราจะสามารถบันทึกไฟล์ตามความต้องการของโปรแกรม ASP อันดับแรกควรจะเข้า
สองวิธีต่อไปนี้ SaveFileAs และ SaveFile ได้รับการประกาศในหน้าต่างการออกแบบ TLB
1. บันทึกไฟล์ตามชื่อไฟล์ที่ระบุ
//บันทึกไฟล์ตามชื่อไฟล์ที่ระบุ พารามิเตอร์ FileName คือชื่อไฟล์ที่ระบุ ค่าส่งคืน True บ่งชี้ว่าบันทึกไฟล์สำเร็จ
ฟังก์ชัน TUploadFile.SaveFileAs (ชื่อไฟล์: OleVariant): OleVariant;
var
longIndex : LongInt;
AFile: ไฟล์ขนาดไบต์;//บันทึกไฟล์ในรูปแบบไบนารี
byteData : ไบต์;
เริ่ม
ผลลัพธ์ := จริง;
พยายาม
มอบหมาย (AFile, FileName);
เขียนใหม่ (AFile);
สำหรับ longIndex := FFileDataStart ถึง FFileDataEnd ทำ
เริ่ม
byteData := ไบต์ ( FContentData[ longIndex ] );
เขียน (AFile, byteData);
จบ;
CloseFile(เอไฟล์);
ยกเว้น
ผลลัพธ์ := เท็จ;
จบ;
จบ;
2. บันทึกไฟล์ด้วยชื่อไฟล์เริ่มต้น
//บันทึกไฟล์ตามชื่อไฟล์เริ่มต้น และบันทึกไฟล์ด้วยชื่อเดียวกันในไดเร็กทอรีที่มีหน้าการโทรอยู่
ฟังก์ชัน TUploadFile.SaveFile: OleVariant;
var
CurrentFilePath : สตริง;
เริ่ม
//รับไดเร็กทอรีที่มีหน้าการโทรอยู่
CurrentFilePath := FScriptingContext.Request.ServerVariables['PATH_TRANSLATED'];
CurrentFilePath := ExtractFilePath( ปัจจุบันไฟล์พาธ );
//บันทึกไฟล์
ผลลัพธ์ := SaveFileAs( CurrentFilePath + ExtractFileName( FFileName ));
จบ;
3. ตัวอย่างการใช้งานส่วนประกอบการอัพโหลด
ในตัวอย่างของเรา DelphiUp.HTM เป็นอินเทอร์เฟซการอัปโหลดไฟล์ และ DelphiUp.ASP ใช้เพื่อดำเนินการอัปโหลดไฟล์
รหัสของ DelphiUp.ASP เป็นดังนี้:
<!--DelphiUp.ASP: หน้าประมวลผลการอัพโหลดไฟล์-->
<html><head><title>อัพโหลดไฟล์</title></head><body>
<% สลัวอัพโหลด ชื่อไฟล์
ตั้งค่าการอัปโหลด = Server.CreateObject("MyUpload.UploadFile")
FileName = อัพโหลด GetFileName
Response.Write "<br>กำลังบันทึกไฟล์ ""&FileName&""..."
ถ้า Upload.SaveFile แล้ว
Response.Write "<br>อัปโหลดไฟล์ ""&FileName&"" สำเร็จแล้ว"
Response.Write "<br>ขนาดไฟล์คือ "&Upload.GetFileSize&" ไบต์"
อื่น
Response.Write "<br>ไฟล์ ""&FileName&"" ไม่สามารถอัปโหลดได้"
สิ้นสุดถ้า
ตั้งค่าการอัปโหลด=ไม่มีอะไร %>
</body></html>
4. คำอธิบายบางประการ
1. ขนาดของไฟล์ DLL ที่คอมไพล์จากซอร์สโค้ดที่สร้างโดยอัตโนมัติโดย DELPHI คือ 215K ซึ่งสามารถพบได้ใน
ในส่วนอินเทอร์เฟซของ ASPTypeLibrary_TLB.PAS ให้ลบหน่วยทั้งหมดใน Uses ยกเว้น ActiveX
เมื่อลบหน่วยทั้งหมดใน Uses ใน MyUpload_TLB.PAS ขนาดของไฟล์ DLL ที่สร้างขึ้นจะลดลงเหลือ 61K
2. วิธีการข้างต้นใช้ได้กับโปรแกรม CGI ด้วย แต่ต้องใช้วัตถุ TWebRequest
โปรแกรมข้างต้นได้รับการดีบั๊กและส่งผ่านภายใต้ PWIN98+Delphi3.0+PWS4.0