Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Các bài viết hướng dẫn, giúp các bạn hiểu và tiếp cận với Visual Basic nhanh hơn
Post Reply
User avatar
NoBi
Quản trị
Quản trị
Posts: 970
Joined: Tue 18/03/2008 1:22 pm
Location: Sài Gòn
Has thanked: 58 times
Been thanked: 68 times
Contact:

Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by NoBi »

Tên bài viết: Hướng dẫn sử dụng hàm API SendMessage & PostMessage
Tác giả: NoBi
Cấp độ bài viết: Nâng cao
Tóm tắt: Hướng dẫn sử dụng hàm API SendMessage & PostMessage
SendMessage

Chúng ta đã biết là hệ điều hành Windows hoạt động dựa trên cơ sở thông điệp (message). Khi HĐH muốn thông tin tới những ứng dụng hay giữa 2 ứng dụng muốn truyền tin với nhau thì đều gửi những thông điệp cho nhau. Ví dụ khi một ứng dụng kết thúc thì HĐH sẽ gửi thông điệp WM_DESTROY tới ứng dụng đó hoặc khi ta thêm 1 item vào Listbox thì ứng dụng/HĐH sẽ gửi thông điệp LB_ADDSTRING tới Listbox. Nếu bạn muốn thay đổi tiêu đề (Title), lấy chuổi văn bản từ Textbox hay đặt 1 chuổi văn bản vào Textbox của 1 ứng dụng khác, hàm API SendMessage sẽ rất hữu dụng cho bạn.

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
  • .hwnd : handle của cửa sổ sẽ nhận thông điệp (message).
  • .wMsg : thông điệp sẽ được gửi tới cửa sổ.
  • .wParam : tham số được gửi cùng với thông điệp (phụ thuộc vào thông điệp).
  • .lParam : tham số được gửi cùng với thông điệp (phụ thuộc vào thông điệp).
Bây giờ chúng ta thử lấy chuỗi text của 1 Textbox sử dụng mặt nạ ***** để hiển thị text (giống như password vậy đó). Hãy copy đoạn code sau vào cửa sổ viết code của Form và nhấn F5 :

  1. Private Const WM_GETTEXT = &HD
  2. Private Const WM_GETTEXTLENGTH = &HE
  3.  
  4. Private Type POINTAPI
  5.     X As Long
  6.     Y As Long
  7. End Type
  8.  
  9. Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
  10. Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
  11. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
  12.  
  13. Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
  14.     Dim Pt As POINTAPI, mWnd As Long
  15.     'Get the current cursor position
  16.    GetCursorPos Pt
  17.     'Get the window under the cursor
  18.    mWnd = WindowFromPoint(Pt.X, Pt.Y)
  19.    
  20.     Dim length As Long
  21.     Dim result As Long
  22.     Dim strtmp As String
  23.    
  24.     length = SendMessage(mWnd, WM_GETTEXTLENGTH, ByVal 0, ByVal 0) + 1
  25.     strtmp = Space(length)
  26.     result = SendMessage(mWnd, WM_GETTEXT, ByVal length, ByVal strtmp)
  27.     Me.Print strtmp
  28.  
  29. End Sub
  30.  
  31. Private Sub Form_Paint()
  32.     Me.CurrentX = 0
  33.     Me.CurrentY = 0
  34.     Me.Print "Click on this form," + vbCrLf + "Hold the mouse button," + vbCrLf + "drag the mouse over another window," + vbCrLf + "release the mouse button" + vbCrLf + "and see what happens!"
  35. End Sub

Bây giờ hãy click chuột lên Form, giữ nguyên như vậy và di chuyển chuột tới cái Textbox nào chứa các dấu * , bạn sẽ thấy được password của nó. Chúc bạn thành công !!!.
:>
User avatar
NoBi
Quản trị
Quản trị
Posts: 970
Joined: Tue 18/03/2008 1:22 pm
Location: Sài Gòn
Has thanked: 58 times
Been thanked: 68 times
Contact:

PostMessage

Post by NoBi »

PostMessage

