首页 新闻 会员 周边 捐助

急!急!急!请问win32api参数乱码如何解决!

0
悬赏园豆:20 [已解决问题] 解决于 2015-10-29 17:24

  我想做一个QQ自动登陆,使用的QQ是2009.现在先模拟打开QQ,然后通过api调用回调函数。回调函数为一个委托方法,但是在方法中整个参数乱码,请问如何解决?

  具体流程为,启动QQ,获取当前启动QQ的句柄,通过EnumChildWindows方法回调方法,但是在EnumWindowsProc中,account和pwd乱码。请问如何解决?

 

public delegate bool CallBack(IntPtr hwnd, int lParam, string account, string pwd );

 
 
 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 static extern IntPtr EnumChildWindows(IntPtr hWndParent, CallBack lpEnumFunc, int lParam);
 
/// <summary>
 /// QQ登录
 /// </summary>
 public static void LoginIn(string account = "123456"string pwd = "123456")
 {
     //启动QQ程序
     StartCmd();
 
     IntPtr h;
     string strName = "QQ2009";
     h = FindWindow(null, strName);
     if (h.ToInt32() != 0)
     {
         MoveWindow(h, 0, 0, 350, 300, true);
         CallBack myCallBack = new CallBack(EnumWindowsProc);
         EnumChildWindows(h, myCallBack, 0);
     }
 }
 
 /// <summary>
 ///将鼠标移动到登陆按钮
 /// </summary>
 /// <param name="h"></param>
 /// <param name="lParam"></param>
 /// <returns></returns>
 private static bool EnumWindowsProc(IntPtr h, int lParam, string account, string pwd)
 {
     //改变账号
     SetCursorPos(900, 530);
     SetForegroundWindow(h);
     SendMessage(h, 0x000C, IntPtr.Zero, account.ToString());
 
     //移动鼠标到登陆按钮
     SetCursorPos(1090, 645);
     SetForegroundWindow(h);
     mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
     return false;
 }
瀞默的主页 瀞默 | 初学一级 | 园豆:149
提问于:2015-10-29 10:49
< >
分享
最佳答案
0

Callback只有两个参数

/// Return Type: BOOL->int
///param0: HWND->HWND__*
///param1: LPARAM->LONG_PTR->int
[System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.StdCall)]
public delegate int WNDENUMPROC(System.IntPtr param0, System.IntPtr param1);

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct HWND__ {
    
    /// int
    public int unused;
}

public partial class NativeMethods {
    
    /// Return Type: BOOL->int
    ///hWndParent: HWND->HWND__*
    ///lpEnumFunc: WNDENUMPROC
    ///lParam: LPARAM->LONG_PTR->int
    [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint="EnumChildWindows")]
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
public static extern  bool EnumChildWindows([System.Runtime.InteropServices.InAttribute()] System.IntPtr hWndParent, WNDENUMPROC lpEnumFunc, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.SysInt)] int lParam) ;

}
收获园豆:20
jello chen | 大侠五级 |园豆:7336 | 2015-10-29 12:59

能麻烦你一下嘛,把我的方法改造一下,你的意思还是不太明白。api我是第一次接触。谢谢!

瀞默 | 园豆:149 (初学一级) | 2015-10-29 13:42

现在我同时要传入账号和密码两个参数。麻烦了,谢谢!

瀞默 | 园豆:149 (初学一级) | 2015-10-29 13:45

@瀞默: 

首先,修改如下,注意将lParam是IntPtr类型

public delegate bool EnumWinProc(IntPtr hwnd, IntPtr lParam);
        [DllImport("user32.Dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumChildWindows(IntPtr parentHandle, EnumWinProc callback, IntPtr lParam);

然后,定义结构体UserData

public struct UserData
{
      public string Accout;
      public string Password;      
}

然后,修改调用,将结构数据Marshal成IntPtr,通过lParam传递到回调中

/// <summary>
 /// QQ登录
 /// </summary>
 public static void LoginIn(string account = "123456", string pwd = "123456")
 {
     //启动QQ程序
     StartCmd();
 
     IntPtr h;
     string strName = "QQ2009";
     h = FindWindow(null, strName);
     if (h.ToInt32() != 0)
     {
         MoveWindow(h, 0, 0, 350, 300, true);
         CallBack myCallBack = new CallBack(EnumWindowsProc);
         UserData userData;
         userData.Account = account;
         userData.Password = pwd;
         IntPtr pUserData = Marshal.AllocHGlobal(Marshal.Sizeof(typeof(UserData)));
         Marshal.StructureToPtr(userData,pUserData,false);
         EnumChildWindows(h, myCallBack, pUserData);
         Marshal.FreeHGlobal(pUserData);
     }
 }

再然后,修改回调,通过lParam获取到Marshal过来的结构数据,如下所示:

/// <summary>
 ///将鼠标移动到登陆按钮
 /// </summary>
 /// <param name="h"></param>
 /// <param name="lParam"></param>
 /// <returns></returns>
 private static bool EnumWindowsProc(IntPtr h, IntPtr lParam)
 {
     //此处获取传递的数据
     UserData userData=(UserData)Marshal.PtrToStructure(lParam,typeof(UserData));
     //改变账号
     SetCursorPos(900, 530);
     SetForegroundWindow(h);
     SendMessage(h, 0x000C, IntPtr.Zero, userData.Account.ToString());
 
     //移动鼠标到登陆按钮
     SetCursorPos(1090, 645);
     SetForegroundWindow(h);
     mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
     return false;
 }

注意以上代码不是在IDE中编写的,所以可能会有手误,请多包涵!

jello chen | 园豆:7336 (大侠五级) | 2015-10-29 17:12

@jello chen: 谢谢了,十分感谢!

瀞默 | 园豆:149 (初学一级) | 2015-10-29 17:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册