Lập trình hướng đối tượng

Giới thiệu về đối tượng

Từ đầu quyển đến giờ, chúng ta chỉ sử dụng biến để chứa những dữ liệu tạm thời trong ứng dụng, chẳng hạn như những giá trị do người sử dụng nhập vào qua giao diện. Tuy nhiên, đây chỉ là một phần nhỏ của VB. VB 6 thực chất là một công cụ lập trình hướng đối tượng rất mạnh.

Bạn có thể cho rằng kỹ thuật này vượt quá khả năng một người mới học lập trình VB. Tuy nhiên, không hẳn như vậy. Lập trình hướng đối tượng (Object Oriented Programming– OOP) giúp lập trình dễ dàng hơn.

Các ví dụ dùng trước đây được lập trình theo kiểu lập trình cổ điển. Điều này không có gì sai bởi vì đây là những chương trình nhỏ và việc sử dụng OOP cho chúng cũng không phù hợp. Với kiểu lập tình cổ điển, còn gọi là Phát triển phần mm theo cấu trúc(StructuredSoftwareDevelopment), ta phải xác định dữ liệu cũng như cách thức để xử lý dữ liệu trong ứng dụng. Một giao diện người sử dụng được cung cấp để hiển thị và nhận dữ liệu từ người sử dụng, sau đó, các hàm và thủ tục con được xây dựng để thực sự xử lý dữ liệu. Điều này có vẻ đơn giản. Để giải quyết một vấn đề lớn, ứng dụng chia thành nhiều vấn đề nhỏ để giải quyết một vấn đề lớn, ứng dụng chia thành nhiều vấn đề nhỏ để giải quyết trong các hàm / thủ tục.

OOPhơi khác một chút. Với lập trình có cấu trúc, cách thức xây dựng ứng dụng, cách chúng kết hợp ở mức chương trình rất khác biệt với thực tế cuộc sống. Lấy một ứng dụng tính lương làm ví dụ. Khi nhân viên được nhận vào làm việc, các thông tin về nhân viên đó sẽ được nhập vào hệ thống tính lương. Sử dụng kỹ thuật lập trình có cấu trúc, ta sẽ dùng một biểu mẫu để chứa các thông tin của nhân viên và viết chương trình để copy tất cả thông tin đã nhập vào biểu mẫu đó vào CSDL chứa ở đâu đó trên mạng công ty. Để tạo ra phiếu trả lương, ta cần có một biểu mẫu in phiếu trả lương cho phép NSD chương trình chọn một nhân viên sẽ trả lương, rồi viết chương trình để thu thập tất cả thông tin từ CSDL và định dạng nó rồi đưa ra máy in.

Ta có thể thấy rằng, giải pháp này nặng về kỹ thuật và nghiêng về xử lý máy tính hơn là cách thực hiện trong thực tế cuộc sống. Lập trình hướng đối tượng sẽ làm cho mọi chuyện trở nên đơn giản hơn nhiều.

Với OOP, ta viết một chương trình dựa trên các đối tượng của thực tế cuộc sống. Ví dụ, nếu ta đang viết một ứng dụng tính lương, đối tượng mà ta cần làm việc sẽ là phòng ban nhân viên . Mỗi đối tượng này có các thuộc tính : ví dụ, một nhân viên có tên và số; một phòng ban có vị trí trưởng phòng. Thêm vào đó, có một số phương thức để phòng phát lương áp dụng cho các đối tượng trên - mỗi tháng một lần, nó quyết định áp dụng phương thức phát lương cho các đối tượng nhân viên. Lập trình OOP cũng tương tự như thế: Ta quyết định đối tượng nào là cần thiết, đối tượng có những thuộc tính nào, và ta sẽ áp dụng những phương thức nào cho đối tượng.

Ta có thể thấy rằng, đây là giải pháp hết sức gần gũi với những vấn đề của thực tế cuộc sống mà ta thường xuyên gặp phải. Nhân viên được xem là đối tượng trong một ứng dụng, và phòng ban là đối tượng có liên quan với nhân viên.

Với lập trình có cấu trúc, ta có xu hướng xem dữ liệu và cách thức xử lý dữ liệu là hai phần tách biệt nhau, hoàn toàn khác với các đối tượng và cách xử lý trong thực tế cuộc sống mà ta vẫn thường làm. Với OOP, ta đóng gói dữ liệu và các chức năng xử lý dữ liệu trong một đối tương (Object) giống hệt với đối tượng trong thực tế cuộc sống. Nhân viên có tên địa ch, vì vậy, đây sẽ là các thuộc tính của đối tượng Nhân viên - dữ liệu. Nhân viên có thể được nhận việc bị đuổi việc , vì vậy, đây sẽ là các phương thức của đối tượng Nhân viên – chức năng.

Bằng cách chia ứng dụng thành nhiều đối tượng và phát triển trên các đối tượng, kỹ thuật này gần gũi hơn với đời sống. Nó giúp tạo ra những chương trình dễ đọc dễ bảo trì. Kỹ thuật này cũng là chọn lựa của nhiều công ty lớn phát triển trong phần mềm.

Đối tượng trong VB

Như vậy các lý thuyết trình bày trên đây thể hiện như thế nào trong VB? Khi ta quyết định đặt một hộp văn bản vào biểu mẫu, ta có phải gọi thủ tục con để tạo hộp văn bản, một thủ tục con khác để đặt hộp văn bản vào vị trí, rồi gọi một thủ tục con khác nữa để định giá trị khởi động? Ta có phải luôn gọi một hàm mỗi khi người sử dụng nhập một giá trị bất kỳ vào hộp văn bản? Dĩ nhiên không phải như vậy.

Những gì ta cần làm là kéo và thả một đối tượng (hay một điều khiển), chẳng hạn như hộp văn bản vào biểu mẫu, rồi dùng các thuộc tính để sửa đổi cách thể hiện chúng. Khi người sử dụng nhập dữ liệu vào hộp văn bản, hộp văn bản sẽ thông báo cho ta biết thông qua các sự kiên Change và sự kiện KeyPress. Mặc dù trước đây, bạn không nhận ra điều này, nhưng ở một mức độ nào đó, bạn đã thực hiện lập trình hướng đối tượng rồi đó.

Ngoài các đối tuợng hay điều khiển được cung cấp sẵn, VB còn cho phép lập trình viên tạo ra các đối tượng thông qua cơ chế modul lớp (Class module). Trong lớp Modul, ta định nghĩa các thuộc tính và phương thức của một đối tượng. Sau khi hoàn tất, để sử dụng đối tượng, trước hết, ta tạo ra đối tượng và gọi các hàm / thủ tục trong modul lớp.

Các đối tượng này có một số đặc tính chung:

Từng đối tượng phải có chức năng tổng quát, được định nghĩa vừa đủ để hiểu nhưng khá mềm dẻo để có thể sử dụng được; nhưng cho phép phát triển thêm tuỳ theo yêu cầu. Ví dụ, một nút lệnh phải có chức năng chung là nhấn vào để thi hành một công việc gì đó. Tuy nhiên, cách thể hiện và hoạt động của nó trong từng trường hợp có thể thay đổi chút ít tuỳ theo cách ta cài thuộc tính và viết code cho phương thức để phản ánh với sự kiện.

