调用API控制另一程序中按钮问题总结(c#跋涉日记)

调用API控制另一程序中按钮问题总结(c#跋涉日记):

在一牛:hbxtlhx(平民百姓)  的帮助和指点以及遍查资料后,总算基本解决了这次遇到的问题。

问题需求:在程序A中调用程序B,并且在适当的时机按B上的一个按钮(tabcontrol->groupbox->button),不得改变B程序的代码。

解决流程:首先上网查资料,发现要使用API函数

using

[DllImport("user32.dll")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

第一个问题,网上代码中给出用SPY查到的button的类名WindowsForms10.BUTTON.app3,如下

IntPtr hwnd_button = FindWindowEx(ActiveWindowHandle, new IntPtr(0), "WindowsForms10.BUTTON.app3", "button4");

这个不正确,到MSDN发帖询问,被指出类名错误,改成null,OK.

(http://community.csdn.net/Expert/topic/5376/5376610.xml?temp=.4895746)

在两个程序中直接放在form里的button间已经可以实现控制与被控制。

但这并不是结束,程序B中的按钮是放在页下的groupbox里的,测试发现不能成功,原因是FindWindowEx找不到button的句柄。

按我的想法吧,从form搜索到tabcontrol句柄,从tabcontrol搜索tabpage,从tabpage搜索groupbox,从groupbox搜索button.多么明晰的思路哦~可惜就是不行,555555

跟代码发现第1个tabcontrol都找不到,因为tabcontrol是没有text的。这下恍然大悟,原来FindWindowEx里要求提供的是text不是name啊。

....测试的时候用的button他的text和name是一样的O~~~~~。晕死,这搞的,太不专业了。

于是又查资料,提问,这次需要用到的是

[DllImport("user32.dll", ExactSpelling = true)]
private static extern bool EnumChildWindows(HandleRef hwndParent, EnumChildrenCallback lpEnumFunc, HandleRef lParam);

(http://community.csdn.net/Expert/topic/5376/5376827.xml?temp=.6059687)

当然,直接用这个是不会成功的。幸好本菜鸟在baidu中搜索到hbxtlhx的另一帖,原来EnumChildrenCallback 是他自定义的一个delegate:

private

把这句加上,这个API函数能用了。

{这里我一直没搞清楚,为什么CALLBACK这个东西自己用不起。网上的代码中都是直接用的,高手指点。顺便说句废话,还是VB这里简单啊,一个addressof就OK了,delegate本菜不熟- -!}

这儿还有个小麻烦,HandleRef 不好用,被偶直接改成了IntPtr不。汗,也不知道有没有影响,不过结果是正确的,就先不管他。

这个函数的作用就是遍历,OK,如此一来,程序B里的button可以找到了。

走到这里,需求已经满足了。但是还有个疑问未能解决,如果在程序A里把button放到tabcontrol里,一切又还原了,这个问题还是留待有缘人吧...

 ----------------------------------------------------------------------

代码如下:

using

using System.Runtime.InteropServices;

Process p;

private void buttonShowForm_Click(object sender, EventArgs e)

{

p = Process.Start(textBoxNewFormLocation.Text);

}

private void buttonPushButton_Click(object sender, EventArgs e)

{

IntPtr ActiveWindowHandle = p.MainWindowHandle;

EnumChildWindows(ActiveWindowHandle, new EnumChildrenCallback(EnumChildWindowsCallback), new IntPtr(0));

const int BM_CLICK = 0x00F5;

Message msg = Message.Create(hwnd_button, BM_CLICK, new IntPtr(0), new IntPtr(0));

PostMessage(msg.HWnd, msg.Msg, msg.WParam, msg.LParam);

}

[DllImport("user32.dll")]

public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

[DllImport("user32.dll", CharSet = CharSet.Auto)]

public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); 

[DllImport("user32.dll", ExactSpelling = true)]  

private static extern bool EnumChildWindows(IntPtr hwndParent, EnumChildrenCallback lpEnumFunc, IntPtr lParam);

private delegate bool EnumChildrenCallback(IntPtr hwnd, IntPtr lParam);

IntPtr hwnd_button;

private bool EnumChildWindowsCallback(IntPtr handle, IntPtr lparam)

{

IntPtr tmpHandle = FindWindowEx(handle, new IntPtr(0), null, "&Advanced GeoCode");

if (tmpHandle.ToInt32() != 0)

{

hwnd_button = tmpHandle;

}

return true;

}

 

 

System.Diagnostics;System.Diagnostics;

 

你可能感兴趣的:(调用API控制另一程序中按钮问题总结(c#跋涉日记))