博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF调用Win32程序的方法
阅读量:4031 次
发布时间:2019-05-24

本文共 3133 字,大约阅读时间需要 10 分钟。

    在MSDN中有专门的章节提到了在WPF中嵌入Win32控件的办法,那就是使用 HwndHost ,只要把 Win32控件的句柄传递给 HwndHost 就可以了。MSDN中的例子演示的都是在同一个 内创建的 Win32控件,我一开始认为只要通过FindWindow等Win32API得到外部Win32程序的窗口句柄,然后将窗口句柄交给 HwndHost 就可以了。实现核心代码如下:

 

      protected override HandleRef BuildWindowCore( HandleRef hwndParent)

  {

  appProc = new ();

  appProc.StartInfo.WindowStyle = ProcessWindowStyle .Hidden;

  appProc.StartInfo.FileName = @"D:/greeninst/netterm/netterm.exe" ;

  appProc.Start();

  //等待初始化完成,实现有点土

   .Sleep(1000);

  hwndHost = Win32Native .FindWindow( "NetTermClass" , null );

  // 嵌入在HwnHost中的窗口必须要 设置为WS_CHILD风格

  uint oldStyle = Win32Native .GetWindowLong(hwndHost, Win32Native .GWL_STYLE);

  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);

  //得到任务栏中按钮的数目

   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);

  }

  这是在WinXP下的处理。好像Win2000、Vista的任务栏的结构是不同的,如果需要运行在这些OS下需要做进一步的改进。

  3、 自动登录。在NetTerm启动以后自动登录到服务器,并且自动输入用户名、密码,并且启动指定的程序。NetTerm支持在启动参数中指定要连接的服务 器地址,这样可以解决自动登录到服务器的问题;使用 SendMessage( handle , Win32Native.WM_CHAR, ch , IntPtr.Zero) 向NetTerm窗口发送模拟按键就可以实现自动键入Linux指令的效果。由于Linux指令需要一定的处理的时间,所以每发完一条指令就要Sleep 一会儿以防止键入指令速度过快。

转载地址:http://zoqbi.baihongyu.com/

你可能感兴趣的文章
linux mint下使用外部SMTP(如网易yeah.net)发邮件
查看>>
北京联通华为光猫HG8346R破解改桥接
查看>>
python使用win32*模块模拟人工操作——城通网盘下载器(一)
查看>>
python append 与浅拷贝
查看>>
Matlab与CUDA C的混合编程配置出现的问题及解决方案
查看>>
2017阿里内推笔试题--算法工程师(运筹优化)
查看>>
python自动化工具之pywinauto(零)
查看>>
python一句话之利用文件对话框获取文件路径
查看>>
PaperDownloader——文献命名6起来
查看>>
PaperDownloader 1.5.1——更加人性化的文献下载命名解决方案
查看>>
如何将PaperDownloader下载的文献存放到任意位置
查看>>
C/C++中关于动态生成一维数组和二维数组的学习
查看>>
系统架构:Web应用架构的新趋势---前端和后端分离的一点想法
查看>>
JVM最简生存指南
查看>>
漂亮的代码,糟糕的行为——解决Java运行时的内存问题
查看>>
Java的对象驻留
查看>>
自己动手写GC
查看>>
Java 8新特性终极指南
查看>>
logback高级特性使用(二) 自定义Pattern模板
查看>>
JVM并发机制探讨—内存模型、内存可见性和指令重排序
查看>>