ชุมชนคนรักภาษาเบสิค - Visual Basic Community

 ลืมรหัสผ่าน
 ลงทะเบียน
ค้นหา
ดู: 291|ตอบกลับ: 0

[VB.NET] โค้ดการ Resize ขนาดของ Form และ Control แบบอัตโนมัติ ตามขนาดหน้าจอคอมพิวเตอร์

[คัดลอกลิงก์]

320

กระทู้

512

โพสต์

6503

เครดิต

ผู้ดูแลระบบ

ทองก้อน ทับทิมกรอบ

Rank: 9Rank: 9Rank: 9

เครดิต
6503


หน้าจอการออกแบบ Design Time ...


การรันโปรแกรมด้วย Visual Basic .Net (2010) ...


การรันโปรแกรมด้วย Visual Basic .Net (2026) Community Edition หน้าจอขนาด 1600 x 900 พิกเซล ...


การรันโปรแกรมกับหน้าจอขนาด 1366 x 768 พิกเซล ...

หลักการออกแบบ Resize Form และ Control
การ Resize ไม่ใช่การย่อหรือขยาย Control ตามใจ แต่เป็นการคำนวณอัตราส่วน (Scale) จากขนาดฟอร์มต้นฉบับเทียบกับขนาดฟอร์มปัจจุบัน แล้วนำอัตราส่วนนั้นไปปรับตำแหน่ง (Location), ขนาด (Size) และ ขนาดตัวอักษร (Font) ของ Control ทุกตัว โดยอ้างอิงจากค่าต้นฉบับที่บันทึกไว้ครั้งแรกเสมอ เพื่อป้องกันการสะสมของความคลาดเคลื่อนจากการ Resize หลายครั้ง วิธีนี้ทำให้ทุก Control ยังคงสัดส่วนเดิม และรองรับการแสดงผลบนหน้าจอที่มีความละเอียดแตกต่างกันได้อย่างถูกต้อง

แนวคิดของการทำ Resize Form
1. บันทึกขนาดและตำแหน่งเดิมของ Form และ Control ทุกตัว
2. คำนวณอัตราส่วนการย่อ/ขยาย (Scale X, Scale Y) จากขนาดฟอร์มปัจจุบัน
3. ปรับ Location, Size และ Font โดยอ้างอิงจากค่าต้นฉบับเสมอ
4. ห้ามนำค่าที่ Resize แล้วมาใช้คำนวณซ้ำ เพื่อป้องกันความคลาดเคลื่อนสะสม
5. ผลลัพธ์คือ UI ยังคงสัดส่วนเดิมและรองรับหลายความละเอียดหน้าจอได้อย่างถูกต้อง

