Skip to content

FBro浏览器控制方法大全

📋 文档概述

本文档基于FBro官方的IFBroSharpBrowser接口,为C#开发者提供完整的浏览器控制方法指南。涵盖了从基础页面导航到高级功能的全面API文档。

🎯 适用场景

  • 自动化测试:实现Web应用的自动化测试流程
  • 数据采集:构建高效的网页数据抓取工具
  • 浏览器内核集成:将浏览器功能嵌入到桌面应用中
  • UI自动化:模拟用户操作进行界面自动化控制

🚀 快速开始

csharp
// 基础使用模式
if (browser != null && browser.IsValid)
{
    // 载入页面
    browser.GetMainFrame().LoadURL("https://www.example.com");
    
    // 等待加载完成
    while (browser.IsLoading())
    {
        Thread.Sleep(100);
    }
    
    // 执行其他操作...
}

📚 功能模块导航

功能模块主要方法应用场景
页面导航LoadURL(), GoBack(), GoForward()基础页面跳转控制
页面状态IsLoading(), Reload(), StopLoad()页面加载状态管理
浏览器信息GetIdentifier(), IsSame(), HasDocument()浏览器实例管理
框架操作GetMainFrame(), GetFocusedFrame()多框架页面处理
窗口控制ShowWindow(), MoveWindow(), SetParent()窗口显示和布局
开发者工具ShowDevTools(), CloseDevTools()调试和开发辅助
事件处理SendKeyEvent(), SendMouseClickEvent()用户交互模拟
高级功能SetProxy(), ClearCacheData()网络配置和缓存管理
离屏渲染WasResized(), Invalidate()无界面模式渲染
VIP功能GetVIPControl()高级指纹和隐私控制

⚠️ 重要提示

  1. 线程安全:所有UI相关操作必须在UI线程中执行
  2. 资源管理:使用完毕后需要正确释放浏览器资源
  3. 异常处理:建议在所有操作中添加适当的异常处理机制
  4. 版本兼容:确保使用的FBro版本支持所需功能

核心属性

IsValid - 浏览器有效性检查

csharp
/// <summary>
/// 检查浏览器是否有效
/// True if this object is currently attached to a valid frame.
/// </summary>
/// <returns>浏览器是否有效</returns>
bool isValid = browser.IsValid;

// 使用示例
if (browser.IsValid)
{
    Console.WriteLine("浏览器实例有效,可以执行操作");
}
else
{
    Console.WriteLine("浏览器实例无效,需要重新创建");
}

基础浏览器导航控制

1. 页面导航方法

csharp
/// <summary>
/// 载入指定URL地址
/// </summary>
/// <param name="url">要载入的URL地址</param>
public void LoadURL(string url)
{
    if (browser != null && browser.IsValid)
    {
        browser.GetMainFrame().LoadURL(url);
        Console.WriteLine($"正在载入地址: {url}");
    }
    else
    {
        Console.WriteLine("无法载入地址:浏览器无效");
    }
}

/// <summary>
/// 载入指定URL地址(带参数验证)
/// </summary>
/// <param name="url">要载入的URL地址</param>
/// <returns>是否成功发起载入请求</returns>
public bool LoadURLSafe(string url)
{
    if (string.IsNullOrWhiteSpace(url))
    {
        Console.WriteLine("载入失败:URL地址为空");
        return false;
    }

    if (!Uri.TryCreate(url, UriKind.Absolute, out Uri uri))
    {
        Console.WriteLine($"载入失败:URL格式无效 - {url}");
        return false;
    }

    if (browser != null && browser.IsValid)
    {
        browser.GetMainFrame().LoadURL(url);
        Console.WriteLine($"正在载入地址: {url}");
        return true;
    }
    else
    {
        Console.WriteLine("载入失败:浏览器无效");
        return false;
    }
}

/// <summary>
/// 检查是否可以后退
/// </summary>
/// <returns>是否可以后退</returns>
public bool CheckCanGoBack()
{
    if (browser != null && browser.IsValid)
    {
        bool canGoBack = browser.CanGoBack();
        Console.WriteLine($"是否可以后退: {canGoBack}");
        return canGoBack;
    }
    return false;
}

/// <summary>
/// 后退到上一页
/// </summary>
public void NavigateBack()
{
    if (browser != null && browser.IsValid && browser.CanGoBack())
    {
        browser.GoBack();
        Console.WriteLine("已执行后退操作");
    }
    else
    {
        Console.WriteLine("无法后退:浏览器无效或已在第一页");
    }
}

/// <summary>
/// 检查是否可以前进
/// </summary>
/// <returns>是否可以前进</returns>
public bool CheckCanGoForward()
{
    if (browser != null && browser.IsValid)
    {
        bool canGoForward = browser.CanGoForward();
        Console.WriteLine($"是否可以前进: {canGoForward}");
        return canGoForward;
    }
    return false;
}

/// <summary>
/// 前进到下一页
/// </summary>
public void NavigateForward()
{
    if (browser != null && browser.IsValid && browser.CanGoForward())
    {
        browser.GoForward();
        Console.WriteLine("已执行前进操作");
    }
    else
    {
        Console.WriteLine("无法前进:浏览器无效或已在最后一页");
    }
}

2. 页面刷新和状态

csharp
/// <summary>
/// 检查页面是否正在加载
/// </summary>
/// <returns>是否正在加载</returns>
public bool CheckIsLoading()
{
    if (browser != null && browser.IsValid)
    {
        bool isLoading = browser.IsLoading();
        Console.WriteLine($"页面加载状态: {(isLoading ? "加载中" : "加载完成")}");
        return isLoading;
    }
    return false;
}

/// <summary>
/// 刷新当前页面
/// </summary>
public void RefreshPage()
{
    if (browser != null && browser.IsValid)
    {
        browser.Reload();
        Console.WriteLine("页面刷新已启动");
    }
    else
    {
        Console.WriteLine("无法刷新:浏览器实例无效");
    }
}

/// <summary>
/// 强制刷新页面(忽略缓存)
/// </summary>
public void ForceRefreshPage()
{
    if (browser != null && browser.IsValid)
    {
        browser.ReloadIgnoreCache();
        Console.WriteLine("强制刷新已启动(忽略缓存)");
    }
    else
    {
        Console.WriteLine("无法强制刷新:浏览器实例无效");
    }
}

/// <summary>
/// 停止页面加载
/// </summary>
public void StopPageLoad()
{
    if (browser != null && browser.IsValid)
    {
        browser.StopLoad();
        Console.WriteLine("页面加载已停止");
    }
    else
    {
        Console.WriteLine("无法停止加载:浏览器实例无效");
    }
}

窗口显示和管理

1. 窗口显示控制

csharp
/// <summary>
/// 显示浏览器窗口
/// </summary>
public void ShowBrowser()
{
    if (browser != null && browser.IsValid)
    {
        browser.ShowWindow(true);
        Console.WriteLine("浏览器窗口已显示");
    }
    else
    {
        Console.WriteLine("无法显示:浏览器实例无效");
    }
}

/// <summary>
/// 隐藏浏览器窗口
/// </summary>
public void HideBrowser()
{
    if (browser != null && browser.IsValid)
    {
        browser.ShowWindow(false);
        Console.WriteLine("浏览器窗口已隐藏");
    }
    else
    {
        Console.WriteLine("无法隐藏:浏览器实例无效");
    }
}

/// <summary>
/// 切换浏览器窗口显示状态
/// </summary>
/// <param name="show">是否显示</param>
public void ToggleBrowserVisibility(bool show)
{
    if (browser != null && browser.IsValid)
    {
        browser.ShowWindow(show);
        Console.WriteLine($"浏览器窗口已{(show ? "显示" : "隐藏")}");
    }
    else
    {
        Console.WriteLine("无法切换显示状态:浏览器实例无效");
    }
}

2. 窗口位置和大小

csharp
/// <summary>
/// 移动浏览器窗口
/// </summary>
/// <param name="x">X坐标</param>
/// <param name="y">Y坐标</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="repaint">是否重绘</param>
public void MoveBrowserWindow(int x, int y, int width, int height, bool repaint = true)
{
    if (browser != null && browser.IsValid)
    {
        browser.MoveWindow(x, y, width, height, repaint);
        Console.WriteLine($"浏览器窗口已移动到: ({x}, {y}), 大小: {width}x{height}");
    }
    else
    {
        Console.WriteLine("无法移动窗口:浏览器实例无效");
    }
}

/// <summary>
/// 设置浏览器父窗口
/// </summary>
/// <param name="parentHandle">父窗口句柄</param>
/// <returns>是否设置成功</returns>
public bool SetBrowserParent(IntPtr parentHandle)
{
    if (browser != null && browser.IsValid)
    {
        bool success = browser.SetParent(parentHandle);
        Console.WriteLine($"设置父窗口{(success ? "成功" : "失败")}");
        return success;
    }
    else
    {
        Console.WriteLine("无法设置父窗口:浏览器实例无效");
        return false;
    }
}

/// <summary>
/// 获取浏览器窗口句柄
/// </summary>
/// <returns>窗口句柄</returns>
public IntPtr GetBrowserWindowHandle()
{
    if (browser != null && browser.IsValid)
    {
        IntPtr handle = browser.GetWindowHandle();
        Console.WriteLine($"浏览器窗口句柄: {handle}");
        return handle;
    }
    else
    {
        Console.WriteLine("无法获取窗口句柄:浏览器实例无效");
        return IntPtr.Zero;
    }
}

