FBro创建浏览器
概述
FBro创建浏览器是FBro框架的核心功能,允许开发者创建嵌入式浏览器实例。创建浏览器时需要配置窗口信息、浏览器设置以及事件回调处理器。
核心方法
FBroSharpControl.CreatBrowser
语法:
csharp
void CreatBrowser(
string url,
FBroSharpWindowsInfo windowsInfo,
FBroSharpBrowserSetting browserSetting,
FBroSharpRequestContext requestContext,
FBroSharpDictionaryValue extraInfo,
FBroSharpBrowserEvent browserEvent,
FBroSharpEventDisableControl eventDisableControl,
string user_flag
)参数说明:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 初始加载的URL地址 |
windowsInfo | FBroSharpWindowsInfo | 是 | 窗口配置信息 |
browserSetting | FBroSharpBrowserSetting | 否 | 浏览器高级设置 |
requestContext | FBroSharpRequestContext | 否 | 请求上下文(用于独立缓存) |
extraInfo | FBroSharpDictionaryValue | 否 | 额外参数信息 |
browserEvent | FBroSharpBrowserEvent | 是 | 浏览器事件回调处理器 |
eventDisableControl | FBroSharpEventDisableControl | 否 | 事件禁用控制 |
user_flag | string | 否 | 用户自定义浏览器标识符 |
user_flag参数详解
作用说明
user_flag参数为每个浏览器实例提供唯一的用户自定义标识符,主要用于:
- 浏览器标识:为每个浏览器分配唯一的业务标识
- 快速检索:通过
FBroSharpBrowserListControl.GetBrowserFromFlag(user_flag)快速获取指定浏览器 - 业务关联:将浏览器与特定业务场景、用户会话或任务关联
- 批量管理:在多浏览器环境中进行分类和批量操作
使用规范
| 属性 | 建议 |
|---|---|
| 唯一性 | 确保在应用程序范围内唯一 |
| 可读性 | 使用有意义的命名,便于调试和维护 |
| 长度 | 建议控制在50字符以内 |
| 字符规范 | 避免特殊字符,推荐使用字母、数字、下划线、连字符 |
| 命名规则 | 采用一致的命名规则,如:模块_功能_序号 |
user_flag应用示例
基础使用:
csharp
private void CreateBrowserWithFlag_Click(object sender, EventArgs e)
{
try
{
// 生成唯一标识
string userFlag = $"main_browser_{DateTime.Now:yyyyMMddHHmmss}";
FBroSharpWindowsInfo windows_info = new FBroSharpWindowsInfo
{
parent_window = this.Handle,
x = 0,
y = 0,
width = this.ClientSize.Width,
height = this.ClientSize.Height
};
BrowserEvent browser_event = new BrowserEvent();
// 创建浏览器并指定user_flag
FBroSharpControl.CreatBrowser(
"https://www.baidu.com",
windows_info,
default,
default,
default,
browser_event,
default,
userFlag // 用户标识
);
Console.WriteLine($"浏览器创建完成,标识: {userFlag}");
// 记录浏览器标识,便于后续操作
SaveBrowserFlag(userFlag);
}
catch (Exception ex)
{
Console.WriteLine($"创建带标识的浏览器失败: {ex.Message}");
}
}
/// <summary>
/// 通过user_flag获取浏览器实例
/// </summary>
/// <param name="userFlag">用户标识</param>
/// <returns>浏览器实例</returns>
private FBroSharpBrowser GetBrowserByFlag(string userFlag)
{
try
{
var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(userFlag);
if (browser != null && browser.IsValid())
{
Console.WriteLine($"成功获取浏览器: {userFlag}");
return browser;
}
else
{
Console.WriteLine($"未找到标识为 {userFlag} 的浏览器");
return null;
}
}
catch (Exception ex)
{
Console.WriteLine($"获取浏览器失败: {ex.Message}");
return null;
}
}多浏览器管理示例:
csharp
/// <summary>
/// 多浏览器管理器
/// 使用user_flag进行浏览器分类和管理
/// </summary>
public class MultiBrowserManager
{
private readonly Dictionary<string, BrowserInfo> browserRegistry = new Dictionary<string, BrowserInfo>();
private readonly object lockObject = new object();
public class BrowserInfo
{
public string Flag { get; set; }
public string Purpose { get; set; }
public DateTime CreatedTime { get; set; }
public string InitialUrl { get; set; }
public Dictionary<string, object> Properties { get; set; } = new Dictionary<string, object>();
}
/// <summary>
/// 创建分类浏览器
/// </summary>
/// <param name="category">浏览器分类</param>
/// <param name="purpose">用途描述</param>
/// <param name="url">初始URL</param>
/// <param name="properties">自定义属性</param>
/// <returns>浏览器标识</returns>
public string CreateCategorizedBrowser(string category, string purpose, string url, Dictionary<string, object> properties = null)
{
try
{
// 生成分类标识
string timestamp = DateTime.Now.ToString("yyyyMMddHHmmssffff");
string userFlag = $"{category}_{purpose}_{timestamp}";
// 记录浏览器信息
var browserInfo = new BrowserInfo
{
Flag = userFlag,
Purpose = purpose,
CreatedTime = DateTime.Now,
InitialUrl = url,
Properties = properties ?? new Dictionary<string, object>()
};
lock (lockObject)
{
browserRegistry[userFlag] = browserInfo;
}
// 创建窗口配置
var windowsInfo = CreateCategorizedWindowInfo(category, browserRegistry.Count);
// 创建额外信息
var extraInfo = FBroSharpDictionaryValue.Create();
extraInfo.SetString("category", category);
extraInfo.SetString("purpose", purpose);
extraInfo.SetString("user_flag", userFlag);
extraInfo.SetString("created_time", browserInfo.CreatedTime.ToString());
// 添加自定义属性
if (properties != null)
{
foreach (var prop in properties)
{
extraInfo.SetString($"prop_{prop.Key}", prop.Value?.ToString() ?? "");
}
}
// 创建事件处理器
var browserEvent = new CategoryBrowserEvent(userFlag, category, purpose);
// 创建浏览器
FBroSharpControl.CreatBrowser(
url,
windowsInfo,
default,
default,
extraInfo,
browserEvent,
default,
userFlag
);
Console.WriteLine($"分类浏览器创建完成: {category}/{purpose} -> {userFlag}");
return userFlag;
}
catch (Exception ex)
{
Console.WriteLine($"创建分类浏览器失败: {ex.Message}");
return null;
}
}
/// <summary>
/// 获取指定分类的所有浏览器
/// </summary>
/// <param name="category">分类名称</param>
/// <returns>浏览器列表</returns>
public List<FBroSharpBrowser> GetBrowsersByCategory(string category)
{
var browsers = new List<FBroSharpBrowser>();
lock (lockObject)
{
var categoryFlags = browserRegistry.Values
.Where(info => info.Flag.StartsWith($"{category}_"))
.Select(info => info.Flag)
.ToList();
foreach (var flag in categoryFlags)
{
var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(flag);
if (browser != null && browser.IsValid())
{
browsers.Add(browser);
}
}
}
return browsers;
}
/// <summary>
/// 批量操作指定分类的浏览器
/// </summary>
/// <param name="category">分类名称</param>
/// <param name="action">操作函数</param>
public void BatchOperateCategory(string category, Action<FBroSharpBrowser, BrowserInfo> action)
{
var browsers = GetBrowsersByCategory(category);
foreach (var browser in browsers)
{
try
{
var flag = GetBrowserFlag(browser);
if (!string.IsNullOrEmpty(flag) && browserRegistry.ContainsKey(flag))
{
action(browser, browserRegistry[flag]);
}
}
catch (Exception ex)
{
Console.WriteLine($"批量操作浏览器失败: {ex.Message}");
}
}
}
/// <summary>
/// 关闭指定分类的所有浏览器
/// </summary>
/// <param name="category">分类名称</param>
public void CloseCategoryBrowsers(string category)
{
BatchOperateCategory(category, (browser, info) =>
{
Console.WriteLine($"关闭浏览器: {info.Purpose} ({info.Flag})");
browser.CloseDevTools();
browser.CloseBrowser(true);
});
}
/// <summary>
/// 创建分类窗口信息
/// </summary>
private FBroSharpWindowsInfo CreateCategorizedWindowInfo(string category, int index)
{
// 根据分类设置不同的窗口配置
switch (category.ToLower())
{
case "popup":
return new FBroSharpWindowsInfo
{
parent_window = IntPtr.Zero,
x = 100 + (index * 50),
y = 100 + (index * 50),
width = 1000,
height = 700,
window_name = $"弹窗浏览器 {index}"
};
case "embedded":
return new FBroSharpWindowsInfo
{
parent_window = IntPtr.Zero,
x = 0,
y = 0,
width = 800,
height = 600
};
case "monitor":
return new FBroSharpWindowsInfo
{
parent_window = IntPtr.Zero,
x = 1920 + (index * 100), // 第二屏幕
y = 100 + (index * 100),
width = 1200,
height = 800,
window_name = $"监控浏览器 {index}"
};
default:
return new FBroSharpWindowsInfo
{
parent_window = IntPtr.Zero,
x = 200 + (index * 30),
y = 200 + (index * 30),
width = 1024,
height = 768,
window_name = $"{category}浏览器 {index}"
};
}
}
/// <summary>
/// 获取浏览器的user_flag
/// </summary>
private string GetBrowserFlag(FBroSharpBrowser browser)
{
// 这里需要根据实际API获取浏览器的user_flag
// 示例实现,具体实现取决于FBro API
lock (lockObject)
{
foreach (var kvp in browserRegistry)
{
var testBrowser = FBroSharpBrowserListControl.GetBrowserFromFlag(kvp.Key);
if (testBrowser != null && testBrowser.IsSame(browser))
{
return kvp.Key;
}
}
}
return null;
}
private IntPtr GetMainWindowHandle()
{
return Process.GetCurrentProcess().MainWindowHandle;
}
/// <summary>
/// 获取浏览器统计信息
/// </summary>
public void PrintBrowserStatistics()
{
lock (lockObject)
{
var categories = browserRegistry.Values
.GroupBy(info => info.Flag.Split('_')[0])
.ToDictionary(g => g.Key, g => g.Count());
Console.WriteLine("浏览器统计信息:");
foreach (var category in categories)
{
Console.WriteLine($" {category.Key}: {category.Value} 个浏览器");
}
Console.WriteLine($"总计: {browserRegistry.Count} 个浏览器");
}
}
}
/// <summary>
/// 分类浏览器专用事件处理器
/// </summary>
public class CategoryBrowserEvent : BrowserEvent
{
private readonly string userFlag;
private readonly string category;
private readonly string purpose;
public CategoryBrowserEvent(string userFlag, string category, string purpose)
{
this.userFlag = userFlag;
this.category = category;
this.purpose = purpose;
}
public override void OnAfterCreated(IFBroSharpBrowser browser, IFBroSharpDictionaryValue extrainfo)
{
base.OnAfterCreated(browser, extrainfo);
Console.WriteLine($"[{category}] 浏览器创建完成: {purpose} ({userFlag})");
// 注入分类标识信息
string categoryJS = $@"
window.FBroBrowserInfo = {{
flag: '{userFlag}',
category: '{category}',
purpose: '{purpose}',
createdTime: '{DateTime.Now:yyyy-MM-dd HH:mm:ss}'
}};
console.log('FBro分类浏览器信息已注入:', window.FBroBrowserInfo);
";
browser.GetMainFrame().ExecuteJavaScript(categoryJS, "", 0);
}
public override void OnBeforeClose(IFBroSharpBrowser browser)
{
Console.WriteLine($"[{category}] 浏览器即将关闭: {purpose} ({userFlag})");
base.OnBeforeClose(browser);
}
}
## 浏览器事件回调类
### BrowserEvent类概述
`BrowserEvent`是继承自`FBroSharpBrowserEvent`的自定义事件处理类,用于处理浏览器的各种生命周期事件、用户交互事件和网络事件。
### 完整的BrowserEvent实现示例
```csharp
using FBroSharp;
using FBroSharp.Const;
using FBroSharp.DataType;
using FBroSharp.Event;
using FBroSharp.Lib;
using FBroSharp.Value;
using System;
using System.Collections.Generic;
using System.Reflection;
using FBroSharp.Callback;
using System.IO;
namespace BaseTest
{
/// <summary>
/// 浏览器列表管理类
/// </summary>
public class BrowserList
{
public static List<FBroSharpBrowser> data = new List<FBroSharpBrowser>();
}
/// <summary>
/// 浏览器事件回调处理类
/// 继承自FBroSharpBrowserEvent,处理浏览器的各种事件
/// </summary>
public class BrowserEvent : FBroSharpBrowserEvent
{
#region 生命周期事件
/// <summary>
/// 浏览器创建完成事件
/// 在浏览器创建完成后触发,此时可以安全地执行浏览器操作
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="extrainfo">额外信息</param>
public override void OnAfterCreated(IFBroSharpBrowser browser, IFBroSharpDictionaryValue extrainfo)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 浏览器创建完成");
// 判断是否为后台浏览器
bool isBackground = extrainfo?.GetBool("是否为后台") ?? false;
if (!isBackground)
{
BrowserList.data.Add((FBroSharpBrowser)browser);
Console.WriteLine($"前台浏览器创建完成,ID: {browser.GetIdentifier()}");
}
else
{
Console.WriteLine($"后台浏览器创建完成,ID: {browser.GetIdentifier()}");
}
// 设置初始配置
ConfigureBrowserAfterCreation(browser);
}
/// <summary>
/// 浏览器即将关闭事件
/// 在浏览器关闭前触发,用于清理资源
/// </summary>
/// <param name="browser">浏览器实例</param>
public override void OnBeforeClose(IFBroSharpBrowser browser)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 浏览器即将关闭");
// 从浏览器列表中移除
for (int i = 0; i < BrowserList.data.Count; i++)
{
var temp_browser = BrowserList.data[i];
if (temp_browser.IsSame(browser))
{
BrowserList.data.RemoveAt(i);
Console.WriteLine($"浏览器已从列表中移除,剩余数量: {BrowserList.data.Count}");
break;
}
}
// 清理浏览器相关资源
CleanupBrowserResources(browser);
}
/// <summary>
/// 执行关闭事件
/// 返回false允许关闭,返回true阻止关闭
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <returns>是否阻止关闭</returns>
public override bool DoClose(IFBroSharpBrowser browser)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 请求关闭浏览器");
// 这里可以添加关闭前的确认逻辑
// 返回false允许关闭,返回true阻止关闭
return false;
}
#endregion
#region 页面加载事件
/// <summary>
/// 加载状态改变事件
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="isLoading">是否正在加载</param>
/// <param name="canGoBack">是否可以后退</param>
/// <param name="canGoForward">是否可以前进</param>
public override void OnLoadingStateChange(IFBroSharpBrowser browser, bool isLoading, bool canGoBack, bool canGoForward)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 加载状态: {(isLoading ? "加载中" : "加载完成")}");
if (!isLoading)
{
Console.WriteLine("页面加载完成,可以执行后续操作");
OnPageLoadCompleted(browser);
}
}
/// <summary>
/// 页面开始加载事件
/// </summary>
public override void OnLoadStart(IFBroSharpBrowser browser, IFBroSharpFrame frame, FBroSharpTransitionType transition_type)
{
if (frame.IsMain())
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 主框架开始加载: {frame.GetURL()}");
}
}
/// <summary>
/// 页面加载完成事件
/// </summary>
public override void OnLoadEnd(IFBroSharpBrowser browser, IFBroSharpFrame frame, int httpStatusCode)
{
if (frame.IsMain())
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 主框架加载完成,状态码: {httpStatusCode}");
}
}
/// <summary>
/// 页面加载错误事件
/// </summary>
public override void OnLoadError(IFBroSharpBrowser browser, IFBroSharpFrame frame, int errorCode, string errorText, string failedUrl)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 加载错误: {errorText} (代码: {errorCode})");
Console.WriteLine($"失败URL: {failedUrl}");
}
#endregion
#region 页面信息变更事件
/// <summary>
/// 页面标题改变事件
/// </summary>
public override void OnTitleChange(IFBroSharpBrowser browser, string title)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 页面标题: {title}");
}
/// <summary>
/// 地址栏改变事件
/// </summary>
public override void OnAddressChange(IFBroSharpBrowser browser, IFBroSharpFrame frame, string url)
{
if (frame.IsMain())
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 地址改变: {url}");
}
}
#endregion
#region 下载事件
/// <summary>
/// 即将下载事件
/// 处理文件下载前的配置
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="download_item">下载项</param>
/// <param name="suggested_name">建议文件名</param>
/// <param name="callback">下载回调</param>
public override void OnBeforeDownload(IFBroSharpBrowser browser, IFBroSharpDownloadItem download_item, string suggested_name, IFBroSharpBeforeDownloadCallback callback)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 准备下载: {suggested_name}");
// 设置下载路径
string downloadPath = Path.Combine(Directory.GetCurrentDirectory(), "Downloads");
if (!Directory.Exists(downloadPath))
{
Directory.CreateDirectory(downloadPath);
}
string fullPath = Path.Combine(downloadPath, suggested_name);
callback.Continue(fullPath, false);
}
/// <summary>
/// 下载进度更新事件
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="download_item">下载项</param>
/// <param name="callback">下载回调</param>
public override void OnDownloadUpdated(IFBroSharpBrowser browser, IFBroSharpDownloadItem download_item, IFBroSharpDownloadItemCallback callback)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 下载进度: {download_item.GetPercentComplete()}%");
Console.WriteLine($"下载速度: {download_item.GetCurrentSpeed()} bytes/s");
if (download_item.IsComplete())
{
Console.WriteLine($"下载完成: {download_item.GetFullPath()}");
}
}
#endregion
#region 右键菜单事件
/// <summary>
/// 即将显示右键菜单事件
/// 可以自定义右键菜单项
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="frame">框架实例</param>
/// <param name="menu_params">菜单参数</param>
/// <param name="model">菜单模型</param>
public override void OnBeforeContextMenu(IFBroSharpBrowser browser, IFBroSharpFrame frame, IFBroSharpContextMenuParams menu_params, IFBroSharpMenuModel model)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 显示右键菜单");
// 添加分隔线
model.AddSeparator();
// 添加自定义菜单
IFBroSharpMenuModel sub_model = model.AddSubMenu(10000, "FBro工具");
sub_model.AddItem(10001, "元素检查");
sub_model.AddItem(10002, "开发者工具");
sub_model.AddSeparator();
sub_model.AddItem(10003, "页面信息");
}
/// <summary>
/// 右键菜单命令执行事件
/// 处理自定义菜单项的点击
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="frame">框架实例</param>
/// <param name="menu_params">菜单参数</param>
/// <param name="command_id">命令ID</param>
/// <param name="event_flags">事件标志</param>
/// <returns>是否处理了命令</returns>
public override bool OnContextMenuCommand(IFBroSharpBrowser browser, IFBroSharpFrame frame, IFBroSharpContextMenuParams menu_params, int command_id, FBroSharpEventFlags event_flags)
{
switch (command_id)
{
case 10001: // 元素检查
var element_at = new FBroSharpElementAt
{
x = menu_params.GetXCoord(),
y = menu_params.GetYCoord()
};
browser.ShowDevTools("元素检查", IntPtr.Zero, 0, 0, 1024, 900, default, element_at, default, default);
return true;
case 10002: // 开发者工具
browser.ShowDevTools("开发者工具", IntPtr.Zero, 0, 0, 1024, 900, default, default, default, default);
return true;
case 10003: // 页面信息
ShowPageInfo(browser, frame);
return true;
}
return false;
}
#endregion
#region 弹窗事件
/// <summary>
/// 即将打开新窗口事件
/// 可以控制弹窗行为
/// </summary>
public override bool OnBeforePopup(IFBroSharpBrowser browser, IFBroSharpFrame frame, string target_url, string target_frame_name,
FBroSharpWindowOpenDisposition target_disposition, bool user_gesture, FBroSharpPopupfeatures popupFeatures, ref FBroSharpWindowsInfo windowInfo,
ref FBroSharpBrowserSetting settings, ref bool no_javascript_access, IFBroSharpUseExtraData user_settings)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 请求打开新窗口: {target_url}");
// 在当前窗口中打开链接,阻止弹窗
frame.LoadURL(target_url);
return true; // 返回true阻止弹窗
}
#endregion
#region 证书和安全事件
/// <summary>
/// 证书错误事件
/// 处理SSL证书错误
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="cert_error">证书错误代码</param>
/// <param name="request_url">请求URL</param>
/// <param name="ssl_info">SSL信息</param>
/// <param name="callback">回调</param>
/// <returns>是否继续访问</returns>
public override bool OnCertificateError(IFBroSharpBrowser browser, int cert_error, string request_url, IFBroSharpSSLInfo ssl_info, IFBroSharpCallback callback)
{
Console.WriteLine($"[{MethodBase.GetCurrentMethod().Name}] 证书错误: {cert_error}");
Console.WriteLine($"URL: {request_url}");
// 继续访问(忽略证书错误)
callback.Continue();
return true;
}
#endregion
#region 控制台消息事件
/// <summary>
/// 控制台消息事件
/// 捕获页面的console输出
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="level">日志级别</param>
/// <param name="message">消息内容</param>
/// <param name="source">消息来源</param>
/// <param name="line">行号</param>
/// <returns>是否阻止输出到控制台</returns>
public override bool OnConsoleMessage(IFBroSharpBrowser browser, FBroLogSeverityType level, string message, string source, int line)
{
string levelStr = level switch
{
FBroLogSeverityType.LOGSEVERITY_DEBUG => "DEBUG",
FBroLogSeverityType.LOGSEVERITY_INFO => "INFO",
FBroLogSeverityType.LOGSEVERITY_WARNING => "WARNING",
FBroLogSeverityType.LOGSEVERITY_ERROR => "ERROR",
_ => "UNKNOWN"
};
Console.WriteLine($"[CONSOLE-{levelStr}] {message} (来源: {source}:{line})");
return false; // 返回false允许继续输出到控制台
}
#endregion
#region 自定义辅助方法
/// <summary>
/// 浏览器创建完成后的配置
/// </summary>
/// <param name="browser">浏览器实例</param>
private void ConfigureBrowserAfterCreation(IFBroSharpBrowser browser)
{
try
{
// 设置缩放级别
browser.SetZoomLevel(0.0);
// 可以在这里添加其他初始化配置
Console.WriteLine("浏览器初始配置完成");
}
catch (Exception ex)
{
Console.WriteLine($"配置浏览器失败: {ex.Message}");
}
}
/// <summary>
/// 页面加载完成后的处理
/// </summary>
/// <param name="browser">浏览器实例</param>
private void OnPageLoadCompleted(IFBroSharpBrowser browser)
{
try
{
// 可以在这里执行JavaScript或其他操作
string jsCode = @"
console.log('页面加载完成,FBro事件处理器已就绪');
document.title = document.title + ' [FBro]';
";
browser.GetMainFrame().ExecuteJavaScript(jsCode, "", 0);
}
catch (Exception ex)
{
Console.WriteLine($"页面加载完成处理失败: {ex.Message}");
}
}
/// <summary>
/// 显示页面信息
/// </summary>
/// <param name="browser">浏览器实例</param>
/// <param name="frame">框架实例</param>
private void ShowPageInfo(IFBroSharpBrowser browser, IFBroSharpFrame frame)
{
try
{
string info = $@"
页面信息:
- URL: {frame.GetURL()}
- 标题: {frame.GetName()}
- 浏览器ID: {browser.GetIdentifier()}
- 是否主框架: {frame.IsMain()}
- 是否有效: {frame.IsValid()}
";
Console.WriteLine(info);
// 也可以通过JavaScript在页面中显示
string jsCode = $@"
alert('页面信息:\nURL: {frame.GetURL()}\n浏览器ID: {browser.GetIdentifier()}');
";
frame.ExecuteJavaScript(jsCode, "", 0);
}
catch (Exception ex)
{
Console.WriteLine($"显示页面信息失败: {ex.Message}");
}
}
/// <summary>
/// 清理浏览器相关资源
/// </summary>
/// <param name="browser">浏览器实例</param>
private void CleanupBrowserResources(IFBroSharpBrowser browser)
{
try
{
// 在这里可以清理与该浏览器相关的资源
Console.WriteLine($"清理浏览器资源: {browser.GetIdentifier()}");
}
catch (Exception ex)
{
Console.WriteLine($"清理浏览器资源失败: {ex.Message}");
}
}
#endregion
}
}基础创建示例
简单创建浏览器
csharp
private void CreateBasicBrowser_Click(object sender, EventArgs e)
{
try
{
// 1. 生成唯一标识
string userFlag = $"basic_browser_{DateTime.Now:yyyyMMddHHmmss}";
// 2. 配置窗口信息
FBroSharpWindowsInfo windows_info = new FBroSharpWindowsInfo
{
parent_window = this.Handle, // 父窗口句柄
x = 0, // X坐标
y = 0, // Y坐标
width = this.ClientSize.Width, // 宽度
height = this.ClientSize.Height // 高度
};
// 3. 创建浏览器事件回调类
BrowserEvent browser_event = new BrowserEvent();
// 4. 创建浏览器
FBroSharpControl.CreatBrowser(
"https://www.baidu.com", // 初始URL
windows_info, // 窗口信息
default, // 浏览器设置(使用默认)
default, // 请求上下文(使用默认)
default, // 额外信息(使用默认)
browser_event, // 事件回调
default, // 事件禁用控制(使用默认)
userFlag // 用户标识
);
Console.WriteLine($"浏览器创建请求已发送,标识: {userFlag}");
// 5. 记录浏览器标识以便后续使用
SaveBrowserFlag(userFlag);
}
catch (Exception ex)
{
Console.WriteLine($"创建浏览器失败: {ex.Message}");
}
}
/// <summary>
/// 保存浏览器标识的辅助方法
/// </summary>
/// <param name="userFlag">用户标识</param>
private void SaveBrowserFlag(string userFlag)
{
// 可以保存到配置文件、数据库或内存中
// 这里简单保存到静态列表中
BrowserFlagManager.RegisterFlag("最新创建的浏览器", userFlag);
Console.WriteLine($"浏览器标识已保存: {userFlag}");
}高级创建示例
带完整配置的浏览器创建
csharp
/// <summary>
/// 创建高级配置的浏览器
/// </summary>
/// <param name="url">初始URL</param>
/// <param name="useCustomCache">是否使用自定义缓存</param>
/// <param name="isPopup">是否为弹窗</param>
/// <param name="customFlag">自定义标识(可选)</param>
public void CreateAdvancedBrowser(string url, bool useCustomCache = false, bool isPopup = false, string customFlag = null)
{
try
{
// 1. 生成或使用自定义标识
string userFlag = customFlag ?? BrowserFlagNaming.GenerateStandardFlag(
isPopup ? "popup" : "embedded",
"advanced",
null
);
// 2. 验证标识
var validation = BrowserFlagValidator.ValidateFlag(userFlag);
if (!validation.IsValid)
{
Console.WriteLine($"标识验证失败: {validation}");
return;
}
// 3. 确保标识唯一
userFlag = BrowserFlagManager.EnsureUniqueFlag(userFlag);
// 4. 窗口信息配置
FBroSharpWindowsInfo windows_info = new FBroSharpWindowsInfo();
if (isPopup)
{
// 弹窗配置
windows_info.parent_window = IntPtr.Zero;
windows_info.x = 100;
windows_info.y = 100;
windows_info.width = 1024;
windows_info.height = 768;
windows_info.window_name = $"FBro高级浏览器-{userFlag}";
}
else
{
// 嵌入式配置
windows_info.parent_window = this.Handle;
windows_info.x = 0;
windows_info.y = 0;
windows_info.width = this.ClientSize.Width;
windows_info.height = this.ClientSize.Height;
}
// 5. 浏览器设置(可选)
FBroSharpBrowserSetting browser_setting = new FBroSharpBrowserSetting
{
// 在这里可以配置浏览器的高级设置
// 具体设置项需要根据FBroSharpBrowserSetting的属性来配置
};
// 6. 请求上下文(自定义缓存)
FBroSharpRequestContext request_context = null;
if (useCustomCache)
{
var contextSet = new FBroSharpRequestContextSet
{
cache_path = Path.Combine(Application.StartupPath, "CustomCache", userFlag)
};
request_context = (FBroSharpRequestContext)FBroSharpRequestContext.CreateContext(contextSet);
}
// 7. 额外信息
FBroSharpDictionaryValue extra_info = FBroSharpDictionaryValue.Create();
extra_info.SetBool("是否为后台", false);
extra_info.SetString("创建时间", DateTime.Now.ToString());
extra_info.SetString("用途", "高级浏览器");
extra_info.SetString("user_flag", userFlag);
extra_info.SetBool("is_popup", isPopup);
extra_info.SetBool("use_custom_cache", useCustomCache);
// 8. 创建事件处理器
BrowserEvent browser_event = new BrowserEvent();
// 9. 事件禁用控制(可选)
FBroSharpEventDisableControl event_disable = new FBroSharpEventDisableControl();
// 可以在这里禁用某些不需要的事件
// 10. 创建浏览器
FBroSharpControl.CreatBrowser(
url,
windows_info,
browser_setting,
request_context,
extra_info,
browser_event,
event_disable,
userFlag // 用户标识
);
// 11. 注册浏览器标识
BrowserFlagManager.RegisterFlag($"高级浏览器-{DateTime.Now:HHmmss}", userFlag);
Console.WriteLine($"高级浏览器创建请求已发送: {url}, 标识: {userFlag}");
}
catch (Exception ex)
{
Console.WriteLine($"创建高级浏览器失败: {ex.Message}");
Console.WriteLine($"堆栈跟踪: {ex.StackTrace}");
}
}批量创建浏览器
csharp
/// <summary>
/// 批量创建多个浏览器
/// </summary>
/// <param name="urls">URL列表</param>
/// <param name="startX">起始X坐标</param>
/// <param name="startY">起始Y坐标</param>
/// <param name="flagPrefix">标识前缀</param>
public void CreateMultipleBrowsers(string[] urls, int startX = 100, int startY = 100, string flagPrefix = "batch")
{
for (int i = 0; i < urls.Length; i++)
{
try
{
// 1. 生成唯一标识
string userFlag = BrowserFlagNaming.GenerateStandardFlag(flagPrefix, $"browser_{i}", i + 1);
// 2. 验证并确保标识唯一
userFlag = BrowserFlagManager.EnsureUniqueFlag(userFlag);
// 3. 错开窗口位置
var windows_info = new FBroSharpWindowsInfo
{
parent_window = IntPtr.Zero, // 创建弹窗
x = startX + (i * 50), // 错开X坐标
y = startY + (i * 50), // 错开Y坐标
width = 800,
height = 600,
window_name = $"批量浏览器 {i + 1} - {userFlag}"
};
// 4. 为每个浏览器创建独立的事件处理器
var browser_event = new BrowserEvent();
// 5. 添加标识信息
var extra_info = FBroSharpDictionaryValue.Create();
extra_info.SetInt("浏览器索引", i);
extra_info.SetString("创建批次", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
extra_info.SetString("user_flag", userFlag);
extra_info.SetString("url", urls[i]);
extra_info.SetInt("total_count", urls.Length);
// 6. 创建浏览器
FBroSharpControl.CreatBrowser(
urls[i],
windows_info,
default,
default,
extra_info,
browser_event,
default,
userFlag // 用户标识
);
// 7. 注册标识映射
BrowserFlagManager.RegisterFlag($"批量浏览器-{i + 1}", userFlag);
Console.WriteLine($"浏览器 {i + 1} 创建请求已发送: {urls[i]}, 标识: {userFlag}");
// 可选:添加延迟避免同时创建过多浏览器
System.Threading.Thread.Sleep(100);
}
catch (Exception ex)
{
Console.WriteLine($"创建浏览器 {i + 1} 失败: {ex.Message}");
}
}
Console.WriteLine($"批量创建完成,共请求创建 {urls.Length} 个浏览器");
}常用事件处理模式
1. 页面加载完成检测
csharp
public class PageLoadDetector : BrowserEvent
{
private readonly Action<IFBroSharpBrowser> onPageLoadComplete;
public PageLoadDetector(Action<IFBroSharpBrowser> onComplete)
{
onPageLoadComplete = onComplete;
}
public override void OnLoadingStateChange(IFBroSharpBrowser browser, bool isLoading, bool canGoBack, bool canGoForward)
{
if (!isLoading)
{
onPageLoadComplete?.Invoke(browser);
}
}
}
// 使用示例
var detector = new PageLoadDetector(browser => {
Console.WriteLine("页面加载完成,开始执行业务逻辑");
// 执行页面加载完成后的操作
});2. 自动下载处理
csharp
public class AutoDownloadHandler : BrowserEvent
{
private readonly string downloadDirectory;
public AutoDownloadHandler(string downloadDir)
{
downloadDirectory = downloadDir;
if (!Directory.Exists(downloadDirectory))
{
Directory.CreateDirectory(downloadDirectory);
}
}
public override void OnBeforeDownload(IFBroSharpBrowser browser, IFBroSharpDownloadItem download_item, string suggested_name, IFBroSharpBeforeDownloadCallback callback)
{
string filepath = Path.Combine(downloadDirectory, suggested_name);
callback.Continue(filepath, false);
Console.WriteLine($"开始下载: {suggested_name} -> {filepath}");
}
public override void OnDownloadUpdated(IFBroSharpBrowser browser, IFBroSharpDownloadItem download_item, IFBroSharpDownloadItemCallback callback)
{
if (download_item.IsComplete())
{
Console.WriteLine($"下载完成: {download_item.GetFullPath()}");
}
}
}3. 控制台日志收集
csharp
public class ConsoleLogger : BrowserEvent
{
private readonly List<ConsoleMessage> consoleLogs = new List<ConsoleMessage>();
public class ConsoleMessage
{
public DateTime Timestamp { get; set; }
public FBroLogSeverityType Level { get; set; }
public string Message { get; set; }
public string Source { get; set; }
public int Line { get; set; }
}
public override bool OnConsoleMessage(IFBroSharpBrowser browser, FBroLogSeverityType level, string message, string source, int line)
{
consoleLogs.Add(new ConsoleMessage
{
Timestamp = DateTime.Now,
Level = level,
Message = message,
Source = source,
Line = line
});
// 如果是错误日志,立即输出
if (level == FBroLogSeverityType.LOGSEVERITY_ERROR)
{
Console.WriteLine($"[页面错误] {message} (来源: {source}:{line})");
}
return false;
}
public List<ConsoleMessage> GetLogs() => new List<ConsoleMessage>(consoleLogs);
public void ClearLogs() => consoleLogs.Clear();
}最佳实践
- 事件处理器复用:为不同用途的浏览器创建专门的事件处理器类
- 资源管理:在
OnBeforeClose中及时清理资源,避免内存泄漏 - 错误处理:在关键事件中添加try-catch,避免异常导致程序崩溃
- 日志记录:合理使用
Console.WriteLine或日志框架记录关键事件 - 异步操作:对于耗时操作,考虑使用异步处理避免阻塞UI
- user_flag管理:制定统一的标识命名规范,便于浏览器分类管理
user_flag最佳实践
命名规范建议
csharp
/// <summary>
/// user_flag命名规范示例
/// </summary>
public static class BrowserFlagNaming
{
/// <summary>
/// 生成标准格式的user_flag
/// 格式:{模块}_{功能}_{时间戳}_{序号}
/// </summary>
/// <param name="module">模块名称</param>
/// <param name="function">功能描述</param>
/// <param name="index">序号(可选)</param>
/// <returns>标准化的user_flag</returns>
public static string GenerateStandardFlag(string module, string function, int? index = null)
{
string timestamp = DateTime.Now.ToString("yyyyMMddHHmmssffff");
string indexSuffix = index.HasValue ? $"_{index:D3}" : "";
return $"{module}_{function}_{timestamp}{indexSuffix}".ToLower();
}
/// <summary>
/// 生成分类标识
/// </summary>
public static string GenerateCategoryFlag(string category, string subcategory, string identifier)
{
return $"{category}_{subcategory}_{identifier}_{DateTime.Now:yyyyMMddHHmmssfff}".ToLower();
}
/// <summary>
/// 生成会话标识
/// </summary>
public static string GenerateSessionFlag(string sessionId, string purpose)
{
return $"session_{sessionId}_{purpose}_{DateTime.Now:yyyyMMddHHmmss}".ToLower();
}
}
// 使用示例
string mainBrowserFlag = BrowserFlagNaming.GenerateStandardFlag("main", "search", 1);
// 结果: main_search_20241201143025000_001
string testBrowserFlag = BrowserFlagNaming.GenerateCategoryFlag("test", "ui", "login_form");
// 结果: test_ui_login_form_20241201143025000
string sessionFlag = BrowserFlagNaming.GenerateSessionFlag("user123", "shopping");
// 结果: session_user123_shopping_20241201143025标识管理工具类
csharp
/// <summary>
/// 浏览器标识管理工具类
/// </summary>
public static class BrowserFlagManager
{
private static readonly Dictionary<string, string> flagMappings = new Dictionary<string, string>();
private static readonly object lockObject = new object();
/// <summary>
/// 注册浏览器标识映射
/// </summary>
/// <param name="logicalName">逻辑名称</param>
/// <param name="actualFlag">实际标识</param>
public static void RegisterFlag(string logicalName, string actualFlag)
{
lock (lockObject)
{
flagMappings[logicalName] = actualFlag;
}
}
/// <summary>
/// 获取浏览器(通过逻辑名称)
/// </summary>
/// <param name="logicalName">逻辑名称</param>
/// <returns>浏览器实例</returns>
public static FBroSharpBrowser GetBrowserByLogicalName(string logicalName)
{
lock (lockObject)
{
if (flagMappings.ContainsKey(logicalName))
{
string actualFlag = flagMappings[logicalName];
return FBroSharpBrowserListControl.GetBrowserFromFlag(actualFlag);
}
}
return null;
}
/// <summary>
/// 移除标识映射
/// </summary>
/// <param name="logicalName">逻辑名称</param>
public static void UnregisterFlag(string logicalName)
{
lock (lockObject)
{
flagMappings.Remove(logicalName);
}
}
/// <summary>
/// 验证标识唯一性
/// </summary>
/// <param name="flag">要验证的标识</param>
/// <returns>是否唯一</returns>
public static bool IsUnique(string flag)
{
var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(flag);
return browser == null;
}
/// <summary>
/// 生成确保唯一的标识
/// </summary>
/// <param name="baseFlag">基础标识</param>
/// <returns>唯一标识</returns>
public static string EnsureUniqueFlag(string baseFlag)
{
if (IsUnique(baseFlag))
{
return baseFlag;
}
int counter = 1;
string uniqueFlag;
do
{
uniqueFlag = $"{baseFlag}_{counter:D3}";
counter++;
} while (!IsUnique(uniqueFlag) && counter < 1000);
return uniqueFlag;
}
/// <summary>
/// 获取所有活跃的标识
/// </summary>
/// <returns>标识列表</returns>
public static List<string> GetAllActiveFlags()
{
lock (lockObject)
{
var activeFlags = new List<string>();
foreach (var kvp in flagMappings)
{
var browser = FBroSharpBrowserListControl.GetBrowserFromFlag(kvp.Value);
if (browser != null && browser.IsValid())
{
activeFlags.Add(kvp.Value);
}
}
return activeFlags;
}
}
}标识验证和监控
csharp
/// <summary>
/// 浏览器标识验证器
/// </summary>
public static class BrowserFlagValidator
{
/// <summary>
/// 验证标识格式
/// </summary>
/// <param name="flag">要验证的标识</param>
/// <returns>验证结果</returns>
public static ValidationResult ValidateFlag(string flag)
{
var result = new ValidationResult { IsValid = true, Flag = flag };
if (string.IsNullOrWhiteSpace(flag))
{
result.IsValid = false;
result.Errors.Add("标识不能为空");
return result;
}
// 长度检查
if (flag.Length > 100)
{
result.IsValid = false;
result.Errors.Add("标识长度不能超过100个字符");
}
// 字符检查
if (!System.Text.RegularExpressions.Regex.IsMatch(flag, @"^[a-zA-Z0-9_\-]+$"))
{
result.IsValid = false;
result.Errors.Add("标识只能包含字母、数字、下划线和连字符");
}
// 格式建议检查
if (!flag.Contains("_"))
{
result.Warnings.Add("建议使用下划线分隔标识的不同部分");
}
// 时间戳检查
if (!System.Text.RegularExpressions.Regex.IsMatch(flag, @"\d{14,}"))
{
result.Warnings.Add("建议在标识中包含时间戳以确保唯一性");
}
return result;
}
public class ValidationResult
{
public bool IsValid { get; set; }
public string Flag { get; set; }
public List<string> Errors { get; set; } = new List<string>();
public List<string> Warnings { get; set; } = new List<string>();
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"标识: {Flag}");
sb.AppendLine($"验证状态: {(IsValid ? "通过" : "失败")}");
if (Errors.Any())
{
sb.AppendLine("错误:");
foreach (var error in Errors)
{
sb.AppendLine($" - {error}");
}
}
if (Warnings.Any())
{
sb.AppendLine("警告:");
foreach (var warning in Warnings)
{
sb.AppendLine($" - {warning}");
}
}
return sb.ToString();
}
}
}使用示例和最佳实践总结
csharp
/// <summary>
/// user_flag最佳实践示例
/// </summary>
public class BestPracticeExample
{
/// <summary>
/// 推荐的浏览器创建方式
/// </summary>
public void RecommendedBrowserCreation()
{
// 1. 生成标准化标识
string baseFlag = BrowserFlagNaming.GenerateStandardFlag("ecommerce", "product_view", 1);
// 2. 验证标识格式
var validation = BrowserFlagValidator.ValidateFlag(baseFlag);
if (!validation.IsValid)
{
Console.WriteLine($"标识验证失败: {validation}");
return;
}
// 3. 确保唯一性
string uniqueFlag = BrowserFlagManager.EnsureUniqueFlag(baseFlag);
// 4. 注册逻辑名称映射
BrowserFlagManager.RegisterFlag("主要商品浏览器", uniqueFlag);
try
{
// 5. 创建浏览器
FBroSharpControl.CreatBrowser(
"https://www.example-shop.com/products",
CreateWindowInfo(),
default,
default,
CreateExtraInfo(uniqueFlag),
new BrowserEvent(),
default,
uniqueFlag
);
Console.WriteLine($"浏览器创建成功,标识: {uniqueFlag}");
}
catch (Exception ex)
{
// 6. 错误时清理映射
BrowserFlagManager.UnregisterFlag("主要商品浏览器");
Console.WriteLine($"浏览器创建失败: {ex.Message}");
}
}
/// <summary>
/// 获取浏览器的推荐方式
/// </summary>
public void RecommendedBrowserRetrieval()
{
// 方式1:通过逻辑名称获取
var browser1 = BrowserFlagManager.GetBrowserByLogicalName("主要商品浏览器");
// 方式2:通过完整标识获取
var browser2 = FBroSharpBrowserListControl.GetBrowserFromFlag("ecommerce_product_view_20241201143025000_001");
// 方式3:验证浏览器有效性
if (browser1 != null && browser1.IsValid())
{
// 安全地使用浏览器
browser1.GetMainFrame().LoadURL("https://new-url.com");
}
}
private FBroSharpWindowsInfo CreateWindowInfo()
{
return new FBroSharpWindowsInfo
{
parent_window = IntPtr.Zero,
x = 100,
y = 100,
width = 1200,
height = 800,
window_name = "商品浏览器"
};
}
private FBroSharpDictionaryValue CreateExtraInfo(string flag)
{
var extraInfo = FBroSharpDictionaryValue.Create();
extraInfo.SetString("user_flag", flag);
extraInfo.SetString("creation_time", DateTime.Now.ToString());
extraInfo.SetString("purpose", "产品浏览");
return extraInfo;
}
}注意事项
- 线程安全:事件回调可能在不同线程中执行,注意线程安全
- 生命周期管理:确保在浏览器关闭前清理所有相关资源
- 回调对象释放:及时调用callback.Dispose()释放回调对象
- 避免循环引用:事件处理器不要持有浏览器的强引用
- user_flag唯一性:确保user_flag在应用程序范围内唯一,避免冲突
- 标识生命周期:浏览器关闭后及时清理相关的标识映射和引用
- 标识长度限制:避免使用过长的user_flag,建议控制在100字符以内
- 特殊字符避免:user_flag中避免使用特殊字符,推荐使用字母、数字、下划线