miniblink 本身是一个核心的浏览器渲染引擎,它不包含完整的用户界面(如右键菜单),这个功能需要你的应用程序来捕获右键事件,然后调用 miniblink 的接口获取源码,并最终展示给用户。

(图片来源网络,侵删)
下面我将分步骤详细解释如何实现这个功能,并提供 C++ 和 Delphi 的示例代码。
实现原理
整个过程可以分为以下几个步骤:
- 创建浏览器窗口:在你的应用程序中创建一个窗口,并嵌入
miniblink控件。 - 加载网页:使用
mbk_navigate或mbk_navigate2等函数加载一个 URL。 - 捕获右键点击事件:在你的应用程序窗口的消息循环中,捕获
WM_CONTEXTMENU消息(对应 Windows 的右键菜单事件)。 - 获取当前页面的源码:在捕获到右键事件后,通过
miniblink的 API 获取当前活动页面的 HTML 源码。 - 展示源码:将获取到的源码显示在一个新的窗口(如一个只读的文本编辑框)或对话框中。
核心 API 函数
实现此功能主要用到以下几个 miniblink API:
mbk_get_webview_by_hwnd(HWND hwnd): 根据你的应用程序窗口句柄,获取对应的mbkWebView对象。mbk_get_current_url(mbkWebView view, char* buffer, int buffer_size): 获取当前页面的 URL(可选,用于在标题栏显示)。mbk_get_page_source(mbkWebView view, char* buffer, int buffer_size): 核心函数,获取当前页面的 HTML 源码,你需要提供一个足够大的缓冲区来存储源码。mbk_get_page_source_length(mbkWebView view): 获取当前页面源码的长度,这对于预先分配缓冲区大小非常有用。
示例代码
示例 1: C++ 实现
这是一个完整的 C++ 示例,展示了如何在一个简单的 Win32 窗口中嵌入 miniblink 并实现右键查看源码功能。

