Bước đầu làm quen với API

  • Thread starter vothanhthu
  • Ngày gửi
V

vothanhthu

Guest
Ý tưởng về một bài API đến với Thứ xuất phát từ bài hỏi đáp của bạn Sieutocviet3, link Trong bài viết, các bạn có hỏi Thứ về hàm DefWindowProcW, Thứ không trả lời bạn cụ thể là bởi vì đây là một hàm API, mà đã là hàm API thì sẽ có rất nhiều điều chúng ta cần phải nắm trước khi trả lời câu hỏi hàm API này dùng làm gì. Nhằm giúp cho tất cả các bạn tìm hiểu về VBA hiểu được hệ thống hàm API rốt cuộc là gì, tại sao nó lại hay và can thiệp được vào đến tận Window. Đó cũng là mục đích mà Thứ lập Topic này.

Lưu ý: Trong bài viết sẽ là tập hợp kiến thức của Thứ về API, do Thứ không phải là dân IT nên có thể sẽ có một số thuật ngữ IT Thứ diễn giải theo cách hiểu đơn giản nhất của một người bình thường như Thứ hiểu được, nếu có gì sai sót mong cách bạn chuyên sâu IT đọc góp ý giúp Thứ hoàn thiện hơn.

Đây sẽ là một chủ đề rất dài, nên Thứ sẽ phân nhỏ ra nhiều nội dung để mọi người có thể nắm kiến thức một cách chắn chắn nhất.

1. API là gì ?
Trước đó, Admin Tuhocvba đã có trình bày khái quát về Window API các bạn có thể tham khảo

Ở đây, Thứ muốn sơ lược lại một vài điều

Khái niệm: API là viết tắt của Application Programming Interface (giao diện lập trình ứng dụng). Nó là 1 giao tiếp phần mềm được dùng bởi các ứng dụng khác nhau.

Mọi hoạt động của Excel nói riêng và các ứng dụng khác nói chung điều phải hoạt động dựa vào cấu trúc của Hệ điều hành mà nó đang sử dụng. Thứ ví dụ, các bạn có 1 file excel và điều có sử dụng chung một câu lệnh

Mã:
Msgbox "Hello TuhocVBA", vbInformation, "Thong bao"
Nhưng các bạn thử chạy nó trên nền Win 10 và Win 8. sẽ có 2 giao diện hoàn toàn khác nhau.
Bạn cần đăng nhập để thấy đính kèm

Rõ ràng, bản thân Excel không tự tạo ra các giao diện Msgbox này mà sử dụng các tài nguyên có sẵn trong Window để tạo. Vì vậy, nếu chúng ta sử dụng một hàm, chương trình tương tác vào quá trình Gởi-Nhận giữa Excel và Window này, chúng ta hoàn toàn có thể tạo ra những thay đổi về giao diện Msgbox, và tương tự là với UserForm. Các hàm API sẽ giúp chúng ta tương tác vào quá trình Gởi-Nhận đó.

Về ứng dụng thì API là một cơ số đồ sộ các hàm trong các thư viện DLL trên nền Window. Để tìm hiểu về các thư viện thông dụng của các hàm API trong Window, các bạn có thể tham khảo bài viết của Admin vbano1 Và tài liệu chính chủ của Microsoft

2. Khai báo một hàm API trong VBA
Để khai báo một hàm API, Admin Tuhocvba cũng đã có trình bày, và Thứ sẽ sơ lược lại. Đây là cấu trúc khai báo một hàm API thông dụng trong VBA

Private Declare [PtrSafe] Function Tên_Hàm Lib "Tên_DLL" [Alias "Tên_Hàm_Thực_Sự"] (Danh_Sách_Hàm) As Kiểu_Trả_Về

[PtrSafe]:
Tùy bạn đang sử dụng Office nào, thêm vào nếu bạn đang sử dụng Office 64bit.
Tên_Hàm: Tên của hàm API, là tên mà bạn sẽ gọi mỗi khi muốn sử dụng, thường sẽ là tên gốc của hàm API bỏ chữ A hoặc W phía sau nếu bạn có sử dụng thêm cấu trúc Alias

*Thế chữ A và W cuối tên hàm gốc là gì?:
Trong API, hầu hết các hàm có nhận tham số kiểu String điều có 2 phiên bản: có xử lý Unicode và không xử lý Unicode. Nếu cả 2 phiên bản cùng nằm trong 1 thư viện DLL, thì để phân biệt, Microsoft thêm chữ A cho phiên bản không xử lý Unicode và W cho phiên bản có xử lý Unicode. Ví dụ cơ bản là DefWindowProcA DefWindowProcW.