*** อาจจะเกิดปัญหาในการสั่งรันโปรแกรมในตอนแรกๆ ลองเลือก Build, Rebuild และ Clean Solution ก่อนครับ ***
มาดูโค้ดในส่วนของฟอร์มหลัก ซึ่งใช้การ Design Time ทั้งหมด (frmResizeDemo.vb) ...
  1. Public Class frmResizeDemo
  2.     Inherits Form   ' สืบทอด Form

  3.     ' ----------------------------------------------------------
  4.     ' ตัวแปรระดับคลาส ตัวช่วย Resize
  5.     ' ----------------------------------------------------------
  6.     Private Resizer As ResizeHelper

  7.     ''' <summary>
  8.     ''' ตัวสร้างฟอร์ม เรียกใช้เมื่อสร้างวัตถุของฟอร์มนี้
  9.     ''' </summary>
  10.     Public Sub New()
  11.         ' เรียกใช้เมธอดที่สร้างคอนโทรลทั้งหมดบนฟอร์ม
  12.         ' (เมธอดนี้ถูกสร้างโดย Visual Studio Designer)
  13.         InitializeComponent()

  14.         ' สร้างวัตถุ ResizeHelper เพื่อใช้จัดการการปรับขนาด
  15.         Resizer = New ResizeHelper()
  16.     End Sub

  17.     ''' <summary>
  18.     ''' Event: เกิดขึ้นเมื่อฟอร์มถูกโหลดครั้งแรก
  19.     ''' ใช้สำหรับเตรียมข้อมูลและตั้งค่าเริ่มต้น
  20.     ''' </summary>
  21.     Private Sub frmResizeDemo_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
  22.         '-----------------------------------------------------
  23.         ' เพิ่มเติม:
  24.         ' Control ต่างๆที่อยู่บนฟอร์ม จะอยู่ใต้ Panel หลัก
  25.         '-----------------------------------------------------

  26.         ' ข้อมูลตัวอย่าง
  27.         cboCountry.SelectedIndex = 0
  28.         ' กำหนดค่าเริ่มต้นให้ DateTimePicker
  29.         dtpBirthDate.Value = DateTime.Now.AddYears(-20)

  30.         '-----------------------------------------------------
  31.         ' สำคัญมาก
  32.         ' ต้องเรียกหลังจาก Control ถูกสร้างครบแล้ว
  33.         ' เพื่อเก็บตำแหน่งเริ่มต้นของทุก Control
  34.         '-----------------------------------------------------
  35.         Resizer.SaveOriginalProperties(Me)

  36.     End Sub

  37.     ''' <summary>
  38.     ''' Event: เกิดขึ้นเมื่อฟอร์มมีการปรับขนาด (เช่น ผู้ใช้ลากขอบฟอร์ม)
  39.     ''' ใช้สำหรับปรับขนาดคอนโทรลตามสัดส่วน
  40.     ''' </summary>
  41.     Private Sub FormDemo_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
  42.         '-----------------------------------------------------
  43.         ' ตรวจสอบว่ามีตัวช่วยปรับขนาดหรือไม่ และบันทึกข้อมูลหรือยัง
  44.         ' ทุกครั้งที่ Form เปลี่ยนขนาด ให้ปรับ Controls ทั้งหมด
  45.         '-----------------------------------------------------
  46.         If Resizer IsNot Nothing Then Resizer.AdjustControls(Me)
  47.     End Sub

  48.     Private Sub btnSave_Click(sender As Object, e As System.EventArgs) Handles btnSave.Click
  49.         MessageBox.Show("ทดสอบเหตุการณ์ในการกดปุ่มคำสั่ง.", "รายงานสถานะ", MessageBoxButtons.OK, MessageBoxIcon.Information)
  50.     End Sub

  51.     Private Sub btnCancel_Click(sender As Object, e As System.EventArgs) Handles btnCancel.Click
  52.         Me.Close()
  53.     End Sub

  54.     Private Sub frmResizeDemo_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
  55.         Me.Dispose()
  56.         GC.SuppressFinalize(Me)
  57.         Application.Exit()
  58.     End Sub
  59. End Class
คัดลอกไปที่คลิปบอร์ด


โค้ดในส่วน Class ของการย่อขยายขนาดของฟอร์มและคอนโทรล (ResizeHelper.vb) ...
  1. Imports System.Drawing

  2. ' ----------------------------------------------------------
  3. ' คำอธิบาย ResizeHelper
  4. ' ----------------------------------------------------------
  5. ' คลาสสำหรับย่อ/ขยาย Form และ Controls ทั้งหมด
  6. ' ตามขนาดของหน้าต่างที่เปลี่ยนแปลง
  7. '
  8. ' หลักการทำงาน
  9. '
  10. ' 1. เมื่อเปิดฟอร์มครั้งแรก
  11. '    -> เก็บตำแหน่ง ขนาด และ Font ของ Control ทุกตัว
  12. '
  13. ' 2. เมื่อ Form ถูก Resize
  14. '    -> คำนวณอัตราส่วนการย่อ/ขยาย
  15. '
  16. ' 3. นำอัตราส่วนไปคูณกับค่าดั้งเดิม
  17. '    -> ทำให้ Control ทุกตัวขยายหรือย่ออย่างสัมพันธ์กัน
  18. ' ----------------------------------------------------------

  19. Public Class ResizeHelper

  20.     '---------------------------------------------------------
  21.     ' ขนาดของฟอร์มในขณะเริ่มต้น
  22.     ' ใช้เป็นค่าต้นฉบับสำหรับคำนวณอัตราส่วน
  23.     '---------------------------------------------------------
  24.     Private OriginalFormSize As Size
  25.     '---------------------------------------------------------
  26.     ' อัตราการย่อ/ขยายแนวนอน
  27.     ' เช่น
  28.     ' เดิม 1920
  29.     ' ใหม่ 960
  30.     ' ScaleWidth = 960 / 1920 = 0.5
  31.     '---------------------------------------------------------
  32.     Private ScaleWidth As Double

  33.     '---------------------------------------------------------
  34.     ' อัตราการย่อ/ขยายแนวตั้ง
  35.     '---------------------------------------------------------
  36.     Private ScaleHeight As Double

  37.     '---------------------------------------------------------
  38.     ' Dictionary สำหรับเก็บข้อมูลเดิมของ Control ทุกตัว
  39.     ' Key   = Control
  40.     ' Value = ขนาด/ตำแหน่ง/Font เดิม
  41.     '---------------------------------------------------------
  42.     Private ReadOnly ControlProperties As New Dictionary(Of Control, ControlPropertyBag)

  43.     ' ----------------------------------------------------------
  44.     ''' <summary>
  45.     ''' ขั้นตอนที่ 1: บันทึกขนาดและตำแหน่งเดิมของ Form และ Control ทั้งหมด
  46.     ''' ควรเรียกใช้เพียงครั้งเดียวตอน Form โหลดเสร็จ (Form_Load)
  47.     ''' </summary>
  48.     Public Sub SaveOriginalProperties(ByVal frm As Form)

  49.         ' เก็บขนาดฟอร์มเริ่มต้น
  50.         OriginalFormSize = frm.Size

  51.         ' เก็บข้อมูลของ Control ทุกตัว
  52.         SaveControlProperties(frm)

  53.     End Sub

  54.     ' ----------------------------------------------------------
  55.     ''' <summary>
  56.     ''' ขั้นตอนที่ 2: คำนวณสัดส่วนและปรับขนาด Control ใหม่
  57.     ''' ควรเรียกใช้ทุกครั้งที่ขนาด Form เปลี่ยนแปลง (Form_Resize)
  58.     ''' </summary>
  59.     Public Sub AdjustControls(ByVal frm As Form)
  60.         ' ป้องกันการหารด้วยศูนย์ กรณีที่ OriginalFormSize ยังไม่ถูกตั้งค่า
  61.         If OriginalFormSize.Width = 0 OrElse OriginalFormSize.Height = 0 Then Return

  62.         ' 1. คำนวณอัตราส่วนใหม่ (ขนาดปัจจุบัน หารด้วย ขนาดเดิม)
  63.         ' ตัวอย่าง: ถ้าเดิมกว้าง 1000 ปัจจุบันกว้าง 500 -> ScaleWidth = 0.5 (ย่อเหลือครึ่งหนึ่ง)
  64.         ScaleWidth = frm.Width / OriginalFormSize.Width
  65.         ScaleHeight = frm.Height / OriginalFormSize.Height

  66.         ' 2. สั่งให้ Form หยุดการวาดหน้าจอชั่วคราว (สำคัญมาก)
  67.         ' เพื่อป้องกันอาการหน้าจอกระพริบ (Flickering) และเพิ่มความเร็วในการประมวลผล
  68.         frm.SuspendLayout()

  69.         ' 3. เริ่มปรับขนาด Control
  70.         ResizeControls(frm)

  71.         ' 4. สั่งให้ Form เริ่มวาดหน้าจอใหม่พร้อมกันทั้งหมด
  72.         frm.ResumeLayout()
  73.     End Sub

  74.     ' ----------------------------------------------------------
  75.     ''' <summary>
  76.     ''' คลาสย่อย (Nested Class) สำหรับเก็บ "ข้อมูลต้นฉบับ" ของ Control แต่ละตัว
  77.     ''' การแยกเป็นคลาสย่อยช่วยให้โค้ดเป็นระเบียบและจัดการข้อมูลได้ง่าย
  78.     ''' </summary>
  79.     Private Class ControlPropertyBag
  80.         Public OriginalSize As Size          ' ขนาดเดิม (กว้าง x สูง)
  81.         Public OriginalLocation As Point     ' ตำแหน่งเดิม (X, Y)
  82.         Public OriginalFontSize As Single    ' ขนาดตัวอักษรเดิม

  83.         ' Constructor: รับค่า Control เข้ามาและบันทึกค่าเดิมทันที
  84.         Public Sub New(ByVal ctrl As Control)
  85.             OriginalSize = ctrl.Size
  86.             OriginalLocation = ctrl.Location
  87.             OriginalFontSize = ctrl.Font.Size
  88.         End Sub
  89.     End Class

  90.     ' ----------------------------------------------------------
  91.     ''' <summary>
  92.     ''' Recursive Function
  93.     ''' ฟังก์ชันวนลูปบันทึกข้อมูล Control (แบบ Recursive)
  94.     ''' Recursive คือการที่ฟังก์ชันเรียกตัวเอง เพื่อเจาะเข้าไปใน Control ที่ซ้อนกัน (เช่น Panel, GroupBox)
  95.     ''' </summary>
  96.     Private Sub SaveControlProperties(ByVal parent As Control)
  97.         ' วนลูปดู Control ลูกทุกตัวที่อยู่ใน Control แม่
  98.         For Each child As Control In parent.Controls
  99.             ' ถ้ายังไม่เคยบันทึกข้อมูลของ Control นี้ ให้บันทึก
  100.             If Not ControlProperties.ContainsKey(child) Then
  101.                 ControlProperties.Add(child, New ControlPropertyBag(child))
  102.             End If

  103.             ' ถ้า Control นี้มีลูกซ้อนอยู่ข้างในอีก (เช่น GroupBox มี TextBox อยู่ข้างใน)
  104.             ' ให้เรียกฟังก์ชันนี้ซ้ำ (Recursive) เพื่อเจาะลงไปบันทึกข้อมูลของลูกด้วย
  105.             If child.HasChildren Then SaveControlProperties(child)
  106.         Next

  107.     End Sub

  108.     ' ----------------------------------------------------------
  109.     ''' <summary>
  110.     ''' ฟังก์ชันวนลูปปรับขนาด Control (แบบ Recursive)
  111.     ''' </summary>
  112.     '''
  113.     Private Sub ResizeControls(ByVal parent As Control)
  114.         For Each child As Control In parent.Controls
  115.             ' ตรวจสอบว่ามีข้อมูลต้นฉบับของ Control นี้เก็บไว้หรือไม่
  116.             If ControlProperties.ContainsKey(child) Then
  117.                 Dim props As ControlPropertyBag = ControlProperties(child)
  118.                 '---------------------------------------------
  119.                 ' ปรับตำแหน่ง X และ Y ตามสัดส่วน
  120.                 '---------------------------------------------
  121.                 child.Left = CInt(props.OriginalLocation.X * ScaleWidth)
  122.                 child.Top = CInt(props.OriginalLocation.Y * ScaleHeight)

  123.                 '---------------------------------------------
  124.                 ' ปรับขนาดความกว้างและความสูง ตามสัดส่วนที่คำนวณไว้
  125.                 '---------------------------------------------
  126.                 child.Width = CInt(props.OriginalSize.Width * ScaleWidth)
  127.                 child.Height = CInt(props.OriginalSize.Height * ScaleHeight)

  128.                 '---------------------------------------------
  129.                 ' ปรับขนาด Font ใช้ Scale ที่น้อยกว่า
  130.                 ' เพื่อไม่ให้ Font สูงเกินไป
  131.                 '---------------------------------------------
  132.                 Dim fontScale As Double
  133.                 ' ใช้ค่า Scale ที่น้อยที่สุดระหว่างกว้างกับสูง เพื่อป้องกันตัวหนังสือล้นกรอบ
  134.                 fontScale = Math.Min(ScaleWidth, ScaleHeight)
  135.                 Dim newFontSize As Single
  136.                 newFontSize = props.OriginalFontSize * CSng(fontScale)
  137.                 ' ป้องกันขนาดฟอนต์เล็กเกินไปจนอ่านไม่ออก (ขั้นต่ำ 4 pt)
  138.                 If newFontSize > 4 Then child.Font = New Font(child.Font.FontFamily, newFontSize, child.Font.Style)
  139.             End If
  140.             '---------------------------------------------
  141.             ' Resize Control ลูกต่อ
  142.             '---------------------------------------------
  143.             If child.HasChildren Then ResizeControls(child)
  144.         Next
  145.     End Sub
  146. End Class
คัดลอกไปที่คลิปบอร์ด

ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) + .Net Framework 4.0 ได้ที่นี่ ...

ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง

คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน

x
สิ่งที่ดีกว่าการให้ คือการให้แบบไม่มีที่สิ้นสุด
ขออภัย! คุณไม่ได้รับสิทธิ์ในการดำเนินการในส่วนนี้ กรุณาเลือกอย่างใดอย่างหนึ่ง ลงชื่อเข้าใช้ | ลงทะเบียน

รายละเอียดเครดิต

ข้อความล้วน|อุปกรณ์พกพา|ประวัติการแบน|G2GNet.com  

GMT+7, 2026-8-21 15:39 , Processed in 0.046555 second(s), 5 queries , File On.

Powered by Discuz! X3.4, Rev.62

Copyright © 2001-2020 Tencent Cloud.

ตอบกระทู้ ขึ้นไปด้านบน ไปที่หน้ารายการกระทู้