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

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

[VB.NET] การสร้าง FlatTabControl ในแบบ Custom Control (OOP)

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

338

กระทู้

534

โพสต์

8093

เครดิต

ผู้ดูแลระบบ

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

Rank: 9Rank: 9Rank: 9

เครดิต
8093
โพสต์ 4 ชั่วโมงที่แล้ว | ดูโพสต์ทั้งหมด |โหมดอ่าน


การนำ FlatTabControl ไปใช้งาน เราไม่จำเป็นต้อง Build ก็ได้ แต่ใช้การเขียนโค้ด VB.NET ในแบบ Run Time (รันโปรแกรมถึงจะเห็นผลลัพธ์ของการทำงาน) เพื่อสร้าง FlatTabControl ขึ้นมาแบบไดนามิค ...

ตัวอย่างการเขียนโค้ดสร้าง FlatTabControl ขึ้นมาแบบ Run Time ...
  1.         ' ประกาศและสร้าง Object ของ FlatTabControl1
  2.         Dim FlatTabControl1 As New FlatTabControl()
  3.         ' กำหนดค่า Properties ต่างๆ ในแบบ Run Time (Dynamic)
  4.         With FlatTabControl1
  5.             .Cursor = Cursors.Hand
  6.             .Dock = DockStyle.Fill
  7.             .DrawMode = TabDrawMode.OwnerDrawFixed
  8.             .Font = New Font("Tahoma", 10.0!, FontStyle.Bold)
  9.             .ItemSize = New Size(140, 50)
  10.             .Location = New Point(0, 0)
  11.             .Name = "FlatTabControl1"
  12.             .SelectedIndex = 0
  13.             .Size = New Size(749, 583)
  14.             .SizeMode = TabSizeMode.Fixed
  15.             .TabIndex = 0
  16.             ' ====== กำหนดสีพื้นหลัง ======
  17.             '.BackColor = Color.FromArgb(255, 255, 255) ' หรือสีอื่นที่ต้องการ เช่น Color.White
  18.             ' สีเทาอ่อน
  19.             .BackColor = Color.FromArgb(240, 240, 240)
  20.             ' สีขาว
  21.             '.BackColor = Color.White
  22.         End With
  23.         Me.Controls.Add(FlatTabControl1)
คัดลอกไปที่คลิปบอร์ด

OOP ย่อมาจาก Object-Oriented Programming หรือในภาษาไทยเรียกว่า "การเขียนโปรแกรมเชิงวัตถุ" เป็นแนวคิดในการออกแบบและพัฒนาซอฟต์แวร์โดยมองทุกอย่างในระบบให้เป็น "วัตถุ (Object)" ซึ่งมีคุณสมบัติและพฤติกรรมในตัวเอง ช่วยให้จัดระเบียบโค้ดได้ง่าย นำโค้ดกลับมาใช้ใหม่ได้สะดวก และดูแลรักษาระบบใหญ่ๆได้ดีขึ้น

วันนี้แอดมินจะมาอธิบายถึงการสร้าง FlatTabControl โดยใช้การสืบทอดคุณสมบัติ (Inheritance) มาจาก TabControl มาตรฐานของไมโครซอฟท์ ซึ่งจะต้องใช้ความรู้พื้นฐานของ OOP เข้ามาเกี่ยวข้อง จุดประสงค์ในการสร้าง FlatTabControl ขึ้นมา นั่นคือ เราไม่ต้องมาสร้าง Control ใหม่ตั้งแต่ศูนย์ แต่บอกคอมไพเลอร์ว่า FlatTabControl ก็คือ TabControl รุ่นหนึ่ง โดยใช้คำสั่ง Inherits TabControl ทำให้ได้คุณสมบัติทั้งหมดของ TabControl มาตรฐานมาโดยอัตโนมัติ: มีแท็บ, มี TabPages, มีคุณสมบัติ SelectedIndex, ItemSize และอื่นๆ อีกมากมาย แต่เราเขียนโค้ดทับ/เพิ่มเติม เพื่อเปลี่ยนพฤติกรรมที่ไม่พอใจหรือต้องการสไตล์ใหม่