Tên_DLL: Tên của thư viện chứa tên hàm API bạn muốn gọi.
Tên_Hàm_Thực_Sự: phần nằm trong ngoặc [] chứng minh có thể có hoặc không. Nếu không có, phần Tên_Hàm bắt buộc bạn phải đặt giống tên hàm API trong Tên_DLL
Danh_Sách_Hàm:
Danh sách các đối số mà hàm API yêu cầu, mỗi hàm API sẽ có các đối số riêng. Nói cho dễ hiểu, giống như hàm Vlookup là phải bắt buộc cấu trúc Vlookup(Giá trị dò, vùng dò, cột dò) vậy, nếu không là lỗi.
Kiểu_Trả_Về: là kiểu giá trị mà hàm API đó trả về

Thứ xin phép lấy lại ví dụ của Admin Tuhocvba về hàm API MessageBeep để tạo tiếng âm thanh thông báo trong Window trên VBA.
Mã:
#If Win64 then 'Nếu là Office 64bit thì
    Private Declare PtrSafe Function MessageBeep Lib "user32" (ByVal sType As Integer) As Integer
#Else 'Ngược lại (ý hiểu là Office 32bit)
    Private Declare Function MessageBeep Lib "user32" (ByVal sType As Integer) As Integer
#End if

Sub Sound_Test()
    MessageBeep (20) 'Gọi hàm MessageBeep với định dạng âm thanh số 20
End Sub
Nếu file của chúng ta là chia sẽ cho nhiều người sử dụng, bạn đâu thể biết được người dùng đang ở Office mấy?. Do đó, ta cần thêm điều kiện #If - #Else - #End if, nên nhớ là có dấu # phía trước nhé. Bình thường, hàm các bạn dùng được đặt cả trong Sub/Function nên không có gì xảy ra. Còn ở đây, bạn đang đặt điều kiện bên ngoài Sub/Function nên cần dấu # phía trước nhé.

Ở đây, con số 20 chắc chắn các bạn sẽ không hiểu nó là gì. Vậy nếu Thứ sửa Code lại như thế này thì sao.
Mã:
Const MB_ICONQUESTION As Long = 20
Sub Sound_Test()
    MessageBeep (MB_ICONQUESTION)
End Sub
Khi viết như vậy, các bạn sẽ hiểu con số 20 này đại diện cho một hàm mang tên MB_ICONQUESTION (Âm thanh khi thông báo đang ở dạng câu hỏi). Giống như khi chúng ta đặt giá trị cho một biến số, Microsoft cũng vậy. Mỗi một hàm, họ đặt một danh sách nhiều biến số, mỗi biến số có một giá trị. Khi muốn sử dụng, ta cần biết giá trị của biến đó là gì thì mới có thể sử dụng được. Như trong ví dụ, nếu bạn muốn sử dụng thông báo dạng MB_ICONQUESTION thì bạn phải sử dụng số 20.

Thế câu hỏi, làm sao để Thứ biết MB_ICONQUESTION là số 20?. Thứ cứ google tên hàm MessageBeep, rồi tra thôi, Hehe !
ValueMeaning
0xFFFFFFFFA simple beep. If the sound card is not available, the sound is generated using the speaker.
MB_ICONASTERISK 0x00000040LSee MB_ICONINFORMATION.
MB_ICONEXCLAMATION 0x00000030LSee MB_ICONWARNING.
MB_ICONERROR 0x00000010LThe sound specified as the Windows Critical Stop sound.
MB_ICONHAND 0x00000010LSee MB_ICONERROR.
MB_ICONINFORMATION 0x00000040LThe sound specified as the Windows Asterisk sound.
MB_ICONQUESTION 0x00000020LThe sound specified as the Windows Question sound.
MB_ICONSTOP 0x00000010LSee MB_ICONERROR.
MB_ICONWARNING 0x00000030LThe sound specified as the Windows Exclamation sound.
MB_OK 0x00000000LThe sound specified as the Windows Default Beep sound.

Mấy con số 0x000000 gì đó, tạm thời chúng ta đừng quan tâm tới. Chưa liên quan đến vấn đề của mình, kệ nó, quan tâm mấy con số cuối thôi Hehe !
Tới đây, chắc các bạn đã hình dung sơ sơ về API rồi nhỉ. Từ từ, Thứ sẽ đưa những thứ phức tạp thành đơn giản nhất cho các bạn ai cũng có thể hiểu được.
(Còn nữa...)
 
