ITbaby
09-03-2004, 23:51
Bạn có bao giờ thấy những chương trình trong đó có dùng biểu mẫu không giống biểu mẫu chuẩn của Windows? Có trường hợp thú vị như thế này: biểu mẫu cho thấy mờ mờ phần bị che khuất (giống như khi ta nhìn qua tấm kính đục sẽ thấy không rõ lắm phần bên dưới). Để tạo được biểu mẫu có dạng bất kỳ, ta có thể dùng nhiều kỹ thuật khác nhau. Cách đơn giản nhất là dùng hàm SetWindowRgn. Cách này tương thích với các phiên bản Windows nhưng có nhược điểm là rất khó tạo được các biểu mẫu có hình phức tạp (một con rồng chẳng hạn).
Tôi xin giới thiệu với bạn một hàm API mới được cung cấp trên Windows 2000 trở lên: hàm SetLayeredWindowAttributes. Hàm API này giúp ta nhanh chóng tạo được biểu mẫu có hình dạng bất kỳ hoặc nửa trong suốt.
Muốn dùng hàm vừa nêu, trước hết bạn cần khai báo một số API trong đơn thể (module) của dự án (project) như trình bày ở đoạn mã 1 và đoạn mã 2. Bạn có thể nhanh chóng tạo ra đoạn mã 1 bằng cách dùng API Viewer. Với đoạn mã 2 (khai báo hàm SetLayeredWindowAttributes và các hằng số cần thiết), bạn chịu khó tự ghi vào vì đấy là hàm API mới.
Đoạn mã 1
Public Const GWL_EXSTYLE = (-20)
Public Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Đoạn mã 2
Public Declare Function SetLayeredWindowAttributes Lib "user32" _
(ByVal hwnd As Long, ByVal crKey As Long, _
ByVal bAlpha As Integer, ByVal dwFlags As Long) As Long
Public Const WS_EX_LAYERED = &H80000
Public Const LWA_COLORKEY = &H1
Public Const LWA_ALPHA = &H2
Hàm SetLayeredWindowAttributes có hai tham số quan trọng:
1. Tham số crKey: Trị màu trong suốt. Những điểm có trị màu là crKey biến mất khi biểu mẫu hiển thị. Khi dùng tham số này, cờ dwFlags phải là LWA_COLORKEY. Ta dùng tham số crKey để tạo biểu mẫu có dạng bất kỳ.
2. Tham số bAlpha: Trị màu từ 0 đến 255 thể hiện độ trong suốt của biểu mẫu. Khi dùng tham số này, cờ dwFlags phải là LWA_ALPHA. Khi bAlpha là 0, biểu mẫu hoàn toàn trong suốt (biến mất). Với bAlpha là 255, biểu mẫu hoàn toàn "đục" (bình thường). Ta dùng tham số bAlpha để tạo biểu mẫu nửa trong suốt.
Bạn có thể kết hợp 2 trị của dwFlags nêu trên để tạo biểu mẫu vừa có hình dạng bất kỳ vừa nửa trong suốt.
Tiếp theo, bạn tạo một hàm SetWindow như đoạn mã 3 nhằm chuẩn bị các thiết lập ban đầu và gọi hàm SetLayeredWindowAttributes để thực hiện mục đích của ta.
Đoạn mã 3
Public Function SetWindow(hwnd As Long, crKey As Long, _
bAlpha As Integer, dwFlags As Long) As Long
Dim ExStyle As Long
Dim i As Integer
Dim result As Long
‘Thay đổi ex_style của biểu mẫu
ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
ExStyle = ExStyle Or WS_EX_LAYERED
SetWindowLong hwnd, GWL_EXSTYLE, ExStyle
Result = SetLayeredWindowAttributes(hwnd,crKey,bAlpha,dwFla gs)
SetWindow = result
End Function
Trong thủ tục Form_Load của biểu mẫu, ta gọi hàm setWindow. Nếu tạo biểu mẫu nửa trong suốt, bạn dùng câu lệnh đại khái như sau (giả sử độ trong suốt là 160):
SetWindow Me.hwnd, _
0, 160, LWA_ALPHA
http://echip.com.vn/echiproot/images/so57/form.jpg
Muốn tạo biểu mẫu có hình dạng bất kỳ, bạn cần đặt thuộc tính BackColor của biểu mẫu là màu trong hình mà bạn muốn nó trở nên trong suốt. Hình 2 cho bạn thấy biểu mẫu với hình con rồng có màu nền là màu hồng H00FF00FF. Để màu nền ấy trở nên trong suốt, bạn đặt BackColor = &H00FF00FF và gọi hàm setWindow trong thủ tục Form_Load như sau:
SetWindow Me.hwnd, _
Me.BackColor, 0, _
LWA_COLORKEY
Hình 2: Khi nền màu hồng của hình trở nên trong suốt,biểu mẫu của ta có dạng của con rồng
http://echip.com.vn/echiproot/images/so57/rong.jpg
Bạn chú ý, khi tạo biểu mẫu có dạng bất kỳ ta phải chọn thuộc tính BorderStyle của biểu mẫu là 0 để làm mất thanh tiêu đề. Điều này làm cho biểu mẫu không di chuyển được. Muốn khắc phục chuyện phiền toái này, bạn dùng hàm API SendMessage và ReleaseCapture (đoạn mã 4) để người dùng có thể di chuyển được biểu mẫu khi "nắm" vào bất kỳ chỗ nào trên biểu mẫu. Bạn có thể tham khảo toàn bộ mã nguồn ở địa chỉ www.echip.com.vn.
Đoạn mã 4
Private Sub Form_MouseDown(Button As Integer, Shift As Integer,_
X As Single, Y As Single)
ReleaseCapture
SendMessage Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0
End Sub
Bạn nghĩ sao nếu ta cho biểu mẫu mờ dần rồi biến mất khi người dùng đóng biểu mẫu? Ta có thể thực hiện hiệu ứng thú vị này bằng một vòng lặp tăng dần độ trong suốt của biểu mẫu. Bạn làm thử xem sao nhé. Rất mong bạn đóng góp ý kiến. Chúc bạn thành công.
copyleft trên echip của tác giả [Triệu Trí Tâm] đem zìa cho pà con đọa chơi nà
Tôi xin giới thiệu với bạn một hàm API mới được cung cấp trên Windows 2000 trở lên: hàm SetLayeredWindowAttributes. Hàm API này giúp ta nhanh chóng tạo được biểu mẫu có hình dạng bất kỳ hoặc nửa trong suốt.
Muốn dùng hàm vừa nêu, trước hết bạn cần khai báo một số API trong đơn thể (module) của dự án (project) như trình bày ở đoạn mã 1 và đoạn mã 2. Bạn có thể nhanh chóng tạo ra đoạn mã 1 bằng cách dùng API Viewer. Với đoạn mã 2 (khai báo hàm SetLayeredWindowAttributes và các hằng số cần thiết), bạn chịu khó tự ghi vào vì đấy là hàm API mới.
Đoạn mã 1
Public Const GWL_EXSTYLE = (-20)
Public Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Đoạn mã 2
Public Declare Function SetLayeredWindowAttributes Lib "user32" _
(ByVal hwnd As Long, ByVal crKey As Long, _
ByVal bAlpha As Integer, ByVal dwFlags As Long) As Long
Public Const WS_EX_LAYERED = &H80000
Public Const LWA_COLORKEY = &H1
Public Const LWA_ALPHA = &H2
Hàm SetLayeredWindowAttributes có hai tham số quan trọng:
1. Tham số crKey: Trị màu trong suốt. Những điểm có trị màu là crKey biến mất khi biểu mẫu hiển thị. Khi dùng tham số này, cờ dwFlags phải là LWA_COLORKEY. Ta dùng tham số crKey để tạo biểu mẫu có dạng bất kỳ.
2. Tham số bAlpha: Trị màu từ 0 đến 255 thể hiện độ trong suốt của biểu mẫu. Khi dùng tham số này, cờ dwFlags phải là LWA_ALPHA. Khi bAlpha là 0, biểu mẫu hoàn toàn trong suốt (biến mất). Với bAlpha là 255, biểu mẫu hoàn toàn "đục" (bình thường). Ta dùng tham số bAlpha để tạo biểu mẫu nửa trong suốt.
Bạn có thể kết hợp 2 trị của dwFlags nêu trên để tạo biểu mẫu vừa có hình dạng bất kỳ vừa nửa trong suốt.
Tiếp theo, bạn tạo một hàm SetWindow như đoạn mã 3 nhằm chuẩn bị các thiết lập ban đầu và gọi hàm SetLayeredWindowAttributes để thực hiện mục đích của ta.
Đoạn mã 3
Public Function SetWindow(hwnd As Long, crKey As Long, _
bAlpha As Integer, dwFlags As Long) As Long
Dim ExStyle As Long
Dim i As Integer
Dim result As Long
‘Thay đổi ex_style của biểu mẫu
ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
ExStyle = ExStyle Or WS_EX_LAYERED
SetWindowLong hwnd, GWL_EXSTYLE, ExStyle
Result = SetLayeredWindowAttributes(hwnd,crKey,bAlpha,dwFla gs)
SetWindow = result
End Function
Trong thủ tục Form_Load của biểu mẫu, ta gọi hàm setWindow. Nếu tạo biểu mẫu nửa trong suốt, bạn dùng câu lệnh đại khái như sau (giả sử độ trong suốt là 160):
SetWindow Me.hwnd, _
0, 160, LWA_ALPHA
http://echip.com.vn/echiproot/images/so57/form.jpg
Muốn tạo biểu mẫu có hình dạng bất kỳ, bạn cần đặt thuộc tính BackColor của biểu mẫu là màu trong hình mà bạn muốn nó trở nên trong suốt. Hình 2 cho bạn thấy biểu mẫu với hình con rồng có màu nền là màu hồng H00FF00FF. Để màu nền ấy trở nên trong suốt, bạn đặt BackColor = &H00FF00FF và gọi hàm setWindow trong thủ tục Form_Load như sau:
SetWindow Me.hwnd, _
Me.BackColor, 0, _
LWA_COLORKEY
Hình 2: Khi nền màu hồng của hình trở nên trong suốt,biểu mẫu của ta có dạng của con rồng
http://echip.com.vn/echiproot/images/so57/rong.jpg
Bạn chú ý, khi tạo biểu mẫu có dạng bất kỳ ta phải chọn thuộc tính BorderStyle của biểu mẫu là 0 để làm mất thanh tiêu đề. Điều này làm cho biểu mẫu không di chuyển được. Muốn khắc phục chuyện phiền toái này, bạn dùng hàm API SendMessage và ReleaseCapture (đoạn mã 4) để người dùng có thể di chuyển được biểu mẫu khi "nắm" vào bất kỳ chỗ nào trên biểu mẫu. Bạn có thể tham khảo toàn bộ mã nguồn ở địa chỉ www.echip.com.vn.
Đoạn mã 4
Private Sub Form_MouseDown(Button As Integer, Shift As Integer,_
X As Single, Y As Single)
ReleaseCapture
SendMessage Me.hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0
End Sub
Bạn nghĩ sao nếu ta cho biểu mẫu mờ dần rồi biến mất khi người dùng đóng biểu mẫu? Ta có thể thực hiện hiệu ứng thú vị này bằng một vòng lặp tăng dần độ trong suốt của biểu mẫu. Bạn làm thử xem sao nhé. Rất mong bạn đóng góp ý kiến. Chúc bạn thành công.
copyleft trên echip của tác giả [Triệu Trí Tâm] đem zìa cho pà con đọa chơi nà