Khi hàm SendMessage gửi 1 message (thông điệp) cho cửa sổ, thông điệp đó sẽ nằm trong hàng đợi (queue) và chờ cửa sổ xử lý hết các thông điệp trước đó rồi mới đến phiên mình (giống như chúng ta xếp hàng mua đồ vậy đó, ai tới trước thì được trước). Đó chính là sự khác nhau giữa hàm SendMessage và PostMessage.
Hàm PostMessage cũng dùng để gửi 1 thông điệp tới cho cửa sổ nhưng thông điệp đó được xử lý ngay tức thì (chắc vì có quen biết ...) :-)

Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Ý nghĩa các tham số giống như của hàm SendMessage đã được giới thiệu ở trên.

Ví dụ bên dưới dùng PostMessage để đóng 1 ứng dụng đang chạy (ở đây là chương trình Calculator)
  1. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
  2. Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
  3. Const WM_CLOSE = &H10
  4.  
  5. Private Sub Form_Load()
  6.  
  7. Dim winHwnd As Long
  8. Dim RetVal As Long    
  9.     ‘Tìm lấy handle của cửa sổ
  10.     winHwnd = FindWindow(vbNullString, "Calculator")
  11.     If winHwnd <> 0 Then    ‘Nếu tìm thấy thì
  12.         ‘Đóng nó lại
  13.         PostMessage winHwnd, WM_CLOSE, 0&, 0&
  14.     Else
  15.         MsgBox "The Calculator is not open."
  16.     End If
  17.  
  18. End Sub

Các bạn chú ý cái này: các hàm API khi thực thi sẽ trả về một giá trị là con số dạng Long, nếu quá trình thực thi thành công, con số này sẽ là <> 0 (true), còn nếu không thành công thì số này sẽ = 0 (false).
:>
User avatar
tieurongtien
Thành viên năng nổ
Thành viên năng nổ
Posts: 78
Joined: Wed 26/03/2008 7:56 pm

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by tieurongtien »

Bác Nobi cho em biết rõ hơn chỗ này được không:
wMsg : thông điệp sẽ được gửi tới cửa sổ.
Thông điệp này gồm những loại nào? Ví dụ mình muốn click lên menu của chương trình khác thì truyền tham số nào?
Đừng xấu hổ khi không biết, chỉ xấu hổ khi không học
User avatar
NoBi
Quản trị
Quản trị
Posts: 970
Joined: Tue 18/03/2008 1:22 pm
Location: Sài Gòn
Has thanked: 58 times
Been thanked: 68 times
Contact:

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by NoBi »

Những thông điệp này mình cũng không nắm hết, chỉ biết được vài cái qua các ví dụ đã xem. Tùy thuộc vào từng đối tượng sẽ có thông điệp tương ứng cho nó, ví dụ Combobox thì thường bắt đầu bằng CB..., Listbox thì bắt đầu bằng LB... và Textbox thì bạn xem cái này. Nói chung cái này nó tùy thuộc vào kinh nghiệm "chiến trường" của mỗi người. :)
Bạn có thể xem thêm thông tin tại đây:
http://www.piclist.com/techref/os/win/a ... local.html
:>
User avatar
lightingking
Thành viên chính thức
Thành viên chính thức
Posts: 30
Joined: Sat 12/04/2008 9:56 pm
Location: Hà Nội
Contact:

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by lightingking »

Bác nobi cho em hỏi một chút:
em postmessage WM_CLOSE cho note pad thì được nhưng với WM_CHAR thì lại chỉ có tác dụng với cửa sổ chương trình(em thử với textbox), còn cửa sổ notepad thì nó không nhận? Vậy là sao?

Code: Select all

Private Const WM_CHAR = &H102Private Const WM_DESTROY = &H2Const WM_CLOSE = &H10Private Declare Function GetFocus Lib "user32" () As LongPrivate Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPrivate Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As LongPrivate Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPrivate Sub Timer1_Timer()'Me.Caption = FindWindow(vbNullString, "Untitled - Notepad")PostMessage FindWindow(vbNullString, "Untitled - Notepad"), WM_CLOSE, 78, 0&Timer1.Enabled = FalseMsgBox "end timer"End Sub 
User avatar
NoBi
Quản trị
Quản trị
Posts: 970
Joined: Tue 18/03/2008 1:22 pm
Location: Sài Gòn
Has thanked: 58 times
Been thanked: 68 times
Contact:

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by NoBi »