Đối tượng giao tiếp bên ngoài thông qua thuộc tính, phương thức, và sự kiện được định nghĩa trước cho nó. Tổ hợp của 3 khái niệm này gọi là giao diện (Interface). Đó là những yếu tố cần biết về một đối tượng để sử dụng chúng.

Có thể sử dụng nhiều đối tượng trong một đề án, ta cũng có nhiều thể hiện khác nhau của một kiểu đối tượng.

Người sử dụng đối tượng không cần quan tâm đến cách lập trình bên trong đối tượng.

Bởi vì người sử dụng chỉ thấy đối tượng điều khiển, ta có thể thay đổi hoạt động bên trong của đối tượng sao cho những thay đổi này không ảnh hưởng đến ứng dụng đang dùng, nghĩa là không thay đổi Interface.

Modul Lớp

Khuôn mẫu để tạo đối tượng là modul lớp. Sau này, modul lớp còn được dùng để tạo điều khiển ActiveX, một kỹ thuật cao hơn của lập trình hướng đối tượng.

Trong bước lập trình căn bản với VB, ta dung modul để chứa các hàm hay thủ tục. Tuỳ theo tầm hoạt động của hàm / thủ tục này, ta có thể gọi chúng trực tiếp từ modul.

Nhưng modul lớp thì không bao giờ được gọi trực tiếp. Để sử dụng một lớp, ta phải tạo đối tượng từ lớp thông qua lệnh New.

Ở đây đối tượng được tạo từ lớp MyClass, còn biến đối tượng MyObject cung cấp một tham chiếu đến đối tượng.

Dim MyObject As New myClass

Dòng lệnh trên tạo một đối tượng gọi là MyObject theo mô tả của lớp MyClass. Hành động này gọi là tạo một Instance từ lớp.Trong cửa sổ Properties, ta có thể phân biệt tên lớp và tên đối tượng. Combo1 là tên đối tượng, trong khi ComboBox là tên lớp.

Ta có thể tạo ra vô số Instance từ một lớp. Mỗi Instance có thể khác nhau một chút tuỳ theo cách ta quy định thuộc tính và sử dụng phương thức.

Thuộc tính và phương thức của lớp

Bên trong một lớp, ta có thủ tục phương thức(Method Procedures) và thủ tục thuộc tính(PropertyProcedures). Quy định một thuộc tính, nghĩa là ta đang gọi hàm x sự kiện PropertyLet.

Trong VB4, modul lớp còn rất thô sơ. Đến VB5, nó bắt đầu hỗ trợ gần gũi hơn cho lập trình hướng đối tượng. Ví dụ: ta có thể tạo ra những điều khiển có thể kết hợp trong môi trường phát triển VB (và những ngôn ngữ khác). Thuộc tính của chúng hiển thị trong cửa sổ Properties, những sự kiện của chúng xuất hiện trong danh sách thả xuống chứa trong cử sổ Code.

Trong VB6, phiên bản ProfessionalEnterprise hỗ trợ Trình xây dựng Lớp(Class Builder) giúp lập trình viên làm việc rất dễ dàng với lớp. Nó cung cấp một loạt các hộp thoại, hướng dẫn ta từng bước để tạo lớp. Tuy nhiên, trong ví dụ này, để hiểu tổ chức một lớp, ta sẽ tạo bằng tay.

Thiết kế lớp có chức năng di chuyển hộp trên màn hình:

1. Tạo đề án mới, kiểu Standard EXE.

2. Từ menu Project, chọn Add Class Module.

3. Chọn ClassModule và nhấn Open. Cửa sổ Code sẽ hiển thị. Nếu nhìn vào cửa sổ ProjectExplorer, ta sẽ thấy một lớp mới xuất hiện.

4. Vì ta muốn tạo một lớp Box, nên ta đổi tên lớp Class1sao cho gợi nhớ: clsBox.

Cụm từ “cls” thể hiện đây là lớp, nhờ đó, chương trình trở nên dễ đọc hơn. Để thực hiện điều này, tìm lớp Class1 trong cửa sổ Properties, đổi thuộc tính Name của nó thành clsBox.

Thuộc tính của Lớp – Public và Private

Lớp Box có 4 thuộc tính là toạ độ góc trái trên (X,Y), chiều cao (Height) và chiều rộng (Width). Bây giờ ta cần khai báo các thuộc tính trên là Public hay Private.

Khi một thuộc tính được khai báo là Public trong một lớp, nó sẽ được sử dụng bởi bất kỳ đoạn chương trình nào có sử dụng lớp này. Trái lại, nếu thuộc tính là Private trong một lớp thì nó sẽ không được truy cập bởi bất cứ đoạn chương trình nào khác.

Ta thử tìm hiểu về thuộc tính Public. So sánh cách khai báo của một thuộc tính Public với một biến Public. Ở đây, biến Public trong một lớp giống như một biến Public bất kỳ nào khác, chỉ có điều là khi ta xử lý nó trong chương trình thì giống như ta đang xử lý với một thuộc tính.

Ví dụ, nếu ta khai báo thuộc tính X là một biến Public, sau đó, khai báo một đối tượng gọi là MyBox dựa trên lớp này, ta có dòng lệnh sau:

MyBox.X = 1000

Tham chiếu đến X tương tự như khi ta xử lý với một thuộc tính thông thường trên các đối tượng hoặc điều khiển bất kỳ khác. Nhưng những gì chúng ta làm là cho phép người sử dụng đối tượng của chúng ta đổi X thành giá trị mà họ mong muốn.

Bây giờ ta sẽ khai báo X là thuộc tính Public, nó cũng tương tự. Nhưng nó cũng không giống hẳn. Đối với thuộc tính Public, mỗi khi nó bị đổi giá trị, một đoạn chương trình bên trong lớp sẽ thi hành. Trong đoạn chương trình này, ta có thể quyết định ta muốn giá trị nào đó mà người sử dụng chỉ ra, và nếu không thì làm một tác vụ gì đó. Do đó, sự khác nhau giữa biến và thuộc tính là: thuộc tính luôn có một đoạn chương tình chạy bên trong mỗi khi nó được truy cập.

Dùng thuộc tính thay cho biến cũng hạn chế khả năng sai sót vì giá trị truyền vào lớp được kiểm nghiệm nhờ đoạn chương trình kiểm tra bên trong lớp.

Trong thực tế, thuộc tính hữu dụng hơn biến vì đôi khi ta cần một xử lý hơn là chỉ gán giá trị. Ví dụ, đổi thuộc tính Color của một hộp văn bản hiệu chỉnh làm nó đổi màu trên màn hình. Đây là một tác vụ không thể thực hiện được với biến. Đoạn chương trình bên trong sẽ gọi một phương thức để thi hành tác vụ này.