/// <summary>
/// 获取打开者窗口句柄
/// </summary>
/// <returns>打开者窗口句柄</returns>
public IntPtr GetOpenerWindowHandle()
{
    if (browser != null && browser.IsValid)
    {
        IntPtr handle = browser.GetOpenerWindowHandle();
        Console.WriteLine($"打开者窗口句柄: {handle}");
        return handle;
    }
    else
    {
        Console.WriteLine("无法获取打开者窗口句柄:浏览器实例无效");
        return IntPtr.Zero;
    }
}

3. 缩放控制

csharp
/// <summary>
/// 获取当前缩放级别
/// </summary>
/// <returns>缩放级别</returns>
public double GetCurrentZoomLevel()
{
    if (browser != null && browser.IsValid)
    {
        double zoomLevel = browser.GetZoomLevel();
        Console.WriteLine($"当前缩放级别: {zoomLevel}");
        return zoomLevel;
    }
    else
    {
        Console.WriteLine("无法获取缩放级别:浏览器实例无效");
        return 0.0;
    }
}

/// <summary>
/// 设置缩放级别
/// </summary>
/// <param name="zoomLevel">缩放级别(0.0为默认,负值缩小,正值放大)</param>
public void SetZoomLevel(double zoomLevel)
{
    if (browser != null && browser.IsValid)
    {
        browser.SetZoomLevel(zoomLevel);
        Console.WriteLine($"缩放级别已设置为: {zoomLevel}");
    }
    else
    {
        Console.WriteLine("无法设置缩放级别:浏览器实例无效");
    }
}

/// <summary>
/// 重置缩放级别到默认值
/// </summary>
public void ResetZoomLevel()
{
    SetZoomLevel(0.0);
    Console.WriteLine("缩放级别已重置为默认值");
}

/// <summary>
/// 放大页面
/// </summary>
/// <param name="step">放大步长</param>
public void ZoomIn(double step = 0.5)
{
    if (browser != null && browser.IsValid)
    {
        double currentZoom = browser.GetZoomLevel();
        double newZoom = currentZoom + step;
        browser.SetZoomLevel(newZoom);
        Console.WriteLine($"页面已放大,缩放级别: {currentZoom} -> {newZoom}");
    }
}

/// <summary>
/// 缩小页面
/// </summary>
/// <param name="step">缩小步长</param>
public void ZoomOut(double step = 0.5)
{
    if (browser != null && browser.IsValid)
    {
        double currentZoom = browser.GetZoomLevel();
        double newZoom = currentZoom - step;
        browser.SetZoomLevel(newZoom);
        Console.WriteLine($"页面已缩小,缩放级别: {currentZoom} -> {newZoom}");
    }
}

浏览器关闭和生命周期

关闭方法

csharp
/// <summary>
/// 优雅关闭浏览器(允许用户确认)
/// </summary>
public void CloseBrowserGracefully()
{
    if (browser != null && browser.IsValid)
    {
        browser.CloseBrowser(false, false);
        Console.WriteLine("浏览器优雅关闭请求已发送");
    }
    else
    {
        Console.WriteLine("无法关闭:浏览器实例无效");
    }
}

/// <summary>
/// 强制关闭浏览器(不等待用户确认)
/// </summary>
public void CloseBrowserForce()
{
    if (browser != null && browser.IsValid)
    {
        browser.CloseBrowser(true, false);
        Console.WriteLine("浏览器强制关闭请求已发送");
    }
    else
    {
        Console.WriteLine("无法强制关闭:浏览器实例无效");
    }
}

/// <summary>
/// 立即关闭并清理浏览器
/// </summary>
public void CloseBrowserImmediate()
{
    if (browser != null && browser.IsValid)
    {
        browser.CloseBrowser(true, true);
        Console.WriteLine("浏览器立即关闭并清理");
    }
    else
    {
        Console.WriteLine("无法立即关闭:浏览器实例无效");
    }
}

/// <summary>
/// 尝试关闭浏览器
/// </summary>
/// <param name="setNull">是否立即设置为空</param>
/// <returns>是否关闭成功</returns>
public bool TryCloseBrowser(bool setNull = false)
{
    if (browser != null && browser.IsValid)
    {
        bool success = browser.TryCloseBrowser(setNull);
        Console.WriteLine($"尝试关闭浏览器{(success ? "成功" : "失败")}");
        return success;
    }
    else
    {
        Console.WriteLine("无法尝试关闭:浏览器实例无效");
        return false;
    }
}

浏览器信息获取

csharp
/// <summary>
/// 获取浏览器唯一标识符
/// </summary>
/// <returns>浏览器ID</returns>
public int GetBrowserIdentifier()
{
    if (browser != null && browser.IsValid)
    {
        int id = browser.GetIdentifier();
        Console.WriteLine($"浏览器ID: {id}");
        return id;
    }
    else
    {
        Console.WriteLine("无法获取浏览器ID:浏览器实例无效");
        return -1;
    }
}

/// <summary>
/// 比较两个浏览器是否为同一个实例
/// </summary>
/// <param name="otherBrowser">要比较的浏览器</param>
/// <returns>是否为同一个浏览器</returns>
public bool IsSameBrowser(IFBroSharpBrowser otherBrowser)
{
    if (browser != null && browser.IsValid && otherBrowser != null)
    {
        bool isSame = browser.IsSame(otherBrowser);
        Console.WriteLine($"是否为同一个浏览器: {isSame}");
        return isSame;
    }
    return false;
}

/// <summary>
/// 检查是否为弹出窗口
/// </summary>
/// <returns>是否为弹出窗口</returns>
public bool IsPopupWindow()
{
    if (browser != null && browser.IsValid)
    {
        bool isPopup = browser.IsPopup();
        Console.WriteLine($"是否为弹出窗口: {isPopup}");
        return isPopup;
    }
    return false;
}

/// <summary>
/// 检查是否有文档加载
/// </summary>
/// <returns>是否有文档</returns>
public bool HasDocumentLoaded()
{
    if (browser != null && browser.IsValid)
    {
        bool hasDocument = browser.HasDocument();
        Console.WriteLine($"是否有文档加载: {hasDocument}");
        return hasDocument;
    }
    return false;
}

/// <summary>
/// 获取窗口标题
/// </summary>
/// <returns>窗口标题</returns>
public string GetWindowTitle()
{
    if (browser != null && browser.IsValid)
    {
        string title = browser.GetWindowsTitle();
        Console.WriteLine($"窗口标题: {title}");
        return title;
    }
    else
    {
        Console.WriteLine("无法获取窗口标题:浏览器实例无效");
        return string.Empty;
    }
}

框架操作

框架获取方法

csharp
/// <summary>
/// 获取主框架
/// </summary>
/// <returns>主框架实例</returns>
public IFBroSharpFrame GetMainFrame()
{
    if (browser != null && browser.IsValid)
    {
        var mainFrame = browser.GetMainFrame();
        if (mainFrame != null)
        {
            Console.WriteLine("成功获取主框架");
            return mainFrame;
        }
        else
        {
            Console.WriteLine("主框架为空");
            return null;
        }
    }
    else
    {
        Console.WriteLine("无法获取主框架:浏览器实例无效");
        return null;
    }
}

/// <summary>
/// 获取焦点框架
/// </summary>
/// <returns>焦点框架实例</returns>
public IFBroSharpFrame GetFocusedFrame()
{
    if (browser != null && browser.IsValid)
    {
        var focusedFrame = browser.GetFocusedFrame();
        if (focusedFrame != null)
        {
            Console.WriteLine("成功获取焦点框架");
            return focusedFrame;
        }
        else
        {
            Console.WriteLine("焦点框架为空");
            return null;
        }
    }
    else
    {
        Console.WriteLine("无法获取焦点框架:浏览器实例无效");
        return null;
    }
}

/// <summary>
/// 通过ID获取框架
/// </summary>
/// <param name="frameId">框架ID</param>
/// <returns>框架实例</returns>
public IFBroSharpFrame GetFrameById(long frameId)
{
    if (browser != null && browser.IsValid)
    {
        var frame = browser.GetFrameById(frameId);
        if (frame != null)
        {
            Console.WriteLine($"成功获取框架 ID: {frameId}");
            return frame;
        }
        else
        {
            Console.WriteLine($"未找到框架 ID: {frameId}");
            return null;
        }
    }
    else
    {
        Console.WriteLine("无法获取框架:浏览器实例无效");
        return null;
    }
}

/// <summary>
/// 通过名称获取框架
/// </summary>
/// <param name="frameName">框架名称</param>
/// <returns>框架实例</returns>
public IFBroSharpFrame GetFrameByName(string frameName)
{
    if (browser != null && browser.IsValid)
    {
        var frame = browser.GetFrameByName(frameName);
        if (frame != null)
        {
            Console.WriteLine($"成功获取框架名称: {frameName}");
            return frame;
        }
        else
        {
            Console.WriteLine($"未找到框架名称: {frameName}");
            return null;
        }
    }
    else
    {
        Console.WriteLine("无法获取框架:浏览器实例无效");
        return null;
    }
}

/// <summary>
/// 获取所有框架ID
/// </summary>
/// <returns>框架ID列表</returns>
public List<long> GetAllFrameIds()
{
    if (browser != null && browser.IsValid)
    {
        var frameIds = browser.GetFrameIdentifiers();
        Console.WriteLine($"获取到 {frameIds.Count} 个框架ID");
        return frameIds;
    }
    else
    {
        Console.WriteLine("无法获取框架ID列表:浏览器实例无效");
        return new List<long>();
    }
}

/// <summary>
/// 获取框架数量
/// </summary>
/// <returns>框架数量</returns>
public int GetFrameCount()
{
    if (browser != null && browser.IsValid)
    {
        int count = browser.GetFrameCount();
        Console.WriteLine($"框架数量: {count}");
        return count;
    }
    else
    {
        Console.WriteLine("无法获取框架数量:浏览器实例无效");
        return 0;
    }
}