Lần sau chú ý nhớ chọn định dạng đúng ngôn ngử cho thẻ code nhé. Như vậy giúp người theo dỏi dể đọc code hơn.

Do handle lấy được là của cửa sổ Notepad, còn cái textbox nằm trong cửa sổ đó có handle khác nữa (giống như cái textbox nằm trong form). Cái textbox trong Notepad có class là "Edit", có thể dùng Spy++ để lấy thông tin chi tiết.
Spy++
Spy++

Code: Select all

Private Const WM_CHAR = &H102 Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As LongPrivate Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPrivate Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long  Private Sub Command1_Click()    Dim hNotepad As Long, hEdit As Long    hNotepad = FindWindow(vbNullString, "Untitled - Notepad")    hEdit = FindWindowEx(hNotepad, 0&, "Edit", vbNullString)    'Ky tu A = 65    PostMessage hEdit, WM_CHAR, 65, 0&End Sub
:>
violetlotous
Thành viên tích cực
Thành viên tích cực
Posts: 101
Joined: Wed 23/04/2008 9:58 am
Has thanked: 8 times
Been thanked: 1 time

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by violetlotous »

Cái này rất hữu ích, Thanks bạn

Bạn cho mình hỏi thêm, trong textbox, mình muốn gởi qua 1 thông điệp là nhấn nút Enter thì thế nào vậy

Và cho mình hỏi thêm về cái này : Private Const WM_CHAR = &H102
WM_CHAR thì mình có thể vào đây tìm: http://www.piclist.com/techref/os/win/a ... local.html
còn giá trị &H102 làm sao mình biết dc.

Thanks
User avatar
Zeroplus
Guru
Guru
Posts: 546
Joined: Sat 16/04/2011 11:31 pm
Location: Gò Dầu - Tây Ninh
Has thanked: 6 times
Been thanked: 98 times
Contact:

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by Zeroplus »

&H102 mới là giá trị cần. Còn khi dùng WM_CHAR thì phải gán cho nó là &H102 ( hằng số) . Sau khi gán thì WM_CHAR hay &H102 đều là một. Àk, để tra cứu bạn dùng API viewer có sẵn trong VB đó :D
violetlotous
Thành viên tích cực
Thành viên tích cực
Posts: 101
Joined: Wed 23/04/2008 9:58 am
Has thanked: 8 times
Been thanked: 1 time

Re: Hướng dẫn sử dụng hàm API SendMessage & PostMessage

Post by violetlotous »

Mình tìm thấy cái này, có lẽ hữu ích.

Code: Select all