Thêm thuộc tính vào lớp.

1. Ta khai báo biến để chứa giá trị thuộc tính

Option Explicit

Private mvarXAs Integer

Biến này có tầm hoạt động bên trong modul lớp.

2. Thêm chương trình vào thuộc tính X:

Public Property Let X( By Val vData As Integer)

mvarX = vData

End Property

Public Property Get X() As Integer

X = mvarX End Property

Đoạn chương trình này không thi hành trực tiếp trừ phi nó được gọi thông qua thuộc tính đối tượng.

Dim MyBox As New clsBox

MyBox.X = 100

Khi ta gán giá trị 100 cho thuộc tính X, thực chất, ta đang gọi thủ tục Property Let X: Public Property Let X(ByValvDataAs Integer)

mvarX = vData

End Property

Giá trị 100 truyền cho tham số vData. Sau đó, nó được gán cho biến cục bộ mvarX, nghĩa là thuộc tính đã được thay đổi và chứa vào đối tượng. Để xem giá trị thuộc tính, ta gọi:

New_Position = MyBox.X

Nghĩa là thủ tục Property Get X thi hành: Public PropertyGetX()As Integer X = mvarX

End Property

- Thủ tục Property Let được gọi khi đổi giá trị thuộc tính. Giá trị đổi sẽ được chứa vào một biến cục bộ bên trong lớp.

- Thủ tục Property Get được gọi khi cần đọc giá trị thuộc tính. Giá trị chứa trong biến cục bộ được trả về Property Get.

Tuy nhiên, hai thủ tục thuộc tính này chỉ làm việc với các kiểu dữ liệu cơ bản như Variant,String,Integer...Đối với thuộc tính chứa đối tượng, thay vì dùng Property Let, ta dùng Property Set. Ví dụ:

Public Property Set Font ( By val New_Font As stdFont) Set mvarFont = New_Font

End Property

Để định thuộc tính Font của đối tượng MyObject từ ứng dụng, ta gửi cho nó đối tượng Font myFont. Tuy nhiên, để đảm bảo VB dùng thủ tục PropertySet, ta đặt từ khoá Set trước thuộc tính:

Dim myFont As New StdFont myFont.Name = ”Courier” myFont.Bold=True

Set MyObject.Font = myFont

Tương tự, ta hoàn tất các thuộc tính còn lại của lớp clsBox.

3. Trong phần General Declarations, thêm các biến cục bộ.

Option Explicit

Private mvarY As Integer Private mvarWidth As Integer Private mvarHeight As Integer

4. Thêm các thủ tục tiếp theo:

Public Property Let Y(By Val vData As Integer)

mvarY = vData

End Property

Public Property Get Y() As Integer

Y = mvarY End Property

Public Property Let Width(By Val vData As Integer)

mvarWidth = vData

End Property

Public Proper t y Get W idth() A s Integer

Width = mvarWidth

End Property

Public Property Let Height(By Val vData As Integer)

mvarHeight = vData

End Property

Public Property Get Height() As Integer

Height = mvarHeight

End Property

5. Lưu modul thành tập tin clsBox.cls

6. Đến đây, ta cần 2 phương thức nữa là vẽ hộp (DrawBox) và xoá hộp (ClearBox). Cả 2 phương thức có một tham số truyền là đối tượng để vẽ hộp lên. Nó có thể là biểu mẫu, hộp hình...

Phương thức của Lớp

Thêm phương thức cho lớp

  1. Thêm đoạn chương trình sau vào modul lớp: PublicSub DrawBox(CanvasAs Object)Canvas.Line (mvarX, mvarY)-(mvarX + mvarWidth, mvarY+ mvarHeight),, B EndSub Đoạn chương trình này sử dụng phương thức Linecủa đối tượng Canvas. Phương thức Linesẽ vẽ một hộp trên biểu mẫu nếu ta đưa vào tham số cuối cùng B (B có nghĩa là hộp – box).
  2. Kế đến, ta thêm ClearBoxvào Lớp: PublicSub ClearBox(CanvasAsObject)Canvas.Line (mvarX, mvarY)-(mvarX + mvarWidth, mvarY+ _mvarHeight), Canvas.BackColor,B EndSub
  3. Lưu modul với tên clsBox.clsVì 2 thủ tục này sẽ được dùng làm phương thức của đối tượng, nên chúng được khai báo Public, nghĩa là chúng có thể được gọi từ bên ngoài modul.

Tạo Instance cho lớp

Tạo hoạt hình với đối tượng hộp

1. Nếu bạn đang mở đề án trong ví dụ trước, chỉ cần nhấn đúp chuột lên biểu mẫu để mở cửa sổ Code. Nếu không, tạo đề án mới kiểu StandardEXE. Từ menu Project, chọn Add Class Module; sau đó, chọn tab Existing trong hộp thoại và chọn clsBox.cls.

2. Tìm sự kiện Click trong hộp danh sách và đưa đoạn chương trình sau vào: Dim A_Box As New clsBox

Biến đối tượng A_Box sẽ giữ một Instance của lớp. Từ kháo New rất quan trọng, nếu thiếu nó, VB sẽ cho rằng ta muốn tạo một bản sao của đối tượng clsBox hiện hành. Khi tham chiếu đến nó, ta sẽ gặp lỗi.

3. Đưa đoạn chương trình sử dụng đối tượng:Private Sub Form_Click()

Dim A_Box As New clsBox

Dim nIndex As Integer

With A _Box

.Y = 0

.Width = 1000

.Height = 1000

For nIndex = 0 T o 1000

.ClearBox Me

.X = nIndex

.DrawBox Me

Next End With End Sub

4. Thi hành chương trình. Nhấn chuột vào biểu mẫu, ta sẽ thấy hộp trượt dọc theo biểu mẫu.

Kiểm tra giá trị thuộc tính

Trong thủ tục thuộc tính Property Let X, nếu ta truyền vào chuỗi ký tự “HelloWorld”, trình biên dịch sẽ báo lỗi.

Public Property Let X(By Val vData As Integer)

m varX = vData

End Property

Tuy nhiên, nếu ta truyền vào số -7983, hộp chắc chắn sẽ không hiển thị trên biểu mẫu.

Ta có thể cấm điều nằy bằng cách:

Public Property Let X(ByVal vData As Integer)

if vData >0 Then mvarX = vData

End Property

Đối tượng sẽ bỏ qua giá trị âm truyền vào.

Thuộc tính chỉ được đọc (Read – Only)

Đối với thuộc tính chỉ được đọc, ta không thể thay đổi giá trị thuộc tính. Muốn vậy, ta chỉ cần loại bỏ thủ tục PropertyLet trong modul lớp.

Tham số tuỳ chọn

Ta có thể sử dụng tham số tuỳ chọn trong các phươngthc, thậm chí các thủtụccủa thuộctính. Ví dụ, ta có thể thêm tham số màu cho phương thức DrawBox. Khi đó, chỉ với phương thức DrawBox, ta có thể vẽ hoặc xoá hộp mà không cần gọi ClearBox.

Dùng tham số tuỳ chọn

1. Dừng chương trình. Trong cửa sổ ProjectExplorer, nhấn đúp chuột lên clsBox để mở cửa sổ Code.

2. Tìm phương thức ClearBox, đánh dấu khối thủ tục và nhấn phím Deleteđể xoá nó đi.

3. Sửa phương thức DrawBox để thêm vào tham số tuỳ chọn màu: Public Sub DrawBox(Canvas As Object, Optional lColorAsLong)

If IsMissing(lColor) Then

Canvas.Line (mvarX, mvarY)-(mvarX + mvarWidth, mvarY+ _

mvarHeight),, B Else

Canvas.Line (mvarX, mvarY)-(mvarX + mvarWidth, mvarY+ _

mvarHeight), lColor, B End If

End Sub

4. Đến đây, chương trình chưa thể biên dịch, vì vẫn còn một dòng lệnh tham chiếu đến phương thức ClearBox.

.DrawBox Me

Xoá dòng này và thay thế bằng dòng lệnh

.DrawBox Me, Me.BackColor

5. Thi hành chương trình. Không có thay đổi trong kết quả.

Từ khoá Optional cho biết tham số phía sau nó không nhất thiết phải truyền khi gọi phương thức. Để biết được khi nào có tham số được truyền, ta dùng hàm IsMissing. Hàm này trả về giá trị True/False. Nếu không có tham số truyền, nó trả về True; nếu có, nó trả về False. Tuỳ theo trường hợp mà ta có xử lý tương ứng. Ở đây, khi có tham số truyền, ta gọi hàm Line có chỉ định màu.

Lưu ý rằng tham số tuỳ chọn phải là tham số cuối cùng trong danh sách được truyền.

Ví dụ, dòng lệnh sau đây không được chấp nhận:

Public Sub MyRoutine (Optional sName As String,nAge As Integer) Ta phải sửa thành:

Public Sub MyRoutine (nAge As Integer, Optional sName As String)

Thận trọng:

Mặc dù tham số tuỳ chọn có tính linh hoạt, giúp ta giảm số dòng chương trình, nhưng nó cũng cho ta những rắc rối kèm theo.

Một trong những lý do để chuyển từ lập trình theo cấu trúc sang lập tình hướng đối tượng là làm cho chương tình dễ đọc, dễ hiểu, dễ xây dựng và dễ bảo trì. Tham số tuỳ chọn làm giảm tính an toàn và tăng độ phức tạp của chương trình khi ta cần gỡ rối.

Tham số tuỳ chọn cung cấp tính năng tái sử dụng chương trình, giúp tạo ra các đối tượng hay thành phần đa mục đích nhưng ta phải cẩn thận và tự hỏi: thêm vào thì có lợi ích gì cho thủ tục của ta, hay là chương trình sẽ tốt hơn nếu ta không dùng nó?

Sự kiện của lớp

Định nghĩa sự kiện cho lớp đã có trong VB5. Nó vẫn hữu dụng với VB6. Chẳng hạn ta muốn mỗi lần hộp được vẽ trên màn hình, sự kiện Draw gây ra hoạt động cập nhật trên màn hình.

Định nghĩa và kích hoạt sự kiện

1. Định nghĩa sự kiện Draw. Một trong những thông tin cần cập nhật là toạ độ (x,y) của hộp. Mở cửa sổ Code và thêm dòng lệnh sau vào phần General Declarations:

Public Event Draw(X As Integer, Y As Integer)

Tuy nhiên, dòng lệnh này chưa thể hiện lúc nào thì sự kiện được kích hoạt.

2. Ta muốn sự kiện Draw được sinh ra mỗi khi hộp được vẽ trên biểu mẫu. Tìm phương thức DrawBox và thêm dòng lệnh in đậm vào cuối của phương thức này:

Public Sub DrawBox(Canvas A s Object, Optional lColor As Long)

If IsMissing(lColor) Then

Canvas.Line (mvarX, mvarY)-(mvarX + mvarWidth, mvarY+ _

mvarHeight),, B Else

Canvas.Line (mvarX, mvarY)-(mvarX + mvarWidth, mvarY+ _

mvarHeight), lColor, B End If

Raise Event Draw(mvarX, mvarY) End Sub

3. Tìm thủ tục xử lý sự kiện Click của biểu mẫu. Tìm và xoá dòng lệnh tạo đối tượng A_Box và thêm một dòng vào phần General Declarations:

Private WithEvents A_Box As clsBox

Private Sub Form_Click() Dim nIndex As Integer With A_Box

.Y = 0

.Width = 1000

.Height = 1000

For nIndex = 0 To 1000

.DrawBox Me, Me.BackColor

.X = nIndex

.DrawBox Me

Next End With

End Sub

4. Thêm một dòng vào sự kiện Form_Load: Private Sub Form_Load()

Set A_Box = New clsBox

End Sub

5. Chọn A_Box từ danh sách trong cửa sổ Code. Chọn sự kiện Draw từ danh sách các sự kiện.

6. Trong sự kiện này, ta dùng lệnh Print để in ra toạ độ của hộp trong cửa sổ gỡ rối (hay còn gọi là cửa sổ Immediate)

Private Sub A_Box_Draw(X As Integer, Y As Integer) Debug.Print "The box just got drawn at " & X &, " & Y

End Sub

7. Thi hành chương trình. Nhấn chuột trên biểu mẫu, ta thấy hộp trượt qua màn hình. Đồng thời trong cửa sổ Immediate, ta thấy các dòng văn bản hiển thị toạ độ hiện hành của hộp.

Ở đây, ta dùng phương thức RaiseEvent để yêu cầu VB phát ra sự kiện Draw, và truyền 2 giá trị của 2 biến thuộc tính mvarXmvarY chứa toạ độ (x, y) của hộp cho sự kiện Draw mới.

Để có thể xử lý các sự kiện của một đối tượng tự tạo, ta cần khai báo đối tượng hơi khác một chút. Trước hết, nó phải được khai báo là Private trong biểu mẫu (hoặc modul), thay vì là Private trong một thủ tục. Sau đó, ta phải dùng từ WithEvents thay vì Dim:

Private WithEvents A_Box As clsBox

Từ khóa WithEvents báo cho VB biết ta đang khai báo một đối tượng có sự kiện, và ta dự định viết chương trình để xử lý những sự kiện này.

Chú ý từ khoá New bị loại bỏ trong dòng lệnh WithEvents. Khi ta viết: Dim A_Box As New clsBox

Nghĩa là không chỉ thông báo cho VB rằng ta sắp sử dụng một đối tượng dựa theo lớp clsBox, ta còn yêu cầu VB cấp phát vùng nhớ cho đối tượng và tạo nó. Tuy nhiên, do hạn chế của VB, điều này không được thực hiện với từ khoá WithEvents. Thay vào đó, ta phải tạo đối tượng riêng, bằng cách thêm dòng lệnh vào sự kiện Form_Load.