Sửa lần cuối bởi điều hành viên:
V

vothanhthu

Guest
3. Handle là gì, tại sao lại quan trọng ?
Handle
: Ta tạm gọi là Chứng minh nhân dân cho dễ hiểu, mà CMND thì mỗi người chỉ có 1 số duy nhất, không ông nào trùng với bà nào. Handle cũng vậy, Biết số CMND một người sẽ biết được người đó là ai, biết Handle của một đối tượng ta sẽ biết được đối tượng ta muốn thao tác là gì.

Handle là một biến kiểu Long trả về giá trị duy nhất cho mỗi đối tượng mà ta chọn. Đối tượng đó có thể là một cửa sổ trong Window hay một Control nào đó trong Excel. Handle giúp cho các hàm API biết được là "Tôi cần thao tác với ai"

* Làm sao để biết được Handle của một đối tượng tại vị trí trỏ chuột

Lưu ý: Mọi Code Thứ ví dụ được viết trên nền Office 32bit, nếu bạn đang sử dụng Office 64bit, hãy đọc bài viết tại #1, thêm cấu trúc PtrSafe vào cho phù hợp nhé !

Để biết được địa chỉ Handle của một đối tượng chỉ định tại vị trí trỏ chuột, ta cần dùng hai hàm như sau:
WindowFromPoint(Tọa_độ X, Tọa độ_Y) : Lấy địa chỉ Handle của một đối tượng dựa vào tọa độ X và Y
GetCursorPos(Biến_lưu_tọa_độ): Lấy tọa độ tại vị trí con trỏ chuột.

Thứ sẽ tạo một Userform và đặt đoạn Code này vào. Muốn biết Handle của đối tượng nào, kéo chuột từ Userform đến đối tượng đó, ta sẽ có được địa chỉ Handle của đối tượng đó ngay.
Mã:
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

    Private Type POINTAPI
        X As Long
        Y As Long
    End Type

Private Sub UserForm_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim Pt As POINTAPI, mWnd As Long

        GetCursorPos Pt 'Lấy giá trị X và Y tại vị trí con trỏ chuột
        mWnd = WindowFromPoint(Pt.X, Pt.Y) 'Lưu biến mWnd = với Handle tại đối tượng có tọa độ X và Y bằng hàm WindowFromPoint
        MsgBox "handle= " & mWnd 'Hiện Msgbox giá trị Handle của đối tượng đã chọn
End Sub
'Nguồn: Caulacbovb.com
Thử kết quả xem nào

Bạn cần đăng nhập để thấy đính kèm


Lưu ý: Do Thứ đang sử dụng chương trình quay ảnh động, nên địa chỉ Handle trong hình sẽ không chính xác. Cách làm là hoàn toàn đúng, nên các bạn làm mà ra địa chỉ Handle khác thì đừng thấy lạ nhé, Hehe !

(Còn nữa...)
 
Sửa lần cuối bởi điều hành viên:
V

vothanhthu

Guest
4. Class Name là gì
Class (Lớp) + Name (Tên): Class Name là tên của một lớp đại diện cho một đối tượng hay một cửa sổ nào đó.

Khó hiểu quá nhỉ, giờ Thứ giải thích đơn giản thế này nhé. Nếu Handle là số CMND của bạn, thì Class Name là tên Tỉnh mà bạn đang sinh sống. Để tìm bạn dễ dàng hơn, thay vì phải truy xuất toàn CMND của tất cả các Tỉnh trên nước Việt Nam, giờ chỉ cần truy xuất số CMND của bạn trong Tỉnh bạn sinh sống thôi. Class Name cũng vậy, nó chính là nơi chứa cái địa chỉ Handle của đối tượng bạn cần truy xuất. Thông tin thêm, cửa sổ Excel bạn đang mở có tên Classs Name là "XLMAIN" đấy nhé.

Vậy lại câu hỏi, làm sao để Thứ biết được đối tượng có địa chỉ Handle đó chỉ tên Class Name là gì ??

4.1. Hàm lấy tên Class Name: GetClassName
Cấu trúc của hàm GetClassName như sau
Mã:
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Trong đó
hwnd:
Tên địa chỉ Handle mà bạn cần lấy tên Class Name
lpClassName: Tên Đối số trả về dạng String để lưu tên Class Name sau khi tìm thấy kết quả (Tại sao tô đỏ thì đọc hết sẽ biết nhé)
nMaxCount: Độ dài tối đa của Class Name bạn cần lấy tên