/// <summary>
/// 获取所有框架名称
/// </summary>
/// <returns>框架名称列表</returns>
public List<string> GetAllFrameNames()
{
    if (browser != null && browser.IsValid)
    {
        var frameNames = browser.GetFrameNames();
        Console.WriteLine($"获取到 {frameNames.Count} 个框架名称");
        return frameNames;
    }
    else
    {
        Console.WriteLine("无法获取框架名称列表:浏览器实例无效");
        return new List<string>();
    }
}

焦点和事件控制

焦点管理

csharp
/// <summary>
/// 设置浏览器焦点
/// </summary>
/// <param name="focus">是否获得焦点</param>
public void SetBrowserFocus(bool focus)
{
    if (browser != null && browser.IsValid)
    {
        browser.SetFocus(focus);
        Console.WriteLine($"浏览器焦点已{(focus ? "获得" : "失去")}");
    }
    else
    {
        Console.WriteLine("无法设置焦点:浏览器实例无效");
    }
}

/// <summary>
/// 发送焦点事件
/// </summary>
/// <param name="setFocus">是否设置焦点</param>
public void SendFocusEvent(bool setFocus)
{
    if (browser != null && browser.IsValid)
    {
        browser.SendFocusEvent(setFocus);
        Console.WriteLine($"焦点事件已发送: {(setFocus ? "获得焦点" : "失去焦点")}");
    }
    else
    {
        Console.WriteLine("无法发送焦点事件:浏览器实例无效");
    }
}

下载和文件操作

下载功能

csharp
/// <summary>
/// 开始下载指定URL
/// </summary>
/// <param name="url">下载URL</param>
public void StartDownload(string url)
{
    if (browser != null && browser.IsValid)
    {
        if (!string.IsNullOrEmpty(url))
        {
            browser.StartDownload(url);
            Console.WriteLine($"开始下载: {url}");
        }
        else
        {
            Console.WriteLine("下载URL不能为空");
        }
    }
    else
    {
        Console.WriteLine("无法开始下载:浏览器实例无效");
    }
}

/// <summary>
/// 下载图片
/// </summary>
/// <param name="imageUrl">图片URL</param>
/// <param name="isFavicon">是否为网站图标</param>
/// <param name="maxImageSize">最大图片大小</param>
/// <param name="bypassCache">是否绕过缓存</param>
/// <param name="callback">下载完成回调</param>
public void DownloadImage(string imageUrl, bool isFavicon = false, uint maxImageSize = 0, 
    bool bypassCache = false, FBroSharpDownloadImageCallback callback = null)
{
    if (browser != null && browser.IsValid)
    {
        if (!string.IsNullOrEmpty(imageUrl))
        {
            browser.DownloadImage(imageUrl, isFavicon, maxImageSize, bypassCache, callback);
            Console.WriteLine($"开始下载图片: {imageUrl}");
        }
        else
        {
            Console.WriteLine("图片URL不能为空");
        }
    }
    else
    {
        Console.WriteLine("无法下载图片:浏览器实例无效");
    }
}

打印功能

csharp
/// <summary>
/// 打印当前页面
/// </summary>
public void PrintCurrentPage()
{
    if (browser != null && browser.IsValid)
    {
        browser.Print();
        Console.WriteLine("打印对话框已打开");
    }
    else
    {
        Console.WriteLine("无法打印:浏览器实例无效");
    }
}

/// <summary>
/// 打印为PDF文件
/// </summary>
/// <param name="filePath">PDF文件路径</param>
/// <param name="pageWidth">页面宽度</param>
/// <param name="pageHeight">页面高度</param>
/// <param name="isLandscape">是否横向</param>
/// <param name="printBackground">是否打印背景</param>
/// <param name="callback">打印完成回调</param>
public void PrintToPDF(string filePath, int pageWidth = 210, int pageHeight = 297, 
    bool isLandscape = false, bool printBackground = false, 
    FBroSharpPdfPrintCallback callback = null)
{
    if (browser != null && browser.IsValid)
    {
        if (!string.IsNullOrEmpty(filePath))
        {
            // 设置边距类型为默认
            var marginType = FBroSharpPdfPrintMargintype.PDF_PRINT_MARGIN_DEFAULT;
            int landscape = isLandscape ? 1 : 0;
            
            browser.PrintToPDF(marginType, filePath, pageHeight, pageWidth, 
                landscape, printBackground, callback);
            Console.WriteLine($"开始生成PDF: {filePath}");
        }
        else
        {
            Console.WriteLine("PDF文件路径不能为空");
        }
    }
    else
    {
        Console.WriteLine("无法打印PDF:浏览器实例无效");
    }
}

文件对话框

csharp
/// <summary>
/// 打开文件选择对话框
/// </summary>
/// <param name="mode">对话框模式</param>
/// <param name="title">对话框标题</param>
/// <param name="defaultFileName">默认文件名</param>
/// <param name="acceptFilters">文件类型过滤器</param>
/// <param name="callback">选择完成回调</param>
public void ShowFileDialog(FBroSharpFileDialogModeType mode, string title = "", 
    string defaultFileName = "", List<string> acceptFilters = null, 
    FBroSharpFileDialogCallback callback = null)
{
    if (browser != null && browser.IsValid)
    {
        acceptFilters = acceptFilters ?? new List<string>();
        browser.RunFileDialog(mode, title, defaultFileName, acceptFilters, callback);
        Console.WriteLine($"文件对话框已打开,模式: {mode}");
    }
    else
    {
        Console.WriteLine("无法打开文件对话框:浏览器实例无效");
    }
}

/// <summary>
/// 打开文件选择对话框(简化版)
/// </summary>
/// <param name="callback">选择完成回调</param>
public void ShowOpenFileDialog(FBroSharpFileDialogCallback callback = null)
{
    var filters = new List<string> { "All Files|*.*", "Text Files|*.txt", "Image Files|*.jpg;*.png;*.gif" };
    ShowFileDialog(FBroSharpFileDialogModeType.FILE_DIALOG_OPEN, "选择文件", "", filters, callback);
}

/// <summary>
/// 打开保存文件对话框(简化版)
/// </summary>
/// <param name="defaultFileName">默认文件名</param>
/// <param name="callback">保存完成回调</param>
public void ShowSaveFileDialog(string defaultFileName = "document.txt", 
    FBroSharpFileDialogCallback callback = null)
{
    var filters = new List<string> { "Text Files|*.txt", "All Files|*.*" };
    ShowFileDialog(FBroSharpFileDialogModeType.FILE_DIALOG_SAVE, "保存文件", defaultFileName, filters, callback);
}

截图功能

基础截图方法

csharp
/// <summary>
/// 截取整个浏览器窗口
/// </summary>
/// <param name="filePath">保存路径</param>
/// <param name="format">图片格式</param>
/// <returns>是否截图成功</returns>
public bool CaptureWindow(string filePath, System.Drawing.Imaging.ImageFormat format = null)
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            format = format ?? System.Drawing.Imaging.ImageFormat.Png;
            var windowHandle = browser.GetWindowHandle();
            
            if (windowHandle != IntPtr.Zero)
            {
                // 获取窗口矩形
                RECT windowRect;
                GetWindowRect(windowHandle, out windowRect);
                
                int width = windowRect.Right - windowRect.Left;
                int height = windowRect.Bottom - windowRect.Top;
                
                using (var bitmap = new System.Drawing.Bitmap(width, height))
                using (var graphics = System.Drawing.Graphics.FromImage(bitmap))
                {
                    var hdc = graphics.GetHdc();
                    PrintWindow(windowHandle, hdc, 0);
                    graphics.ReleaseHdc(hdc);
                    
                    bitmap.Save(filePath, format);
                    Console.WriteLine($"窗口截图已保存: {filePath}");
                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"窗口截图失败: {ex.Message}");
        }
    }
    
    Console.WriteLine("无法截图:浏览器实例无效");
    return false;
}

/// <summary>
/// 截取浏览器内容区域(不包含边框)
/// </summary>
/// <param name="filePath">保存路径</param>
/// <param name="format">图片格式</param>
/// <returns>是否截图成功</returns>
public bool CaptureContent(string filePath, System.Drawing.Imaging.ImageFormat format = null)
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            format = format ?? System.Drawing.Imaging.ImageFormat.Png;
            var windowHandle = browser.GetWindowHandle();
            
            if (windowHandle != IntPtr.Zero)
            {
                // 获取客户区矩形
                RECT clientRect;
                GetClientRect(windowHandle, out clientRect);
                
                int width = clientRect.Right - clientRect.Left;
                int height = clientRect.Bottom - clientRect.Top;
                
                using (var bitmap = new System.Drawing.Bitmap(width, height))
                using (var graphics = System.Drawing.Graphics.FromImage(bitmap))
                {
                    var clientDC = GetDC(windowHandle);
                    var hdc = graphics.GetHdc();
                    
                    BitBlt(hdc, 0, 0, width, height, clientDC, 0, 0, SRCCOPY);
                    
                    graphics.ReleaseHdc(hdc);
                    ReleaseDC(windowHandle, clientDC);
                    
                    bitmap.Save(filePath, format);
                    Console.WriteLine($"内容截图已保存: {filePath}");
                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"内容截图失败: {ex.Message}");
        }
    }
    
    Console.WriteLine("无法截图:浏览器实例无效");
    return false;
}

