wpf中嵌入另一个子进程exe像本地的一个页面那样

  1 //新的一个子进程浏览器
  2 private void OpenNewWebBrowser(string webBrowserName, string url)
  3 {
  4 IntPtr targetPtr = this.CreateWebProcess();
  5 
  6 IntPtr pagePtr = this.GetOrAddNewPage(webBrowserName, url);
  7 
  8 lock (_lockObj)
  9 {
 10 _webBrowserPtr.Add(webBrowserName, targetPtr);
 11 }
 12 
 13 this.SetWebBrowserLoc(webBrowserName, pagePtr);
 14 
 15 this.SendParam(webBrowserName, url);
 16 }
 17 
 18 
 19 //创建一个新的webbrowser进程
 20 private IntPtr CreateWebProcess()
 21 {
 22 ProcessStartInfo psi = new ProcessStartInfo(_webBrowserStartPath);
 23 psi.WindowStyle = ProcessWindowStyle.Hidden;
 24 var process = Process.Start(psi);
 25 IntPtr targetPtr = IntPtr.Zero;
 26 while (targetPtr == IntPtr.Zero) //循环目标窗口启动完成
 27 {
 28 targetPtr = process.MainWindowHandle;
 29 if (targetPtr != IntPtr.Zero)
 30 {
 31 break;
 32 }
 33 Thread.Sleep(10);
 34 }
 35 return targetPtr;
 36 }
 37 
 38 private IntPtr GetOrAddNewPage(string webBrowserName, string url)
 39         {
 40            // if (!_urlAndPanelPtr.ContainsKey(url))
 41             {
 42                 System.Windows.Forms.Panel p = new System.Windows.Forms.Panel();
 43                 WindowsFormsHost host = new WindowsFormsHost();
 44                 host.Tag = webBrowserName;
 45                 host.Background = Brushes.Transparent;
 46                 host.Child = p;
 47 
 48                 host.Visibility = System.Windows.Visibility.Visible;
 49                 _webContainer.Children.Add(host);
 50 
 51               //  lock (_lockObj)
 52                //     _urlAndPanelPtr.Add(url, p.Handle);
 53                 return p.Handle;// 允许一个地址打开多个
 54             }
 55            // return _urlAndPanelPtr[url];
 56         }
 57 
 58  //设置浏览器位置
 59         private void SetWebBrowserLoc(string webBrowserName, IntPtr pagePtr)
 60         {
 61             if (!_webBrowserPtr.ContainsKey(webBrowserName))
 62                 return;
 63 
 64             IntPtr webBrowserPtr = _webBrowserPtr[webBrowserName];
 65 
 66             double h = _webContainer.ActualHeight;
 67 
 68             double w = _webContainer.ActualWidth;
 69 
 70             IntPtr preParentHandle=  Win32Helper.SetParent(webBrowserPtr, pagePtr);
 71 
 72             //如果设置父窗体失败,则重试5次
 73             int tryNum = 5;
 74             while(preParentHandle==IntPtr.Zero)
 75             {
 76                 Thread.Sleep(10);
 77 
 78                 preParentHandle = Win32Helper.SetParent(webBrowserPtr, pagePtr);
 79 
 80                 if (tryNum <= 0) break;
 81 
 82                 tryNum--;
 83             }
 84 
 85             bool moveResult= Win32Helper.MoveWindow(webBrowserPtr, 0, 0, (int)w, (int)h, true);
 86 
 87             //如果窗体位置移动失败,则尝试5次
 88             tryNum = 5;
 89             while(!moveResult)
 90             {
 91                 Thread.Sleep(10);
 92                 moveResult = Win32Helper.MoveWindow(webBrowserPtr, 0, 0, (int)w, (int)h, true);
 93                 if (tryNum <= 0) break;
 94 
 95                 tryNum--;
 96             }
 97         }
 98 
 99 
