如何在C#控制台应用中创建无框浏览器窗口并实现交互与尺寸设置?
当然可以实现!在C#控制台应用里创建无框浏览器窗口、和主程序交互以及设置窗口尺寸都是完全可行的,下面我一步步给你讲清楚具体怎么做:
一、核心实现思路
控制台本身是纯文本环境,要创建带浏览器的UI窗口,我们需要借助.NET的WinForms框架加上微软官方的WebView2控件——这是目前最推荐的方案,兼容性好、功能完整,能轻松实现无框效果和双向交互。
首先你需要做两个准备:
- 给控制台项目添加
System.Windows.Forms和System.Drawing的引用(右键项目→添加→引用→勾选这两个) - 通过NuGet安装
Microsoft.Web.WebView2包(可以用Package Manager Console执行Install-Package Microsoft.Web.WebView2)
二、创建无框浏览器窗口的完整代码示例
直接上可运行的代码,每一步我都加了注释:
using System; using System.Drawing; using System.Windows.Forms; using Microsoft.Web.WebView2.WinForms; class Program { static WebView2 _webView; static Form _browserForm; static Point _mouseDownLocation; // 用于无框窗口拖动 static void Main(string[] args) { // 初始化WinForms的视觉样式和环境 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // 创建无框窗口 _browserForm = new Form { FormBorderStyle = FormBorderStyle.None, // 关键:去掉窗口边框 Size = new Size(800, 600), // 设置初始窗口尺寸 StartPosition = FormStartPosition.CenterScreen, // 居中显示 BackColor = Color.White }; // 给无框窗口添加拖动功能(可选,但很实用) _browserForm.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) { _mouseDownLocation = e.Location; } }; _browserForm.MouseMove += (s, e) => { if (e.Button == MouseButtons.Left) { _browserForm.Location = new Point( _browserForm.Location.X + e.X - _mouseDownLocation.X, _browserForm.Location.Y + e.Y - _mouseDownLocation.Y); } }; // 创建WebView2浏览器控件 _webView = new WebView2 { Dock = DockStyle.Fill, // 让浏览器填充整个窗口 Source = new Uri("https://example.com") // 替换成你要加载的URL }; // 等待WebView2初始化完成,设置交互桥接 _webView.CoreWebView2InitializationCompleted += async (s, e) => { // 注入一个供前端JS调用的对象,实现浏览器→控制台的消息传递 _webView.CoreWebView2.AddHostObjectToScript("consoleBridge", new ConsoleMessageBridge()); // 也可以提前注入一段JS,方便前端调用 await _webView.ExecuteScriptAsync(@" window.sendToConsole = function(msg) { window.chrome.webview.hostObjects.consoleBridge.ReceiveBrowserMessage(msg); }; "); }; // 将浏览器控件添加到窗口 _browserForm.Controls.Add(_webView); // 启动窗口的消息循环(后台运行,不阻塞控制台输入) var uiThread = new System.Threading.Thread(() => Application.Run(_browserForm)); uiThread.SetApartmentState(System.Threading.ApartmentState.STA); uiThread.Start(); // 控制台交互逻辑:监听用户输入 Console.WriteLine("控制台指令:"); Console.WriteLine("- close:关闭浏览器窗口"); Console.WriteLine("- sendmsg:给浏览器发送消息"); Console.WriteLine("- resize [宽度] [高度]:调整窗口尺寸"); Console.WriteLine("----------------------------------------"); string input; do { input = Console.ReadLine()?.Trim().ToLower(); switch (input) { case "close": _browserForm.Invoke(new Action(() => _browserForm.Close())); break; case "sendmsg": _webView.Invoke(async () => { await _webView.ExecuteScriptAsync("alert('来自控制台的消息:Hello Browser!')"); }); break; case var resizeCmd when resizeCmd?.StartsWith("resize") == true: var parts = resizeCmd.Split(' ', StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 3 && int.TryParse(parts[1], out int width) && int.TryParse(parts[2], out int height)) { _browserForm.Invoke(() => _browserForm.Size = new Size(width, height)); Console.WriteLine($"窗口已调整为:{width}×{height}"); } else { Console.WriteLine("格式错误,请输入:resize 800 600"); } break; default: Console.WriteLine("未知指令,请重新输入"); break; } } while (input != "close"); } } // 桥接类:必须标记为ComVisible,供WebView2的JS调用 [System.Runtime.InteropServices.ComVisible(true)] public class ConsoleMessageBridge { public void ReceiveBrowserMessage(string message) { Console.WriteLine($"【浏览器发来消息】:{message}"); } }
三、双向消息交互的具体实现
上面的代码已经包含了完整的双向交互逻辑,我再拆解一下:
1. 浏览器 → 控制台
通过AddHostObjectToScript方法将C#对象注入到前端JS环境,前端可以直接调用这个对象的方法传递消息。比如在前端页面里执行:
sendToConsole("我是浏览器页面的消息!");
控制台就会收到这条消息并打印。
2. 控制台 → 浏览器
控制台通过调用WebView2的ExecuteScriptAsync方法执行JS代码,实现给浏览器发送指令或消息。比如示例里的alert弹窗,你也可以调用前端自定义的函数,传递更复杂的数据。
注意点:
WinForms控件必须在UI线程操作,所以控制台的指令需要用Invoke方法切换到UI线程执行,避免跨线程异常。
四、窗口尺寸的设置
示例里已经实现了两种设置方式:
- 初始化时设置:创建
Form对象时直接给Size属性赋值,比如new Size(1024, 768) - 运行时动态调整:通过控制台指令
resize [宽度] [高度]动态修改窗口尺寸,核心代码是_browserForm.Size = new Size(width, height),同样要注意在UI线程执行。
额外提示
- 第一次运行WebView2需要下载对应的Runtime,如果不想让用户手动安装,可以通过NuGet安装
Microsoft.Web.WebView2.Runtime.x86/x64/arm64包,把Runtime打包到项目里。 - 无框窗口如果需要关闭按钮,可以自己在窗口里添加一个按钮控件,绑定
Close事件。
内容的提问来源于stack exchange,提问作者user4602228