(图片来源网络,侵删)
#include <windows.h>
#include <tchar.h>
#include <mbk.h> // miniblink API 头文件
#pragma comment(lib, "mbk.lib") // 链接 miniblink 库
// 全局变量
HINSTANCE g_hInst = NULL;
HWND g_hwndBrowser = NULL; // miniblink 控件的窗口句柄
mbkWebView g_mbkView = NULL;
// 函数声明
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void ShowPageSource(mbkWebView view);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
g_hInst = hInstance;
// 1. 初始化 miniblink
mbk_initialize();
// 2. 注册窗口类
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = _T("MiniblinkWindow");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wc);
// 3. 创建主窗口
HWND hwnd = CreateWindow(_T("MiniblinkWindow"), _T("Miniblink 右键查看源码示例"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
if (!hwnd) {
MessageBox(NULL, _T("窗口创建失败!"), _T("错误"), MB_ICONERROR);
return -1;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// 4. 创建 miniblink 控件并嵌入主窗口
g_hwndBrowser = CreateWindowEx(0, L"miniblink", L"", WS_CHILD | WS_VISIBLE, 0, 0, 800, 600, hwnd, NULL, hInstance, NULL);
if (g_hwndBrowser) {
g_mbkView = mbk_get_webview_by_hwnd(g_hwndBrowser);
if (g_mbkView) {
// 加载一个示例网页
mbk_navigate(g_mbkView, "https://www.baidu.com");
}
}
// 5. 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 6. 清理
if (g_mbkView) {
mbk_release_webview(g_mbkView);
}
mbk_uninitialize();
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_SIZE:
// 当窗口大小改变时,调整 miniblink 控件大小
if (g_hwndBrowser) {
SetWindowPos(g_hwndBrowser, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER);
}
break;
case WM_CONTEXTMENU:
// 捕获右键菜单事件
if (g_mbkView) {
ShowPageSource(g_mbkView);
}
return 0; // 阻止默认的右键菜单
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
// 显示页面源码的函数
void ShowPageSource(mbkWebView view) {
// 1. 先获取源码长度
int length = mbk_get_page_source_length(view);
if (length <= 0) {
MessageBox(NULL, _T("无法获取页面源码长度或页面为空!"), _T("错误"), MB_ICONERROR);
return;
}
// 2. 分配缓冲区 (+1 用于字符串结束符 '\0')
char* source = new (std::nothrow) char[length + 1];
if (!source) {
MessageBox(NULL, _T("内存分配失败!"), _T("错误"), MB_ICONERROR);
return;
}
// 3. 获取源码
if (mbk_get_page_source(view, source, length + 1) == 0) { // 返回0表示成功
// 4. 显示源码
// 这里用一个简单的消息框来展示,对于大页面不适用
// 实际项目中应使用一个多行文本框的对话框
// 示例:截取前 512 个字符显示
char preview[513] = { 0 };
strncpy_s(preview, source, 512);
char title[256];
mbk_get_current_url(view, title, sizeof(title));
std::string msg = std::string("页面源码 (预览):\n\n") + preview + "\n\n... (源码过长,已截断)";
MessageBoxA(NULL, msg.c_str(), title, MB_OK | MB_ICONINFORMATION);
} else {
MessageBox(NULL, _T("获取页面源码失败!"), _T("错误"), MB_ICONERROR);
}
// 5. 释放缓冲区
delete[] source;
}
示例 2: Delphi (Pascal) 实现
在 Delphi 中,实现逻辑与 C++ 类似,但语法不同,你需要使用 TWinControl 来承载 miniblink。
unit UnitMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TFormMain = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure WndMessage(var Message: TMessage); message WM_CONTEXTMENU;
private
{ Private declarations }
FBrowserHandle: HWND;
FMbkView: mbkWebView; // 假设 mbkWebView 类型已定义
procedure ShowPageSource;
public
{ Public declarations }
end;
var
FormMain: TFormMain;
implementation
{$R *.dfm}
uses mbk; // 引入 miniblink 的头文件
procedure TFormMain.FormCreate(Sender: TObject);
begin
// 1. 初始化 miniblink
mbk_initialize;
// 2. 创建一个 TWinControl 作为容器
// 在实际 VCL 项目中,你可能直接使用 TWinControl 或其子类
// 这里为了演示,我们动态创建一个
// FBrowserHandle := CreateWindowEx(0, 'miniblink', '', WS_CHILD or WS_VISIBLE, 0, 0, ClientWidth, ClientHeight, Handle, 0, HInstance, nil);
// 更简单的方式是使用一个 Panel
Panel1.Align := alClient;
FBrowserHandle := Panel1.Handle; // 假设你有一个名为 Panel1 的 TPanel
if FBrowserHandle <> 0 then
begin
FMbkView := mbk_get_webview_by_hwnd(FBrowserHandle);
if Assigned(FMbkView) then
begin
// 加载一个网页
mbk_navigate(FMbkView, 'https://www.delphi.org');
end;
end;
end;
procedure TFormMain.FormDestroy(Sender: TObject);
begin
if Assigned(FMbkView) then
begin
mbk_release_webview(FMbkView);
FMbkView := nil;
end;
mbk_uninitialize;
end;
procedure TFormMain.FormResize(Sender: TObject);
begin
// 窗口大小改变时,浏览器控件会自动调整大小,因为 Panel1.Align = alClient
end;
// 捕获 WM_CONTEXTMENU 消息
procedure TFormMain.WndMessage(var Message: TMessage);
begin
if Message.Msg = WM_CONTEXTMENU then
begin
if Assigned(FMbkView) then
begin
ShowPageSource;
end;
Message.Result := 1; // 阻止默认的右键菜单
end
else
inherited;
end;
// 显示页面源码
procedure TFormMain.ShowPageSource;
var
Length: Integer;
Source: PAnsiChar;
URL: PAnsiChar;
Memo: TForm;
MemoEdit: TMemo;
begin
Length := mbk_get_page_source_length(FMbkView);
if Length <= 0 then
begin
ShowMessage('无法获取页面源码或页面为空!');
Exit;
end;
GetMem(Source, Length + 1);
try
if mbk_get_page_source(FMbkView, Source, Length + 1) = 0 then
begin
// 创建一个新窗体来显示源码
Memo := TForm.Create(Self);
Memo.Caption := '页面源码';
Memo.Width := 800;
Memo.Height := 600;
Memo.Position := poScreenCenter;
MemoEdit := TMemo.Create(Memo);
MemoEdit.Parent := Memo;
MemoEdit.Align := alClient;
MemoEdit.Lines.Text := string(Source); // PAnsiChar 转 String
Memo.ShowModal;
end
else
begin
ShowMessage('获取页面源码失败!');
end;
finally
FreeMem(Source);
end;
end;
end.
重要注意事项
- API 版本:确保你使用的
miniblink库(.lib和.h文件)与你项目中调用的函数版本一致,较新的版本可能 API 有所不同。 - 内存管理:使用
new或GetMem分配的内存,一定要记得用delete或FreeMem释放,避免内存泄漏。mbk_get_page_source_length的存在就是为了方便你精确分配内存。 - 缓冲区大小:在调用
mbk_get_page_source时,传入的缓冲区大小必须大于或等于mbk_get_page_source_length返回的值 + 1(为了存放空字符\0)。 - 异步加载:网页是异步加载的,如果你在页面还没完全加载完成时就右键点击,
mbk_get_page_source可能获取到的是不完整的源码,你可能需要监听页面的onload事件,确保页面加载完成后再允许查看源码,这可以通过mbk_on_document_loaded等回调函数实现。 - 用户体验:对于非常大的网页(如现代单页应用),源码可能非常长,直接用
MessageBox或简单的文本框显示会很卡,在实际应用中,应该使用性能更好的代码编辑器组件(如 SynEdit、Scintilla 等)来展示和浏览源码。 - 错误处理:代码中的错误处理(如内存分配失败、API 调用失败)是必要的,这能提高程序的稳定性。
通过以上步骤和代码,你就可以成功地在基于 miniblink 的应用程序中实现右键查看网页源码的功能了。

(图片来源网络,侵删)
