HeSanbi
Nam Nhân✨Hiếu Lễ Nghĩa Trí Tín✨
- Tham gia
- 24/2/13
- Bài viết
- 2,591
- Được thích
- 3,991
- Giới tính
- Nam
Hôm nay tôi hướng dẫn các bạn một phương pháp lập trình nâng cao mới, nhầm tạo một thủ tục với hai chế độ gọi (bài viết này chỉ nói về chủ đề này) là gọi một lần (Single Call) và gọi hai lần liên tục (Double Call).
Như thế nào là chế độ gọi?
Như thế nào là Single Call và Double Call?
Với một thủ tục có hai chế độ gọi như vậy sẽ giúp các bạn có thể thêm chức năng thứ hai cho thủ tục bạn tạo. Rất tiện dụng cho nhiều trường hợp.
Ưu điểm của phương pháp này như:
Để tạo được chế độ Double Call ta cần sử dụng Hàm WinApi, để tạo một Callback Function, sẽ gọi lại thủ tục với một khoảng thời gian đủ để lần nhấn thứ hai thành công. Thời gian mỗi lần cho mỗi hai lần nhấn giao động trong khoảng 75 đến 170 mili giây.
Mã dưới đây đã được tạo để thực hiện mục tiêu như trên, với hàm ProcCaller có nhiệm vụ điều khiển lần gọi, để bắt sự kiện gọi hai lần liên tục.
Tạo một thủ tục và gọi hàm ProcCaller trong thủ tục bạn tạo với đối số đầu là tên của thủ tục đã tạo, đối số thứ hai là khoảng thời gian đủ để bắt lần gọi thứ hai.
Hàm ProcCaller trả lại các giá trị -1,0, 1, và 2 đại diện cho hành động: Đã hủy hành động, không làm gì cả, đã gọi một lần và đã gọi hai lần liên tục.
Ví dụ: bạn cần tạo thủ tục HelloWorld1
Hoặc thêm thời gian đủ để bắt sự kiện gọi lần hai, đơn vị 1/1000 của giây:
Hoặc thủ tục cần nhận đối số:
Hoặc thủ tục cần nhận đối số là đối tượng - Object, thì thêm khai báo Static:
Để bỏ qua ProcCaller bắt sự kiện tạm thời, để gọi một sự kiện hoặc không, ta cần thêm đối số OnlyEvent:
ProcCaller("HelloWorld4", OnlyEvent:=1)
Dưới đây là mã viết một lần duy nhất cho mọi thủ tục có hai chế độ Single và Double, với hàm chính là ProcCaller
(Hãy sao chép mã vào một Module mới)
Chúc các bạn thành công!
Phương pháp lập trình để tạo Effect cho nút nhấn trong trang tính được viết trong bài viết dưới đây, các bạn có thể tham khảo thêm!
Như thế nào là chế độ gọi?
Chẳng hạn như gọi hàm hoặc thủ tục từ một control, một Shape, nút nhấn trên Ribbon, nút nhấn trên Menu Context (Menu khi nhấn chuột phải), phím tắt người dùng tạo,... , có hành động nhấn từ chuột hoặc Bàn Phím. Thường thì chúng chỉ có một hành động chuột là Click, hoặc phím nhấn 1 lần là thực thi. Thì nay có phương pháp Double Call, thì ta có thể thêm sự kiện Double Click.
Như thế nào là Single Call và Double Call?
Là khi gọi thủ tục thì nếu sự kiện Double Call được bắt thì Single Call sẽ bị hủy. Gọi Single Call Trong khoảng thời gian 75 đến 170 mili giây, nếu không bắt được sự kiện Double Call, thì gọi Single Call thành công.
Với một thủ tục có hai chế độ gọi như vậy sẽ giúp các bạn có thể thêm chức năng thứ hai cho thủ tục bạn tạo. Rất tiện dụng cho nhiều trường hợp.
Ưu điểm của phương pháp này như:
- Nếu gọi thủ tục bởi nút nhấn, vừa nhấn vừa dịch chuyển chuột, thì quá trình gọi thủ tục sẽ bị hủy bỏ.
- Áp dụng vào phím tắt, để di chuyển trang tính: Bạn chỉ cần tạo một phím tắt gán thủ tục, nhấn phím tắt một lần sẽ về trang trước đó, nhấn hai lần để quay trở lại.
- Tạo nút nhấn có chế độ Double Click cho Nút nhấn trong trang tính.
Để tạo được chế độ Double Call ta cần sử dụng Hàm WinApi, để tạo một Callback Function, sẽ gọi lại thủ tục với một khoảng thời gian đủ để lần nhấn thứ hai thành công. Thời gian mỗi lần cho mỗi hai lần nhấn giao động trong khoảng 75 đến 170 mili giây.
Mã dưới đây đã được tạo để thực hiện mục tiêu như trên, với hàm ProcCaller có nhiệm vụ điều khiển lần gọi, để bắt sự kiện gọi hai lần liên tục.
Tạo một thủ tục và gọi hàm ProcCaller trong thủ tục bạn tạo với đối số đầu là tên của thủ tục đã tạo, đối số thứ hai là khoảng thời gian đủ để bắt lần gọi thứ hai.
Hàm ProcCaller trả lại các giá trị -1,0, 1, và 2 đại diện cho hành động: Đã hủy hành động, không làm gì cả, đã gọi một lần và đã gọi hai lần liên tục.
Ví dụ: bạn cần tạo thủ tục HelloWorld1
JavaScript:
Private Sub HelloWorld1()
Select Case ProcCaller("HelloWorld1")
Case 1: Debug.Print "ProcCaller: Single Call"
Case 2: Debug.Print "ProcCaller: Double Call"
End Select
End Sub
Hoặc thêm thời gian đủ để bắt sự kiện gọi lần hai, đơn vị 1/1000 của giây:
JavaScript:
Private Sub HelloWorld2()
Select Case ProcCaller("HelloWorld2",0.15)
Case 1: Debug.Print "ProcCaller: Single Call"
Case 2: Debug.Print "ProcCaller: Double Call"
End Select
End Sub
Hoặc thủ tục cần nhận đối số:
JavaScript:
Private Sub HelloWorld3(Optional Byval Direction%, Optional Byval Action%, Optional Byval Text$)
Select Case ProcCaller("HelloWorld3 " & cstr(Direction) & "," & cstr(Action) & ",""" & Replace(Replace(Text,"'","''"),"""","""""") & """"
Case 1: Debug.Print "ProcCaller: Single Call"
Case 2: Debug.Print "ProcCaller: Double Call"
End Select
End Sub
Hoặc thủ tục cần nhận đối số là đối tượng - Object, thì thêm khai báo Static:
JavaScript:
Private Sub HelloWorld4(Optional Byval control as Object)
Static stControl as Object
Select Case ProcCaller("HelloWorld4")
Case 0: Set stControl = control
Case 1: Debug.Print "ProcCaller: Single Call" 'Gọi lại stControl
Case 2: Debug.Print "ProcCaller: Double Call" 'Gọi lại stControl
End Select
End Sub
Để bỏ qua ProcCaller bắt sự kiện tạm thời, để gọi một sự kiện hoặc không, ta cần thêm đối số OnlyEvent:
ProcCaller("HelloWorld4", OnlyEvent:=1)
Dưới đây là mã viết một lần duy nhất cho mọi thủ tục có hai chế độ Single và Double, với hàm chính là ProcCaller
(Hãy sao chép mã vào một Module mới)
JavaScript:
Option Explicit
Option Private Module
Private Type POINTAPI
x As Long
y As Long
End Type
#If VBA7 And Win64 Then
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongLong, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As LongPtr
#ElseIf VBA7 Then
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As Long) As Long
#Else
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
#End If
#If VBA7 Then
Private Declare PtrSafe Function GetCursorPos Lib "user32" (p As POINTAPI) As Long
#Else
Private Declare Function GetCursorPos Lib "user32" (p As POINTAPI) As Long
#End If
Private Type v64
#If VBA7 And Win64 Then
'z As LongLong
'#ElseIf VBA7 Then
z As LongPtr
#Else
z As Long
#End If
End Type
Private Enum IdEventProcTimer
IdEventProcedureCall = 1001
End Enum
Private Type ProcCallerDirective
hwnd As v64
IdEvent As v64
click As Integer
OnAction As String
SpaceTime As Single
Timer As Single
Cursor As POINTAPI
End Type
Private PCD As ProcCallerDirective
Function ProcCaller( _
Optional ByVal OnAction As String, _
Optional ByVal SpaceTime As Double = 0.155, _
Optional ByVal OnlyEvent%) As Integer
On Error Resume Next
With PCD
If OnlyEvent > 0 Then .click = 0: .Timer = 0: ProcCaller = OnlyEvent: Exit Function
If .click = 1 Then .click = 0: .Timer = 0: ProcCaller = 1: Exit Function
If .Timer < Timer And .click = 0 Then
ProcCaller = 0
GetCursorPos .Cursor
.OnAction = OnAction
.click = -1
.Timer = Timer + SpaceTime
.hwnd.z = Application.hwnd
.IdEvent.z = IdEventProcedureCall
Call SetTimer(.hwnd.z, IdEventProcedureCall, SpaceTime * 1000, AddressOf TimerProc_ButtonClick)
Else
' DblClick
Dim p As POINTAPI: GetCursorPos p
If p.x = .Cursor.x And p.y = .Cursor.y Then ProcCaller = 2 Else [SIZE=5]ProcCaller = -2[/SIZE]
KillTimer .hwnd.z, .IdEvent.z: .click = 0
End If
End With
Err.Clear
End Function
#If VBA7 And Win64 Then
Private Sub TimerProc_ButtonClick(ByVal hwnd As LongPtr, ByVal wMsg^, ByVal IdEvent As LongPtr, ByVal dwTime^)
#ElseIf VBA7 Then
Private Sub TimerProc_ButtonClick(ByVal hwnd As LongPtr, ByVal wMsg&, ByVal IdEvent As LongPtr, ByVal dwTime&)
#Else
Private Sub TimerProc_ButtonClick(ByVal hwnd&, ByVal wMsg&, ByVal IdEvent&, ByVal dwTime&)
#End If
On Error Resume Next
KillTimer hwnd, IdEvent
Select Case IdEvent
Case IdEventProcedureCall:
With PCD
If .OnAction <> Empty And .click = -1 Then
Dim p As POINTAPI: GetCursorPos p
If p.x = .Cursor.x And p.y = .Cursor.y Then
.click = 1: Application.OnTime Now, onProject(.OnAction)
End If
End If
End With
End Select
End Sub
Private Function onProject(ByVal Procedure$, Optional ByVal project$ = vbNullChar) As String
' OnTime: 'Procedure 1'
' OnAction, AssignMacro: Procedure (1)
If project = vbNullChar Or project = Empty Then project = ThisWorkbook.Name
If Procedure Like "'*'!*" Then
onProject = Procedure
Else
If Procedure Like "*)" Or Not Procedure Like "* *" Then
onProject = "'" & Replace(project, "'", "''") & "'!" & Procedure
Else
onProject = "'" & Replace(project, "'", "''") & "'!'" & Procedure & "'"
End If
End If
End Function
Chúc các bạn thành công!
Phương pháp lập trình để tạo Effect cho nút nhấn trong trang tính được viết trong bài viết dưới đây, các bạn có thể tham khảo thêm!
Các Hàm quản lý ảnh: vị trí, kích thước, cắt, xóa, sắp xếp
Hôm nay tôi chia sẻ với bạn các Hàm bổ trợ quản lý ảnh cực kỳ thú vị, chức năng bao gồm: chỉnh vị trí, kích thước, cắt, xóa và sắp xếp ảnh một cách đơn giản, thuận tiện và nhanh gọn, giúp các bạn bớt khó khăn trong việc tinh chỉnh ảnh khi trong trang tính của bạn có quá nhiều đối tượng hình ảnh...
www.giaiphapexcel.com
Lần chỉnh sửa cuối: