在一牛: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;