สรุปหลักการ OOP ที่เกี่ยวข้อง

Inheritance
การใช้ Inherits TabControl → หมายถึง Control ที่เราสร้าง (FlatTabControl) จะได้รับคุณสมบัติและพฤติกรรมทั้งหมดของ TabControl มาตั้งต้น แล้วเราสามารถ "โมดิฟาย" หรือ "Override" พฤติกรรมบางส่วนได้เอง

Polymorphism  
การใช้ Override เมธอด เช่น OnPaint, OnMouseMove, OnMouseLeave ทำให้พฤติกรรมการวาดและการตอบสนองต่อเมาส์เปลี่ยนไปตามที่เรากำหนดเอง

Encapsulation  
เก็บสถานะ เช่น HoverIndex เป็น Private และเปิดเผยเฉพาะสิ่งที่ผู้ใช้ Control ใช้งาน เช่น FlatTabControl1.SelectedIndex

Abstraction
ผู้ใช้ FlatTabControl ไม่ต้องรู้รายละเอียดการวาดกราฟิกหรือการจัดการเมาส์ เพียงลาก Control ไปใช้เหมือน TabControl ปกติ

การทำงานของโค้ด
1. Constructor (New)
- กำหนด Style ให้ Control ใช้ Double Buffer, UserPaint → เพื่อให้วาดเองได้ลื่นไหล
- กำหนด DrawMode = OwnerDrawFixed → คุณเป็นคนวาดแท็บเองทั้งหมด
- กำหนด ItemSize, Font, Cursor → ปรับรูปลักษณ์แท็บ

2. OnMouseMove / OnMouseLeave
- ตรวจสอบว่าเมาส์อยู่บนแท็บไหน → เก็บค่าไว้ใน HoverIndex
- เรียก Invalidate() เพื่อบังคับให้ Control วาดใหม่

3. OnPaint
- ล้างพื้นหลังด้วยสีขาว
- วาดแท็บทีละตัว โดยเลือกสีตามสถานะ (Selected, Hover, Normal)
- ใช้ RoundRect เพื่อสร้างกรอบโค้งมน
- วาดข้อความด้วย TextRenderer.DrawText
- วาดพื้นหลังของ Page ด้วยสีขาว

4. RoundRect Function
- สร้าง GraphicsPath ที่มีมุมโค้งมน → ใช้ในการวาดแท็บให้ดู Flat + Modern

สรุป
การสร้าง Custom Control โดย Inherits จาก Control มาตรฐาน เป็นการใช้ OOP อย่างเต็มรูปแบบ:
1. Inheritance → รับคุณสมบัติเดิม
2. Polymorphism → เปลี่ยนพฤติกรรมด้วย Override
3. Encapsulation → ซ่อนรายละเอียดภายใน
4. Reusability → ใช้งานซ้ำได้ในหลายโปรเจกต์

