通过句柄嵌入程序到外部程序中
2013-12-18 09:41
316 查看
protected override HandleRef BuildWindowCore( HandleRef hwndParent) { appProc = new Process (); appProc.StartInfo.WindowStyle = ProcessWindowStyle .Hidden; appProc.StartInfo.FileName = @"D:\greeninst\netterm\netterm.exe" ; appProc.Start(); //等待初始化完成,实现有点土 Thread .Sleep(1000); hwndHost = Win32Native .FindWindow( "NetTermClass" , null ); // 嵌入在HwnHost中的窗口必须要 设置为WS_CHILD风格 uint oldStyle = Win32Native .GetWindowLong(hwndHost, Win32Native .GWL_STYLE);
//&~WS_BORDER去掉边框,这样看起来更像一个内嵌的程序,注意()的作用,改变默认的优先级 Win32Native .SetWindowLong(hwndHost, Win32Native .GWL_STYLE, (oldStyle | Win32Native .WS_CHILD)); //将netterm的父窗口设置为HwndHost Win32Native .SetParent(hwndHost, hwndParent.Handle); return new HandleRef ( this , hwndHost); }
这里启动的是NetTerm这个外部程序。实践证明我这种想法是可行的,但是唯一的问题就是虽然外部Win32程序显示到WPF程序中来了,但是很奇怪的是嵌入的Win32程序再也无法点击了,点击按钮、输入按键都不起作用,程序好像死了一样。经过分析,我认为由于通过 SetParent这个 Win32API
将NetTerm的父窗口设置为了 HwndHost,这样 NetTerm就不再有自己独立的窗口消息循环,而是眼巴巴等着 HwndHost这个爹给他发
消息。可能由于WPF对于消息循环的处理不同于以前的Win32程序,导致所有的鼠标点击、按键
消息都不能被传递给NetTerm这个儿子,这样NetTerm就得不到任何消息,所以就像死了一样。
解决这个问题的思路是截获WPF的窗口消息,然后把它通过 SendMessage
这个Win32API 转发给NetTerm。但是找了半天也没找到WPF的消息处理的地方,请教同事以后得知WPF根本不像传统的Win32程序那样有窗口消息循环,而是自己搞了一套。郁闷了一会儿,突然灵光一现:管它什么WPF不WPF,它本质上还是Win32程序,只不过是一个内部使用了DirectX技术的Win32程序而已,只要是Win32程序一定有办法拿到它的窗口消息循环。啥办法呢?对!就是窗口钩子。使用 SetWindowsHookEx这个Win32API可以截获一个窗口所有的
消息循环,这样只要挑出来发给 HwndHost
的消息,然后把它转发给 NetTerm窗口就ok了。经过改造以后NetTerm终于活过来了!!!
解决了最核心的问题就该处理普通问题了,主要问题及对策如下:
1、隐藏NetTerm的窗口边框,这样看起来就感觉不出来NetTerm是一个外部程序了。思路很简单使用 GetWindowLong得到窗口原来的风格,然后再附加一个 WS_BORDER
风格就ok了。
//设置为WS_CHILD风格 uint oldStyle = Win32Native .GetWindowLong(hwndHost, Win32Native .GWL_STYLE); //&~WS_BORDER去掉边框,这样看起来更像一个内嵌的程序,注意()的作用,改变默认的优先级 Win32Native .SetWindowLong(hwndHost, Win32Native .GWL_STYLE, (oldStyle | Win32Native .WS_CHILD)&~ Win32Native .WS_BORDER);
2、隐藏NetTerm在任务栏上的按钮
只要找到任务栏的句柄,然后首先向它发送TB_BUTTONCOUNT得到它上边按钮的个数,由于NetTerm是刚刚启动的,可以认为最后一个按钮就是NetTerm的按钮,只要向任务栏的句柄发送TB_DELETEBUTTON消息将最后一个按钮删掉就ok了。
private void HideTaskBarButton() { IntPtr vHandle = Win32Native.FindWindow("Shell_TrayWnd", null); vHandle = Win32Native.FindWindowEx(vHandle, IntPtr.Zero, "ReBarWindow32", IntPtr.Zero); vHandle = Win32Native.FindWindowEx(vHandle, IntPtr.Zero, "MSTaskSwWClass", IntPtr.Zero); vHandle = Win32Native.FindWindowEx(vHandle, IntPtr.Zero, "ToolbarWindow32", IntPtr.Zero); //得到任务栏中按钮的数目 int vCount = Win32Native.SendMessage(new HandleRef(this, vHandle), (uint)Win32Native.TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero).ToInt32(); //认为最后一个按钮就是被嵌套程序的按钮,删除它 Win32Native.SendMessage(new HandleRef(this, vHandle), Win32Native.TB_DELETEBUTTON, new IntPtr(vCount - 1), IntPtr.Zero); }
相关文章推荐
- Qt调用外部程序|通过句柄实现程序最小化到任务栏或者恢复到主界面|读取ini文件
- Lua通过COM调用外部程序excel及调用windows api
- 通过程序名称查找窗口句柄
- 外部程序通过COM启动AutoCAD时RPC_E_CALL_REJECTED的问题解决办法
- 通过给程序里嵌入manifest,使得程序运行时弹出UAC窗口
- 将外部程序嵌入到Qt界面中
- 通过给程序里嵌入manifest,使得程序运行时弹出UAC窗口
- 网络扫描技术揭秘读书笔记2--嵌入外部程序
- C#中通过Process启动的外部第三方程序MainWindowHandle句柄为0
- c# 通过Windows服务启动外部程序
- 外部程序通过COM启动AutoCAD时RPC_E_CALL_REJECTED的问题解决办法
- 通过Windows Service启动外部程序
- C# 通过窗口句柄获取程序路径 图标
- 通过jvm api实现从外部对java程序作gc垃圾回收
- 通过给程序里嵌入manifest,使得程序运行时弹出UAC窗口
- c# 通过Windows服务启动外部程序
- c# 获取鼠标处窗口句柄,程序嵌入桌面
- Delphi 获取外部程序句柄与发送消息
- AutoCAD2013 + VS2015,不可以直接在“调试”中直接启动外部程序的方式来调试,只能通过在解决方案中加入acad.exe并将acad.exe为启动项
- Lua通过COM调用外部程序excel及调用windows api