精华内容
下载资源
问答
  • 仿QQ客户端登录界面

    2013-08-10 22:12:00
    仿QQ客户端登录界面
  • 客户端登录

    2013-09-03 19:27:37
    基本完成常用的客户端登录界面布局,仿qq登录,微薄客户端登录等,方便用户开发
  • 最近需要写一个本机qq客户端登录检测的功能,首先,在点击打开链接找到了如下C语言代码:#include <windows.h> #include <stdio.h> #include <string.h> BOOL CALLBACK ...

    最近需要写一个本机qq客户端登录检测的功能,首先,在点击打开链接找到了如下C语言代码:

    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
     
    BOOL CALLBACK enumwindowsproc(HWND hwnd,LPARAM lParam){
       char name[255]={0};
         char rp[] = "qqexchangewnd_shortcut_prefix_";
          int l = strlen(rp);
          GetWindowText(hwnd,name,255);
         if(strstr(name,rp)){
             printf("%X\t%s\n",hwnd,name+l);
         }
         return 1;
     }
    
    
    
     int main(){
       EnumWindows(enumwindowsproc,NULL);
     }

    编译了一下,可以使用,看了下代码,原理是获取本地打开窗口名,获取qq号码

    在java中导入jna的jar包使用JNA,完成了以上功能,实例代码如下:

    import java.util.HashMap;
    import java.util.Map;
    import com.sun.jna.Native;
    import com.sun.jna.Pointer;
    import com.sun.jna.win32.StdCallLibrary;
    
    /*****
     * 当前登录QQ信息检测
     * 
     * @author wjw
     * 
     * @since 2018-03-07
     * 
     * @version v1.0
     *
     */
    public class QQLoginCheck {
    	/*******QQ窗口文本内容前缀****eg:qqexchangewnd_shortcut_prefix_123456(其中123456即为qq号)*****/
    	private static final String QQ_WINDOW_TEXT_PRE = "qqexchangewnd_shortcut_prefix_";
    	
    	private static final  User32 user32 = User32.INSTANCE;
    	
    	public interface User32 extends StdCallLibrary {
    	        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
    	        interface WNDENUMPROC extends StdCallCallback {
    	            boolean callback(Pointer hWnd, Pointer arg);
    	        }
    	        boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer arg);
    
    	        int GetWindowTextA(Pointer hWnd, byte[] lpString, int nMaxCount);
    	    }
    	
    	
    	
    	/******
    	 * 获取当前登录qq的信息
    	 * @return map集合
    	 */
    	public static Map<String,String> getLoginQQList(){
    		final Map<String,String> map = new HashMap<String,String>(5);
    		
    		user32.EnumWindows(new User32.WNDENUMPROC() {
                public boolean callback(Pointer hWnd, Pointer userData) {
                    byte[] windowText = new byte[512];
                    user32.GetWindowTextA(hWnd, windowText, 512);
                    String wText = Native.toString(windowText);
                    if(_filterQQInfo(wText)){
                    	map.put(hWnd.toString(), wText.substring(wText.indexOf(QQ_WINDOW_TEXT_PRE) + QQ_WINDOW_TEXT_PRE.length()));
                    }
                    return true;
                }
            }, null);
    		
    		
    		
    		return map;
    	}
    	
    	
    	/****
    	 * 过滤有效qq窗体信息
    	 * @param windowText
    	 * @return 是否为qq窗体信息
    	 */
    	private static boolean _filterQQInfo(String windowText){
    		
    		if(windowText.startsWith(QQ_WINDOW_TEXT_PRE))
    			return true;
    		return false;
    	}
    	
    	
    	public static void main(String[] args) {
    		System.out.println(getLoginQQList());
    	}
    	
    }
    


    运行结果类似如下:

    {native@0x4008f6=12345678, native@0x20e2c=87654321}

    其中map的value中保存的即为当前登录的qq号信息


    end

    如有错误,欢迎指正



    展开全文
  • QQ登录Android客户端示例
  • QQ登录Android客户端示例
  • 在项目中需要利用userId和时间戳生成订单,这就要保证一个用户在同一时间只能在一个客户端上进行操作,而且为了账号的安全性。所以就想实现QQ那样的后者挤掉前者的功能。 由于自己是一边学一边写的项目,所以对...

    在项目中需要利用userId和时间戳生成订单,这就要保证一个用户在同一时间只能在一个客户端上进行操作,而且为了账号的安全性。所以就想实现QQ那样的后者挤掉前者的功能。

    由于自己是一边学一边写的项目,所以对session这些功能的特性没有充分的了解。刚开始以为很简单,直接后者登录时直接查询当前用户信息是否已经存在在session中,如果存在移除掉前者的session信息就可以,因为每个session都有自己的sessionId。这简直不要太简单。结果无知就是天真。首先思路没啥问题,等到去写方法得时候太发现session是每个会话独有的,其他的连接是不能访问其他连接的session的,而且也没有直接通过sessionId移除session这种方法。

    于是百度看看别人都是怎么做的。也是利用的session。思路是把session和用户状态存储到一个临时表中,然后给了两种方案,一种是hashMap,一种是servletcontext。两种都不是很了解。于是百度,一下是关于两种的解释:

    hashMao百度百科

    servletcontext百度百科

    二者比较之后我觉得servletcontext简单易操作,而且整个服务器端可以共享数据,服务器启动自动生成,关闭即销毁。刚好符合需求。开搞。先上最终效果:

     可以看到左边浏览器已经登录了迪丽热巴账号,右边再去登录,这时左边不管是页面刷新还是跳转其他页面,都会重定向到登陆页,并提示账号在其他地方登录!

    上代码;

    登录成功时,将用户信息存入session中,取出sessionId和用户Id,以用户id为key(因为每个用户id都是唯一的,sessionId会改变的)。

     UserInfo userInfo = userRepositories.findByAccountAndPassword(account,password);
                session.setAttribute("loginUser",userInfo);/*登录成功把用户信息存入session中,便于调用*/
                String userId = String.valueOf(userInfo.getId());/*获取当前用户id并初始化为String类型*/
                String sessionId = session.getId();/*获取当前会话的sessionId*/
                ServletContext servletContext = GetServletContext.getServletContext();
                servletContext.setAttribute(userId,sessionId);/*以用户id为key,sessionId为value存储到容器中*/
                session.removeAttribute("loginState");
                return "登录成功";

     然后写一个检查session的方法,判断当前session中是否有用户登录信息,没有的话说明没登录,返回true,如果存在登录信息,取出当前sessionId以及servletcontext中此用户id对应的sessionId,判断两个sessionId是否相等,相等的话,说明是同一个连接会话,也返回true。不相等的话,就说明后面登录的sessionId已经覆盖掉了之前servletcontext中的sessionId,存在异地登录,返回false。

    public class CheckSession{
        
        public static boolean checkSession(){
            HttpSession session = GetSession.getSession();
            UserInfo userInfo = (UserInfo) session.getAttribute("loginUser");
            if (userInfo == null){
                return true;
            }else{
                ServletContext servletContext = GetServletContext.getServletContext();
                String sessionId = session.getId();
                String userId = String.valueOf(userInfo.getId());
                String oldSessionId = (String) servletContext.getAttribute(userId);
                if (oldSessionId == null || oldSessionId.equals(sessionId)){/*如果不存在此用户的sessionId(一般不可能)
                                                                             或者新旧id相等,说明是同一个登录*/
                    return true;
                }else {
                    return false;/*否则就是不同客户端登录,返回false*/
                }
            }
    
        }
    }

    然后写一个移除session的方法,因为我这里每个页面拦截判断后都需要执行。

    public class DelSecondUser {
        public static void delSecondUser(){
            HttpSession session = GetRequest.getRequest().getSession();
            session.removeAttribute("loginUser");
            session.setAttribute("loginState","1");/*存储一个状态,用于前端判断是多客户端登录,账号被挤掉了*/
        }
    }

    关于在普通类方法中怎么获得session等,可以查看我上一篇博客:springboot普通类获取session等

    然后去拦截器那里进行判断:

    @GetMapping({"/index", ""})
        public String index(ModelMap modelMap) {
            if (!CheckSession.checkSession()) {
                DelSecondUser.delSecondUser();
                return "redirect:user";
            } else {
               
                return "index";
            }
        }

    这里我是用@GetMapping来拦截路径请求的,首先就执行checksession判断,如果返回的是false,说明账号已经在其他地方登录了,那么这个就得会话的session就得被移除,所以执行delSecondUser方法,并重定向到登陆页。不是的话就进行正常逻辑操作。每个页面都进行这个逻辑判断。就可以实现只要刷新或跳转页面就会退出。

    至于怎么在登录页判断是不是被挤掉账号而过来的进行提示

    记得我们在移除session的那个方法里写了这样一个语句。

     session.setAttribute("loginState","1");/*存储一个状态,用于前端判断是多客户端登录,账号被挤掉了*/

    如果是被挤到的,那么给前端一个1的状态。

    然后在登录页放一个隐藏的标签来接收它:

    <span style="display:none;"th:if="${session.loginState!=null}"th:text="${session.loginState}" id="ifLogin"></span><!--如果是1代表是被挤掉而重定向过来的-->
    <span style="display: none;" th:if="${session.loginState==null}" th:text="0" id="ifLogin"></span><!--默认是0-->

    在登录页的js里写一个判断方法:

    //判断是不是被挤出登录
    function ifLogin(){
        var state = $('#ifLogin').text().trim();
        if (state == "1"){
            layer.confirm('您的账号在其他地方登录,请确认是否本人操作?', {
                btn: ['是我本人操作','不是我,立即修改密码'] //按钮
                ,closeBtn:0
                ,title:"警告"
                ,btnAlign: 'c'
            }, function(){
                layer.msg('好的!请注意保护个人账号安全!',{icon:6});
            }, function(){
                location.href="forgetPd";
            });
        }
    }

    每次进入页面都进行判断,是不是1,是1就给出提示。

    如果在登录界面再次登录,那么就移除掉这loginstate状态,前面登录那里有写到。

    但是有一种情况,比如涉及到用户登录的情况下才能执行的业务逻辑,假如a客户端用户1正在充值,订单号是需要从session中取出用户id加时间戳生成的,这时候b客户端突然有人用用户1的账号登录了,a客户端的session被移除了,但是a客户端页面没刷新,用户1可以继续点击充值按钮,这时候后台取不到session信息,报错。

    所以我们在后台需要执行一个判断,如果取不到session,直接返回一个结果前端判断即可,如果取得到则继续业务操作就行。

    至此此功能完整实现。

    由于本人比较小白,所以表述上有啥错误或者有更好的方法,欢迎大佬们指正和指教*^_^*

    展开全文
  • 为什么同一台电脑登录同一个QQ号码我在QQ安全中心看到的登录IP地址不同,客户端登录永远是一个106.23.XX.XX的,而我登录QQ空间,QQ秀财付通包括用QQ网页版登录,IP地址永远是114.33.xx.xx。这是什么原因?怎么设置...
  • MFC开发QQ游戏客户端登录界面

    千次阅读 2008-03-04 11:54:00
    开始:按下“高级设置”后 图片均采用QQ游戏的BMP图。图片界面是利用对图片的拼接并计算Rgn后进行CombineRgn ,最后SetWindowRgn实现。上面的广告是一个HTML页面。可以通过MFC中的HtmlView来做。 图片按钮的制做是...

    开始:

    按下“高级设置”后

     

    图片均采用QQ游戏的BMP图。

    图片界面是利用对图片的拼接并计算Rgn后进行CombineRgn ,最后SetWindowRgn实现。

    上面的广告是一个HTML页面。

    可以通过MFC中的HtmlView来做。 

    图片按钮的制做是基于一个CStatic。

    我建立了一个基于CStatic的派生类。并在类里增加成员对象CBitmap m_BKBmp;

    通过对m_BKBmp的设置取得图片。

    在OnMouseMove消息进行处理。使图片在鼠标经过。按下,抬起时有不同的状态值。

    在显示时跟据状态值进行BitBlt来秀图片的某一块矩形。

    这是根据QQ游戏的资源分析而做的方案。

    图中“高级设置”一项的图片采用了三块(左,中,右)拼接而成。跟据按钮长度来设置中间图片的渲染次数达到秀一个长条的效果。

    CheckBox也是一个图片。

    图片的文件资源也是仿照QQ一样。直接用BMP切拼图放在对应目录。

    打算等有空了,找人来做几套图吧。弄一下换肤效果。

    展开全文
  • 1.qq2008自动登录 class QQ2008AutoLogin{publicstaticvoid AutoLogin(string qq, string passwd){Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Tencent\...

    1.qq2008自动登录

    class QQ2008AutoLogin
    {
    publicstaticvoid AutoLogin(string qq, string passwd)
    {
    Microsoft.Win32.RegistryKey regKey
    = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Tencent\\PlatForm_Type_List\\1", true);
    string qq2008Path = regKey.GetValue("TypePath").ToString();
    regKey.Close();
    bool blAcntSts =true;//true隐身,false为上线
    Process.Start(qq2008Path, "/START QQUIN:"+ qq +" PWDHASH:"+ HashBase64(passwd) +" /STAT:"+ (blAcntSts ?"40" : "41"));
    }

    ///<summary>
    /// 返回指定字符串以Base64编码的哈希值,用于qq2008登录
    ///</summary>
    ///<param name="str">要计算哈希值的字符串</param>
    ///<returns></returns>
    privatestaticstring HashBase64(string str)
    {
    byte[] result =newbyte[str.Length];
    try
    {
    MD5 md
    =new MD5CryptoServiceProvider();
    result
    = md.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str));
    return Convert.ToBase64String(result);
    }
    catch
    {
    return"";
    }
    }

    }

    2.qq2009自动登录

    ///<summary>
    /// 适用于1.41.1451.0版本
    ///</summary>
    class QQ2009AutoLogin
    {
    ///<summary>
    /// 查找窗口句柄
    ///</summary>
    ///<param name="lpClassName">窗口类名</param>
    ///<param name="lpWindowName">窗口标题</param>
    ///<returns></returns>
    [DllImport("user32.dll")]
    privatestaticextern IntPtr FindWindow(string lpClassName, string lpWindowName);

    ///<summary>
    /// 查找子窗口句柄
    ///</summary>
    ///<param name="hwndParent">要查找子窗口的父窗口句柄</param>
    ///<param name="hwndChildAfter">上一个子窗口句柄</param>
    ///<param name="lpszClass">子窗口类名</param>
    ///<param name="lpszWindow">窗口标题</param>
    ///<returns></returns>
    [DllImport("User32.DLL")]
    privatestaticextern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    ///<summary>
    /// 获得一个窗口的句柄,该窗口与某源窗口有特定的关系
    ///</summary>
    ///<param name="hwd">源窗口</param>
    ///<param name="flags">指定结果窗口与源窗口的关系</param>
    ///<returns></returns>
    [DllImport("user32.dll")]
    publicstaticextern IntPtr GetWindow(IntPtr hwd, int flags);

    ///<summary>
    /// 设置指定窗口为当前活动窗口
    ///</summary>
    ///<param name="hWnd">窗口句柄</param>
    [DllImport("User32.DLL")]
    privatestaticexternbool SetForegroundWindow(IntPtr hWnd);

    ///<summary>
    /// 向指定窗口发送字符串
    ///</summary>
    [DllImport("User32.dll", EntryPoint ="SendMessage")]
    privatestaticexternint SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

    ///<summary>
    /// 可向指定窗口发送回车键
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="SendMessage", SetLastError =true, CharSet = CharSet.Auto)]
    privatestaticexternint SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);

    ///<summary>
    /// 发送按键消息用PostMessage比较好,SendMessage有时会不起作用
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="PostMessage", SetLastError =true)]
    privatestaticexternbool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    constint WM_SETTEXT =0x000C;//发送文本
    constint WM_KEYDOWN =0x0100;//按键按下
    constint WM_KEYUP =0x0101;//按键放开
    constint WM_CLICK =0x00F5;//鼠标点击
    constint WM_SETFOCUS =0x0007;//设置焦点参数 

    publicstaticvoid AutoLogin(string qq, string passwd)
    {
    IntPtr mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2009");
    if (mainHwnd == IntPtr.Zero)
    {
    Microsoft.Win32.RegistryKey regKey
    = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Tencent\\PlatForm_Type_List\\3", true);
    string qq2009Path = regKey.GetValue("TypePath").ToString();
    regKey.Close();
    if (!string.IsNullOrEmpty(qq2009Path))
    {
    Process.Start(qq2009Path);
    Thread.Sleep(
    500);
    while (true)
    {
    mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2009");
    if (mainHwnd != IntPtr.Zero)
    break;
    Thread.Sleep(
    100);
    }
    }
    else
    {
    MessageBox.Show(
    "未能找到QQ2009安装目录,请手动打开QQ程序!");
    return;
    }
    }
    SetForegroundWindow(mainHwnd);
    Thread.Sleep(
    500);
    IntPtr userHwnd
    = FindWindowEx(mainHwnd, IntPtr.Zero, "ATL:30A4E1D8", "");//获取账号框句柄
    IntPtr passHwnd = GetWindow(userHwnd, 2);
    SendMessage(userHwnd, WM_SETTEXT, IntPtr.Zero, qq);
    //发送qq号码
    SendMessage(passHwnd, WM_SETFOCUS, 0, 0);//设置焦点到密码框,发送tab键不能转到密码框
    WindowsAPI.SendDelCode(10);//QQ记住密码所有长度为10,只需发送10个Del就可删除原来记住的密码
    WindowsAPI.SendNoUnicode(passwd);
    Thread.Sleep(
    200);
    //发送回车键
    //PostMessage(mainHwnd, WM_KEYDOWN, 13, 0);
    //PostMessage(mainHwnd, WM_KEYUP, 13, 0);
    SendMessage(mainHwnd, WM_KEYDOWN, 0x0D, 0);
    }

    publicstaticvoid AutoLogin2(string qq, string passwd)
    {
    Microsoft.Win32.RegistryKey regKey
    = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Tencent\\PlatForm_Type_List\\3", true);
    string qq2009Path = regKey.GetValue("TypePath").ToString();
    regKey.Close();
    IntPtr mainHwnd
    = IntPtr.Zero;
    if (!string.IsNullOrEmpty(qq2009Path))
    {
    Process.Start(qq2009Path);
    Thread.Sleep(
    500);
    while (true)
    {
    mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2009");
    if (mainHwnd != IntPtr.Zero)
    break;
    Thread.Sleep(
    100);
    }
    }
    else
    {
    MessageBox.Show(
    "未能找到QQ2009安装目录,请手动打开QQ程序!");
    return;
    }
    SetForegroundWindow(mainHwnd);
    Thread.Sleep(
    500);
    SendKeys.Send(qq);
    //光标定位账号框
    SendKeys.Send("{tab}");
    SendKeys.Send(passwd);
    SendKeys.Send(
    "{enter}");
    }
    }

    3.qq2010自动登录

    (1).适用于qq2010 1.50.1720.0正式版本

    ///<summary>
    /// 适用于1.50.1720.0正式版本
    ///</summary>
    class QQ2010AutoLogin
    {
    ///<summary>
    /// 查找窗口句柄
    ///</summary>
    ///<param name="lpClassName">窗口类名</param>
    ///<param name="lpWindowName">窗口标题</param>
    ///<returns></returns>
    [DllImport("user32.dll")]
    privatestaticextern IntPtr FindWindow(string lpClassName, string lpWindowName);

    ///<summary>
    /// 查找子窗口句柄
    ///</summary>
    ///<param name="hwndParent">要查找子窗口的父窗口句柄</param>
    ///<param name="hwndChildAfter">上一个子窗口句柄</param>
    ///<param name="lpszClass">子窗口类名</param>
    ///<param name="lpszWindow">窗口标题</param>
    ///<returns></returns>
    [DllImport("User32.DLL")]
    privatestaticextern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    ///<summary>
    /// 获得一个窗口的句柄,该窗口与某源窗口有特定的关系
    ///</summary>
    ///<param name="hwd">源窗口</param>
    ///<param name="flags">指定结果窗口与源窗口的关系</param>
    ///<returns></returns>
    [DllImport("user32.dll")]
    publicstaticextern IntPtr GetWindow(IntPtr hwd, int flags);

    ///<summary>
    /// 设置指定窗口为当前活动窗口
    ///</summary>
    ///<param name="hWnd">窗口句柄</param>
    [DllImport("User32.DLL")]
    privatestaticexternbool SetForegroundWindow(IntPtr hWnd);

    ///<summary>
    /// 向指定窗口发送字符串
    ///</summary>
    [DllImport("User32.dll", EntryPoint ="SendMessage")]
    privatestaticexternint SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

    ///<summary>
    /// 可向指定窗口发送回车键
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="SendMessage", SetLastError =true, CharSet = CharSet.Auto)]
    privatestaticexternint SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);

    ///<summary>
    /// 发送按键消息用PostMessage比较好,SendMessage有时会不起作用
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="PostMessage", SetLastError =true)]
    privatestaticexternbool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    ///<summary>
    /// 枚举所有子窗口
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="EnumChildWindows")]
    privatestaticexternbool EnumChildWindows(IntPtr hWndParent, EnumChildWindowsProc lpEnumFunc, int lParam);

    ///<summary>
    /// 获取指定句柄类名
    ///</summary>
    ///<param name="hwnd">指定句柄</param>
    ///<param name="lpClassName">指向接收窗口类名字符串的缓冲区的指针</param>
    ///<param name="nMaxCount">缓冲区的字节数</param>
    ///<returns></returns>
    [DllImport("user32.dll", EntryPoint ="GetClassName")]
    privatestaticexternint GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);

    constint WM_KEYDOWN =0x0100;//按键按下
    constint WM_KEYUP =0x0101;//按键放开
    constint WM_SETTEXT =0x000C;//发送文本
    constint WM_CLICK =0x00F5;//鼠标点击
    constint WM_SETFOCUS =0x0007;//设置焦点参数

    static IntPtr mainHwnd = IntPtr.Zero;//主窗口句柄
    static IntPtr passHwnd = IntPtr.Zero;//密码框句柄

    delegatebool EnumChildWindowsProc(IntPtr hwnd, uint lParam);
    delegatebool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

    publicstaticvoid AutoLogin(string qq, string passwd)
    {
    mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2010");
    if (mainHwnd == IntPtr.Zero)
    {
    Microsoft.Win32.RegistryKey regKey
    = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Tencent\\PlatForm_Type_List\\3", true);
    string qq2010Path = regKey.GetValue("TypePath").ToString();
    regKey.Close();
    if (!string.IsNullOrEmpty(qq2010Path))
    {
    Process.Start(qq2010Path);
    Thread.Sleep(
    500);
    while (true)
    {
    mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2010");
    if (mainHwnd != IntPtr.Zero)
    break;
    Thread.Sleep(
    100);
    }
    }
    else
    {
    MessageBox.Show(
    "未能找到QQ2010安装目录,请手动打开QQ程序!");
    return;
    }
    }
    SetForegroundWindow(mainHwnd);
    Thread.Sleep(
    500);
    IntPtr userHwnd
    = FindWindowEx(mainHwnd, IntPtr.Zero, "ATL:30A441A8", "");//获取账号框句柄
    //passHwnd = FindWindowEx(mainHwnd, IntPtr.Zero, "Edit", "");//这种方法找不到密码框句柄

    //下面两种方法找密码框句柄
    passHwnd = GetWindow(userHwnd, 2);
    //获取密码框句柄用循环
    //EnumChildWindowsProc myEnumChild = new EnumChildWindowsProc(EumWinChiPro);
    //try
    //{
    // EnumChildWindows(mainHwnd, myEnumChild, 0);
    //}
    //catch (Exception ex)
    //{
    // Console.WriteLine(ex.Message + "\r\n " + ex.Source + "\r\n\r\n " + ex.StackTrace.ToString());
    //}

    //while (passHwnd == IntPtr.Zero)
    //{
    // Thread.Sleep(200);
    //}
    SendMessage(userHwnd, WM_SETTEXT, IntPtr.Zero, qq);//发送qq号码
    SendMessage(passHwnd, WM_SETFOCUS, 0, 0);//设置焦点到密码框,发送tab键有时不能转到密码框
    WindowsAPI.SendDelCode(10);//QQ记住密码所有长度为10,只需发送10个Del就可删除原来记住的密码
    WindowsAPI.SendNoUnicode(passwd);
    Thread.Sleep(
    500);
    //发送回车键
    //PostMessage(mainHwnd, WM_KEYDOWN, 13, 0);
    //PostMessage(mainHwnd, WM_KEYUP, 13, 0);
    SendMessage(mainHwnd, WM_KEYDOWN, 0x0D, 0);
    }

    privatestaticbool EumWinChiPro(IntPtr hWnd, uint lParam)
    {
    StringBuilder s
    =new StringBuilder(50);
    GetClassName(hWnd, s,
    50);
    if (s.ToString() =="Edit")
    {
    passHwnd
    = hWnd;
    returnfalse;
    }
    returntrue;
    }
    }

    (2).qq2010sp2_1.55.1870.0正式版本

    ///<summary>
    /// 适用于qq2010sp2_1.55.1870.0正式版本
    ///</summary>
    class QQ2010AutoLogin2
    {
    ///<summary>
    /// 查找窗口句柄
    ///</summary>
    ///<param name="lpClassName">窗口类名</param>
    ///<param name="lpWindowName">窗口标题</param>
    ///<returns></returns>
    [DllImport("user32.dll")]
    privatestaticextern IntPtr FindWindow(string lpClassName, string lpWindowName);

    ///<summary>
    /// 查找子窗口句柄
    ///</summary>
    ///<param name="hwndParent">要查找子窗口的父窗口句柄</param>
    ///<param name="hwndChildAfter">上一个子窗口句柄</param>
    ///<param name="lpszClass">子窗口类名</param>
    ///<param name="lpszWindow">窗口标题</param>
    ///<returns></returns>
    [DllImport("User32.DLL")]
    privatestaticextern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    ///<summary>
    /// 设置指定窗口为当前活动窗口
    ///</summary>
    ///<param name="hWnd">窗口句柄</param>
    [DllImport("User32.DLL")]
    privatestaticexternbool SetForegroundWindow(IntPtr hWnd);

    ///<summary>
    /// 可将最小化窗口还原
    ///</summary>
    ///<param name="hWnd"></param>
    ///<param name="nCmdShow"></param>
    ///<returns></returns>
    [DllImport("user32.dll")]
    privatestaticexternbool ShowWindow(IntPtr hWnd, int nCmdShow);

    ///<summary>
    /// 向指定窗口发送字符串
    ///</summary>
    [DllImport("User32.dll", EntryPoint ="SendMessage")]
    privatestaticexternint SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

    ///<summary>
    /// 可向指定窗口发送按键
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="SendMessage", SetLastError =true, CharSet = CharSet.Auto)]
    privatestaticexternint SendMessage(IntPtr hwnd, uint wMsg, uint wParam, uint lParam);

    ///<summary>
    /// 发送按键消息用PostMessage比较好,SendMessage有时会不起作用
    ///</summary>
    [DllImport("user32.dll", EntryPoint ="PostMessage", SetLastError =true)]
    privatestaticexternbool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    // 注意,运行时知道如何列集一个矩形
    [DllImport("user32.dll")]
    publicstaticexternint GetWindowRect(int hwnd, ref Rectangle rc);

    //SendMessage参数
    constint WM_KEYDOWN =0x0100;//普通按键按下
    constint WM_KEYUP =0x0101;//普通按键放开
    constint WM_SYSKEYDOWN =0x104;//系统按键按下
    constint WM_SYSKEYUP =0x105;//系统按键按下放开
    constint WM_SYSCHAR =0x0106;//发送单个字符
    constint WM_SETTEXT =0x000C;//发送文本
    constint WM_CLICK =0x00F5;//模拟鼠标左键点击
    constint WM_SETFOCUS =0x0007;//设置焦点

    constint SW_RESTORE =9;//恢复最小化的窗口

    static IntPtr mainHwnd = IntPtr.Zero;//主窗口句柄

    publicstaticvoid AutoLogin(string qq, string passwd)
    {
    mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2010");
    if (mainHwnd != IntPtr.Zero)
    {
    Rectangle rectMain
    =new Rectangle();
    GetWindowRect(mainHwnd.ToInt32(),
    ref rectMain);
    if (rectMain.Height - rectMain.Y !=250)//width:rectMain.Width-rectMain.X
    {
    Microsoft.Win32.RegistryKey regKey
    = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Tencent\\PlatForm_Type_List\\3", true);
    string qq2010Path = regKey.GetValue("TypePath").ToString();
    regKey.Close();
    if (!string.IsNullOrEmpty(qq2010Path))
    {
    Process.Start(qq2010Path);
    Thread.Sleep(
    500);
    while (true)
    {
    mainHwnd
    = FindWindow("TXGuiFoundation", "QQ2010");
    if (mainHwnd != IntPtr.Zero)
    break;
    Thread.Sleep(
    100);
    }
    }
    else
    {
    MessageBox.Show(
    "未能找到QQ2010安装目录,请手动打开QQ程序!");
    return;
    }
    }
    }
    ShowWindow(mainHwnd, SW_RESTORE);
    //将最小化窗口还原
    SetForegroundWindow(mainHwnd);
    Thread.Sleep(
    500);

    //获取账号框句柄
    IntPtr userHwnd = FindWindowEx(mainHwnd, IntPtr.Zero, "ATL:30A551F0", "");
    //SendMessage(passHwnd, WM_SETFOCUS, 0, 0);//设置焦点到密码框,发送tab键不能转到密码框

    Rectangle rect
    =new Rectangle();
    GetWindowRect(userHwnd.ToInt32(),
    ref rect);//获取文本框居中相对屏幕中的位置
    //模拟鼠标左键点击事件,将Tab还原到文本框,WM_SETFOCUS不能还原Tab
    WindowsAPI.SendMouseLeftClick((int)WindowsAPI.MOUSEEVENTF.LEFTDOWN, (int)WindowsAPI.MOUSEEVENTF.LEFTUP, rect.Left +5, rect.Height -10);

    //删除原来qq号码
    SendMessage(userHwnd, WM_SYSKEYDOWN, WindowsAPI.VK_Delete, 0);
    SendMessage(userHwnd, WM_SYSKEYUP, WindowsAPI.VK_Delete,
    0);

    SendMessage(userHwnd, WM_SETTEXT, IntPtr.Zero, qq);
    //发送qq号码
    Thread.Sleep(10);
    //发送tab键,两种方法
    SendMessage(userHwnd, WM_KEYDOWN, WindowsAPI.VK_TAB, 0);//发送tab
    SendMessage(userHwnd, WM_KEYUP, WindowsAPI.VK_TAB, 0);//释放tab
    //WindowsAPI.SendSingleKey(WindowsAPI.VK_TAB);
    Thread.Sleep(10);
    WindowsAPI.SendDelCode(
    10);//删除原来记住的密码
    WindowsAPI.SendNoUnicode(passwd);
    Thread.Sleep(
    500);
    //发送回车键
    //PostMessage(mainHwnd, WM_KEYDOWN, 13, 0);
    //PostMessage(mainHwnd, WM_KEYUP, 13, 0);
    SendMessage(mainHwnd, WM_KEYDOWN, 0x0D, 0);
    }

    }

    界面程序代码参考 http://www.cnblogs.com/slyzly/articles/1940473.html

    程序有不足之处或更好方法希望批评指出。

    更简单的实现方法:http://www.cnblogs.com/szyicol/archive/2010/05/26/1744579.html#1837094

    qq2012以下通用方法已经实现,需要请留言

    转载于:https://www.cnblogs.com/slyzly/articles/1940552.html

    展开全文
  • using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;using System.Threading;using System.Windows....namespace QQ2010AutoLogin{publicclass WindowsAP...
  • 然后QQ客户端后发起的请求就会抢登录,那么用户再点击其它页面时就会认为这个链接已经在别处登录 而失效, 请问如果避免这种情况? PS: 1.我是开发者身份,非用户 2.另外我还发现,QQ客户端内置的浏览器会...
  • 一 通常可能会在做项目的时候遇到此种需求:CAS客户端应用完成用户注册功能后直接跳转至CAS服务器登录并显示自定义的客户端某个页面;而不是用户完成注册后再次登录CAS服务器登录页面进行登录.这就是完成用户注册后...
  • 为了更好的为开发者服务,QQ互联新版SDK(android 1.6和ios 1.5)携QQ sso登录和分享到QQ好友功能于2013年5月15日正式上线,欢迎广大开发者升级体验新一代移动互联能力提供的优质用户体验! 1. QQ账号登录利器...
  • 番薯软件QQ客户端批量挂机,安全挂机出常用,免码登录必备.手头有大量Q的朋友,如果不经常晒号的话,会导致号码回收,用web或3G方式挂机容易出现登录限制。番薯软件推出较安全的挂
  • QQ项目第一天(客户端登录界面)

    千次阅读 2011-10-05 14:11:08
    这是qq项目的 客户端登录界面,呵呵,费了不少力气!!!!!   需要的代码的加qq群:151648295
  • 作者CoderZhuXH,源码XHChatQQ,一行代码调用QQ客户端,发起临时会话. 使用方法 一.请在info.plist文件中 将QQ(mqq字段)添加到白名单 1.设置方法:在info.plist添加LSApplicationQueriesSchemes字段 类型Array 2....
  • C#编写支持多个QQ登录QQ客户端

    千次阅读 2006-10-26 16:56:00
    因为前段时间比较无聊,就顺便研究了一下QQ 2006 Beta3 的底层协议,于是乎就顺手写了一个QQ客户端,现在只实现了登录,KeepAlive,下载在线好友,发送/接收消息.这几个最基本的功能,其他的功能呢打算放到下一版本在做,为...
  • 由于好久没有再登录QQ邮箱了,今天使用MBP的mail客户端登录了下,竟然一直出现无法验证账户名或密码的问题,很是纳闷呀。。。以图为证

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,569
精华内容 627
关键字:

qq客户端登录