自定义对话框
本节内容可以参考示例文件"CaseStudy\WebViewer\自定义对话框.Table"。
WebViewer提供了ScriptDialogOpening事件,让我们可以接管网页中的JS对话框(alert、confirm、prompt),用Foxtable自己的对话框取而代之。
由WebViewer允许前端JS直接调用Foxtable的全部功能,所以本节存在的意义仅在于:不修改原有的网页代码就能用Foxtable对话框代替JS对话框。
我们可以:
1、用 Foxtable 的 MessageBoxA 替代JS的 alert 和 confirm
2、用 Foxtable 的 InputValue 函数替代网页的 prompt,甚至直接设计一个复杂的窗口来代替之。
要启用自定义对话框,首先关闭默认对话框,代码为:
wv.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled
=
False
然后设置ScriptDialogOpening事件代码显示自己的对话框或窗口。
该事件的e参数属性有:
| 属性 | 类型 | 说明 |
|---|---|---|
| Kind | CoreWebView2ScriptDialogKind | 对话框类型:Alert、Confirm、Prompt、BeforeUnload |
| Message | String | 对话框显示的消息内容 |
| Uri | String | 触发对话框的页面URL |
| DefaultText | String | 仅对Prompt有效,表示输入框的默认值 |
| ResultText | String | 仅对Prompt有效,设置用户输入的返回值 |
该事件还有两个方法:
| 方法 | 说明 |
|---|---|
| Accept() |
接受对话框。对于不同对话框类型含义不同: Alert:关闭对话框 Confirm:返回True(用户点击“是”) Prompt:返回ResultText中设置的值 BeforeUnload:允许离开页面 |
| GetDeferral() | 获取延迟对象,用于异步处理对话框。必须在异步操作完成后调用Complete()。 |
示例
1、窗口的AfterLoad事件代码:
'''Async
Dim
wv
As
WebViewer = e.Form.Controls("WebViewer1").WebViewer
Await
wv.EnsureCoreWebView2Async(Nothing)
wv.CoreWebView2.Settings.AreDefaultScriptDialogsEnabled =
False
'
构建测试页面
Dim
html
As
String
=
<![CDATA[
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ScriptDialog
测试</title>
<style>
body { font-family:
微软雅黑;
padding: 20px; background: #f5f7fa; }
.container { max-width: 600px; margin: 0 auto; background: white;
border-radius: 10px; padding: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h2 { color: #333; border-bottom: 2px solid #0078d7; padding-bottom:
10px; }
.btn-group { margin: 20px 0; }
button { padding: 10px 20px; margin: 5px; border: none; border-radius:
5px; cursor: pointer; font-size: 14px; }
.alert { background: #ffc107; color: #333; }
.confirm { background: #17a2b8; color: white; }
.prompt { background: #28a745; color: white; }
.result { margin-top: 20px; padding: 15px; background: #f8f9fa;
border-radius: 5px; border-left: 4px solid #0078d7; }
</style>
</head>
<body>
<div class="container">
<h2>📋 ScriptDialog
测试</h2>
<div class="btn-group">
<button class="alert" onclick="showAlert()">Alert</button>
<button class="confirm" onclick="showConfirm()">Confirm</button>
<button class="prompt" onclick="showPrompt()">Prompt</button>
</div>
<div class="result" id="result">
等待操作结果...
</div>
<script>
function showAlert() {
alert('这是一个
Alert 对话框!');
document.getElementById('result').innerText = 'Alert
已关闭';
}
function showConfirm() {
const result = confirm('确定要继续操作吗?');
document.getElementById('result').innerText = 'Confirm
结果:
' + (result ? '确定'
: '取消');
}
function showPrompt() {
const result = prompt('请输入您的名字:',
'张三');
if (result !== null) {
document.getElementById('result').innerText = 'Prompt
结果:
' + result;
} else {
document.getElementById('result').innerText = 'Prompt
已取消';
}
}
</script>
</div>
</body>
</html>
]]>.Value
wv.NavigateToString(html)
2、WebViewer的ScriptDialogOpening事件代码:
'''Async
Dim
diff = e.GetDeferral()
'通知系统,Foxtable接管了,中间不要Return哦
Select
Case
e.Kind
Case
CoreWebView2ScriptDialogKind.Alert
Await
MessageBoxA.Show(e.Message,
"Foxable",
MessageBoxButtons.OK, MessageBoxIcon.Information)
e.Accept()
Case
CoreWebView2ScriptDialogKind.Confirm
Dim
result
As
DialogResult =
Await
MessageBoxA.Show(e.Message,
"Foxtable",
MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If
result = DialogResult.Yes
Then
e.Accept()
'
调用
Accept()
表示用户点击“是”,页面收到
true
Else
'
不调用
Accept()
表示用户点击“否”
End
If
Case
CoreWebView2ScriptDialogKind.Prompt
Dim
value
As
String
= e.DefaultText
Dim
isOK
As
Boolean
'由于涉及到UI,必须包装在同步代码中
BaseMainForm.Invoke(Sub()
isOK = InputValue(value,
"网页
Prompt",
e.Message)
End
Sub)
If
isOK
Then
e.ResultText = value
e.Accept()
'
调用
Accept(),表示用户点击“确定”,返回输入值
Else
'
不调用
Accept()
表示用户点击“取消”
End
If
End
Select
diff.Complete()
'通知系统,Foxtable处理结束
注意:
1. 首尾要调用 GetDeferral() 和
Complete(),由于事件处理中包含异步操作,必须先获取延迟对象并在最后调用Complete方法,否则页面可能会卡死。
2、MessageBoxA专门为异步操作设计,可以直接使用,但InputValue不是的,
由于其涉及UI(自己设计输入窗口也是),必须用BaseMainForm.Invoke包装执行,参考:插入同步代码