chore(browser): sync current working implementation

Rollback tag: pre-current-browser-sync-20260818
This commit is contained in:
2026-08-18 14:30:23 +08:00
parent 6b78bbbf04
commit d3587a16f1
17 changed files with 133 additions and 437 deletions
+62 -111
View File
@@ -78,17 +78,17 @@ namespace Lskj.Control.BrowserSetting
string arg2 = message.Arguments.GetString(2);
string arg3 = message.Arguments.GetString(3);
string arg4 = message.Arguments.GetString(4);
PostToUiThread(
ERPInfo.Instance.MainControl,
delegate
if (ERPInfo.Instance.MainControl.InvokeRequired)
{
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
{
BsOpenModuleHandler.OpenModule(
arg0,
arg1,
arg2,
arg3,
arg4);
});
BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
}));
}
else
{
BrowserSetting.BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
}
}
else if (message.Name.Equals("OpenOnRightClick"))
{
@@ -96,103 +96,75 @@ namespace Lskj.Control.BrowserSetting
string arg1 = message.Arguments.GetString(1);
string arg2 = message.Arguments.GetString(2);
string arg3 = message.Arguments.GetString(3);
PostToUiThread(
ERPInfo.Instance.MainControl,
delegate
if (ERPInfo.Instance.MainControl.InvokeRequired)
{
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
{
BsOpenModuleHandler.OpenRightModule(
arg0,
arg1,
arg2,
arg3);
});
BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
}));
}
else
{
BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
}
}
else if (message.Name.Equals("CloseWin"))
{
var browserControl = frmWebBrowser;
PostToUiThread(
browserControl,
delegate
if (frmWebBrowser != null && frmWebBrowser.Parent != null && frmWebBrowser.Parent.Parent != null && frmWebBrowser.Parent.Parent is BaseForm baseForm)
{
if (baseForm.InvokeRequired)
{
baseForm.Invoke(new Action(() =>
{
baseForm.DialogResult = DialogResult.OK;
baseForm.Close();
}));
}
else
{
// Parent/Parent is a WinForms control-tree read and must
// not run on CEF's UI thread.
var parent = browserControl.Parent;
var baseForm = parent == null
? null
: parent.Parent as BaseForm;
if (baseForm == null || baseForm.IsDisposed)
return;
baseForm.DialogResult = DialogResult.OK;
baseForm.Close();
});
}
}
}
else if (message.Name.Equals("SelectPro"))
{
string arg0 = message.Arguments.GetString(0);
string arg1 = message.Arguments.GetString(1);
bool isclose = arg1!=null&&!string.IsNullOrWhiteSpace(arg1) && arg1.Equals("1") ? true : false;
var browserControl = frmWebBrowser;
PostToUiThread(
browserControl,
delegate
if (frmWebBrowser != null && frmWebBrowser.Parent != null && frmWebBrowser.Parent.Parent != null && frmWebBrowser.Parent.Parent is BaseForm baseForm)
{
if (baseForm.InvokeRequired)
{
baseForm.Invoke(new Action(() =>
{
BsOpenModuleHandler.AddReturnRow(arg0);
if (isclose)
{
baseForm.DialogResult = DialogResult.OK;
baseForm.Close();
}
}));
}
else
{
var parent = browserControl.Parent;
var baseForm = parent == null
? null
: parent.Parent as BaseForm;
if (baseForm == null || baseForm.IsDisposed)
return;
BsOpenModuleHandler.AddReturnRow(arg0);
if (isclose)
if (isclose)
{
baseForm.DialogResult = DialogResult.OK;
baseForm.Close();
}
});
}
}
}
}
return base.OnProcessMessageReceived(browser, frame, sourceProcess, message);
}
private static void PostToUiThread(
System.Windows.Forms.Control control,
Action action)
{
if (control == null || action == null || control.IsDisposed ||
!control.IsHandleCreated)
return;
Action guardedAction = delegate
{
if (control.IsDisposed)
return;
try
{
action();
}
catch (Exception exception)
{
ReportProcessMessageFailure(exception);
}
};
try
{
// CEF invokes OnProcessMessageReceived on its UI thread. A
// synchronous Control.Invoke can block that thread inside a
// modal dialog while the dialog waits for CEF to create its
// browser. Always queue the operation and return to CEF first.
control.BeginInvoke(guardedAction);
}
catch (Exception exception)
{
ReportProcessMessageFailure(exception);
}
}
private static void ReportProcessMessageFailure(Exception exception)
{
try
@@ -201,10 +173,10 @@ namespace Lskj.Control.BrowserSetting
}
catch
{
// Never propagate logging failures into a native CEF callback.
// Logging must never rethrow across the native CEF callback.
}
Action showError = delegate
Action showError = () =>
{
try
{
@@ -212,14 +184,14 @@ namespace Lskj.Control.BrowserSetting
}
catch
{
// Error reporting must never terminate the browser callback.
}
};
try
{
System.Windows.Forms.Control mainControl = ERPInfo.Instance.MainControl;
if (mainControl == null || mainControl.IsDisposed ||
!mainControl.IsHandleCreated)
if (mainControl == null || mainControl.IsDisposed || !mainControl.IsHandleCreated)
return;
if (mainControl.InvokeRequired)
@@ -229,36 +201,15 @@ namespace Lskj.Control.BrowserSetting
}
catch
{
// The main window may close while the callback is reporting.
// The main window may close while the CEF callback is reporting.
}
}
public void Created(CefBrowser cefBrowser)
{
if (frmWebBrowser != null && OnCreated != null)
if (OnCreated != null)
{
OnCreated(cefBrowser, EventArgs.Empty);
}
}
public bool Closing(CefBrowser browser)
{
var control = frmWebBrowser;
return control != null && control.BrowserClosing(browser);
}
public void Closed(CefBrowser browser)
{
var control = frmWebBrowser;
if (control != null)
{
control.BrowserClosed(browser);
if (control.cefBrowserSettings == null)
{
frmWebBrowser = null;
OnCreated = null;
}
}
}
}
}
@@ -42,7 +42,7 @@ namespace Lskj.Control.BrowserSetting
}
if (BsClient != null && BsClient.frmWebBrowser != null && BsClient.frmWebBrowser.Parent != null && BsClient.frmWebBrowser.Parent.Name.Equals("previewFrm"))
{
BsClient.frmWebBrowser.CloseBrowser();
browser.GetHost().CloseBrowser();
}
else if (BsClient != null && BsClient.frmWebBrowser != null)
{
@@ -196,24 +196,11 @@ namespace Lskj.Control.BrowserSetting
try
{
if (browser == null) return null;
IntPtr browserHandle;
using (var browserHost = browser.GetHost())
{
browserHandle = browserHost.GetWindowHandle();
}
IntPtr browserHandle = browser.GetHost().GetWindowHandle();
if (browserHandle == IntPtr.Zero) return null;
IntPtr parentHandle = GetParent(browserHandle);
System.Windows.Forms.Control control = null;
while (parentHandle != IntPtr.Zero && control == null)
{
// The CEF child now sits inside an application-owned native
// host. Walk through that host to preserve the original
// FrmWebBrowser-based module lookup.
control = System.Windows.Forms.Control.FromHandle(parentHandle);
parentHandle = GetParent(parentHandle);
}
if (control == null) return null;
if (parentHandle == IntPtr.Zero) return null;
System.Windows.Forms.Control control = System.Windows.Forms.Control.FromHandle(parentHandle);
if (control != null && control.Parent != null && control.Parent.Parent != null)
{
@@ -20,20 +20,9 @@ namespace Lskj.Control.BrowserSetting
base.OnAfterCreated(browser);
BsClient.Created(browser);
}
protected override bool DoClose(CefBrowser browser)
{
// CEF sends WM_CLOSE to the parked application-owned host after
// this callback. The host only allows that second close attempt.
return BsClient.Closing(browser);
}
protected override void OnBeforeClose(CefBrowser browser)
{
base.OnBeforeClose(browser);
// Release owner references after CEF completes its async close.
BsClient.Closed(browser);
}
protected override bool OnBeforePopup(
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xilium.CefGlue;
using Lskj.Business;
namespace Lskj.Control.BrowserSetting
{
@@ -47,12 +46,7 @@ namespace Lskj.Control.BrowserSetting
protected override void OnRenderProcessTerminated(CefBrowser browser, CefTerminationStatus status)
{
// Reloading immediately from this callback can create a new
// renderer while the old one is tearing down and cause a native
// libcef crash loop. Record the termination and let the module
// lifecycle decide whether a later reopen is appropriate.
LogUtil.WriteError("CEF 渲染进程已终止,状态=" + status,
new InvalidOperationException("CEF renderer termination status=" + status));
browser.Reload();
}
}
@@ -1,6 +1,5 @@
using Lskj.Business;
using Lskj.Model;
using Lskj.Util;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -55,19 +54,6 @@ namespace Lskj.Control.BrowserSetting2
return contextMenuHandler;
}
protected override bool OnProcessMessageReceived(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
{
try
{
return OnProcessMessageReceivedCore(browser, frame, sourceProcess, message);
}
catch (Exception exception)
{
ReportProcessMessageFailure(exception);
return true;
}
}
private bool OnProcessMessageReceivedCore(CefBrowser browser, CefFrame frame, CefProcessId sourceProcess, CefProcessMessage message)
{
if (message.Name.Equals("OpenModule"))
{
@@ -76,17 +62,17 @@ namespace Lskj.Control.BrowserSetting2
string arg2 = message.Arguments.GetString(2);
string arg3 = message.Arguments.GetString(3);
string arg4 = message.Arguments.GetString(4);
PostToUiThread(
ERPInfo.Instance.MainControl,
delegate
if (ERPInfo.Instance.MainControl.InvokeRequired)
{
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
{
BrowserSetting.BsOpenModuleHandler.OpenModule(
arg0,
arg1,
arg2,
arg3,
arg4);
});
BrowserSetting.BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
}));
}
else
{
BrowserSetting.BsOpenModuleHandler.OpenModule(arg0, arg1, arg2, arg3, arg4);
}
}
else if (message.Name.Equals("OpenOnRightClick"))
{
@@ -94,140 +80,43 @@ namespace Lskj.Control.BrowserSetting2
string arg1 = message.Arguments.GetString(1);
string arg2 = message.Arguments.GetString(2);
string arg3 = message.Arguments.GetString(3);
PostToUiThread(
ERPInfo.Instance.MainControl,
delegate
if (ERPInfo.Instance.MainControl.InvokeRequired)
{
ERPInfo.Instance.MainControl.Invoke(new Action(() =>
{
BrowserSetting.BsOpenModuleHandler.OpenRightModule(
arg0,
arg1,
arg2,
arg3);
});
BrowserSetting.BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
}));
}
else
{
BrowserSetting.BsOpenModuleHandler.OpenRightModule(arg0, arg1, arg2, arg3);
}
}
else if (message.Name.Equals("CloseWin"))
{
var browserControl = frmWebBrowser;
PostToUiThread(
browserControl,
delegate
if (frmWebBrowser != null && frmWebBrowser.Parent != null && frmWebBrowser.Parent.Parent != null && frmWebBrowser.Parent.Parent is BaseForm baseForm)
{
if (baseForm.InvokeRequired)
{
baseForm.Invoke(new Action(() =>
{
baseForm.Close();
}));
}
else
{
// Resolve the owning form only after returning to the
// WinForms UI thread.
var parent = browserControl.Parent;
var baseForm = parent == null
? null
: parent.Parent as BaseForm;
if (baseForm == null || baseForm.IsDisposed)
return;
baseForm.Close();
});
}
}
}
return base.OnProcessMessageReceived(browser, frame, sourceProcess, message);
}
private static void PostToUiThread(
System.Windows.Forms.Control control,
Action action)
{
if (control == null || action == null || control.IsDisposed ||
!control.IsHandleCreated)
return;
Action guardedAction = delegate
{
if (control.IsDisposed)
return;
try
{
action();
}
catch (Exception exception)
{
ReportProcessMessageFailure(exception);
}
};
try
{
// Never keep CEF's UI thread blocked while WinForms opens a
// modal module that may create another CEF browser.
control.BeginInvoke(guardedAction);
}
catch (Exception exception)
{
ReportProcessMessageFailure(exception);
}
}
private static void ReportProcessMessageFailure(Exception exception)
{
try
{
LogHelper.Instance.WriteError(exception);
}
catch
{
// Never propagate logging failures into a native CEF callback.
}
Action showError = delegate
{
try
{
MessageUtil.Show(exception);
}
catch
{
}
};
try
{
System.Windows.Forms.Control mainControl = ERPInfo.Instance.MainControl;
if (mainControl == null || mainControl.IsDisposed ||
!mainControl.IsHandleCreated)
return;
if (mainControl.InvokeRequired)
mainControl.BeginInvoke(showError);
else
showError();
}
catch
{
// The main window may close while the callback is reporting.
}
}
public void Created(CefBrowser cefBrowser)
{
if (frmWebBrowser != null && OnCreated != null)
if (OnCreated != null)
{
OnCreated(cefBrowser, EventArgs.Empty);
}
}
public bool Closing(CefBrowser browser)
{
var control = frmWebBrowser;
return control != null && control.BrowserClosing(browser);
}
public void Closed(CefBrowser browser)
{
var control = frmWebBrowser;
if (control != null)
{
control.BrowserClosed(browser);
if (control.cefBrowserSettings == null)
{
frmWebBrowser = null;
OnCreated = null;
}
}
}
}
}
@@ -20,20 +20,9 @@ namespace Lskj.Control.BrowserSetting2
base.OnAfterCreated(browser);
BsClient.Created(browser);
}
protected override bool DoClose(CefBrowser browser)
{
// CEF sends WM_CLOSE to the parked application-owned host after
// this callback. The host only allows that second close attempt.
return BsClient.Closing(browser);
}
protected override void OnBeforeClose(CefBrowser browser)
{
base.OnBeforeClose(browser);
// Release owner references after CEF completes its async close.
BsClient.Closed(browser);
}
protected override bool OnBeforePopup(
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xilium.CefGlue;
using Lskj.Business;
namespace Lskj.Control.BrowserSetting2
{
@@ -47,9 +46,7 @@ namespace Lskj.Control.BrowserSetting2
protected override void OnRenderProcessTerminated(CefBrowser browser, CefTerminationStatus status)
{
// Do not start a new renderer during native teardown.
LogUtil.WriteError("CEF 渲染进程已终止,状态=" + status,
new InvalidOperationException("CEF renderer termination status=" + status));
browser.Reload();
}
}
-2
View File
@@ -14,8 +14,6 @@ namespace Lskj.Control
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing)
CloseBrowserForDispose();
if (disposing && (components != null))
{
components.Dispose();
-39
View File
@@ -109,45 +109,6 @@ namespace Lskj.Control
cefBrowserSettings.GetMainFrame().LoadUrl(webResponse.ResponseUri.AbsoluteUri);
}
}
internal bool BrowserClosing(CefBrowser browser)
{
return false;
}
internal void BrowserClosed(CefBrowser browser)
{
var currentBrowser = cefBrowserSettings;
if (currentBrowser == null || browser == null)
return;
bool sameBrowser = ReferenceEquals(currentBrowser, browser);
if (!sameBrowser)
{
try
{
sameBrowser = currentBrowser.IsSame(browser);
}
catch (Exception)
{
}
}
if (sameBrowser)
Interlocked.CompareExchange(ref cefBrowserSettings, null, currentBrowser);
}
internal void CloseBrowser()
{
var browser = cefBrowserSettings;
if (browser != null)
browser.GetHost().CloseBrowser();
}
private void CloseBrowserForDispose()
{
}
public static string ToEnUrl(string url)
{
string[] urlParams = url.Split('?');
-2
View File
@@ -14,8 +14,6 @@ namespace Lskj.Control
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing)
CloseBrowserForDispose();
if (disposing && (components != null))
{
components.Dispose();
-39
View File
@@ -126,45 +126,6 @@ namespace Lskj.Control
cefBrowserSettings.GetMainFrame().LoadUrl(webResponse.ResponseUri.AbsoluteUri);
}
}
internal bool BrowserClosing(CefBrowser browser)
{
return false;
}
internal void BrowserClosed(CefBrowser browser)
{
var currentBrowser = cefBrowserSettings;
if (currentBrowser == null || browser == null)
return;
bool sameBrowser = ReferenceEquals(currentBrowser, browser);
if (!sameBrowser)
{
try
{
sameBrowser = currentBrowser.IsSame(browser);
}
catch (Exception)
{
}
}
if (sameBrowser)
Interlocked.CompareExchange(ref cefBrowserSettings, null, currentBrowser);
}
internal void CloseBrowser()
{
var browser = cefBrowserSettings;
if (browser != null)
browser.GetHost().CloseBrowser();
}
private void CloseBrowserForDispose()
{
}
public static string ToEnUrl(string url)
{
string[] urlParams = url.Split('?');
+1 -24
View File
@@ -33,30 +33,7 @@ namespace Lskj.PubBrower
this.SubForm = main;
this.SubForm.Text = moduleModel.FormText;
main.PubBrowerModel = moduleModel;
// CEF must be created after the caller has established the final
// WinForms owner/parent hierarchy and the form HWND exists.
if (moduleModel.downLoadFlag == 1)
{
main.OnLoad();
}
else
{
EventHandler shown = null;
shown = delegate
{
main.Shown -= shown;
try
{
main.OnLoad();
}
catch (Exception ex)
{
LogUtil.WriteError("Lskj.PubBrower.dll--初始化错误-->" + obj.ToString(), ex);
}
};
main.Shown += shown;
}
main.OnLoad();
}
catch (Exception ex)
{
+1 -1
View File
@@ -100,8 +100,8 @@ namespace Lskj.PubBrower
previewFrm previewFrm = new previewFrm();
previewFrm.moduleWebView.PubBrowerModel = this.PubBrowerModel;
previewFrm.Dock = DockStyle.Fill;
this.Controls.Add(previewFrm);
previewFrm.OnLoad(url, RightKeyFlag);
this.Controls.Add(previewFrm);
}
}
catch (Exception ex)
+14
View File
@@ -16,6 +16,7 @@ namespace Lskj.PubBrower
public previewFrm()
{
InitializeComponent();
this.SizeChanged += OnSizeChanged;
}
/// <summary>
/// <para>说明:窗口加载</para>
@@ -47,5 +48,18 @@ namespace Lskj.PubBrower
MessageUtil.Show(Message, ex.Message);
}
}
/// <summary>
/// 窗体大小改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSizeChanged(object sender, EventArgs e)
{
if (this.moduleWebView.cefBrowserSettings != null)
{
var handle = this.moduleWebView.cefBrowserSettings.GetHost().GetWindowHandle();
this.moduleWebView.ResizeWindow(handle, this.Width, this.Height);
}
}
}
}
+1 -24
View File
@@ -33,30 +33,7 @@ namespace Lskj.PubBrower2
this.SubForm = main;
this.SubForm.Text = moduleModel.FormText;
main.PubBrowerModel = moduleModel;
// CEF must be created after the caller has established the final
// WinForms owner/parent hierarchy and the form HWND exists.
if (moduleModel.downLoadFlag == 1)
{
main.OnLoad();
}
else
{
EventHandler shown = null;
shown = delegate
{
main.Shown -= shown;
try
{
main.OnLoad();
}
catch (Exception ex)
{
LogUtil.WriteError("Lskj.PubBrower2.dll--初始化错误-->" + obj.ToString(), ex);
}
};
main.Shown += shown;
}
main.OnLoad();
}
catch (Exception ex)
{
+1 -1
View File
@@ -95,8 +95,8 @@ namespace Lskj.PubBrower2
previewFrm previewFrm = new previewFrm();
previewFrm.moduleWebView.PubBrowerModel = this.PubBrowerModel;
previewFrm.Dock = DockStyle.Fill;
this.Controls.Add(previewFrm);
previewFrm.OnLoad(url, RightKeyFlag);
this.Controls.Add(previewFrm);
}
}
+14
View File
@@ -16,6 +16,7 @@ namespace Lskj.PubBrower2
public previewFrm()
{
InitializeComponent();
this.SizeChanged += OnSizeChanged;
}
/// <summary>
/// <para>说明:窗口加载</para>
@@ -48,5 +49,18 @@ namespace Lskj.PubBrower2
}
}
/// <summary>
/// 窗体大小改变时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSizeChanged(object sender, EventArgs e)
{
if (this.moduleWebView.cefBrowserSettings != null)
{
var handle = this.moduleWebView.cefBrowserSettings.GetHost().GetWindowHandle();
this.moduleWebView.ResizeWindow(handle, this.Width, this.Height);
}
}
}
}