/// <summary>
/// 截取指定区域
/// </summary>
/// <param name="filePath">保存路径</param>
/// <param name="x">X坐标</param>
/// <param name="y">Y坐标</param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="format">图片格式</param>
/// <returns>是否截图成功</returns>
public bool CaptureRegion(string filePath, int x, int y, int width, int height, 
    System.Drawing.Imaging.ImageFormat format = null)
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            format = format ?? System.Drawing.Imaging.ImageFormat.Png;
            var windowHandle = browser.GetWindowHandle();
            
            if (windowHandle != IntPtr.Zero)
            {
                using (var bitmap = new System.Drawing.Bitmap(width, height))
                using (var graphics = System.Drawing.Graphics.FromImage(bitmap))
                {
                    var clientDC = GetDC(windowHandle);
                    var hdc = graphics.GetHdc();
                    
                    BitBlt(hdc, 0, 0, width, height, clientDC, x, y, SRCCOPY);
                    
                    graphics.ReleaseHdc(hdc);
                    ReleaseDC(windowHandle, clientDC);
                    
                    bitmap.Save(filePath, format);
                    Console.WriteLine($"区域截图已保存: {filePath} (区域: {x},{y},{width}x{height})");
                    return true;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"区域截图失败: {ex.Message}");
        }
    }
    
    Console.WriteLine("无法截图:浏览器实例无效");
    return false;
}

高级截图方法

csharp
/// <summary>
/// 截取整个页面(包含滚动内容)
/// </summary>
/// <param name="filePath">保存路径</param>
/// <param name="format">图片格式</param>
/// <returns>是否截图成功</returns>
public async System.Threading.Tasks.Task<bool> CaptureFullPage(string filePath, 
    System.Drawing.Imaging.ImageFormat format = null)
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            format = format ?? System.Drawing.Imaging.ImageFormat.Png;
            
            // 获取页面总高度
            var mainFrame = browser.GetMainFrame();
            if (mainFrame == null) return false;
            
            // 执行JavaScript获取页面尺寸
            var script = @"
                (function() {
                    return {
                        width: Math.max(document.documentElement.scrollWidth, document.body.scrollWidth),
                        height: Math.max(document.documentElement.scrollHeight, document.body.scrollHeight),
                        viewportWidth: window.innerWidth,
                        viewportHeight: window.innerHeight
                    };
                })();
            ";
            
            // 这里需要实现JavaScript执行和结果获取
            // 由于是示例,我们使用简化的方法
            var windowHandle = browser.GetWindowHandle();
            RECT clientRect;
            GetClientRect(windowHandle, out clientRect);
            
            int viewportWidth = clientRect.Right - clientRect.Left;
            int viewportHeight = clientRect.Bottom - clientRect.Top;
            
            // 模拟获取页面总高度(实际应通过JavaScript获取)
            int totalHeight = viewportHeight * 3; // 假设页面高度是视口的3倍
            int totalWidth = viewportWidth;
            
            using (var fullBitmap = new System.Drawing.Bitmap(totalWidth, totalHeight))
            using (var fullGraphics = System.Drawing.Graphics.FromImage(fullBitmap))
            {
                int currentY = 0;
                int scrollStep = viewportHeight - 50; // 留50像素重叠
                
                while (currentY < totalHeight)
                {
                    // 滚动到指定位置
                    await ScrollToPosition(0, currentY);
                    await System.Threading.Tasks.Task.Delay(500); // 等待滚动完成
                    
                    // 截取当前视口
                    using (var viewportBitmap = new System.Drawing.Bitmap(viewportWidth, viewportHeight))
                    using (var viewportGraphics = System.Drawing.Graphics.FromImage(viewportBitmap))
                    {
                        var clientDC = GetDC(windowHandle);
                        var hdc = viewportGraphics.GetHdc();
                        
                        BitBlt(hdc, 0, 0, viewportWidth, viewportHeight, clientDC, 0, 0, SRCCOPY);
                        
                        viewportGraphics.ReleaseHdc(hdc);
                        ReleaseDC(windowHandle, clientDC);
                        
                        // 将视口图像绘制到完整图像上
                        fullGraphics.DrawImage(viewportBitmap, 0, currentY);
                    }
                    
                    currentY += scrollStep;
                }
                
                fullBitmap.Save(filePath, format);
                Console.WriteLine($"完整页面截图已保存: {filePath}");
                return true;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"完整页面截图失败: {ex.Message}");
        }
    }
    
    Console.WriteLine("无法截图:浏览器实例无效");
    return false;
}

/// <summary>
/// 滚动到指定位置
/// </summary>
/// <param name="x">X坐标</param>
/// <param name="y">Y坐标</param>
private async System.Threading.Tasks.Task ScrollToPosition(int x, int y)
{
    if (browser != null && browser.IsValid)
    {
        var mainFrame = browser.GetMainFrame();
        if (mainFrame != null)
        {
            var script = $"window.scrollTo({x}, {y});";
            // 这里需要执行JavaScript,具体实现依赖于FBro的JavaScript执行方法
            // mainFrame.ExecuteJavaScript(script, "", 0);
        }
    }
}

/// <summary>
/// 截图并返回字节数组
/// </summary>
/// <param name="format">图片格式</param>
/// <returns>图片字节数组</returns>
public byte[] CaptureToBytes(System.Drawing.Imaging.ImageFormat format = null)
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            format = format ?? System.Drawing.Imaging.ImageFormat.Png;
            var windowHandle = browser.GetWindowHandle();
            
            if (windowHandle != IntPtr.Zero)
            {
                RECT clientRect;
                GetClientRect(windowHandle, out clientRect);
                
                int width = clientRect.Right - clientRect.Left;
                int height = clientRect.Bottom - clientRect.Top;
                
                using (var bitmap = new System.Drawing.Bitmap(width, height))
                using (var graphics = System.Drawing.Graphics.FromImage(bitmap))
                {
                    var clientDC = GetDC(windowHandle);
                    var hdc = graphics.GetHdc();
                    
                    BitBlt(hdc, 0, 0, width, height, clientDC, 0, 0, SRCCOPY);
                    
                    graphics.ReleaseHdc(hdc);
                    ReleaseDC(windowHandle, clientDC);
                    
                    using (var memoryStream = new System.IO.MemoryStream())
                    {
                        bitmap.Save(memoryStream, format);
                        Console.WriteLine($"截图已转换为字节数组,大小: {memoryStream.Length} 字节");
                        return memoryStream.ToArray();
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"截图转字节数组失败: {ex.Message}");
        }
    }
    
    Console.WriteLine("无法截图:浏览器实例无效");
    return null;
}

/// <summary>
/// 截图并转换为Base64字符串
/// </summary>
/// <param name="format">图片格式</param>
/// <returns>Base64字符串</returns>
public string CaptureToBase64(System.Drawing.Imaging.ImageFormat format = null)
{
    var bytes = CaptureToBytes(format);
    if (bytes != null)
    {
        var base64 = Convert.ToBase64String(bytes);
        Console.WriteLine($"截图已转换为Base64字符串,长度: {base64.Length} 字符");
        return base64;
    }
    
    return null;
}

智能截图功能

csharp
/// <summary>
/// 智能截图管理器
/// </summary>
public class SmartScreenshotManager
{
    private readonly IFBroSharpBrowser _browser;
    private readonly string _outputDirectory;
    private int _screenshotCounter;

    public SmartScreenshotManager(IFBroSharpBrowser browser, string outputDirectory = null)
    {
        _browser = browser;
        _outputDirectory = outputDirectory ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Screenshots");
        _screenshotCounter = 1;
        
        // 确保输出目录存在
        if (!Directory.Exists(_outputDirectory))
        {
            Directory.CreateDirectory(_outputDirectory);
        }
    }

    /// <summary>
    /// 自动命名截图
    /// </summary>
    /// <param name="prefix">文件名前缀</param>
    /// <param name="format">图片格式</param>
    /// <returns>截图文件路径</returns>
    public string AutoCapture(string prefix = "screenshot", System.Drawing.Imaging.ImageFormat format = null)
    {
        format = format ?? System.Drawing.Imaging.ImageFormat.Png;
        var extension = GetImageExtension(format);
        var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
        var fileName = $"{prefix}_{timestamp}_{_screenshotCounter:D3}.{extension}";
        var filePath = Path.Combine(_outputDirectory, fileName);
        
        var browserController = new BrowserController(_browser); // 假设有这样的控制器
        if (browserController.CaptureContent(filePath, format))
        {
            _screenshotCounter++;
            return filePath;
        }
        
        return null;
    }

    /// <summary>
    /// 定时截图
    /// </summary>
    /// <param name="intervalSeconds">间隔秒数</param>
    /// <param name="maxCount">最大截图数量</param>
    /// <returns>截图任务</returns>
    public async System.Threading.Tasks.Task<List<string>> TimedCapture(int intervalSeconds, int maxCount = 10)
    {
        var capturedFiles = new List<string>();
        
        for (int i = 0; i < maxCount; i++)
        {
            if (_browser == null || !_browser.IsValid)
                break;
                
            var filePath = AutoCapture($"timed_{i + 1}");
            if (!string.IsNullOrEmpty(filePath))
            {
                capturedFiles.Add(filePath);
                Console.WriteLine($"定时截图 {i + 1}/{maxCount}: {filePath}");
            }
            
            if (i < maxCount - 1) // 最后一次不需要等待
            {
                await System.Threading.Tasks.Task.Delay(intervalSeconds * 1000);
            }
        }
        
        Console.WriteLine($"定时截图完成,共截取 {capturedFiles.Count} 张图片");
        return capturedFiles;
    }