Private Const VK_0 = &H30
Private Const VK_1 = &H31
Private Const VK_2 = &H32
Private Const VK_3 = &H33
Private Const VK_4 = &H34
Private Const VK_5 = &H35
Private Const VK_6 = &H36
Private Const VK_7 = &H37
Private Const VK_8 = &H38
Private Const VK_9 = &H39
Private Const VK_A = &H41
Private Const VK_B = &H42
Private Const VK_C = &H43
Private Const VK_D = &H44
Private Const VK_E = &H45
Private Const VK_F = &H46
Private Const VK_G = &H47
Private Const VK_H = &H48
Private Const VK_I = &H49
Private Const VK_J = &H4A
Private Const VK_K = &H4B
Private Const VK_L = &H4C
Private Const VK_M = &H4D
Private Const VK_N = &H4E
Private Const VK_O = &H4F
Private Const VK_P = &H50
Private Const VK_Q = &H51
Private Const VK_R = &H52
Private Const VK_S = &H53
Private Const VK_T = &H54
Private Const VK_U = &H55
Private Const VK_V = &H56
Private Const VK_W = &H57
Private Const VK_X = &H58
Private Const VK_Y = &H59
Private Const VK_Z = &H5A
Private Const VK_ADD = &H6B
Private Const VK_ATTN = &HF6
Private Const VK_BACK = &H8
Private Const VK_CANCEL = &H3
Private Const VK_CAPITAL = &H14
Private Const VK_CLEAR = &HC
Private Const VK_CONTROL = &H11
Private Const VK_CRSEL = &HF7
Private Const VK_DECIMAL = &H6E
Private Const VK_DELETE = &H2E
Private Const VK_DIVIDE = &H6F
Private Const VK_DOWN = &H28
Private Const VK_END = &H23
Private Const VK_EREOF = &HF9
Private Const VK_ESCAPE = &H1B
Private Const VK_EXECUTE = &H2B
Private Const VK_EXSEL = &HF8
Private Const VK_F1 = &H70
Private Const VK_F10 = &H79
Private Const VK_F11 = &H7A
Private Const VK_F12 = &H7B
Private Const VK_F13 = &H7C
Private Const VK_F14 = &H7D
Private Const VK_F15 = &H7E
Private Const VK_F16 = &H7F
Private Const VK_F17 = &H80
Private Const VK_F18 = &H81
Private Const VK_F19 = &H82
Private Const VK_F2 = &H71
Private Const VK_F20 = &H83
Private Const VK_F21 = &H84
Private Const VK_F22 = &H85
Private Const VK_F23 = &H86
Private Const VK_F24 = &H87
Private Const VK_F3 = &H72
Private Const VK_F4 = &H73
Private Const VK_F5 = &H74
Private Const VK_F6 = &H75
Private Const VK_F7 = &H76
Private Const VK_F8 = &H77
Private Const VK_F9 = &H78
Private Const VK_HELP = &H2F
Private Const VK_HOME = &H24
Private Const VK_INSERT = &H2D
Private Const VK_LBUTTON = &H1
Private Const VK_LCONTROL = &HA2
Private Const VK_LEFT = &H25
Private Const VK_LMENU = &HA4
Private Const VK_LSHIFT = &HA0
Private Const VK_MBUTTON = &H4
Private Const VK_MENU = &H12
Private Const VK_MULTIPLY = &H6A
Private Const VK_NEXT = &H22
Private Const VK_NONAME = &HFC
Private Const VK_NUMLOCK = &H90
Private Const VK_NUMPAD0 = &H60
Private Const VK_NUMPAD1 = &H61
Private Const VK_NUMPAD2 = &H62
Private Const VK_NUMPAD3 = &H63
Private Const VK_NUMPAD4 = &H64
Private Const VK_NUMPAD5 = &H65
Private Const VK_NUMPAD6 = &H66
Private Const VK_NUMPAD7 = &H67
Private Const VK_NUMPAD8 = &H68
Private Const VK_NUMPAD9 = &H69
Private Const VK_OEM_CLEAR = &HFE
Private Const VK_PA1 = &HFD
Private Const VK_PAUSE = &H13
Private Const VK_PLAY = &HFA
Private Const VK_PRINT = &H2A
Private Const VK_PRIOR = &H21
Private Const VK_PROCESSKEY = &HE5
Private Const VK_RBUTTON = &H2
Private Const VK_RCONTROL = &HA3
Private Const VK_RETURN = &HD
Private Const VK_RIGHT = &H27
Private Const VK_RMENU = &HA5
Private Const VK_RSHIFT = &HA1
Private Const VK_SCROLL = &H91
Private Const VK_SELECT = &H29
Private Const VK_SEPARATOR = &H6C
Private Const VK_SHIFT = &H10
Private Const VK_SNAPSHOT = &H2C
Private Const VK_SPACE = &H20
Private Const VK_SUBTRACT = &H6D
Private Const VK_TAB = &H9
Private Const VK_UP = &H26
Private Const VK_ZOOM = &HFB
Private Const KEYEVENTF_EXTENDEDKEY = &H1
Private Const KEYEVENTF_KEYUP = &H2
Private Const SW_HIDE = 0
Private Const SW_SHOWNORMAL = 1
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_MAXIMIZE = 3
Private Const SW_SHOWNOACTIVATE = 4
Private Const SW_SHOW = 5
Private Const SW_MINIMIZE = 6
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_RESTORE = 9
Post Reply

Return to “[VB] Bài viết hướng dẫn”