100 
101 
102 
103 
104 
105  public class WebEmbedHelper: IWebEmbedHelper
106     {
107         string _isNeedReflesh = "0";//是否需要刷新url页面
108         readonly Grid _webContainer = null;
109         /// <summary>
110         /// webbrowser容器句柄
111         /// </summary>
112         readonly IntPtr _parentIntPrt;
113         static Dictionary<string, IntPtr> _urlAndPanelPtr = new Dictionary<string, IntPtr>();//url- panel句柄
114         static Dictionary<string, IntPtr> _webBrowserPtr = new Dictionary<string, IntPtr>();//名称 - webbrowser窗体句柄
115         static Dictionary<string, IntPtr> _urlAndBroserPrt = new Dictionary<string, IntPtr>();//url -webbrowser窗体句柄
116         //url - 回调函数
117         static Dictionary<string, Action<string, string>> _msgCallBackDic = new Dictionary<string, Action<string, string>>();
118         readonly string _webBrowserStartPath;
119 
120          string _currentOpenUrl;//当前打开的url页面
121          IntPtr _webProcessPtr;//当前的WebBrowser进程句柄
122          bool _isChrome = false;
123         public  IntPtr WebProcessPtr
124          {
125             get
126              {
127                  return _webProcessPtr;
128              }
129             set
130              {
131                  _webProcessPtr = value;
132              }
133          }
134         public Action<int, object> GetWinAction { get; set; }//获取主客户端进程消息的action
135 
136         static object _lockObj = new object();
137 
138         /// <summary>
139         /// WebBrowser构造函数
140         /// </summary>
141         /// <param name="parentIntPrt">WebBrowser容器父窗体句柄</param>
142         /// <param name="grid">用于装载WebBrowser的容器</param>
143         /// <param name="webBrowserStartPath">WebBrowser启动完整路径</param>
144         public WebEmbedHelper(IntPtr parentIntPrt, Grid grid, string webBrowserStartPath)
145         {
146             _parentIntPrt = parentIntPrt;
147             _webContainer = grid;
148             _webBrowserStartPath = webBrowserStartPath;
149 
150             this.GetWinAction = ReceiveWinMsg;
151 
152             _webContainer.SizeChanged += webContainer_SizeChanged;
153         }
154 
155         //窗体大小变更,对应的页面也应该自适应
156         private void webContainer_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
157         {
158             double w = _webContainer.ActualWidth;
159             double h = _webContainer.ActualHeight;
160             foreach (var itm in _webBrowserPtr)
161             {
162                 Win32Helper.MoveWindow(itm.Value, 0, 0, (int)w, (int)h, true);
163             }
164         }
165 
166         #region//打开web相关的私有方法
167         private IntPtr GetOrAddNewPage(string webBrowserName, string url)
168         {
169            // if (!_urlAndPanelPtr.ContainsKey(url))
170             {
171                 System.Windows.Forms.Panel p = new System.Windows.Forms.Panel();
172                 WindowsFormsHost host = new WindowsFormsHost();
173                 host.Tag = webBrowserName;
174                 host.Background = Brushes.Transparent;
175                 host.Child = p;
176 
177                 host.Visibility = System.Windows.Visibility.Visible;
178                 _webContainer.Children.Add(host);
179 
180               //  lock (_lockObj)
181                //     _urlAndPanelPtr.Add(url, p.Handle);
182                 return p.Handle;// 允许一个地址打开多个
183             }
184            // return _urlAndPanelPtr[url];
185         }
186 
187         private void FindAndOpenWebBrowser(string webBrowserName, string url)
188         {
189             if (!_webBrowserPtr.ContainsKey(webBrowserName))
190             {
191                 this.OpenNewWebBrowser(webBrowserName, url);
192             }
193             else
194             {
195                 OpenExistWebBrowser(webBrowserName, url);
196             }
197         }
198 
199         //打开新的浏览器
200         private void OpenNewWebBrowser(string webBrowserName, string url)
201         {
202             IntPtr targetPtr = this.CreateWebProcess();
203          
204             IntPtr pagePtr = this.GetOrAddNewPage(webBrowserName, url);
205 
206             lock (_lockObj)
207             {
208                 _webBrowserPtr.Add(webBrowserName, targetPtr);
209             }
210 
211             this.SetWebBrowserLoc(webBrowserName, pagePtr);
212 
213             this.SendParam(webBrowserName, url);
214         }
215         //打开已存在的页面
216         private void OpenExistWebBrowser(string webBrowserName, string url)
217         {
218             //显示隐藏窗体
219             foreach (var itm in _webContainer.Children)
220             {
221                 WindowsFormsHost wfh = itm as WindowsFormsHost;
222                 if (wfh == null) continue;
223                 if (wfh.Tag.ToString() == webBrowserName)
224                     wfh.Visibility = Visibility.Visible;
225                 else
226                     wfh.Visibility = Visibility.Collapsed;
227             }
228 
229             IntPtr webBrowserPtr = _webBrowserPtr[webBrowserName];
230 
231             double h = _webContainer.ActualHeight - 10;
232 
233             double w = _webContainer.ActualWidth - 10;
234 
235             Win32Helper.MoveWindow(webBrowserPtr, 0, 0, (int)w, (int)h, true);
236 
237             this.SendParam(webBrowserName, url);
238         }
239         //设置浏览器位置
240         private void SetWebBrowserLoc(string webBrowserName, IntPtr pagePtr)
241         {
242             if (!_webBrowserPtr.ContainsKey(webBrowserName))
243                 return;
244 
245             IntPtr webBrowserPtr = _webBrowserPtr[webBrowserName];
246 
247             double h = _webContainer.ActualHeight;
248 
249             double w = _webContainer.ActualWidth;
250 
251             IntPtr preParentHandle=  Win32Helper.SetParent(webBrowserPtr, pagePtr);
252 
253             //如果设置父窗体失败,则重试5次
254             int tryNum = 5;
255             while(preParentHandle==IntPtr.Zero)
256             {
257                 Thread.Sleep(10);
258 
259                 preParentHandle = Win32Helper.SetParent(webBrowserPtr, pagePtr);
260 
261                 if (tryNum <= 0) break;
262 
263                 tryNum--;
264             }
265 
266             bool moveResult= Win32Helper.MoveWindow(webBrowserPtr, 0, 0, (int)w, (int)h, true);
267 
268             //如果窗体位置移动失败,则尝试5次
269             tryNum = 5;
270             while(!moveResult)
271             {
272                 Thread.Sleep(10);
273                 moveResult = Win32Helper.MoveWindow(webBrowserPtr, 0, 0, (int)w, (int)h, true);
274                 if (tryNum <= 0) break;
275 
276                 tryNum--;
277             }
278         }
279         //向浏览器发送数据
280         private void SendParam(string webBrowserName, string url)
281         {
282             if (!_webBrowserPtr.ContainsKey(webBrowserName))
283                 return;
284 
285             _webProcessPtr = _webBrowserPtr[webBrowserName];
286 
287             UrlModel um = new UrlModel() { Url = url, isChrome = _isChrome };
288 
289             if (this._isNeedReflesh == "1")
290                 um.IsNeedRefresh = true;
291 
292             //发送message
293             this.SendMessage(um);
294         }
295 
296 
297         public void SendLoadedParam(string pMsgId, string pUrl)
298         {
299 
300             UrlModel um = new UrlModel() { MsgId = pMsgId, Url = pUrl };
301             //发送message
302             this.SendMessage(um);
303         }
304 
305         #endregion
306 
307         //创建一个新的webbrowser进程
308         private IntPtr CreateWebProcess()
309         {
310             ProcessStartInfo psi = new ProcessStartInfo(_webBrowserStartPath);
311             psi.WindowStyle = ProcessWindowStyle.Hidden;
312             var process = Process.Start(psi);
313             IntPtr targetPtr = IntPtr.Zero;
314             while (targetPtr == IntPtr.Zero) //循环目标窗口启动完成
315             {
316                 targetPtr = process.MainWindowHandle;
317                 if (targetPtr != IntPtr.Zero)
318                 {
319                     break;
320                 }
321                 Thread.Sleep(10);
322             }
323             return targetPtr;
324         }
325         /// <summary>
326         /// 接收web页面JS调用发送的数据
327         /// </summary>
328         private void ReceiveWinMsg(int index,object msg)
329         {
330             if (msg == null) return;
331             string data = msg.ToString();
332 
333             if (!data.Contains("MsgId")) return;
334 
335             ////js->web->web进程-->客户端主进程
336             JsInvokeClientModel jm = JsonConvert.DeserializeObject<JsInvokeClientModel>(data);
337             if (jm != null && _msgCallBackDic.ContainsKey(jm.Url))
338             {
339                 //将web页面js调用的参数回调到具体订阅的业务模块中
340                 _msgCallBackDic[jm.Url](jm.Cmd, jm.Params);
341             }
342 
343             //客户端主进程->web进程->js
344             ClientInvokeJsModel jsResp = JsonConvert.DeserializeObject<ClientInvokeJsModel>(data);
345             if (jsResp != null && _jsCallBackData.ContainsKey(jsResp.MsgId))
346             {
347                 jsResp.IsCompleted = true;
348                 _jsCallBackData[jsResp.MsgId] = jsResp;
349             }
350         }
351         /// <summary>
352         /// 发送message
353         /// </summary>
354         /// <param name="message"></param>
355         private void SendMessage(MessageBase message)
356         {
357             ////将message序列化为json传输
358             string json = JsonConvert.SerializeObject(message);
359             byte[] sarr = System.Text.Encoding.Default.GetBytes(json);
360             int len = sarr.Length;
361             CopyDataStruct cds = new CopyDataStruct
362             {
363                 DwData = (IntPtr)100,
364                 LpData = json,
365                 CbData = len + 1
366             };
367           var value=   Win32Helper.SendMessage(this._webProcessPtr, WmConst.WM_COPYDATA, this._parentIntPrt, ref cds);
368         }
369 
370        
371 
372         #region//Interface实现
373         public void Open(string url, string webBrowserName = null, bool isNeedReflesh = false, Action<string, string> callBack = null, bool  pIsChrome=false)
374         {
375             _currentOpenUrl = url;
376             _isChrome = pIsChrome;
377             _isNeedReflesh = isNeedReflesh ? "1" : "0";
378 
379             if (string.IsNullOrEmpty(webBrowserName))
380                 webBrowserName = "defaultName";
381 
382             //IE浏览器打开方式:查找webBrowser进程窗体句柄
383             this.FindAndOpenWebBrowser(webBrowserName, url);
384             //谷歌的打开方式
385 
386             //绑定委托
387             if (callBack != null)
388             {
389                 if (!_msgCallBackDic.ContainsKey(url))
390                     _msgCallBackDic.Add(url, callBack);
391                 else
392                     _msgCallBackDic[url] = callBack;
393             }
394 
395             // 移除允许 一个url地址 多个窗体打开
396             //if (!_urlAndBroserPrt.ContainsKey(url) && _webBrowserPtr.ContainsKey(webBrowserName))
397             //{
398             //    _urlAndBroserPrt.Add(url, _webBrowserPtr[webBrowserName]);
399             //}
400         }
401 
402         public void Close(string webBrowserName, string url = null)
403         {
404             //特殊处置,为了兼容模块嵌入页面同时“设置”项也嵌入页面问题,先查询key的前6位
405             if (webBrowserName.Length > 6)
406                 webBrowserName = webBrowserName.Substring(0, 6);
407 
408             List<string> delKeys = new List<string>();
409             foreach(var itm in _webBrowserPtr)
410             {
411                 if(itm.Key.Contains(webBrowserName))
412                 {
413                     delKeys.Add(itm.Key);
414                 }
415             }
416 
417             foreach(var key in delKeys)
418             {
419                 if (_webBrowserPtr.ContainsKey(key))
420                 {
421                     IntPtr ptr = _webBrowserPtr[key];
422                     //发送关闭命令
423                     Win32Helper.SendMessage(ptr, WmConst.C_WM_CLOSE, 0, 0);
424                     _webBrowserPtr.Remove(key);
425                 }
426             }
427             
428             if (!string.IsNullOrEmpty(url))
429             {
430                 //_urlAndPanelPtr.Remove(url);
431                 _msgCallBackDic.Remove(url);
432             }
433         }
434 
435         static Dictionary<string, ClientInvokeJsModel> _jsCallBackData = new Dictionary<string, ClientInvokeJsModel>();
436         //public async Task<object> InvokeScript(string scriptName)
437         //{
438         //   return await this.InvokeScript(scriptName, null);
439         //}
440 
441         //public async Task<object> InvokeScript(string scriptName, params object[] args)
442         //{
443         //    ClientInvokeJsModel js = new ClientInvokeJsModel() { Url = _currentOpenUrl, ScriptName = scriptName, ReqParamList = args };
444 
445         //    js.MsgId = Guid.NewGuid().ToString();
446 
447         //    if (!_jsCallBackData.ContainsKey(js.MsgId))
448         //    {
449         //        _jsCallBackData.Add(js.MsgId, js);
450         //    }
451         //    this.SendMessage(js);
452         //    object result = null;
453         //    await Task<object>.Run(() =>
454         //    {
455         //        while (true)
456         //        {
457         //            if (_jsCallBackData[js.MsgId].IsCompleted)
458         //            {
459         //                result = _jsCallBackData[js.MsgId];
460         //                _jsCallBackData.Remove(js.MsgId); break;
461         //            }
462         //        }
463         //    });
464 
465         //    return result;
466         //}
467 
468 
469         #endregion
470     }
原文地址:https://www.cnblogs.com/bkyrslf/p/13301118.html