    /// <summary>
    /// 比较两次截图的差异
    /// </summary>
    /// <param name="filePath1">第一张图片路径</param>
    /// <param name="filePath2">第二张图片路径</param>
    /// <returns>差异百分比</returns>
    public double CompareScreenshots(string filePath1, string filePath2)
    {
        try
        {
            using (var bitmap1 = new System.Drawing.Bitmap(filePath1))
            using (var bitmap2 = new System.Drawing.Bitmap(filePath2))
            {
                if (bitmap1.Width != bitmap2.Width || bitmap1.Height != bitmap2.Height)
                {
                    Console.WriteLine("图片尺寸不同,无法比较");
                    return -1;
                }

                int totalPixels = bitmap1.Width * bitmap1.Height;
                int differentPixels = 0;

                for (int x = 0; x < bitmap1.Width; x++)
                {
                    for (int y = 0; y < bitmap1.Height; y++)
                    {
                        var pixel1 = bitmap1.GetPixel(x, y);
                        var pixel2 = bitmap2.GetPixel(x, y);
                        
                        if (pixel1 != pixel2)
                        {
                            differentPixels++;
                        }
                    }
                }

                double differencePercentage = (double)differentPixels / totalPixels * 100;
                Console.WriteLine($"图片差异: {differencePercentage:F2}%");
                return differencePercentage;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"比较截图失败: {ex.Message}");
            return -1;
        }
    }

    /// <summary>
    /// 清理旧截图
    /// </summary>
    /// <param name="daysToKeep">保留天数</param>
    public void CleanupOldScreenshots(int daysToKeep = 7)
    {
        try
        {
            var cutoffDate = DateTime.Now.AddDays(-daysToKeep);
            var files = Directory.GetFiles(_outputDirectory, "*.png")
                .Concat(Directory.GetFiles(_outputDirectory, "*.jpg"))
                .Concat(Directory.GetFiles(_outputDirectory, "*.bmp"));

            int deletedCount = 0;
            foreach (var file in files)
            {
                var fileInfo = new FileInfo(file);
                if (fileInfo.CreationTime < cutoffDate)
                {
                    File.Delete(file);
                    deletedCount++;
                }
            }

            Console.WriteLine($"清理完成,删除了 {deletedCount} 个旧截图文件");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"清理截图失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取图片格式对应的文件扩展名
    /// </summary>
    private string GetImageExtension(System.Drawing.Imaging.ImageFormat format)
    {
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Png)) return "png";
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Jpeg)) return "jpg";
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Bmp)) return "bmp";
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Gif)) return "gif";
        return "png"; // 默认
    }
}

/// <summary>
/// 截图配置类
/// </summary>
public class ScreenshotConfig
{
    public System.Drawing.Imaging.ImageFormat Format { get; set; } = System.Drawing.Imaging.ImageFormat.Png;
    public string OutputDirectory { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Screenshots");
    public string FileNamePrefix { get; set; } = "browser_screenshot";
    public bool IncludeTimestamp { get; set; } = true;
    public bool AutoCreateDirectory { get; set; } = true;
    public int Quality { get; set; } = 95; // JPEG质量
}

/// <summary>
/// 高级截图控制器
/// </summary>
public class AdvancedScreenshotController
{
    private readonly IFBroSharpBrowser _browser;
    private readonly ScreenshotConfig _config;

    public AdvancedScreenshotController(IFBroSharpBrowser browser, ScreenshotConfig config = null)
    {
        _browser = browser;
        _config = config ?? new ScreenshotConfig();
        
        if (_config.AutoCreateDirectory && !Directory.Exists(_config.OutputDirectory))
        {
            Directory.CreateDirectory(_config.OutputDirectory);
        }
    }

    /// <summary>
    /// 配置化截图
    /// </summary>
    /// <param name="customFileName">自定义文件名</param>
    /// <returns>截图文件路径</returns>
    public string CaptureWithConfig(string customFileName = null)
    {
        try
        {
            string fileName;
            if (!string.IsNullOrEmpty(customFileName))
            {
                fileName = customFileName;
            }
            else
            {
                var timestamp = _config.IncludeTimestamp ? DateTime.Now.ToString("_yyyyMMdd_HHmmss") : "";
                var extension = GetExtensionFromFormat(_config.Format);
                fileName = $"{_config.FileNamePrefix}{timestamp}.{extension}";
            }

            var filePath = Path.Combine(_config.OutputDirectory, fileName);
            
            // 这里需要调用实际的截图方法
            var browserController = new BrowserController(_browser);
            if (browserController.CaptureContent(filePath, _config.Format))
            {
                Console.WriteLine($"配置化截图完成: {filePath}");
                return filePath;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"配置化截图失败: {ex.Message}");
        }
        
        return null;
    }

    private string GetExtensionFromFormat(System.Drawing.Imaging.ImageFormat format)
    {
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Png)) return "png";
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Jpeg)) return "jpg";
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Bmp)) return "bmp";
        if (format.Equals(System.Drawing.Imaging.ImageFormat.Gif)) return "gif";
        return "png";
    }
}

### Windows API 声明