Hoạt động: Hàm GetClassName sẽ lấy được tên Class Name dựa vào địa chỉ hwnd mà bạn cung cấp, sau đó lưu vào biến lpClassName với độ dài tối đa là nMaxCount

Nếu các bạn có để ý, Thứ đã khai báo tên hàm từ GetClassNameA trong User32 thành GetClassName . Chữ A là gì thì tại #1 mình có giải thích đó nha. Mục đích là giúp ta dễ nhìn và sử dụng hơn, các bạn có thể khai báo không đổi tên vẫn được, không sao cả, Hehe !

4.2. Hàm lấy địa chỉ Handle: FindWindow

Cấu trúc khai báo của hàm FindWindow như sau:

Mã:
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Trong đó
lpClassName:
Tên Class Name chứa địa chỉ Handle cần tìm kiếm
lpWindowName: Tên cửa sổ chứa địa chỉ Handle cần tìm kiếm

Đây là một hàm tối quan trọng trong việc tìm kiếm địa chỉ Handle khi viết hàm API. Tại sao lại quan trọng ư?, vì hàm chỉ cần biết tên Class Name và tên cửa sổ là đã có thể lấy được địa chỉ Handle của đối tượng đó rồi. Thậm chí còn có thể bỏ 1 trong 2 giá trị tìm kiếm, kết quả trả về sẽ là địa chỉ Handle thỏa điều kiện cuối cùng được tìm thấy.

4.3. Ví dụ minh họa cho hàm GetClassName và FindWindow
Đoạn Code dưới đây sẽ trả về giá trị là địa chỉ Handle và tên Class Name dựa vào Tên cửa sổ đang bật.
Mã:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Private Sub Form_Load()
    Dim WinWnd As Long, Ret As String, RetVal As Long, lpClassName As String

    Ret = InputBox("Enter the exact window title:" + Chr$(13) + Chr$(10) + "Note: must be an exact match") 'Hiện InputBox để nhập tên cửa sổ

    WinWnd = FindWindow(vbNullString, Ret) 'Gán hàm WinWnd = địa chỉ Handle tìm kiếm bằng hàm FindWindow
    If WinWnd = 0 Then MsgBox "Couldn't find the window ...": Exit Sub
    If Ret = "" Then Exit Sub
   
    lpClassName = Space(256)  'Tạo bộ đệm 256 kí tự

    RetVal = GetClassName(WinWnd, lpClassName, 256) 'Lấy tên Class Name

    MsgBox "Handle: " & WinWnd
    MsgBox "Classname: " + lpClassName
    'Nguon: Caulacbovb.com
End Sub
Trong Code có 2 đoạn Thứ cho rằng là quan trọng cần giải thích cho các bạn hiểu
Mã:
 WinWnd = FindWindow(vbNullString, Ret)
Đoạn Code này sẽ tìm kiếm tên cửa sổ (Ret), không rõ tên Class Name là gì (vbNullString), và kết quả được lưu vào biến WinWnd

Mã:
lpClassName = Space(256)  'Tạo bộ đệm 256 kí tự
RetVal = GetClassName(WinWnd, lpClassName, 256)
Thứ cần giải thích kỹ ở đây, tại sao phải là Space(256). lpClassName Thứ có giải thích là Đối số trả về dạng String. Nó khác với dấu = mà chúng ta vẫn hay sử dụng để gán giá trị nhé. Đối với một hàm API, để nhận các Đối số trả về dạng String, ta cần một Đối số khai báo cũng dạng String có độ dài nhất định, còn được gọi là bộ đệm. Nói chung, khi một hàm API có Đối số trả về dạng String, thì ta cần cho nó một bộ đệm bằng hàm Space(Số lượng kí tự), và thường là 256 byte.

Và đây là kết quả sau khi chạy Code
Bạn cần đăng nhập để thấy đính kèm

(Còn nữa...)
 
V

vothanhthu

