• 用VB实现的QQ自动登录器


    '在VB中建一工程,工程名为QQAutoLogin。移除系统自动添加的窗体Form1。在该工程下添加一模块,模块名为QQAutoLoginMod。复制以下代码到模块中。
    Option Explicit
    '-----------------------API 定义-------------------------------
    Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongByVal wMsg As LongByVal wParam As Long, lParam As Any) As Long
    Declare Function GetFocus Lib "user32" () As Long
    Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As LongByVal lParam As LongAs Long
    Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As LongAs Long
    Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As LongByVal bInheritHandle As LongByVal dwProcessId As LongAs Long
    Declare Function GetModuleFileNameEx Lib "psapi" Alias "GetModuleFileNameExA" (ByVal hProcess As LongByVal hModule As LongByVal lpFileName As StringByVal nSize As LongAs Long
    Declare Function IsWindowVisible Lib "user32" (ByVal hWnd As LongAs Long
    Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As LongAs Long
    Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As LongByVal lpEnumFunc As LongByVal lParam As LongAs Long
    Declare Function GetClientRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
    Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hWnd As LongByVal lpClassName As StringByVal nMaxCount As LongAs Long
    Declare Function GetParent Lib "user32" (ByVal hWnd As LongAs Long
    Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As ByteByVal bScan As ByteByVal dwFlags As LongByVal dwExtraInfo As Long)
    Declare Function ShowWindow Lib "user32" (ByVal hWnd As LongByVal nCmdShow As LongAs Long
    Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As LongAs Long
    '-----------------------结构定义-------------------------------
    Public Type RECT
        
    Left As Long
        Top 
    As Long
        
    Right As Long
        Bottom 
    As Long
    End Type

    '-----------------------常量定义-------------------------------
    Const WM_SETTEXT = &HC
    Const STANDARD_RIGHTS_REQUIRED = &HF0000
    Const SYNCHRONIZE = &H100000
    Const PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
    Const KEYEVENTF_KEYUP = &H2
    Const SW_SHOWNORMAL = 1

    Dim QQ_ExeFileName As String 'QQ.exe全路径文件名
    Dim QQ_MainhWnd As Long 'QQ登录窗口句柄
    Dim QQ_NumEdithWnd As Long 'QQ号码框句柄
    Dim QQ_PwdEdithWnd As Long 'QQ密码柄句柄
    Private Function QQ_AutoPressKey(hWnd As Long, strKey As String)
        
    Dim nLength As Long, VKey As Long, i As Long
        
        strKey 
    = UCase(strKey)
        nLength 
    = Len(strKey)
        
        
        
    For i = 1 To nLength
            VKey 
    = Asc(Mid(strKey, i, 1))
            
    Call AutoPressKey(VKey)
        
    Next
    End Function
    Public Function AutoPressKey(VKey As Long)
        keybd_event VKey, 
    000 '模拟键按下
        keybd_event VKey, 0, KEYEVENTF_KEYUP, 0 '模拟键弹起
    End Function

    Private Function QQ_GetMainhWnd()
        EnumWindows 
    AddressOf QQ_EnumMainhWndProc, 0 '枚举所有顶层窗口
    End Function

    Private Function QQ_EnumMainhWndProc(ByVal hWnd As LongByVal lParam As LongAs Boolean
        
    Dim nPID As Long, nTID As Long
        
    Dim hProcess As Long, strFileName As String
        
        nTID 
    = GetWindowThreadProcessId(hWnd, nPID) '根据窗口句柄获得拥有窗口的进程ID和线程ID
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, True, nPID) '根据进程ID打开进程获得进程句柄
        strFileName = Space(255)
        GetModuleFileNameEx hProcess, 
    0, strFileName, 255 '根据进程句柄获得进程主模块文件名
        If Left$(strFileName, InStr(1, strFileName, Chr(0)) - 1= QQ_ExeFileName Then
            
    If IsWindowVisible(hWnd) Then '整个QQ.exe登录期间只有登录窗口是可见的
                QQ_MainhWnd = hWnd
                QQ_EnumMainhWndProc 
    = False '枚举函数返回False结束循环枚举
                CloseHandle hProcess
                
    Exit Function
            
    End If
        
    End If
        CloseHandle hProcess
        
        QQ_EnumMainhWndProc 
    = True
    End Function
    Private Function QQ_GetSubhWnd()
        EnumChildWindows QQ_MainhWnd, 
    AddressOf EnumSubhWndProc, 0 '枚举QQ登录窗口下的所有子窗口
    End Function

    Private Function EnumSubhWndProc(ByVal hWnd As LongByVal lParam As LongAs Long
        
    Dim stRect As RECT, nWidth As Long, nHeight As Long
        
    Dim strClassName As String * 255, tmphWnd As Long
        
        GetClientRect hWnd, stRect 
    '取得窗口客户区距形区域大小
        nWidth = stRect.Right - stRect.Left
        nHeight 
    = stRect.Bottom - stRect.Top
        
        strClassName 
    = Space(255)
        GetClassName hWnd, strClassName, 
    255 '根据窗口句柄获得窗口类名
        Select Case Left$(strClassName, InStr(1, strClassName, Chr(0)) - 1)
        
    Case "Edit" '如果该窗口是文本框类
            tmphWnd = GetParent(hWnd) '获得该窗口的父窗口
            strClassName = Space(255)
            GetClassName tmphWnd, strClassName, 
    255 '取得父窗口类名
            If tmphWnd <> QQ_MainhWnd Then '如果该子窗口的父窗口不是QQ登录窗口的话
                '注意:QQ号码框被设计在一个ComboBox类的组合框中。
                '父子关系如下:QQ登录窗口__ComboBox(父窗口为QQ登录窗口)__QQ号码框(父窗口为ComboBox)
                '这种关系在QQ登录窗口中是唯一的,要查找QQ号码框要满足的条件如下:
                '1:类名必须是Edit  2:父窗口类名必须是ComboBox
                If Left$(strClassName, InStr(1, strClassName, Chr(0)) - 1= "ComboBox" Then
                    
    '加多一层检查,QQ号码框的距形大小,这个也是唯一的。
                    '其实单单检查这个也可以查找到QQ号码框
                    '注意这个会随着QQ版本的不同可能会有所不同,因为QQ的界面腾迅一直使其在变(漂亮)
                    If nWidth = 127 And nHeight = 14 Then
                        QQ_NumEdithWnd 
    = hWnd
                    
    End If
                
    ElseIf Left$(strClassName, InStr(1, strClassName, Chr(0)) - 1= "#32770" Then
                    
    '要查找QQ密码框要满足的条件如下:
                    '1:类名必须是Button  2:父窗口类名必须是#32770(对话框)
                    '注意以上两个并不是唯一的,必须加多以下一层检查
                    If nWidth = 131 And nHeight = 14 Then '单单检查这个也可以,这个是唯一的(2007版)
                        QQ_PwdEdithWnd = hWnd
                    
    End If
                
    End If
            
    End If
        
    Case "Button"
            
    'If nWidth = 75 And nHeight = 21 Then
                'MsgBox "登录框"
            'End If
        End Select
        
        EnumSubhWndProc 
    = True
    End Function
    Public Function QQ_AutoLogin(strExeFileName As String, strNum As String, strPwd As String)
        
    Shell strExeFileName    '外部运行QQ.exe
        Sleep 1000  '延时1000毫秒
        QQ_MainhWnd = 0  '初始化登录窗口句柄
        Call QQ_GetMainhWnd '获取QQ登录窗口句柄(自定义函数)
        If QQ_MainhWnd Then Debug.Print "成功获得主窗口句柄"  '调试语句,可删除
        QQ_NumEdithWnd = 0 '初始化号码框和密码框句柄
        QQ_PwdEdithWnd = 0
        
    If QQ_MainhWnd Then Call QQ_GetSubhWnd  '获取QQ号码框和密码框句柄(自定义函数)
        If QQ_NumEdithWnd And QQ_PwdEdithWnd Then Debug.Print "成功获得号码框和密码框句柄"  '调试语句,可删除
        SendMessage QQ_NumEdithWnd, WM_SETTEXT, 00 '清空号码框
        '有人问为什么不用SetFocus直接设置焦点而用模拟按下Tab键,那是因为QQ不响应获得焦点消息,调用SetFocus达不到效果
        '还有一个在QQ登录窗口Tab键只在号码框和密码框之间来回切换,不信你试一下
        Call SetForegroundWindow(QQ_MainhWnd) '保证模拟键盘输入之前QQ登录窗口的显示状态
        If GetFocus() <> QQ_NumEdithWnd Then Call AutoPressKey(vbKeyTab) '保证模拟键盘输入之前焦点在号码框
        Call QQ_AutoPressKey(QQ_NumEdithWnd, strNum) '模拟键盘自动输入QQ号码
        Sleep 500
        
    If GetFocus() <> QQ_PwdEdithWnd Then Call AutoPressKey(vbKeyTab) '保证模拟键盘输入之前焦点在密码框
        Call QQ_AutoPressKey(QQ_PwdEdithWnd, strPwd) '模拟键盘自动输入QQ密码
        Sleep 500
        
    Call AutoPressKey(vbKeyReturn) '模拟键盘输入回车键开始登录
    End Function

    Sub Main()
        
    Dim strNum As String, strPwd As String
        
        strNum 
    = "4598456"
        strPwd 
    = "nihaoma"
        QQ_ExeFileName 
    = "D:\Program Files\Tencent\QQ\QQ.exe"
        
    Call QQ_AutoLogin(QQ_ExeFileName, strNum, strPwd)  'QQ自动登录函数(自定义函数)
    End Sub

    '程序还有以下几个致命的缺陷:
    '
    1:如果在该程序运行之前已经有QQ程序在运行(未登录或已登录的),那判断QQ登录主窗口的代码就可能会不正确了
    '
    2:模拟键盘输入那地方还有点问题,在模拟的中间有可能被别的程序打断,一失去焦点就乱了
  • 相关阅读:
    enumerate函数和zip函数返回的对象,都需要用list()函数转换为列表
    zip函数
    列表和元组的互相转换
    元组和列表的区别
    帮小朋友写的第一个程序
    remove del pop的区别
    如何运用Linux进行查看tomcat日志
    Linux大全
    liunx中组合查询的命令
    常见的问题
  • 原文地址:https://www.cnblogs.com/ZYM/p/1151944.html
Copyright © 2020-2023  润新知