โค้ดในส่วนของการสร้าง FlatTabControl ... FlatTabControl.vb
  1. Imports System.Drawing.Drawing2D

  2. Public Class FlatTabControl
  3.     ' Inherits หมายถึง Control -> TabControl -> FlatTabControl
  4.     ' การที่ใช้ Inherits TabControl แทนที่จะใช้ Inherits UserControl แปลว่า ไม่ได้สร้างของใหม่จากศูนย์
  5.     ' แต่กำลัง "ดัดแปลง/ตกแต่ง" ของเดิมที่มีอยู่แล้วใน .NET Framework
  6.     Inherits TabControl
  7.     ' Custom Control หรือ Extended Control คือการสืบทอดจาก Control มาตรฐาน
  8.     ' FlatTabControl ก็คือ TabControl ตัวหนึ่งนั่นแหละ แต่มีการเปลี่ยนแปลงคุณสมบัติ เช่น รูปร่าง สี ฯลฯ ให้เป็นไปตามที่เราต้องการ ดังนี้
  9.     ' ลากลง Form ได้
  10.     ' มี Properties เดิมทั้งหมด
  11.     ' มี Events เดิมทั้งหมด
  12.     ' มี TabPages เดิมทั้งหมด
  13.     ' ==================================================================================
  14.     ' | หลัก OOP                | ใน FlatTabControl
  15.     ' | **Inheritance**      | Inherits TabControl การสืบทอดทำให้ใช้งานได้ทุกความสามารถของ TabControl มาใช้งานทันที (ไม่ต้องเขียนโค้ดใหม่)
  16.     ' | **Encapsulation**   | เก็บสถานะ เช่น HoverIndex เป็น Private และเปิดเผยเฉพาะสิ่งที่ผู้ใช้ Control ใช้งาน เช่น FlatTabControl1.SelectedIndex
  17.     ' | **Polymorphism**  | Overrides OnPaint, OnMouseMove, OnMouseLeave ใช้ชื่อ Method เดิม แต่เปลี่ยนพฤติกรรมเดิมของ TabControl
  18.     ' | **Abstraction**      | ผู้ใช้ FlatTabControl ไม่ต้องรู้รายละเอียดการวาดกราฟิกหรือการจัดการเมาส์ เพียงลาก Control ไปใช้เหมือน TabControl ปกติ
  19.     ' ==================================================================================

  20.     ' Encapsulation คือ ซ่อนข้อมูลภายใน
  21.     ' ผู้ใช้ FlatTabControl จะไม่รู้เลยว่ามี HoverIndex เพราะมี Private ซ่อนเอาไว้
  22.     Private HoverIndex As Integer = -1

  23.     Public Sub New()
  24.         ' เพื่อให้ System ตั้งค่าพื้นฐาน
  25.         MyBase.New()

  26.         ' Abstraction (การดูดซับ) ใช้ในการสร้าง Interface
  27.         Me.SetStyle(ControlStyles.AllPaintingInWmPaint _
  28.                     Or ControlStyles.OptimizedDoubleBuffer _
  29.                     Or ControlStyles.ResizeRedraw _
  30.                     Or ControlStyles.UserPaint, True)

  31.         Me.DrawMode = TabDrawMode.OwnerDrawFixed
  32.         Me.SizeMode = TabSizeMode.Fixed
  33.         Me.ItemSize = New Size(140, 50)
  34.         Me.Font = New Font("Tahoma", 10, FontStyle.Bold)
  35.     End Sub

  36.     ' Overrides หมายถึงว่ามีของเดิมใน Tab Control อยู่แล้ว แต่ขอแก้ไขใหม่ (หรือเรียกของ Microsoft มาก่อน แล้วค่อยมาทำของเราอีกที)
  37.     ' หรือกล่าวแบบสั้นๆ คือ การที่คลาสลูก เขียนทับพฤติกรรมของคลาสแม่
  38.     Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
  39.         ' ระบบของ Microsoft อาจจะไม่ทำงาน เราจึงต้องสั่ง MyBase.OnMouseMove(e) ดักเอาไว้ก่อน
  40.         MyBase.OnMouseMove(e)
  41.         HoverIndex = -1
  42.         For i As Integer = 0 To Me.TabPages.Count - 1
  43.             If Me.GetTabRect(i).Contains(e.Location) Then
  44.                 HoverIndex = i
  45.                 Exit For
  46.             End If
  47.         Next
  48.         Me.Invalidate()
  49.     End Sub

  50.     Protected Overrides Sub OnMouseLeave(e As EventArgs)
  51.         MyBase.OnMouseLeave(e)
  52.         HoverIndex = -1
  53.         Me.Invalidate()
  54.     End Sub

  55.     ' Encapsulation (การห่อหุ้ม) แม้จะเป็น Custom Control แต่เรายังคงซ่อนรายละเอียดการวาดภาพที่ซับซ้อนไว้ภายในคลาส
  56.     ' ตัวแปร HoverIndex, ฟังก์ชัน RoundRect, การคำนวณสีภายใน OnPaint ถูกห่อหุ้มไว้
  57.     ' ผู้ใช้งานภายนอก (คนเอา Control ไปใช้) ไม่ต้องรู้ ว่ามันวาดยังไง
  58.     ' เขาจะแค่เห็นว่า Control มี Property SelectedIndex หรือ TabPages ให้ใช้งานเหมือนเดิม
  59.     Protected Overrides Sub OnPaint(e As PaintEventArgs)
  60.         e.Graphics.Clear(Color.White)
  61.         e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
  62.         '=========================
  63.         ' วาดแท็บ
  64.         '=========================
  65.         For i As Integer = 0 To Me.TabPages.Count - 1
  66.             Dim r As Rectangle = Me.GetTabRect(i)
  67.             r.Inflate(-3, -3)
  68.             Dim back As Color
  69.             Dim fore As Color
  70.             If i = Me.SelectedIndex Then
  71.                 back = Color.FromArgb(25, 118, 210)
  72.                 fore = Color.White
  73.             ElseIf i = HoverIndex Then
  74.                 back = Color.Gainsboro
  75.                 fore = Color.Black
  76.             Else
  77.                 back = Color.FromArgb(45, 45, 48)
  78.                 fore = Color.WhiteSmoke
  79.             End If

  80.             ' เมื่อออกจากบล็อก Using จะเรียก Dispose() ทันที (แม้จะเกิด Exception ก็ตาม)
  81.             ' ถ้าสร้างทิ้งไว้ไม่ Dispose พอวน Loop หลายๆรอบ (หรือเปิดปิด Tab บ่อยๆ) จะทำให้เกิด Memory Leak
  82.             ' และอาจทำให้โปรแกรมค้างหรือแสดงผลผิดเพี้ยนได้
  83.             Using gp As GraphicsPath = RoundRect(r, 8)   ' <------ สร้าง GraphicsPath
  84.                 Using br As New SolidBrush(back)          ' <------ สร้าง Brush (ซ้อนกัน)
  85.                     e.Graphics.FillPath(br, gp)
  86.                 End Using
  87.                 Using pn As New Pen(Color.FromArgb(90, 90, 90))   ' <------ สร้าง Pen
  88.                     e.Graphics.DrawPath(pn, gp)
  89.                 End Using
  90.             End Using
  91.             TextRenderer.DrawText( _
  92.                 e.Graphics, _
  93.                 Me.TabPages(i).Text, _
  94.                 Me.Font, _
  95.                 r, _
  96.                 fore, _
  97.                 TextFormatFlags.HorizontalCenter Or _
  98.                 TextFormatFlags.VerticalCenter)
  99.         Next
  100.         '=========================
  101.         ' พื้นหลังของ Page
  102.         '=========================
  103.         Dim PageRect As Rectangle
  104.         PageRect = Me.DisplayRectangle
  105.         PageRect.Inflate(1, 1)
  106.         Using br As New SolidBrush(Color.White)
  107.             e.Graphics.FillRectangle(br, PageRect)
  108.         End Using
  109.     End Sub

  110.     '=========================
  111.     ' วาดเส้นโค้ง
  112.     '=========================
  113.     Private Function RoundRect(r As Rectangle, radius As Integer) As GraphicsPath
  114.         Dim gp As New GraphicsPath
  115.         gp.AddArc(r.Left, r.Top, radius, radius, 180, 90)
  116.         gp.AddArc(r.Right - radius, r.Top, radius, radius, 270, 90)
  117.         gp.AddArc(r.Right - radius, r.Bottom - radius, radius, radius, 0, 90)
  118.         gp.AddArc(r.Left, r.Bottom - radius, radius, radius, 90, 90)
  119.         gp.CloseFigure()
  120.         Return gp
  121.     End Function

  122. End Class
คัดลอกไปที่คลิปบอร์ด

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

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

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

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

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

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

GMT+7, 2026-7-27 18:44 , Processed in 0.147668 second(s), 5 queries , File On.

Powered by Discuz! X3.4, Rev.62

Copyright © 2001-2020 Tencent Cloud.

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