9.2 ขั้นตอนทั่วไปสำหรับการพัฒนาฟังก์ชั่นการลากและวาง
Drag and Drop เป็นฟังก์ชั่นที่อำนวยความสะดวกในการทำงานของวัตถุที่ได้รับจาก Windows และสามารถพัฒนาได้อย่างง่ายดายใน Delphi
ออกมา ตามกระบวนการดำเนินการแบบลากและวางขั้นตอนการพัฒนาสามารถแบ่งออกเป็นสี่ขั้นตอนคือ:
●เริ่มต้นการทำงาน
●รับรายการลาก
●วางรายการลาก
●หยุดการทำงานลาก
ในระหว่างกระบวนการแนะนำเราจะรวมตัวอย่างแท็บ (Tagged Set) ตัวอย่างการทำงานลากและดร็อป การออกแบบอินเตอร์เฟสจะแสดงในรูป
เมื่อผู้ใช้ลากแท็กไปยังตำแหน่งของแท็กอื่นที่รันไทม์แท็กจะย้ายไปยังตำแหน่งนั้นและสาเหตุ
การจัดเรียงใหม่ของชุดแท็ก
9.2.1 เริ่มลาก
เมื่อ DragMode ถูกตั้งค่าเป็น dmautomatic ให้ลากโดยอัตโนมัติเมื่อผู้ใช้กดเมาส์บนตัวควบคุมต้นทาง
เริ่มต้น; หากคุณต้องการเริ่มลาก
ใช้วิธี Begindrag
ในการลากและวางแท็บเราใช้การประมวลผลเหตุการณ์ Mousedown ด้านล่างเพื่อเริ่มลากแท็ก
ขั้นแรกให้ตรวจสอบว่าปุ่มซ้ายที่กดเป็นปุ่มซ้ายแล้วพิจารณาว่ารายการนั้นถูกกฎหมายหรือไม่
ขั้นตอน tform1.tabset1mousedown (ผู้ส่ง: tobject; ปุ่ม: tmouseButton;
SHIFT: TSHIFTSTATE;
วาจา
Dragitem: จำนวนเต็ม;
เริ่ม
ถ้าปุ่ม = mbleft แล้ว
เริ่ม
dragitem: = tabset1.itematpos (จุด (x, y));
if (dragitem> -1) และ (dragitem <tabset1.tabs.count) จากนั้น
tabset1.begindrag (เท็จ);
จบ;
จบ;
9.2.2 รับรายการลาก
การควบคุมสามารถรับไอเท็มการลากจะถูกกำหนดโดยเหตุการณ์ ondragover ของการควบคุมหรือไม่ ในการลากแท็บชุดสิ่งสำคัญคือการใช้ตำแหน่งเมาส์เพื่อตัดสิน
โพรซีเดอร์ TFORM1.TABSET1DRAGOVER (ผู้ส่ง, ที่มา: tObject; x, y: จำนวนเต็ม;
รัฐ: tdragstate;
วาจา
Droppos: จำนวนเต็ม;
เริ่ม
ถ้า source = tabset1 แล้ว
เริ่ม
droppos: = tabset1.itematpos (จุด (x, y));
ยอมรับ: = (droppos> -1) และ (droppos <> tabset1.tabindex) และ
(droppos <tabset1.tabs.count);
จบ;
อื่น
ยอมรับ: = เท็จ;
จบ;
9.2.3 วางรายการลากลง
เมื่อการประมวลผลเหตุการณ์ ondragover ส่งคืนยอมรับจริงและรายการจะลดลงเหตุการณ์ ondragdrop
กระบวนการลากและลดการตอบสนอง ในอินสแตนซ์การลากและวางแท็บมันคือการเปลี่ยนตำแหน่งของแท็ก
ขั้นตอน TFORM1.TABSET1DRAGDROP (ผู้ส่ง, ที่มา: tObject; x, y: จำนวนเต็ม);
วาจา
Oldpos: จำนวนเต็ม;
newpos: จำนวนเต็ม;
เริ่ม
ถ้า source = tabset1 แล้ว
เริ่ม
oldpos: = tabset1.tabindex;
newpos: = tabset1.itematpos (จุด (x, y));
if (newPos> -1) และ (newPos <> oldpos) แล้ว
tabset1.tabs.move (oldpos, newpos);
จบ;
จบ;
9.2.4 การดำเนินการลากสิ้นสุด
มีสองวิธีในการยุติการทำงานการลาก: ผู้ใช้จะเผยแพร่ปุ่มเมาส์หรือโปรแกรมใช้วิธี endDrag
ถูกบังคับให้ยกเลิกการลาก มีสองผลที่ตามมาจากการสิ้นสุดการทำงานของการลาก: DROP ได้รับการยอมรับหรือดรอปถูกละเว้น
หลังจากการดำเนินการลากเสร็จสิ้นการควบคุมต้นทางจะได้รับข้อความเพื่อตอบสนองต่อเหตุการณ์การลาก onendDrag
9.3 การลากและวางตัวอย่างแอปพลิเคชัน: Drag and Drop for File Manager
แม้ว่าตัวอย่างแอปพลิเคชันตัวจัดการไฟล์ที่พัฒนาขึ้นในบทที่ 6 ได้เริ่มเป็นรูปเป็นร่าง แต่ก็ใช้งานได้
เมื่อเทียบกับตัวจัดการไฟล์ของ Windows ยังมีข้อบกพร่องมากมาย ข้อเสียเปรียบที่ใหญ่ที่สุดคือไม่รองรับการลากและส่งการเคลื่อนไหวของไฟล์
และลากและวางสำเนา ในตอนท้ายของบทนี้เราสามารถสร้างข้อบกพร่องนี้ได้
การลากและวางไฟล์หมายถึงไฟล์เมื่อผู้ใช้ลากไฟล์ไปยังไดเรกทอรีภายใต้แผนผังไดเรกทอรีและวางลง
มันจะย้ายไปยังไดเรกทอรีนี้โดยอัตโนมัติ
เมื่อคุณใส่และวางลงไฟล์จะถูกคัดลอกไปยังไดเรกทอรีปัจจุบันของไดรฟ์โดยอัตโนมัติ กล่องรายการไฟล์เป็นตัวควบคุมต้นทางและ
แผนผังไดเรกทอรีและฉลากไดรฟ์ของการควบคุมเป้าหมายสามารถอยู่ในช่วงย่อยที่แตกต่างกัน ไดเรกทอรีปัจจุบันของไดรฟ์คือย่อยใด ๆ
ผลการดำเนินการล่าสุดของหน้าต่างโดยไม่คำนึงว่าหน้าต่างย่อยนี้มีความสัมพันธ์กับแหล่งลากและเป้าหมายการลาก
ในการใช้ฟังก์ชั่นข้างต้นมีสองปัญหาที่ต้องแก้ไขก่อน:
1. จะบันทึกไดเรกทอรีปัจจุบันของแต่ละไดรฟ์ได้อย่างไร?
สำหรับสิ่งนี้เรากำหนดตัวแปรทั่วโลก:
var currentdirlist: อาร์เรย์ [0 ... 25] ของสตริง [70];
ในเหตุการณ์ onchange ของ directoryoutline:
ขั้นตอน tfmform.directoryoutlineChange (ผู้ส่ง: tobject);
เริ่ม
CreateCaption;
FileList.Clear;
FileList.directory: = DirectoryOutline.directory;
FileList.Update;
CurrentDirlist [drivetabset.tabindex]: = directoryoutline.directory;
filemanager.directorypanel.caption: = directoryoutline.directory;
จบ;
เนื่องจาก DrivetAbset ตอบสนองต่อเหตุการณ์ onclick ก่อนที่จะตอบสนองต่อเหตุการณ์ ondragdrop และเปิดใช้งานโดยเหตุการณ์
ส่งเหตุการณ์ OnChange ของ DirectoryOutline ดังนั้นจึงสามารถรับประกันได้ว่าจะใช้ในเหตุการณ์ ondragdrop ได้ตลอดเวลา
รายการอาร์เรย์ CurrentDirlist ไม่ใช่สตริงที่ว่างเปล่า
2. จะตรวจสอบให้แน่ใจว่าไม่เกี่ยวข้องกับการเคลื่อนไหวและคัดลอกด้วยหน้าต่างย่อยได้อย่างไร?
ปัญหาสำคัญที่นี่คือเมื่อเราตัดสินการควบคุมแหล่งที่มาเราใช้ตัวดำเนินการ IS เพื่อทำการตรวจสอบประเภท:
หากแหล่งที่มาเป็น tfileList แล้ว ...
หากเราใช้คำสั่งต่อไปนี้:
ถ้า source = filelist แล้ว
-
จากนั้นการเคลื่อนไหวและการคัดลอกจะถูก จำกัด ขอบเขตของหน้าต่างย่อยนี้
เมื่อเราแก้ไขคำถามข้างต้นงานของเราเพิ่งทำตามขั้นตอนการพัฒนาทั่วไปของการลากและวางและเราก็ทำมันทีละขั้นตอน
1. นักแสดงเริ่มต้นการทำงาน
ขั้นตอน tfmform.filelistmousedown (ผู้ส่ง: tobject; ปุ่ม: tmouseButton;
SHIFT: TSHIFTSTATE;
เริ่ม
ถ้าปุ่ม = mbleft แล้ว
กับผู้ส่งเป็น tfileListbox ทำ
เริ่ม
ถ้า itematpos (จุด (x, y), true)> = 0 แล้ว
Begindrag (เท็จ);
จบ;
จบ;
itematpos ใช้เพื่อตรวจสอบว่ามีไฟล์ในปัจจุบันหรือไม่ เมธอด Begindrag ผ่านพารามิเตอร์เท็จช่วยให้ FileList จัดการเหตุการณ์เมาส์แยกกันโดยไม่เริ่มลาก ในความเป็นจริงสถานการณ์นี้มีอยู่ในปริมาณมาก
2. DirectoryOutline และ DrivetAbset ตัดสินใจว่าจะยอมรับการลากและวางลงในที่เกิดเหตุ
ขั้นตอน tfmform.directoryoutlinedRagover (ผู้ส่ง, แหล่งที่มา: tobject; x,
Y: จำนวนเต็ม;
เริ่ม
หากแหล่งที่มาคือ tfileListbox แล้ว
ยอมรับ: = จริง;
จบ;
ขั้นตอน tfmform.drivetabsetDragover (ผู้ส่ง, แหล่งที่มา: tobject; x, x,
Y: จำนวนเต็ม;
วาจา
proppos: จำนวนเต็ม;
เริ่ม
หากแหล่งที่มาคือ tfileListbox แล้ว
ด้วย drivetabset ทำ
เริ่ม
proppos: = itematpos (จุด (x, y));
ยอมรับ: = (proppos> -1) และ (proppos <tabs.count);
จบ;
จบ;
DirectoryOutline เป็นการยอมรับอย่างไม่มีเงื่อนไขในขณะที่ DrivetAbset จำเป็นต้องตรวจสอบว่าเป็นแท็กทางกฎหมายหรือไม่
3. การตอบสนองแบบลากและหล่น
DirectoryOutline Drag และ Drop ใช้เพื่อใช้ฟังก์ชั่นการเคลื่อนไหวของไฟล์ การเรียกเหตุการณ์ยืนยันในโปรแกรม
ในระหว่างกระบวนการประมวลผลเส้นทางเป้าหมายจะได้รับจาก directoryoutline.items [getItem (x, y)]. FullPath
ขั้นตอน tfmform.directoryoutlinedRagdrop (ผู้ส่งที่มา: tobject; x, x,
y: จำนวนเต็ม);
เริ่ม
หากแหล่งที่มาคือ tfileListbox แล้ว
ด้วย DirectoryOutline DO
เริ่ม
confarmChange ('ย้าย', fileList.filename, รายการ [getItem (x, y)]. fullPath);
จบ;
จบ;
DrivetAbset Drag และ Drop ใช้เพื่อใช้ฟังก์ชั่นการคัดลอกไฟล์ แปลงตำแหน่งปัจจุบันเป็นไดรเวอร์ที่เกี่ยวข้องในโปรแกรม
ตัวอักษรแอคทูเอเตอร์เส้นทางเป้าหมายได้มาจาก CurrentDirlist [drivetabset.tabindex]
ขั้นตอน tfmform.drivetabsetDragdrop (ผู้ส่ง, แหล่งที่มา: tobject; x, y: จำนวนเต็ม);
วาจา
apoint: tpoint;
เริ่ม
apoint.x: = x;
drivetabset.tabindex: = drivetabset.itematpos (apoint);
หากแหล่งที่มาคือ tfileListbox แล้ว
ด้วย drivetabset ทำ
เริ่ม
ถ้า CurrentDirlist [TabIndex] <> '' แล้ว
confarmchange ('คัดลอก', Thefilename, CurrentDirlist [TabIndex]);
จบ;
จบ;
4. การตอบสนองต่อการลากเพื่อการลากและอัปเดตรายการไฟล์
ขั้นตอน tfmform.fileListendDrag (ผู้ส่ง, เป้าหมาย: tobject; x, y: จำนวนเต็ม);
เริ่ม
ถ้าเป้าหมาย <> ไม่มี fileList.Update;
จบ;