คำสำคัญ : กล่องโต้ตอบ, กล่องโต้ตอบ, resizable
1. เกิดปัญหาขึ้น
ปัญหามาจาก Stanley_xu หวังว่าจะได้ปุ่มปิดเท่านั้น (สามารถช่วยได้) ไม่มีไอคอนสำหรับโปรแกรมที่ด้านบนซ้ายและกล่องโต้ตอบสามารถเปลี่ยนขนาดหน้าต่างได้
คุณสมบัติ Borderstyle และ Bordericons ถูกตั้งค่าสำหรับ tform ใน VCL เพื่อลดความซับซ้อนของการตั้งค่าสไตล์หน้าต่าง (มิฉะนั้นฟังก์ชั่น API เช่น SetWindowlong และ GetWindowlong จะต้องเรียก) คำจำกัดความและคำอธิบายของ tformborderstyle และ tbordericon มีดังนี้:
ความหมายของคุณค่า
BSDialog ไม่สามารถปรับเปลี่ยนได้
BSSingle ไม่สามารถปรับเปลี่ยนได้
bsnonenotresizable;
BSSIZEBLE มาตรฐานขอบ
bstoolwindow ชอบ bssingle แต่มีคำบรรยายเล็ก ๆ น้อย ๆ
bssizetoolwin ชอบ bssizable พร้อมคำบรรยายภาพขนาดเล็ก
type tbordericon = (bisystemmenu, biminimize, bimaximize, bihelp);
tbordericons = ชุดของ tbordericon;
ความหมายของคุณค่า
bisystemmenu แบบฟอร์มมีเมนูควบคุม (หรือที่เรียกว่าเมนูระบบ)
biminimize แบบฟอร์มมีปุ่มลดลง
bimaximize แบบฟอร์มมีปุ่มเพิ่มสูงสุด
Bihelp ถ้า Borderstyle เป็น bsdialog หรือ biminimize และ bimaximize จะถูกแยกออกเครื่องหมายคำถามจะปรากฏขึ้นในแถบชื่อเรื่องของแบบฟอร์มและเมื่อคลิกเคอร์เซอร์จะเปลี่ยนเป็น Crhelp;
เห็นได้ชัดว่า Borderstyle และ Bordericons สามารถตอบสนองความต้องการทั่วไปเท่านั้นและเป็นไปไม่ได้ที่จะใช้กล่องโต้ตอบที่สามารถปรับเปลี่ยนขนาดได้
โดยทั่วไปถ้าฉันต้องการได้รับหน้าต่างที่ไม่สามารถขยายได้สูงสุด แต่สามารถเปลี่ยนขนาดได้ฉันตั้งค่าเส้นขอบเป็น bssizable ลบ biminimize และ bimaximize ของ bordericons และผลลัพธ์ก็เป็นเช่นนี้: หน้าต่างสามารถแก้ไขได้ แต่มี ไอคอนที่มุมซ้ายบน:
รูปที่ 1 กล่องโต้ตอบพร้อมไอคอน
โปรดทราบว่ามีไอคอนอยู่ที่มุมซ้ายบน
เป้าหมายของเราคือเอฟเฟกต์ทั้งสองด้านล่าง
รูปที่ 2 เปิดกล่องโต้ตอบไฟล์
รูปที่ 3 กล่องโต้ตอบเรียกดูโฟลเดอร์
2. ครึ่งปัญหาได้รับการแก้ไข
ฉันค้นหา MSDN และพบบทความที่สอนวิธีการออกแบบหน้าทรัพย์สินที่สามารถเปลี่ยนขนาด (ใน MFC, CPropertySheet ปรากฏเป็นหน้าย่อย cproperTypage ซึ่งสืบทอดมาจาก cdialog และไม่สามารถปรับขนาดได้) "วิธีการออกแบบคุณสมบัติ MFC ที่ปรับขนาดได้ แผ่นวิธีที่แนะนำในบทความคือการปรับเปลี่ยนสไตล์หน้าต่างก่อนที่หน้าคุณสมบัติจะถูกสร้างขึ้นจากนั้นประมวลผลข้อความ WM_SIZE ด้วยตนเอง
int callback cmypropertysheet :: xmnpropsheetcallback (hwnd hwnd, ข้อความ uint, lparam lparam)
-
extern int callback afxpropsheetCallback (HWND, ข้อความ UINT, LPARAM LPARAM);
// xmn: โทรกลับของ MFC
int nres = afxpropsheetCallback (hwnd, ข้อความ, lparam);
สลับ (ข้อความ)
-
กรณี pscb_precreate:
// ตั้งค่าสไตล์หน้าต่างของเราเอง
((lpdlgtemplate) lparam)-> style | = (ds_3dlook | ds_setfont
|
หยุดพัก;
-
กลับ nres;
-
ฉันได้ลองใช้วิธีเดียวกันในรูปแบบของ VCL ตั้งค่าเส้นขอบเป็น bsdialog เมื่อออกแบบแล้วใช้วิธี createparams มากเกินไป แต่ผลลัพธ์คือกล่องโต้ตอบกลายเป็นเส้นขอบหนา (เนื่องจากมีสไตล์ ws_thickframe) เมาส์สามารถเปลี่ยนได้โดยอัตโนมัติหลังจากย้ายไปที่แต่ละเส้นขอบและไม่มีไอคอนที่มุมซ้ายบน แต่หน้าต่างไม่สามารถเปลี่ยนขนาดของมันได้ (กระบวนการประมวลผลข้อความ WM_SIZE ที่เพิ่มเข้ามาไม่ได้ถูกทริกเกอร์) ปัญหาคืออะไร?
รูปที่ 4 กล่องโต้ตอบที่ยังไม่เป็นที่น่าพอใจอย่างสมบูรณ์
3. แก้ปัญหา
ฉันตรวจสอบซอร์สโค้ดของแบบฟอร์มและพบปัญหา มีกระบวนการฝังระบบ modifysystemmenu ในกระบวนการประมวลผลข้อความ WM_NCCreate ของ tCustomform ซึ่งใช้ในการปรับเปลี่ยนเมนูระบบของแบบฟอร์ม โปรดทราบว่าข้อความสีแดงด้านล่างบอกว่า "ทำให้เมนูระบบดูเหมือนกล่องโต้ตอบ" อีกสองสามประโยคของรหัสจะลบรายการเมนูระบบไปยังจุดที่ "ย้าย" และ "ปิด" เท่านั้น
ขั้นตอน tcustomform.wmnccreate (ข้อความ var: twmnccreate);
โพรซีเดอร์ modifysystemmenu;
วาจา
Sysmenu: Hmenu;
เริ่ม
-
{แก้ไขเมนูระบบให้ดูเหมือนว่าเป็น s'pose to}
sysmenu: = getSystemMenu (ด้ามจับ, เท็จ);
ถ้า fborderstyle = bsdialog แล้ว
เริ่ม
{ทำให้เมนูระบบดูเหมือนกล่องโต้ตอบที่มีเท่านั้น
ย้ายและปิด}
deletemenu (sysmenu, sc_tasklist, mf_bycommand);
deletemenu (sysmenu, 7, mf_byposition);
deletemenu (sysmenu, 5, mf_byposition);
deletemenu (sysmenu, sc_maximize, mf_bycommand);
deletemenu (sysmenu, sc_minimize, mf_bycommand);
deletemenu (sysmenu, sc_size, mf_bycommand);
deletemenu (sysmenu, sc_restore, mf_bycommand);
จบสิ้น
-
จบ;
เริ่ม
สืบทอด;
Setmenu (fmenu);
ถ้าไม่ใช่ (csdesigning ในส่วนประกอบ) จากนั้น modifysystemmenu;
จบ;
ดังนั้นปัญหาคือว่าเนื่องจาก "sc_size" ถูกลบสไตล์หน้าต่างมีความผิดปกติ: มี ws_thickframe (ขนาดหน้าต่างสามารถแก้ไขได้) แต่ไม่ตอบสนองต่อข้อความ WM_SIZE (SC_SIZE ถูกลบ)
การแก้ปัญหานั้นง่ายมาก: ใช้กระบวนการประมวลผลข้อความ WM_NCCreate ของคุณเองและปรับเปลี่ยนเมนูระบบด้วยตนเอง
โพรซีเดอร์ tzocdlgresizable.wmnccreate (ข้อความ var: twmnccreate);
// รหัสต่อไปนี้ถูกคัดลอกจาก Form.PAS Line 4047, Delphi 7 SP1
โพรซีเดอร์ modifysystemmenu;
วาจา
Sysmenu: Hmenu;
เริ่ม
sysmenu: = getSystemMenu (ด้ามจับ, เท็จ);
{ทำให้เมนูระบบดูเหมือนกล่องโต้ตอบที่มีเท่านั้น
ย้ายขนาดและคำสั่งปิด}
deletemenu (sysmenu, sc_tasklist, mf_bycommand);
deletemenu (sysmenu, 7, mf_byposition);
// อย่าลบตัวแยกก่อนคำสั่งปิด
// deletemenu (sysmenu, 5, mf_byposition);
deletemenu (sysmenu, sc_maximize, mf_bycommand);
deletemenu (sysmenu, sc_minimize, mf_bycommand);
{อย่าลบคำสั่งขนาดไม่เช่นนั้นเราจะสูญเสียไฟล์
ความสามารถในการปรับขนาดกล่องโต้ตอบ}
// deletemenu (sysmenu, sc_size, mf_bycommand);
deletemenu (sysmenu, sc_restore, mf_bycommand);
จบ;
เริ่ม
{ข้ามตัวจัดการ wm_nccreate ของ tcustomform ซึ่งลบออก
คำสั่งขนาดจากเมนูระบบ}
สืบทอด defaulthandler (ข้อความ);
// การจัดการกับเมนูระบบในแบบของเราเอง
modifysystemmenu;
จบ;
4. คลาส tzocdlgresizable
โซลูชันสุดท้ายที่ฉันห่อหุ้มเป็นคลาสที่สืบทอดมาจาก TFOR tzocdlgresizable
BTW: ฉันยังเพิ่มแอตทริบิวต์ SizeGrip ลงใน tzocdlgresizable
รูปที่ 5 กล่องโต้ตอบที่มี SizeGrip โดยไม่มีไอคอน
ดาวน์โหลด (EXE และรหัสแหล่งที่มา)
http://www.zocsoft.com/temp/resizable_dialog.rar
5. วัสดุอ้างอิง:
MSDN: วิธีการออกแบบแผ่นคุณสมบัติ MFC ที่ปรับขนาดได้
ที่อยู่อ้างอิง: "การใช้กล่องโต้ตอบที่สามารถเปลี่ยนขนาดใน Delphi"