Menganalisa dan membuat mesin penjawab otomatis Y!M

Posted by Kamarudin • 4 minute read • Comments

Sebelum kita melanjutkan pembahasan ada beberapa istilah yang harus kita ketahui yaitu Parent Window (Window Induk), Child Window (Window Anak) dan bagaimana cara mendapatkan nilai Handle Window (hWnd) atau dengan istilah yang lebih sederhana Process ID.

Setiap aplikasi yang berjalan di Windows umumnya memiliki jendela atau form. Jika ada beberapa jendela/form aplikasi berbeda yang terbuka, maka sistem akan memberikan semacam identitas bagi setiap jendela yang terbuka tersebut, di mana masing-masing jendela/form memiliki identitas atau alamat yang berbeda satu sama lain.

Konsep Child-Parent sangat sederhana, karena pengertian yang diberikan sama persis dengan namanya. Child/anak merupakan sebuah handle window yang berada di dalam handle window lainnya yang biasa disebut parent/induk. Oke kita lihat contoh berikut :

Dengan cara yang sama lakukan terhadap YM dan menghasilkan gambar berikut :

Nah yang jadi pertanyaan bagaimana caranya untuk mendapatkan nilai Handle, Caption dan Class dan yang terpenting disini adalah nilai Class. Ada banyak tool yang bisa digunakan salah satunya adalah Spy++, merupakan tool bawaan visual studio 6.

Oke kita langsung saja menjalankan program Spy++, lihat gambar :

Selanjutnya Anda tinggal drag icon ke aplikasi YM, lihat gambar :

Nah sampe disini analisis sudah selesai dan kita sudah mendapatkan semua informasi yang dibutuhkan, yaitu urutan windows parent<-anak :

  1. YSearchMenuWndClass <- IMClass <- YHTMLContainer <- Internet Explorer_Server
  2. YSearchMenuWndClass <- IMClass <- YIMInputWindow

Perlu diketahui bahwal class/window Internet Explorer_Server dan** YIMInputWindow** bukan class terluar, sehingga kita perlu mengetahui class diatasnya. Jadi untuk membaca pesan yang masuk, urutan class yang harus kita lalui adalah : YSearchMenuWndClass ->  IMClass -> YHTMLContainer -> Internet Explorer_Server

Sedangkan untuk membalas pesan yang masuk, urutan kelas yang harus kita lalui adalah : YSearchMenuWndClass ->  IMClass -> YIMInputWindow

Untuk memanipulasi class/window diatas kita membutuhkan windows handle/process id dari class tersebut, bagi yang sudah terbiasa menggunakan fungsi-fungsi API kemungkinan sudah tau fungsi API apa saja yang kita butuhkan. Jika masih bingung apa itu fungsi API, coba mampir ke sini.

Yaph benar udah taukan fungsi API yang kita gunakan untuk mendapatkan windows handle/process id :

  1. FindWindow -> untuk mendapatkan process id induk class (YSearchMenuWndClass)
  2. FindWindowEx -> untuk mendapatkan process id sub class (IMClass, YHTMLContainer, Internet Explorer_Server dan YIMInputWindow) berikut deklarasi lengkapnya :
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

Oke berikutnya adalah bagian coding lengkap, bagaimana cara mengambil informasi yang ada di window Internet Explorer_Server dan mengirim pesan melalui window YIMInputWindow dan jangan lupa tambahkan references Microsoft HTML Object Library di project Anda.

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

Private Declare Function SendMessageByString Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
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

Private Declare Function ObjectFromLresult Lib "oleacc" (ByVal lResult As Long, riid As UUID, ByVal wParam As Long, ppvObject As Any) As Long
Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" (ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, lParam As Any, ByVal fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) As Long
Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long

Type UUID
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(0 To 7) As Byte
End Type

Private Const SMTO_ABORTIFHUNG = &H2
Private Const WM_SETTEXT = &HC
Private Const WM_KEYDOWN = &H100
Private Const VK_RETURN = &HD

Dim hwndYMMainClass     As Long
Dim hwndIMClass         As Long

Private Function IEDOMFromhWnd(ByVal hWnd As Long) As IHTMLDocument
    Dim IID_IHTMLDocument   As UUID
    Dim doc                 As IHTMLDocument2
    Dim lres                As Long 'if = 0 isn't inet window.
    Dim lMsg                As Long
    Dim hr                  As Long

    '---END-DECLARES---------
    lMsg = RegisterWindowMessage("WM_HTML_GETOBJECT") 'Register Wnd Message
    Call SendMessageTimeout(hWnd, lMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, lres) 'Get's Object

    '---CHECKS-FOR-WINDOW----
    hr = ObjectFromLresult(lres, IID_IHTMLDocument, 0, IEDOMFromhWnd)
End Function

Private Function getIEText(ByVal hWnd As Long) As String
    Dim doc As IHTMLDocument2

    'On Error Resume Next

    If hWnd <> 0 Then
        Set doc = IEDOMFromhWnd(hWnd)
    Else
        getIEText = "-[TEXT CANNOT BE FOUND]-"
        Exit Function

    End If

    '---CHECKS-FOR-HWND------
    If doc.body.innerText = vbNullString Then
        getIEText = "ERROR! [WINDOW DOESN'T CONTAIN HTML]"
        Exit Function
    End If
    '---CHECKS-FOR-HTML-EMBEDDED

    getIEText = doc.body.innerText
End Function

Private Sub cmdCetakPesan_Click()
    Dim hwndYHTMLContainer  As Long
    Dim hwndIEServer        As Long

    Dim pesan               As String

    hwndYMMainClass = FindWindow("YSearchMenuWndClass", vbNullString)
    If hwndYMMainClass <> 0 Then
        hwndIMClass = FindWindowEx(hwndYMMainClass, 0&, "IMClass", vbNullString)
        hwndYHTMLContainer = FindWindowEx(hwndIMClass, 0&, "YHTMLContainer", vbNullString)
        hwndIEServer = FindWindowEx(hwndYHTMLContainer, 0&, "Internet Explorer_Server", vbNullString)

        pesan = getIEText(hwndIEServer) 'informasi pesan disini masih kurang bagus jadi harus di parsing lagi
        Debug.Print pesan
    End If
End Sub

Private Sub cmdKirimPesan_Click()
    Dim hwndYIMInputWindow  As Long
    Dim hwndButton          As Long

    hwndYMMainClass = FindWindow("YSearchMenuWndClass", vbNullString)
    hwndIMClass = FindWindowEx(hwndYMMainClass, 0&, "IMClass", vbNullString)
    hwndYIMInputWindow = FindWindowEx(hwndIMClass, 0&, "YIMInputWindow", vbNullString)
    Call SendMessageByString(hwndYIMInputWindow, WM_SETTEXT, 0&, "Isi pesannya disini...")
    Call SendMessage(hwndYIMInputWindow, WM_KEYDOWN, VK_RETURN, 0&)
End Sub

Yaph mungkin itu saja penjelasan singkat untuk membuat mesin penjawab otomatis YM! untuk uji coba ini saya menggunakan YM! versi 8.1.0.421 bagi yang akan mencoba di versi 9 sudah saya cek ada sedikit perbedaan nama class/window, yang penting caranya sama seperti diatas tinggal sesuaikan saja.

Bagian terakhir dari artikel ini bisa Anda ikuti disini.

Selamat mencoba :blush:

Comments