```csharp
/// <summary>
/// Windows API 声明
/// </summary>
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, uint nFlags);

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, 
    IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);

private const uint SRCCOPY = 0x00CC0020;

查找功能

页面内容查找

csharp
/// <summary>
/// 在页面中查找文本
/// </summary>
/// <param name="searchText">要查找的文本</param>
/// <param name="forward">是否向前查找</param>
/// <param name="matchCase">是否区分大小写</param>
/// <param name="findNext">是否查找下一个</param>
public void FindInPage(string searchText, bool forward = true, bool matchCase = false, bool findNext = false)
{
    if (browser != null && browser.IsValid)
    {
        if (!string.IsNullOrEmpty(searchText))
        {
            browser.Find(searchText, forward, matchCase, findNext);
            Console.WriteLine($"开始查找: '{searchText}' (方向: {(forward ? "向前" : "向后")}, 大小写: {(matchCase ? "区分" : "不区分")})");
        }
        else
        {
            Console.WriteLine("查找文本不能为空");
        }
    }
    else
    {
        Console.WriteLine("无法查找:浏览器实例无效");
    }
}

/// <summary>
/// 查找下一个匹配项
/// </summary>
/// <param name="searchText">查找文本</param>
/// <param name="matchCase">是否区分大小写</param>
public void FindNext(string searchText, bool matchCase = false)
{
    FindInPage(searchText, true, matchCase, true);
}

/// <summary>
/// 查找上一个匹配项
/// </summary>
/// <param name="searchText">查找文本</param>
/// <param name="matchCase">是否区分大小写</param>
public void FindPrevious(string searchText, bool matchCase = false)
{
    FindInPage(searchText, false, matchCase, true);
}

/// <summary>
/// 停止查找
/// </summary>
/// <param name="clearSelection">是否清除选中内容</param>
public void StopFinding(bool clearSelection = true)
{
    if (browser != null && browser.IsValid)
    {
        browser.StopFinding(clearSelection);
        Console.WriteLine($"查找已停止{(clearSelection ? ",选中内容已清除" : "")}");
    }
    else
    {
        Console.WriteLine("无法停止查找:浏览器实例无效");
    }
}

音频控制

音频静音管理

csharp
/// <summary>
/// 检查页面是否静音
/// </summary>
/// <returns>是否静音</returns>
public bool IsPageMuted()
{
    if (browser != null && browser.IsValid)
    {
        bool isMuted = browser.IsAudioMuted();
        Console.WriteLine($"页面音频状态: {(isMuted ? "静音" : "正常")}");
        return isMuted;
    }
    else
    {
        Console.WriteLine("无法检查音频状态:浏览器实例无效");
        return false;
    }
}

/// <summary>
/// 设置页面静音状态
/// </summary>
/// <param name="mute">是否静音</param>
public void SetPageMute(bool mute)
{
    if (browser != null && browser.IsValid)
    {
        browser.SetAudioMuted(mute);
        Console.WriteLine($"页面音频已{(mute ? "静音" : "取消静音")}");
    }
    else
    {
        Console.WriteLine("无法设置音频状态:浏览器实例无效");
    }
}

/// <summary>
/// 切换页面静音状态
/// </summary>
public void TogglePageMute()
{
    if (browser != null && browser.IsValid)
    {
        bool currentMute = browser.IsAudioMuted();
        browser.SetAudioMuted(!currentMute);
        Console.WriteLine($"页面音频已{(!currentMute ? "静音" : "取消静音")}");
    }
    else
    {
        Console.WriteLine("无法切换音频状态:浏览器实例无效");
    }
}

高级功能

自动调整大小

csharp
/// <summary>
/// 设置自动调整大小
/// </summary>
/// <param name="enabled">是否启用自动调整</param>
/// <param name="minWidth">最小宽度</param>
/// <param name="minHeight">最小高度</param>
/// <param name="maxWidth">最大宽度</param>
/// <param name="maxHeight">最大高度</param>
public void SetAutoResize(bool enabled, int minWidth = 100, int minHeight = 100, 
    int maxWidth = 1920, int maxHeight = 1080)
{
    if (browser != null && browser.IsValid)
    {
        browser.SetAutoResizeEnabled(enabled, minHeight, minWidth, maxHeight, maxWidth);
        Console.WriteLine($"自动调整大小已{(enabled ? "启用" : "禁用")}");
        if (enabled)
        {
            Console.WriteLine($"尺寸范围: {minWidth}x{minHeight} - {maxWidth}x{maxHeight}");
        }
    }
    else
    {
        Console.WriteLine("无法设置自动调整大小:浏览器实例无效");
    }
}

浏览器视图检查

csharp
/// <summary>
/// 检查是否有浏览器视图
/// </summary>
/// <returns>是否有视图</returns>
public bool HasBrowserView()
{
    if (browser != null && browser.IsValid)
    {
        bool hasView = browser.HasView();
        Console.WriteLine($"是否有浏览器视图: {hasView}");
        return hasView;
    }
    return false;
}

/// <summary>
/// 检查是否为后台主机
/// </summary>
/// <returns>是否为后台主机</returns>
public bool IsBackgroundHost()
{
    if (browser != null && browser.IsValid)
    {
        bool isBackground = browser.IsBackgroundHost();
        Console.WriteLine($"是否为后台主机: {isBackground}");
        return isBackground;
    }
    return false;
}

开发者工具管理

csharp
/// <summary>
/// 打开开发者工具
/// </summary>
/// <param name="title">开发者工具窗口标题</param>
/// <param name="parent">父窗口句柄</param>
/// <param name="x">窗口X坐标</param>
/// <param name="y">窗口Y坐标</param>
/// <param name="width">窗口宽度</param>
/// <param name="height">窗口高度</param>
/// <param name="browserSettings">浏览器设置信息(可选)</param>
/// <param name="elementAt">要检查的元素位置(可选)</param>
/// <param name="browserEvent">浏览器事件处理器(可选)</param>
/// <param name="eventControl">事件控制器(可选)</param>
public void ShowDevTools(string title = "开发者工具", IntPtr parent = default, 
    int x = 100, int y = 100, int width = 1200, int height = 800,
    FBroSharpBrowserSetting browserSettings = null,
    FBroSharpElementAt elementAt = null,
    FBroSharpBrowserEvent browserEvent = null,
    FBroSharpEventDisableControl eventControl = null)
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            browser.ShowDevTools(title, parent, x, y, width, height, 
                browserSettings, elementAt, browserEvent, eventControl);
            Console.WriteLine($"开发者工具已打开 - 标题: {title}, 位置: ({x}, {y}), 大小: {width}x{height}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"打开开发者工具失败: {ex.Message}");
        }
    }
    else
    {
        Console.WriteLine("无法打开开发者工具:浏览器实例无效");
    }
}

/// <summary>
/// 关闭开发者工具
/// </summary>
public void CloseDevTools()
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            browser.CloseDevTools();
            Console.WriteLine("开发者工具已关闭");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"关闭开发者工具失败: {ex.Message}");
        }
    }
    else
    {
        Console.WriteLine("无法关闭开发者工具:浏览器实例无效");
    }
}

/// <summary>
/// 检查是否为开发者工具浏览器
/// </summary>
/// <returns>是否为开发者工具</returns>
public bool IsDevToolsBrowser()
{
    if (browser != null && browser.IsValid)
    {
        bool isDevTools = browser.IsDevTools();
        Console.WriteLine($"是否为开发者工具: {isDevTools}");
        return isDevTools;
    }
    return false;
}

/// <summary>
/// 打开开发者工具并检查指定元素
/// </summary>
/// <param name="elementX">元素X坐标</param>
/// <param name="elementY">元素Y坐标</param>
/// <param name="title">窗口标题</param>
public void ShowDevToolsAndInspectElement(int elementX, int elementY, string title = "元素检查器")
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            // 创建元素位置对象
            var elementAt = new FBroSharpElementAt
            {
                X = elementX,
                Y = elementY
            };
            
            ShowDevTools(title, IntPtr.Zero, 100, 100, 1200, 800, null, elementAt);
            Console.WriteLine($"已打开开发者工具并检查元素 ({elementX}, {elementY})");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"检查元素失败: {ex.Message}");
        }
    }
    else
    {
        Console.WriteLine("无法检查元素:浏览器实例无效");
    }
}

/// <summary>
/// 快速打开开发者工具(使用默认设置)
/// </summary>
public void QuickShowDevTools()
{
    ShowDevTools("DevTools", IntPtr.Zero, 200, 200, 1000, 600);
}

/// <summary>
/// 切换开发者工具显示状态
/// </summary>
public void ToggleDevTools()
{
    if (browser != null && browser.IsValid)
    {
        if (IsDevToolsBrowser())
        {
            Console.WriteLine("当前浏览器实例为开发者工具,无法切换");
            return;
        }
        
        // 简单的切换逻辑:尝试关闭,如果没有开发者工具则打开
        try
        {
            // 先尝试关闭
            CloseDevTools();
            
            // 等待一小段时间后打开(如果之前没有开发者工具的话)
            System.Threading.Thread.Sleep(100);
            QuickShowDevTools();
        }
        catch
        {
            // 如果关闭失败,可能是没有开发者工具,直接打开
            QuickShowDevTools();
        }
    }
    else
    {
        Console.WriteLine("无法切换开发者工具:浏览器实例无效");
    }
}

用户标识和额外数据

csharp
/// <summary>
/// 获取用户标识
/// </summary>
/// <returns>用户标识</returns>
public string GetUserFlag()
{
    if (browser != null && browser.IsValid)
    {
        string userFlag = browser.GetUserFlag();
        Console.WriteLine($"用户标识: {userFlag}");
        return userFlag;
    }
    else
    {
        Console.WriteLine("无法获取用户标识:浏览器实例无效");
        return string.Empty;
    }
}

/// <summary>
/// 获取额外数据
/// </summary>
/// <returns>额外数据字典</returns>
public IFBroSharpDictionaryValue GetExtraInfo()
{
    if (browser != null && browser.IsValid)
    {
        var extraInfo = browser.GetExtrainfo();
        Console.WriteLine("额外数据已获取");
        return extraInfo;
    }
    else
    {
        Console.WriteLine("无法获取额外数据:浏览器实例无效");
        return null;
    }
}

性能监控

内存使用监控

csharp
using System.Diagnostics;

/// <summary>
/// 获取浏览器进程内存使用情况
/// </summary>
/// <returns>内存使用信息</returns>
public BrowserMemoryInfo GetBrowserMemoryUsage()
{
    if (browser != null && browser.IsValid)
    {
        try
        {
            var windowHandle = browser.GetWindowHandle();
            if (windowHandle != IntPtr.Zero)
            {
                // 通过窗口句柄获取进程ID
                uint processId;
                GetWindowThreadProcessId(windowHandle, out processId);
                
                var process = Process.GetProcessById((int)processId);
                var memoryInfo = new BrowserMemoryInfo
                {
                    WorkingSet = process.WorkingSet64,
                    PrivateMemory = process.PrivateMemorySize64,
                    VirtualMemory = process.VirtualMemorySize64,
                    PagedMemory = process.PagedMemorySize64,
                    NonPagedMemory = process.NonpagedSystemMemorySize64,
                    PeakWorkingSet = process.PeakWorkingSet64,
                    PeakVirtualMemory = process.PeakVirtualMemorySize64
                };
                
                Console.WriteLine($"浏览器内存使用 - 工作集: {FormatBytes(memoryInfo.WorkingSet)}, " +
                                $"私有内存: {FormatBytes(memoryInfo.PrivateMemory)}");
                
                return memoryInfo;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"获取内存使用失败: {ex.Message}");
        }
    }
    
    Console.WriteLine("无法获取内存使用:浏览器实例无效");
    return new BrowserMemoryInfo();
}

/// <summary>
/// 获取当前工作集内存(简化版)
/// </summary>
/// <returns>工作集内存大小(字节)</returns>
public long GetWorkingSetMemory()
{
    var memoryInfo = GetBrowserMemoryUsage();
    return memoryInfo.WorkingSet;
}

/// <summary>
/// 获取私有内存使用(简化版)
/// </summary>
/// <returns>私有内存大小(字节)</returns>
public long GetPrivateMemory()
{
    var memoryInfo = GetBrowserMemoryUsage();
    return memoryInfo.PrivateMemory;
}

/// <summary>
/// 检查内存使用是否超过阈值
/// </summary>
/// <param name="thresholdMB">阈值(MB)</param>
/// <returns>是否超过阈值</returns>
public bool IsMemoryUsageExceeded(long thresholdMB)
{
    var workingSetMB = GetWorkingSetMemory() / (1024 * 1024);
    bool exceeded = workingSetMB > thresholdMB;
    
    Console.WriteLine($"当前内存使用: {workingSetMB}MB, 阈值: {thresholdMB}MB, " +
                     $"状态: {(exceeded ? "超过" : "正常")}");
    
    return exceeded;
}

/// <summary>
/// Windows API - 获取窗口对应的进程ID
/// </summary>
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);

/// <summary>
/// 格式化字节数为易读格式
/// </summary>
/// <param name="bytes">字节数</param>
/// <returns>格式化后的字符串</returns>
private static string FormatBytes(long bytes)
{
    string[] sizes = { "B", "KB", "MB", "GB", "TB" };
    double len = bytes;
    int order = 0;
    
    while (len >= 1024 && order < sizes.Length - 1)
    {
        order++;
        len = len / 1024;
    }
    
    return $"{len:0.##} {sizes[order]}";
}

/// <summary>
/// 浏览器内存信息
/// </summary>
public class BrowserMemoryInfo
{
    public long WorkingSet { get; set; }
    public long PrivateMemory { get; set; }
    public long VirtualMemory { get; set; }
    public long PagedMemory { get; set; }
    public long NonPagedMemory { get; set; }
    public long PeakWorkingSet { get; set; }
    public long PeakVirtualMemory { get; set; }
}

使用场景和最佳实践

场景1:基础浏览器控制

csharp
/// <summary>
/// 基础浏览器控制示例
/// </summary>
public void BasicBrowserControlExample()
{
    // 检查浏览器有效性
    if (!browser.IsValid)
    {
        Console.WriteLine("浏览器无效,无法执行操作");
        return;
    }
    
    // 显示浏览器
    ShowBrowser();
    
    // 设置合适的缩放级别
    SetZoomLevel(0.0); // 默认缩放
    
    // 获取基本信息
    var browserId = GetBrowserIdentifier();
    var title = GetWindowTitle();
    
    Console.WriteLine($"浏览器控制示例完成 - ID: {browserId}, 标题: {title}");
}

场景2:窗口管理

csharp
/// <summary>
/// 窗口管理示例
/// </summary>
public void WindowManagementExample()
{
    if (!browser.IsValid) return;
    
    // 获取当前窗口句柄
    var handle = GetBrowserWindowHandle();
    
    // 移动并调整窗口大小
    MoveBrowserWindow(100, 100, 1200, 800);
    
    // 设置焦点
    SetBrowserFocus(true);
    
    // 显示窗口
    ShowBrowser();
    
    Console.WriteLine("窗口管理完成");
}

场景3:内容操作

csharp
/// <summary>
/// 内容操作示例
/// </summary>
public void ContentOperationExample()
{
    if (!browser.IsValid) return;
    
    // 等待页面加载完成
    while (CheckIsLoading())
    {
        System.Threading.Thread.Sleep(100);
    }
    
    // 在页面中查找内容
    FindInPage("关键词", true, false, false);
    
    // 打印页面
    PrintCurrentPage();
    
    Console.WriteLine("内容操作完成");
}

场景4:截图功能

csharp
/// <summary>
/// 基础截图示例
/// </summary>
public void BasicScreenshotExample()
{
    if (!browser.IsValid) return;
    
    var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
    
    // 截取整个浏览器窗口
    var windowScreenshotPath = $@"C:\Screenshots\window_{timestamp}.png";
    if (CaptureWindow(windowScreenshotPath))
    {
        Console.WriteLine($"窗口截图保存成功: {windowScreenshotPath}");
    }
    
    // 截取浏览器内容区域
    var contentScreenshotPath = $@"C:\Screenshots\content_{timestamp}.png";
    if (CaptureContent(contentScreenshotPath))
    {
        Console.WriteLine($"内容截图保存成功: {contentScreenshotPath}");
    }
    
    // 截取指定区域 (左上角 100x100 像素区域)
    var regionScreenshotPath = $@"C:\Screenshots\region_{timestamp}.png";
    if (CaptureRegion(regionScreenshotPath, 0, 0, 100, 100))
    {
        Console.WriteLine($"区域截图保存成功: {regionScreenshotPath}");
    }
    
    // 获取截图的Base64编码
    var base64Screenshot = CaptureToBase64();
    if (!string.IsNullOrEmpty(base64Screenshot))
    {
        Console.WriteLine($"Base64截图获取成功,长度: {base64Screenshot.Length}");
        // 可以将Base64字符串发送到服务器或保存到数据库
    }
    
    Console.WriteLine("基础截图示例完成");
}

/// <summary>
/// 高级截图示例
/// </summary>
public async void AdvancedScreenshotExample()
{
    if (!browser.IsValid) return;
    
    // 智能截图管理器
    var screenshotManager = new SmartScreenshotManager(browser, @"C:\Screenshots");
    
    // 自动命名截图
    var autoPath = screenshotManager.AutoCapture("test_page");
    Console.WriteLine($"自动截图保存: {autoPath}");
    
    // 定时截图 - 每5秒截图一次,共截图3次
    var timedScreenshots = await screenshotManager.TimedCapture(5, 3);
    Console.WriteLine($"定时截图完成,共 {timedScreenshots.Count} 张图片");
    
    // 截取完整页面(包含滚动内容)
    var fullPagePath = $@"C:\Screenshots\fullpage_{DateTime.Now:yyyyMMdd_HHmmss}.png";
    var success = await CaptureFullPage(fullPagePath);
    if (success)
    {
        Console.WriteLine($"完整页面截图保存: {fullPagePath}");
    }
    
    // 比较两张截图的差异
    if (timedScreenshots.Count >= 2)
    {
        var difference = screenshotManager.CompareScreenshots(timedScreenshots[0], timedScreenshots[1]);
        Console.WriteLine($"前两张截图差异: {difference:F2}%");
    }
    
    // 清理7天前的旧截图
    screenshotManager.CleanupOldScreenshots(7);
    
    Console.WriteLine("高级截图示例完成");
}

/// <summary>
/// 配置化截图示例
/// </summary>
public void ConfigurableScreenshotExample()
{
    if (!browser.IsValid) return;
    
    // 创建截图配置
    var config = new ScreenshotConfig
    {
        Format = System.Drawing.Imaging.ImageFormat.Jpeg,
        OutputDirectory = @"C:\Screenshots\JPEG",
        FileNamePrefix = "browser_capture",
        IncludeTimestamp = true,
        Quality = 95
    };
    
    // 高级截图控制器
    var screenshotController = new AdvancedScreenshotController(browser, config);
    
    // 使用配置进行截图
    var configuredPath = screenshotController.CaptureWithConfig();
    Console.WriteLine($"配置化截图完成: {configuredPath}");
    
    // 自定义文件名截图
    var customPath = screenshotController.CaptureWithConfig("custom_name.jpg");
    Console.WriteLine($"自定义名称截图完成: {customPath}");
    
    Console.WriteLine("配置化截图示例完成");
}

场景5:性能监控

csharp
/// <summary>
/// 性能监控示例
/// </summary>
public void PerformanceMonitoringExample()
{
    if (!browser.IsValid) return;
    
    // 获取基本性能信息
    var performance = GetBrowserPerformance();
    Console.WriteLine($"浏览器ID: {performance.BrowserId}");
    Console.WriteLine($"内存使用: {FormatBytes(performance.MemoryInfo.WorkingSet)}");
    Console.WriteLine($"CPU使用率: {performance.CpuUsagePercentage:F2}%");
    Console.WriteLine($"线程数: {performance.CpuInfo.ThreadCount}");
    
    // 检查性能警报
    var alert = CheckPerformanceAlert(500, 80.0); // 500MB内存阈值,80%CPU阈值
    if (alert.HasAnyAlert)
    {
        if (alert.HasMemoryAlert)
        {
            Console.WriteLine($"内存警报: 当前使用 {alert.MemoryUsageMB}MB,超过阈值 {alert.MemoryThresholdMB}MB");
        }
        if (alert.HasCpuAlert)
        {
            Console.WriteLine($"CPU警报: 当前使用率 {alert.CpuUsagePercentage:F2}%,超过阈值 {alert.CpuThresholdPercentage}%");
        }
    }
    
    Console.WriteLine("性能监控完成");
}

/// <summary>
/// 持续性能监控示例
/// </summary>
public async void ContinuousPerformanceMonitoringExample()
{
    if (!browser.IsValid) return;
    
    // 启动性能监控,每5秒检查一次
    var monitoringTask = StartPerformanceMonitoring(5000, (performance) =>
    {
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] " +
                         $"内存: {FormatBytes(performance.MemoryInfo.WorkingSet)}, " +
                         $"CPU: {performance.CpuUsagePercentage:F1}%, " +
                         $"线程: {performance.CpuInfo.ThreadCount}");
        
        // 检查是否需要优化
        if (performance.MemoryInfo.WorkingSet > 500 * 1024 * 1024) // 超过500MB
        {
            Console.WriteLine("警告: 内存使用过高,建议优化");
        }
        
        if (performance.CpuUsagePercentage > 80.0) // 超过80%
        {
            Console.WriteLine("警告: CPU使用率过高,建议优化");
        }
    });
    
    // 监控10分钟后停止
    await System.Threading.Tasks.Task.Delay(TimeSpan.FromMinutes(10));
    Console.WriteLine("性能监控已停止");
}

/// <summary>
/// 性能管理器使用示例
/// </summary>
public void PerformanceManagerExample()
{
    if (!browser.IsValid) return;
    
    var manager = new BrowserPerformanceManager(browser);
    
    // 启动监控
    manager.StartMonitoring();
    
    // 获取实时报告
    var report = manager.GetCurrentReport();
    Console.WriteLine($"性能报告: {report}");
    
    // 停止监控
    manager.StopMonitoring();
}

场景6:开发者工具调试

csharp
/// <summary>
/// 基础开发者工具使用示例
/// </summary>
public void BasicDevToolsExample()
{
    if (!browser.IsValid) return;
    
    Console.WriteLine("开始开发者工具调试示例");
    
    // 快速打开开发者工具
    QuickShowDevTools();
    
    // 等待一段时间,让用户查看
    System.Threading.Thread.Sleep(2000);
    
    // 关闭开发者工具
    CloseDevTools();
    
    Console.WriteLine("基础开发者工具示例完成");
}

/// <summary>
/// 元素检查调试示例
/// </summary>
public void ElementInspectionExample()
{
    if (!browser.IsValid) return;
    
    Console.WriteLine("开始元素检查调试");
    
    // 在页面中心位置检查元素
    var centerX = 400; // 假设页面宽度800px
    var centerY = 300; // 假设页面高度600px
    
    ShowDevToolsAndInspectElement(centerX, centerY, "元素检查器");
    
    Console.WriteLine($"已打开开发者工具并检查元素 ({centerX}, {centerY})");
    
    // 可以继续检查其他元素
    System.Threading.Thread.Sleep(3000);
    
    // 检查页面顶部的元素
    ShowDevToolsAndInspectElement(200, 50, "页面顶部检查");
    
    Console.WriteLine("元素检查示例完成");
}

/// <summary>
/// 自定义开发者工具窗口示例
/// </summary>
public void CustomDevToolsWindowExample()
{
    if (!browser.IsValid) return;
    
    Console.WriteLine("开始自定义开发者工具窗口示例");
    
    // 获取当前浏览器窗口句柄作为父窗口
    var parentHandle = GetBrowserWindowHandle();
    
    // 创建自定义位置和大小的开发者工具
    ShowDevTools(
        title: "自定义调试器",
        parent: parentHandle,
        x: 50,          // 距离屏幕左边50px
        y: 50,          // 距离屏幕顶部50px
        width: 1400,    // 宽度1400px
        height: 900     // 高度900px
    );
    
    Console.WriteLine("自定义开发者工具窗口已打开");
    
    // 等待用户使用
    System.Threading.Thread.Sleep(5000);
    
    // 关闭工具
    CloseDevTools();
    
    Console.WriteLine("自定义开发者工具窗口示例完成");
}

/// <summary>
/// 调试工作流程示例
/// </summary>
public void DebuggingWorkflowExample()
{
    if (!browser.IsValid) return;
    
    Console.WriteLine("开始调试工作流程示例");
    
    try
    {
        // 步骤1:检查浏览器状态
        if (IsDevToolsBrowser())
        {
            Console.WriteLine("当前为开发者工具浏览器,无法执行调试操作");
            return;
        }
        
        // 步骤2:等待页面加载完成
        Console.WriteLine("等待页面加载完成...");
        while (CheckIsLoading())
        {
            System.Threading.Thread.Sleep(500);
        }
        
        // 步骤3:打开开发者工具进行调试
        Console.WriteLine("打开开发者工具...");
        ShowDevTools("页面调试器", IntPtr.Zero, 100, 100, 1200, 800);
        
        // 步骤4:模拟调试时间
        Console.WriteLine("调试中,请在开发者工具中进行操作...");
        System.Threading.Thread.Sleep(10000); // 给用户10秒时间调试
        
        // 步骤5:检查特定元素
        Console.WriteLine("检查页面表单元素...");
        ShowDevToolsAndInspectElement(300, 200, "表单检查器");
        
        // 步骤6:调试完成后清理
        System.Threading.Thread.Sleep(5000);
        Console.WriteLine("调试完成,关闭开发者工具...");
        CloseDevTools();
        
        Console.WriteLine("调试工作流程示例完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"调试工作流程出错: {ex.Message}");
        
        // 确保关闭开发者工具
        try
        {
            CloseDevTools();
        }
        catch
        {
            // 忽略关闭时的错误
        }
    }
}

/// <summary>
/// 开发者工具管理器示例
/// </summary>
public class DevToolsManager
{
    private readonly IFBroSharpBrowser browser;
    private bool isDevToolsOpen = false;
    
    public DevToolsManager(IFBroSharpBrowser browser)
    {
        this.browser = browser;
    }
    
    /// <summary>
    /// 智能切换开发者工具
    /// </summary>
    public void SmartToggle()
    {
        if (!browser.IsValid) return;
        
        if (isDevToolsOpen)
        {
            CloseDevTools();
            isDevToolsOpen = false;
            Console.WriteLine("开发者工具已关闭");
        }
        else
        {
            browser.ShowDevTools("智能调试器", IntPtr.Zero, 200, 200, 1000, 700, 
                null, null, null, null);
            isDevToolsOpen = true;
            Console.WriteLine("开发者工具已打开");
        }
    }
    
    /// <summary>
    /// 在指定位置打开开发者工具
    /// </summary>
    public void OpenAtPosition(int x, int y, string elementDescription = "")
    {
        if (!browser.IsValid) return;
        
        var title = string.IsNullOrEmpty(elementDescription) ? 
            "位置调试器" : $"调试器 - {elementDescription}";
        
        var elementAt = new FBroSharpElementAt { X = x, Y = y };
        
        browser.ShowDevTools(title, IntPtr.Zero, 150, 150, 1100, 750, 
            null, elementAt, null, null);
        
        isDevToolsOpen = true;
        Console.WriteLine($"在位置 ({x}, {y}) 打开开发者工具: {title}");
    }
    
    /// <summary>
    /// 批量元素检查
    /// </summary>
    public void BatchInspectElements(List<(int x, int y, string description)> elements)
    {
        if (!browser.IsValid || elements == null || elements.Count == 0) return;
        
        Console.WriteLine($"开始批量检查 {elements.Count} 个元素");
        
        foreach (var (x, y, description) in elements)
        {
            Console.WriteLine($"检查元素: {description} at ({x}, {y})");
            OpenAtPosition(x, y, description);
            
            // 给用户时间查看每个元素
            System.Threading.Thread.Sleep(3000);
        }
        
        // 检查完成后关闭
        CloseDevTools();
        isDevToolsOpen = false;
        Console.WriteLine("批量元素检查完成");
    }
    
    /// <summary>
    /// 清理资源
    /// </summary>
    public void Cleanup()
    {
        if (isDevToolsOpen)
        {
            CloseDevTools();
            isDevToolsOpen = false;
        }
    }
}

/// <summary>
/// 开发者工具管理器使用示例
/// </summary>
public void DevToolsManagerExample()
{
    if (!browser.IsValid) return;
    
    var devToolsManager = new DevToolsManager(browser);
    
    try
    {
        // 智能切换
        devToolsManager.SmartToggle();
        System.Threading.Thread.Sleep(2000);
        devToolsManager.SmartToggle();
        
        // 批量检查页面元素
        var elementsToInspect = new List<(int x, int y, string description)>
        {
            (100, 100, "页面头部"),
            (300, 250, "主要内容区"),
            (200, 400, "侧边栏"),
            (350, 500, "页面底部")
        };
        
        devToolsManager.BatchInspectElements(elementsToInspect);
        
        Console.WriteLine("开发者工具管理器示例完成");
    }
    finally
    {
        // 确保清理资源
        devToolsManager.Cleanup();
    }
}

注意事项

1. 浏览器有效性检查

  • 在执行任何操作前,都应该检查browser.IsValid
  • 无效的浏览器实例无法执行任何操作

2. 线程安全

  • 大部分浏览器操作必须在UI线程中执行
  • 跨线程操作需要使用适当的调度机制

3. 资源管理

  • 及时释放不需要的浏览器实例
  • 正确处理浏览器关闭事件

4. 错误处理

  • 为所有浏览器操作添加适当的异常处理
  • 检查方法返回值和参数有效性

5. 性能优化

  • 避免频繁的窗口操作
  • 合理设置缩放级别和窗口大小
  • 适当使用缓存和批量操作

6. 性能监控注意事项

  • 性能监控会消耗一定的系统资源,避免过于频繁的采样
  • CPU使用率计算需要时间间隔,建议采样间隔不少于500毫秒
  • 长时间监控时注意清理历史数据,避免内存泄漏
  • 跨进程监控时要处理进程可能已终止的情况
  • 性能阈值应根据实际应用场景合理设置

7. 进程管理

  • 通过窗口句柄获取进程ID时,要处理句柄无效的情况
  • 进程信息获取可能因权限不足而失败,需要适当的异常处理
  • 某些性能计数器在不同Windows版本上可能有差异

8. 内存监控最佳实践

  • 工作集内存(WorkingSet)通常是最有用的内存指标
  • 私有内存(PrivateMemory)反映进程独占的内存使用
  • 虚拟内存(VirtualMemory)包含所有已分配的虚拟地址空间
  • 定期监控峰值内存使用,帮助识别内存泄漏

9. 截图功能注意事项

  • 截图操作可能消耗较多内存和CPU资源,避免过于频繁的截图
  • 大分辨率截图文件可能很大,注意磁盘空间管理
  • 完整页面截图需要滚动操作,可能影响用户体验
  • 在无头模式下,某些截图方法可能无法正常工作
  • 不同图片格式有不同的压缩比和质量特点:PNG无损但文件大,JPEG有损但文件小

10. 截图最佳实践

  • 对于文档类内容,建议使用PNG格式保持清晰度
  • 对于照片类内容,可以使用JPEG格式减小文件大小
  • 使用异步方法进行完整页面截图,避免阻塞UI线程
  • 定期清理历史截图文件,避免磁盘空间耗尽
  • 截图前确保页面已完全加载,避免截取到加载中的状态
  • 考虑添加截图水印或时间戳以便后续识别

11. Windows API 集成注意事项

  • Windows API调用需要适当的权限,某些API在受限环境下可能失败
  • 不同Windows版本的API行为可能有差异,建议进行兼容性测试
  • 使用P/Invoke时要注意内存管理,及时释放非托管资源
  • 在高DPI环境下,坐标计算可能需要额外的缩放处理

12. 开发者工具使用注意事项

  • 开发者工具是独立的浏览器窗口,会额外消耗系统资源,使用完后应及时关闭
  • 不能在开发者工具浏览器实例上再次打开开发者工具,使用前应检查IsDevToolsBrowser()
  • 开发者工具窗口的父窗口参数在CefBrowserView模式下会被忽略
  • 元素检查坐标基于页面坐标系,需要考虑页面缩放和滚动偏移
  • 多次调用ShowDevTools()会聚焦到已存在的开发者工具窗口,而不会创建新窗口
  • 开发者工具的事件处理器和设置参数都是可选的,可传入null使用默认值
  • 在自动化场景中应谨慎使用开发者工具,避免干扰正常的浏览器操作流程
  • 开发者工具窗口关闭时不会触发主浏览器的关闭事件,需要分别管理
  • 长时间开启开发者工具可能影响页面性能,特别是在资源密集的页面上

通过这些方法和最佳实践,您可以全面控制FBro浏览器的各个方面,实现丰富的浏览器应用功能。

如果文档对您有帮助,欢迎 请喝咖啡 ☕ | 软件发布 | 源码购买