Tóm lại, đối với sự kiện, ta cần nhớ:

- Khai báo sự kiện dùng Public Event.

- Phát sự kiện dùng RaiseEvent

- Tạo đối tượng với Dim WithEvents, không dùng New.

- Tạo đối tượng như sau:

Set < đối tượng> = New <lớp>

- Viết chương trình để bắt sự kiện tương tự xử lý sự kiện của điều khiển.

Huỷ đối tượng

Sau khi sử dụng một đối tượng và không cần dừng nữa, ta cần huỷ nó đi. Điều này đặc biệt quan trọng khi ta sử dụng nhiều đối tượng trong ứng dụng. Nếu không huỷ đối tượng, sự hao hụt vùng nhớ sẽ làm giảm khả năng hoạt động của ứng dụng. Ta dùng dòng lệnh sau:

Set < đối tượng> = Nothing

Nơi lý tưởng để huỷ một đối tượng là trong sự kiện Unload của biểu mẫu. Ví dụ:

Private Sub Form_Unload (Cancel As Integer) Set A_Box = Nothing

End Sub

Biến đối tượng

Cho đến bây giờ, ta chỉ tham chiếu đến điều khiển hay biểu mẫu thông qua tên ta đặt cho chúng lúc thiết kế. Cách làm này chỉ phù hợp đối với các chương tình đơn giản. Đặt đối tượng vào biến và tham chiếu đến nó bằng tên biến cho phép ta sử dụng cùng đoạn chương trình cho vô số các instance khác nhau của một kiểu đối tượng.

Với biến đối tượng ta có thể:

- Tạo điều khiển mới trong lúc thi hành.

- Copy điều khiển để sinh ra một instance mới của điêu khiển hiện hành.

- Tạo bản sao biểu mẫu cùng tên, cùng điều khiển và chương trình; nhưng từng biểu mẫu chứa và xử lý những dữ liệu khác nhau – tương tự nhiều tài liệu trong ứng dụng của Word hay nhiều bảng tính trong Excel.

Biến đối tượng cung cấp khả năng xây dựng các thủ tục tổng quát để xử lý với những điều khiển nhất định. Ví dụ, một thủ tục kiểm tra dữ liệu của hộp văn bản chỉ dùng trong trường hợp tên điều khiển được chỉ ra trong chương tình. Tuy nhiên, để thủ tục trở thành độc lập với điều khiển bất kỳ, ta xem điều khiển như một biến đối tượng. Dim New Employee As New cEmployee

Tạo điều khiển lúc thi hành

Cách đơn giản nhất là tạo một mảng điều khiển vào lúc thiết kế, sau đó, mở rộng mảng bằng chương trình lúc thi hành. Nếu ta định thuộc tính Indexcủa điều khiển đầu tiên là 0 lúc thiết kế, ta có thêm điều khiển lúc thi hành. Điều khiển tạo lúc thi hành có cùng tên, kiểu, và thủ tục xử lý sự kiện như điều khiển ban đầu.

Tương tự biến mảng, ta có thể mở rộng hoặc rút gọn mảng điều khiển. Điểm khác nhau là ta không Redimmảng điều khiển như với biến mảng. Thay vào đó, ta phải Load bản instance mới của điều khiển vào mảng. Khi muốn xoá điều khiển, ta Unload chúng.

Tạo điều khiển lúc thi hành

Thử tạo một dãy các nút lệnh trên biểu mẫu. Vẽ một nút lệnh lúc thiết kế và dùng chương trình để tạo phần còn lại.

1. Tạo đề án mới và vẽ một nút lệnh trên biểu mẫu.

2. Đổi thuộc tính Index thành 0. Khi ấy một mảng điều khiển có một phần tử được tạo ra.

3. Đưa đoạn chương tình sau vào thủ tục Click của nút lệnh: Private Sub Command1_Click(IndexAs Integer)

Statics NextOperation As String

Dim nIndex As Integer

For nIndex = 1 To 5

If sNextOperation = " UNLOAD" Then

Unload Command1(nIndex) Else

Load Command1(nIndex) With Command1(nIndex)

.Top = Command1(nIndex - 1).Top +Command1(nIndex- 1).Height

.Caption = nIndex

.Visible = True

End With End If Next

If sNextOperation = "UNLOAD" Then sNextOperation = "LOAD"

Else

sNextOperation = " UNLOAD" End If

End Sub

4. Thi hành đoạn chương trình và nhấn trên nút lệnh vài lần. Mỗi lần nhấn, 5 nút lệnh được tạo hoặc xoá.

5. Lưu vào đĩa với tên NewCtrl.vbp

Vòng lặp For...Nexttạo hoặc xoá nút lệnh này tuỳ theo nội dung biến sNextOperation. Trước hết, nội dung của sNextOperationđược kiểm tra để xem cần Loadhay Unload các phần tử. Lần đầu, sNextOperationchưa được gán, nó rơi vào phần False, nghĩa là Load.

Bởi mặc định, điều khiển mới tạo lúc thi hành xuất hiện tại cùng vị trí với điều khiển gốc, và không hiển thị. Do đó, ta có thể đổi vị trí và điều chỉnh kích cỡ mà không để người sử dụng thấy. Nó cũng cấm Windows vẽ lại mỗi lần nạp các điều khiển, không những làm chậm chương trình mà còn hiển thị không có trật tự trong khi ta đang di chuyển chúng. Ta chỉ cho chúng hiển thị sau khi đã có vị trí mới.

Sự kiện của mảng điều khiển

Mặc dù hiển thị khác nhau, 6 phần tử vẫn chia sẻ một thủ tục xử lý sự kiện, vì nhấn vào một nút bất kỳ, chúng đề đáp ứng như nau. Ta có thể xử lý các sự kiện theo từng nút lệnh phân biệt, dựa trên Indexcủa mảng điều khiển.

Xử lý sự kiện với mảng điều khiển

1. Mở đề án NewCtrl.vbp và chọn sự kiện Click trên nút lệnh.

2. Thêm đoạn chương trình sau vào:

Private Sub Command1_Click(Index As Integer) Statics NextOperation As String

Dim nIndex As Integer Select Case Index Case 0

For nIndex = 1 To 5

If sNextOperation = "UNLOAD" Then

Unload Command1(nIndex) Else

Load Command1(nIndex) With Command1(nIndex)