Guest
* Ứng dụng thực tế
Để giải tỏa kiến thức một chút, chúng ta sẽ cùng nhau phân tích một vài hàm API mà trên tuhocvba.net đã áp dụng cho các trường hợp thực tế. Chúng ta sẽ phân tích hàm API hiển thị Msgbox tiếng việt của Admin Tuhocvba để làm ví dụ nhé, link bài viết . Sau đây là Code của hàm Msgbox Tiếng Việt trong bài viết:
Mã:
#If VBA7 And Win64 Then
    Private Declare PtrSafe Function MessageBoxW Lib "user32" _
              (ByVal hwnd As LongPtr, ByVal lpText As LongPtr, _
               ByVal lpCaption As LongPtr, ByVal wType As Long) As Long
    Private Declare PtrSafe Function GetFocus Lib "user32" () As LongPtr
#Else
    Private Declare Function MessageBoxW Lib "user32" _
              (ByVal hwnd As Long, ByVal lpText As Long, _
               ByVal lpCaption As Long, ByVal wType As Long) As Long
    Private Declare Function GetFocus Lib "user32" () As Long
#End If

  Public Function MsgBoxUnicode(ByVal Prompt As String, _
                                  Optional ByVal Buttons As VbMsgBoxStyle = vbOKOnly, _
                                  Optional ByVal Title As String = "Microsoft Excel") As Long

    MsgBoxUnicode = MessageBoxW(GetFocus(), StrPtr(Prompt), StrPtr(Title), Buttons)
    ' MsgBoxUnicode = MessageBoxW(0, StrPtr(Prompt), StrPtr(Title), Buttons)
  End Function
Đầu tiên, chúng ta sẽ đi vào tìm hiểu các hàm API này trước khi hiểu cách thức chúng hoạt động.

MessageBoxW(Handle_Window, Nội_dung, Tiêu_đề, Loại_thông_báo)
Trong đó:
Handle_Window:
Đây là địa chỉ Handle của cửa sổ Window ta đang muốn tương tác. Nếu bỏ trống, Msgbox tạo ra sẽ không thuộc bất cứ cửa sổ nào.
Nội_dung:
Nội dung của msgbox
Tiêu_đề: Tiêu đề của msgbox
Loại_thông_báo: Loại thông báo bạn muốn (vbOKOnly, vbOKCancek...)

Vì mục đích là ta cần viết tiếng việt có dấu trên msgbox, nên ta sẽ dùng hàm MessageBoxW. Nhìn chung, cấu trúc hàm MessageBoxW sẽ tương đối giống hàm Msgbox mà chúng ta vẫn hay biết, chỉ khác ở trật tự và thêm cái địa chỉ Handle của cửa sổ Window.

Hàm GetFocus(): Hàm này không có thông số gì cả, giá trị trả về là địa chỉ Handle của một cửa sổ Window đang hiện trên màn hình của bạn.

Khi chúng ta sẽ sử dụng hàm Msgbox thông thường, Excel sẽ dùng cách dữ liệu chúng ta gởi đã nạp (Nội dung, tiêu đề...) gởi lệnh đến các hàm API trong Window. Sau đó, Window sẽ trả kết quả về và Excel hiện lên msgbox như chúng ta thường thấy. Bây giờ, chúng ta sẽ can thiệp vào trong quá trình đó, ép buộc Excel làm theo chúng ta luôn, Hehe.

Chúng ta sẽ có một Function thông thường mang tên MsgBoxUnicode. Hàm này sẽ thay thế cho hàm Msgbox thông thường của chúng ta. Cấu trúc hàm này sẽ là tương tự hàm Msgbox
Mã:
  Public Function MsgBoxUnicode(ByVal Prompt As String, _
                                  Optional ByVal Buttons As VbMsgBoxStyle = vbOKOnly, _
                                  Optional ByVal Title As String = "Microsoft Excel") As Long
Trong hàm, có 2 cấu trúc tùy chọn. Nếu loại thông báo và tiêu đề bạn bỏ trống, nó sẽ là vbOKOnly và "Microsoft Excel".

Chúng ta sẽ phân tích sâu đoạn Code này
Mã:
MsgBoxUnicode = MessageBoxW(GetFocus(), StrPtr(Prompt), StrPtr(Title), Buttons)
Khi khởi chạy, hàm MsgBoxUnicode sẽ gọi hàm API MessageBoxW mang theo các giá trị của hàm MsgBoxUnicode.

Ở đây, tại sao lại có hàm StrPtr(Chuỗi_kí_tự_dạng_String). Bạn để ý ban đầu, hàm MessageBoxW chứa các đối số là các kiểu dữ liệu dạng Long, mà hàm MsgBoxUnicode ta nạp vào đang là các dữ liệu dạng String. Hàm StrPtr trả về vị trí của Chuỗi_kí_tự_dạng_String sẽ nằm ở đâu trong bộ nhớ, giá trị dạng Long.
Bạn cần đăng nhập để thấy đính kèm