.Top = Command1(nIndex.Top +Command1(nIndex- 1).Height

.Caption = nIndex

.Visible = True

End With

End If

Next

If sNextOperation = "UNLOAD" Then sNextOperation = "LOAD"

Else

sNextOperation = "UNLOAD" End If

Case 1, 2, 3, 4, 5

MsgBox " You pressed Button " & Index

End Select

End Sub

3. Thi hành chương trình. Nhấn chuột trên từng nút lệnh, một thông điệp xuất hiện cho biết thứ tự nút nhấn.

Quản lý điều khiển như biến đối tượng

Không chỉ dùng biến đối tượng như mảng điều khiển, ta còn có thể truyền biến đối tượng và mảng đối tượng vào thủ tục hay hàm.

Ví dụ, ta có khoảng 30 họpp văn bản trên biểu mẫu, từng cái nhận dữ liệu khác nhau. Một số chỉ nhận kiểu số, một số chỉ nhận chữ cái, số khác chấp nhận cả hai, trong khi số còn lại kiểm tra số ký tự nhập vào xem có vượt quá số lượng quy định không? Nếu xử lý riêng rẽ từng điều khiển, ta sẽ tốn rất nhiều đoạn chương tình. Giải pháp là xem hộp văn bản như một đối tượng, và truyền nó đến một thủ tục tổng quát.

Hàm kiểm tra hộp văn bản

Hàm này sẽ tự động biết kiểu dữ liệu mà mỗi hộp văn bản cũng như chiều dài tối đa của dữ liệu.

Kiểm tra hộp văn bản

1. Tạo đề án mới và vẽ một biểu mẫu gồm các điều khiển như sau:

2. Thiết lập thuộc tính cho hộp văn bản như sau:

Mô tả Thuộc tính Giá trị
Hộp “alphabetic only” (chỉnhận chữ) NameIndexTag txtValidate0A12
Hộp “Numbers” (chỉ nhậnsố) NameIndexTag txtValidate1N5

Hộp “Anything” (nhận mọi thứ)

Name Index Tag

txtValidate

0

*4

Lưu ý rằng chữ cái trong thuộc tính Tagtrong cửa sổ Properties phải là chữ in hoa, nếu không ví dụ không hoạt động.

3. Phần còn lại là viết chương trình. Mở cửa sổ Code, đưa đoạn chương trình sau vào:

Option Explicit

Private Sub ValidateKey Press(txtControl As TextBox, nKeyAscii As Integer) Dim sMaxLength As String

Dim sKey As String * 1

If nKeyAscii < 32 Or nKeyAscii > 126 Then Exit Sub sMaxLength = Right$(txtControl.Tag, Len(txtControl.Tag)- 1)

If Len (txtControl.Text) > = Val(sMaxLength) Then

Beep nKeyAscii = 0

Exit Sub

End If

Select Case Left$(txtControl.Tag, 1) Case "A"

sKey = UCase(Chr$(nKeyAscii))

If Asc(sKey) < 65O rAsc(sKey)>90 Then

Beep nKey Ascii = 0

Exit Sub

End If

Case "N"

If nKey Ascii < 48 Or nKey Ascii > 57 Then

Beep nKey Ascii = 0

Exit Sub

End If End Select End Sub

4. Thi hành chương trình.ValidateKeyPress là thủ tục ở mức biểu mẫu và được khai báo trong phần General. nKeyAscii là mã của phím nhấn. Vì từ khoá ByVal không được nêu ra, nên tham số được truyền bằng tham chiếu. Đổi KeyAscii về 0 trong sự kiện KeyPress nghĩa là phím nhấn.

Thuộc tính Tag được dùng như một nhãn riêng đa năng cho các điều khiển. Nó cho biết kiểu dữ liệu được cho phép trong mỗi hộp văn bản. Ký tự đầu tiên định nghĩa kiểu dữ liệu cho phép, ‘A’ nghĩa là chỉ có chữ cái, ‘N’ nghĩa là số, còn lại là các kiểu khác. Con số kế tiếp quy định số ký tự tối đa trong mỗi hộp văn bản.

Ta có thể đổi kiểu dữ liệu của mỗi hộp văn bản bằng cách đổi thuộc tính Tagtrong cửa sổ Properties.

Giai đoạn đầu tiên, chương tình kiểm tra nKeyAscii cho các ký tự đặc biệt. Nếu chúng được nhấn, phím đó sẽ được bỏ qua.

If nKey Ascii < 32 Or nKey Ascii > 126 Then Exit Sub

Dòng lệnh kế lấy giá trị từ thuộc tính Tag đưa vào biến sMaxLength. Sau đó, kiểm tra chiều dài tối đa:

If Len (txtControl.Text) > = Val(sMaxLength) Then

Beep nKey As cii = 0

Exit Sub

End If

SelectCaseso sánh phím ký tự với kiểu dữ liệu quy định trong thuộc tính Tag. Hàm

Chr$ chuyển mã ký tự nKeyAscii thành chuỗi ký tự tương ứng. Hàm Asclàm ngược lại và trả về mã ký tự ASCII của một ký tự.

Khai báo biến đối tượng

Ta có thể khai báo một biến đối tượng một cách tường minh như khai báo biến thông thường bằng cách cung cấp một kiểu dữ liệu mà VB nhận ra.

Dim txtControl As TextBox

Chương trình sẽ hiệu quả, dễ gỡ rối và chạy nhanh hơn khi khai báo biến đối tượng tường minh. Tuy nhiên, VB cũng cho phép khai báo một biến đối tượng “ẩn”:

Dim cltControl As Control

Tham số hàm và thủ tục có thể khai báo kiểu này. Nó cho phép ta truyền một điều khiển bất kỳ. Sau đó, dùng dòng lệnh TypeOf để kiểm tra kiểu điều khiển liên quan đến một đối tượng.

Nếu khai báo tường minh, VB kiểm tra thuộc tính của đối tượng ngay lúc biên dịch. Nếu khai báo ẩn, VB chỉ kiểm tra thuộc tính lúc thi hành.

Kiểu của biến đối tượng

Sau đây là danh sách các kiểu đối tượng tường minh mà VB có thể nhận ra:

CheckBox ComboBox CommandButton MDIForm
Data DirListBox DriveListBox FileListBox
Grid Frame HscrollBar Image
Label Line ListBox menu
OptionButton OLE PictureBox Shape
TextBox Timer VscrollBar Form

Đây là những đối tượng chuẩn. Chúng là những tên lớp và được đặt kế bên tên điều khiển trong cửa sổ Properties.

So sánh khai báo tường minh và ẩn

1. Tạo đề án mới. Vẽ biểu mẫu như sau:

2. Đặt tên điều khiển nhãn trống là lblTime, nút lệnh là cmdExplicit cmdImplicit.

3. Mở cửa sổ Code, đưa đoạn chương trình sau vào: Private Sub cmdExplicit_Click()

Dim varTime As Variant Dim nIndex As Integer varTime = Now

For nIndex = 1 To 15000

Time_Explicit cmdExplicit, nIndex

Next

cmdExplicit.Caption = "&Explicit"

lblTime.Caption = Minute(Now - varTime)& " Mins, " & _ Second(Now - varTime) & " Secs"

End Sub

Private Sub cmdImplicit_Click() Dim varTime As Variant

Dim nIndex As Integer varTime = Now

For nIndex = 1 To 15000

Time_Implicit cmdImplicit, nIndex

Next

cmdImplicit.Caption = "&Implicit"

lblTime.Caption = Minute(Now - varTime)& " Mins, " & _ Second(Now - varTime) & " Secs"

End Sub

Đưa 2 thủ tục sau vào phần ( General )

Private Sub Time Explicit(cmdCommand As ComandButton, nNumber As Integer)

cmdComm and.Caption = nNumber

End Sub

Private Sub Time_Implicit(cmdComm and As Control,nNumber As Integer)

cmdCommand.Caption = nNumber

End Sub

4. Thi hành ứng dụng bằng cách nhấn F5.

5. Khi biểu mẫu xuất hiện, nhấn nút Explicit. Chương trình báo thời gian hiển thị liên tục 15000 tiêu đề khác nhau trên nút lệnh. Nút lệnh là một biến đối tượng được khai báo tường minh.

6. Nhấn chuột trên nút Implicit. Mọi việc xảy ra tương tự, nhưng lần này nút lệnh là một biến đối tượng được khai báo ẩn.

Để ý bạn sẽ thấy nhấn trên Implicitchậm hơn nhấn trên Explicit khoảng 10%.

Tập hợp

Mỗi biểu mẫu trong ứng dụng có một tập hợp các điều khiển nội tại. Trong lúc thi hành, ta có thể dùng tập hợp để truy cập đến điều khiển trên biểu mẫu. Ta không cần biết tên của mỗi điều khiển, thậm chí kiểu điều khiển. Khác với mảng điều khiển, ta không cần khai báo, và tất cả điều khiển trên biểu mẫu được tự động xem như một phần của biểu mẫu. Khi thêm hay xoá một điều khiển trên biểu mẫu, VB tự động quản lý việc thêm hay xoá điều khiển trong tập hợp.

Truy cập phần tử trong tập hợp tương tự truy cập phần tử trong mảng thông thường.

Tập hợp rất tiện lợi cho các biểu mẫu nhập liệu. Ví dụ, ta có thể viết một thủ tục chung để duyệt qua tập hợp này và tìm kiếm chỉ những điều khiển dữ liệu và sau đó gán cho thuộc tính CSDL của chúng một đướng dẫn đến tập tin CSDL của khách hàng.

Khác với mảng điều khiển, tập hợp điều khiển không hỗ trợ các sự kiện. Tuy nhiên, từng điều khiển trong tập hợp đều có nhưng thuộc tính, phương thức và sự kiện.

Thuộc tính Controls

Thuộc tính Controlscủa biểu mẫu chỉ được truy cập thông qua chương tình. Nó thực chất là một mảng các biến đối tượng, trong đó, mỗi phần tử của mảng là một điều khiển đơn: phần tử số 0 là điều khiển đầu tiên trên biểu mẫu, phần tử số 1 là điều khiển thứ 2...

Số thứ tự trong mảng được gán tự động khi ta vẽ điều khiển lên biểu mẫu trong lúc thiết kế. Nếu có 2 hộp văn bản trên biểu mẫu, ta có thể đổi thuộc tính Text của từng điều khiển như sau:

Form1.Controls(0).Text=”Control 0” For m1.Controls(1).Text=”Control 1”

Cú pháp:

<tên biểu mẫu>.Controls (<số thứ tự>).<thuộc tính> = <giá trị>

Xác định điều khiển trên biểu mẫu

Mảng Controlscó một thuộc tính gọi là Count, xác định số điều khiển trên biểu mẫu. Lưu ý rằng mảng được đánh số từ 0. Nếu Countlà 3, nghĩa là các phần tử sẽ đánh số lần lượt là 0,1,2.

Ta có thể dùng TypeOfđể xử lý với nhóm các điều khiển tương tự. Mặc dù không chỉ ra chính xác một phần tử, nhưng ta có thể xác định các điều khiển cùng kiểu.

For cControlNo = 0 To Form1.Controls.Count –1

If TypeOf Form1.Controls(nControlNo) Is TextBox Then

:

:

End if

Next

Ta duyệt qua từng phần tử của tập hợp trên Form1 từ 0 đến phần tử cuối cùng, Count –1. Với từng điều khiển, ta dùng TypeOfđể kiểm tra xem nó có phải là hộp văn bản hay không.

Tuy nhiên, làm việc trên chỉ mục hơi thô thiển, ta dùng cách khác trực quan hơn: For Each objControlIn Form1.Controls

If TypeOf bjControl Is TextBox Then

:

:

End if

Next

Đổi màu

Dùng mảng điều khiển để đổi màu các điều khiển trên biểu mẫu.

1. Tạo đề án mới và vẽ các điều khiển lên biểu mẫu như sau:

Lưu ý rằng ta cần đặt 2 điềukhiểnkhunglên biểu mẫu, sau đó thêm các điều khiển khác lên trên. Khi đó, mỗi lần di chuyển khung, điều khiển cũng sẽ di chuyển theo.

2. Đặt tên biểu mẫu là frmColors và tên nút lệnh lần lượt là cmdBackground, cmdForeground, cmdQuit. Tên hộp đánh dấu lần lượt là chkCheckBoxes, chkFrames, chkTextBoxes chkLabels.

3. Thêm một điều khiển hộp thoại thông dụng vào biểu mẫu và đặt tên là dlgColors.

Lưu ý rằng nếu điều khiển chưa có trong hộp công cụ, chọn Components... từ menu

Project, sau đó, đánh dấu chọn MicrosoftCommon DialogControl6.0.

4. Viết chương trình cho nút Background: Private Sub cmdBackground_Click()

Dim nColor As Long

Dim FormControl As Control On Error Go To BackcolorError dlgColors.CancelError = True dlgColors.Flags = &H1&

dlgColors.ShowColor nColor = dlgColors.Color

For EachFormControl In frmColors.Controls

If TypeOf FormControl Is TextBox And chkTextBoxes.Value = 1 Then

FormControl.BackColor = nColor

If TypeOf FormControl Is Frame And chkFrames.Value = 1 Then

FormControl.BackColor = nColor

If TypeOf FormControl Is Label And chkLabels.Value = 1 Then

FormControl.BackColor = nColor

If TypeOf FormControl Is CheckBox And chkCheckBoxes.Value = 1 Then

FormControl.BackColor = nColor

Next

Exit Sub

Back colorError:

MsgBox ("You pressed the cancel button.") End Sub

5. Chương trình cho nút Foreground: Private Sub cmdForeground_Click()

Dim nColor As Long

Dim FormControl As Control On Error Go To ForecolorError dlgColors.CancelError = True dlgColors.Flags&H1& dlgColors.ShowColor

nColor = dlgColors.Color

For Each FormControlIn frmColors.Controls

If TypeOf FormControl Is TextBox And chkTextBoxes.Value = 1 Then

FormControl.ForeColor = nColor

If TypeOf FormControl Is Frame And chkFrames.Value = 1 Then

FormControl.ForeColor = nColor

If TypeOf FormControl Is Label And chkLabels.Value = 1 Then

FormControl.ForeColor = nColor

If TypeOf FormControl Is CheckBox And chkCheckBoxes.Value = 1 Then

FormControl.ForeColor = nColor

Next

Exit Sub

ForecolorError:

MsgBox ("You pressed the cancel button.") End Sub

6. Viết chương trình cho nút

Quit: Private Sub cmdQuit_Click()

' Quit the application by unloading the form

Unload frmColors

End Sub

7. Thi hành chương trình. Chọn vào hộp đánh dấu để chọn kiểu điều khiển ta muốn đổi màu, nhấn nút Backgroundhay Foreground để thi hành việc đổi. Một hộp thoại màu xuất hiện cho phép ta chọn màu.

Thuộc tính CancelErrorcủa điều khiển hộp thoại thông dụng được quy định là True, nghĩa là lỗi số 32755 được phát sẽ gửi chương trình trực tiếp bẫy lỗi.

Vòng lặp For Each...Next duyệt qua từng điều khiển trong tập hợp, đặt từng phần tử vào biến đối tượng FormControlDùng TypeOfđể kiểm tra kiểu điều khiển. Lưu ý dùng từ khoá Isvới TypeOf thay vì dùng dấu kiểm tra bằng.

Biểu mẫu MDI

Biểu mẫu MDI cho phép nhóm các biểu mẫu và chức năng trong một cửa sổ lớn. Tuy nhiên, biểu mẫu MDI có một số nhược điểm: chỉ có một vài điều khiển được vẽ trên biểu mẫu MDI. Đó là điều khiển định giờ và hộp hình. Trong phiên bản Professional và Enterprise ta có thể vẽ thêm thanh trạng thái và thanh công cụ. Hộp hình vẽ trong biểu mẫu MDI luôn có cùng bề rộng với biểu mẫu và tự động được đặt ở phần trên cùng hoặc dưới cùng của biểu mẫu. Ta không thể điều chỉnh bằng tay. Nếu ta cố canh trái hoặc canh phải, hộp hình sẽ chiếm toàn bộ biểu mẫu MDI.

Biểu mẫu con (Child Form)

Thuộc tính MDIChild của một biểu mẫu là một giá trị True/False cho biết biểu mẫu có phải là biểu mẫu con trong một biểu mẫu MDI hay không. Bởi vì VB chỉ cho phép tồn tại một biểu mẫu MDI trong ứng dụng, biểu mẫu con tự động nhận biết cửa sổ cha và khi thi hành, nó chỉ hoạt động bên trong cửa sổ cha.

Vào lúc thiết kế, không thể phân biệt cửa sổ độc lập với cửa sổ con, chỉ khác nhau ở chỗ thuộc tính MDIChildmà thôi. Thuộc tính này không gán được vào lúc thi hành, nếu không, ta sẽ nhận thông báo lỗi trước khi chương trình treo.

Cửa sổ con

1. Tạo đề án mới và đặt tên biểu mẫu mặc định là frmChild. Đổi thuộc tính MDIChild thành True.

2. Từ menu Project, chọn Add MDI Form để tạo một cửa sổ MDI và đặt tên cho nó là frmParent.

3. Thêm menu cho biểu mẫu MDI gồm 2 mục: New và Exit. Đặt tên cho chúng là mnuFNew và mnuFExit.

4. Thêm menu cho cửa sổ con bao gồm: File, Edit, View, Options.

5. Viết chương trình cho menu New

Private Sub mnuFNew_Click() Load frmChild

End Sub

6. Từ menu Project, chọn Project1 Properties và chọn biểu mẫu khởi động là biểu mẫu MDI.

7. Thi hành ứng dụng. Khi mới xuất hiện, cửa sổ MDI chưa có cửa sổ con và hiển thị menu của chính nó. Nếu ta chọn New từ menu File, cửa sổ con hiển thị. menu của biểu mẫu MDI được thay thế bằng menu của cửa sổ con. Trạng thái đầu của cửa sổ MDI sẽ được phục hồi toàn bộ củă sổ con bị tắt.

8. Lưu đề án với tên MDIChild.vbp.

Tạo Instance của biểu mẫu

Sử dụng biến đối tượng để tạo ra những bản sao của một biểu mẫu. Từng bản sao có các điều khiển và menu như nhau, nhưng có những dữ liệu khác nhau. Mặc dù chương trình cũng như tên biến và tên điều khiển như nhau, nhưng dữ liệu được chứa ở những nơi khác nhau trong bộ nhớ.

Tạo Instance của biểu mẫu

1. Mở lại đề án MDIChild.vbp. Chon biểu mẫu frmParant.

2. Chọn New từ menu File của biểu mẫu MDI. Mở cửa sổ Code và đưa đoạn chương trình sau vào:

Private Sub mnuFNew_Click()

Dim OurNewForm As New frmChild

OurNewForm.Show

End Sub

3. Đoạn chương trình trên dùng biến đối tượng để tạo một instance cho cửa sổ frmChild.

4. Xoá toàn bộ menu của cửa sổ con.

5. Thi hành chương trình. Mỗi lần nhấn New, một cửa sổ mới được tạo.

6. Lưu đề án với tên mới bằng cách chọn Save File Form As... và Save Project

As... từ menu File. Đặt tên là MDIChild1.vbp

Xác định biểu mẫu

Vì ta có thể tạo ra 10 biểu mẫu đồng nhất có cùng tên, nên việc xác định cửa sổ là cần thiết. Từ khoá Me cho phép ta tham chiếu đến cửa sổ hiện hành, là cửa sổ đang có focus, hay nói cách khác, là cửa sổ nhận được mọi phím nhấn hay click chuột bất kỳ.

Ta có thể dùng: activeform.txtEmployee.text = Peter” nhưng dùng me là cách thông dụng nhất.

Tạo danh sách cửa sổ

Tạo danh sách cửa sổ

1. Mở đề án MDIChild1.vbp. Chọn hiển thị biểu mẫu frmParent

2. Tạo tuỳ chọn Window trên menu

Đưa đoạn chương trình sau vào:

Private Sub mnuWArrange_Click() frmParent.Arrange vbArrangeIcons

End Sub

Private Sub mnuWCascade_Click() frmParent.Arrange vbCascade End Sub

Private Sub mnuWTile_Click() frmParent.Arrange vbTileHorizontal

End Sub

3. Thi hành ứng dụng với các menu được tạo.

Sắp xếp cửa sổ

Dùng phương thức Arrangevới biểu mẫu MDI để sắp xếp các cửa sổ con. Các hằng nội tại sau đây là các kiểu sắp xếp củă sổ do VB cung cấp:

Giá trị Hằng Mô tả
0 vbCascade Xếp các cửa sổ con theo kiểu thác nước trải từ góctrái trên qua góc bên phải dưới.
1 vbTileHorizontal Dàn đều các cửa sổ con sao cho chúng chia mànhình thành những dải ngang.
2 vbTileVertical Dàn đều các cửa sổ con sao cho chúng chia mànhình thành những dải dọc.
3 vbArrangeIcons Các cửa sổ con được thu nhỏ thành những biểutượng và được xếp thẳng hàng.