Nguồn hình ảnh: Cảm ơn bạn maiban2068 đã cung cấp thêm thông tin, giúp chúng ta hiểu rõ hơn về hàm StrPtr.

Vậy là chúng ta đã cùng nhau phân tích ý nghĩa của các hàm API, cách kết hợp với các hàm thông thường, được ứng dụng cho việc viết Tiếng Việt có dấu trên Excel. Hy vọng qua bài viết, các bạn đã nắm hơn về các ứng dụng của hàm API.

(Còn nữa..)
 
Sửa lần cuối bởi điều hành viên:
V

vothanhthu

Guest
5. Cách tìm kiếm cấu trúc, hằng số trong hàm API
Tại bài viết #1, Ta biết được rằng hằng số MB_ICONQUESTION = 20 bằng cách tra Google. Trong thực tế, giá trị của các hằng số và cấu trúc hàm API là cực kì nhiều và khó nhớ.

Ta có cấu trúc của hàm MessageBox
Mã:
Private Declare PtrSafe Function MessageBoxW Lib "user32" _
              (ByVal hwnd As LongPtr, ByVal lpText As LongPtr, _
               ByVal lpCaption As LongPtr, ByVal wType As Long) As Long
Vậy làm sao để ta biết được cấu trúc của hàm MessageBox trong Win 64bit là phải như thế này?. Làm sao để khi sử dụng một hằng số, một hàm API nào đó, ta chỉ cần gõ là ra giá trị, cấu trúc hàm API đó. Để làm được việc đó, người ta sẽ phải sử dụng một phần mềm bên thứ 3 đóng vai trò như một thư viện để tra cứu.

Trên mạng sẽ có rất nhiều phần mềm làm được việc này. Nhưng hôm nay, mình sẽ hướng dẫn các bạn sử dụng phần mềm Windows API Viewer do giao diện đẹp và dễ dàng sử dụng, Các bạn có thể vào liên kết và tải về .

Bạn cần đăng nhập để thấy đính kèm

Khung các điều kiện tìm kiếm:
Platform: Hệ Win mà máy bạn đang sử dụng (x64 là 64bit, x86 là 32bit)
API Type: Loại API mà bạn muốn tìm kiếm. Declarations (Hàm), Constants (Hằng số), Types.
Types of Procedure: Chỉ khả dụng khi API Type bạn chọn là Declarations. Đây là loại hàm mà bạn muốn tìm kiếm (Sub, Function)
Condition(s): Điều kiện mà bạn muốn tìm kiếm.

Khi gõ giá trị tìm kiếm tại Enter the first characters of the API, kết quả sẽ được show ra tại Available APIs, khi chọn vào dòng nào thì sẽ hiện cấu trúc/giá trị của hàm/hằng số đó tại Preview. Nếu muốn lưu lại xem nhiều lần thì chọn Add.

Phần mềm Windows API Viewer sẽ giúp ích cho các bạn rất nhiều trong việc tìm kiếm cấu trúc của các hàm API cũng như giá trị của các hằng số.

(Còn nữa...)
 

tuhocvba

Administrator
Thành viên BQT
@Trọng hòa
Bạn có thể bớt chút thời gian để trình bày lại cho dễ hiểu không ạ?

  • Nếu bạn không biết cách upload ảnh lên diễn đàn, bạn vui lòng tham khảo topic sau: .
  • Bạn lưu ý phải sử dụng thẻ Code khi viết code trên forum. Xin xem mục 4 trong .
  • Bạn nên nói rõ Input là gì? Output muốn ra sao?
  • Bạn nên có file demo. Bạn có thể upload file lên google drive hoặc mediafire.com rồi dẫn link về diễn đàn.

Một bài viết trình bày dễ hiểu là một bài viết sử dụng hình minh họa trực quan. Một bài viết chỉ toàn chữ sẽ khiến người khác không muốn đọc.
 

vqlongbn

Thành viên mới
Em copy code vào mà nó chỉ show msgbox khi click trong userform thôi ad ạ
code trên dùng event mouse_up tức là bạn nhả chuột ra nó mới chạy, bạn hãy ấn click chuột trong userform rồi di đến đối tượng bạn muốn, lúc này bạn nhả chuột ra sẽ có msgbox hiển thị handle của đối tượng
 
Top