TWebBrowser 封裝 MSHTML (Trident/EdgeHTML),支援將網頁內容切換為可編輯模式。本文示範兩種標準編輯模式:contentEditable (元素級) 與 designMode (文檔級),並提供完整的編輯器原型程式碼。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, SHDocVw, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
Panel1: TPanel;
BtnEdit: TButton;
ChkEditable: TCheckBox;
BtnShowText: TButton;
procedure FormCreate(Sender: TObject);
procedure ChkEditableClick(Sender: TObject);
procedure BtnShowTextClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// 介面佈局
Panel1.Align := alTop;
Panel1.Height := 40;
ChkEditable.Parent := Panel1;
ChkEditable.Anchor := [akTop, akRight];
ChkEditable.Caption := '編輯模式';
ChkEditable.OnClick := ChkEditableClick;
BtnShowText.Parent := Panel1;
BtnShowText.Anchor := [akTop, akRight];
BtnShowText.Left := ChkEditable.Left - BtnShowText.Width - 10;
BtnShowText.Caption := '顯示純文字';
BtnShowText.OnClick := BtnShowTextClick;
WebBrowser1.Align := alClient;
WebBrowser1.Navigate('https://example.com'); // 載入測試頁面
end;
procedure TForm1.ChkEditableClick(Sender: TObject);
var
Doc: IHTMLDocument2;
begin
// 取得 MSHTML 文檔介面
Doc := WebBrowser1.Document as IHTMLDocument2;
if not Assigned(Doc) then Exit;
// 模式 1: contentEditable (元素級,推薦)
// 僅讓 body 可編輯,保留其他結構
Doc.body.contentEditable := IfThen(ChkEditable.Checked, 'true', 'false');
// 模式 2: designMode (文檔級,舊標準)
// 整個文檔可編輯,某些瀏覽器引擎需要此模式
// Doc.designMode := IfThen(ChkEditable.Checked, 'On', 'Off');
end;
procedure TForm1.BtnShowTextClick(Sender: TObject);
var
Doc: IHTMLDocument2;
BodyText: string;
begin
Doc := WebBrowser1.Document as IHTMLDocument2;
if Assigned(Doc) and Assigned(Doc.body) then
begin
// 取得可見文字 (不含 HTML 標籤)
BodyText := Doc.body.innerText;
ShowMessage(BodyText);
end;
end;
end.
| 特性 | contentEditable | designMode |
|---|---|---|
| 作用範圍 | 單一元素及其子樹 | 整個文檔 |
| 屬性值 | 'true'/'false'/'inherit' (字串) | 'On'/'Off' (字串) |
| 標準 | HTML5 標準 | 舊版 IE 專有,後被標準化 |
| 巢狀控制 | 可在可編輯區域內設 contentEditable='false' 禁用子區 | 全域開關,難以局部控制 |
| 相容性 | 現代瀏覽器完美支援 | 舊版 IE/EdgeHTML 必須用此模式 |
| 推薦度 | ⭐⭐⭐⭐⭐ | ⭐⭐ (相容舊專案) |
uses MSHTML;
procedure TForm1.ExecEditCommand(const CmdID: string; const Value: OleVariant = EmptyParam);
var
Doc: IHTMLDocument2;
begin
Doc := WebBrowser1.Document as IHTMLDocument2;
if Assigned(Doc) then
Doc.execCommand(CmdID, False, Value);
end;
// 使用範例
ExecEditCommand('Bold'); // 加粗
ExecEditCommand('Italic'); // 斜體
ExecEditCommand('Underline'); // 底線
ExecEditCommand('CreateLink', 'https://example.com'); // 插入連結
ExecEditCommand('InsertImage', 'https://example.com/img.png'); // 插入圖片
ExecEditCommand('ForeColor', '#FF0000'); // 字體顏色
ExecEditCommand('BackColor', '#FFFF00'); // 背景色
ExecEditCommand('FontName', '微軟正黑體'); // 字型
ExecEditCommand('FontSize', '3'); // 字號 (1-7)
ExecEditCommand('JustifyCenter'); // 置中
ExecEditCommand('InsertOrderedList'); // 有序清單
ExecEditCommand('InsertUnorderedList'); // 無序清單
ExecEditCommand('Undo'); // 復原
ExecEditCommand('Redo'); // 重做
ExecEditCommand('SelectAll'); // 全選
ExecEditCommand('Delete'); // 刪除選取
ExecEditCommand('Unlink'); // 移除連結
function GetHTMLContent: string;
var
Doc: IHTMLDocument2;
begin
Result := '';
Doc := WebBrowser1.Document as IHTMLDocument2;
if Assigned(Doc) and Assigned(Doc.body) then
Result := Doc.body.innerHTML;
end;
procedure SetHTMLContent(const HTML: string);
var
Doc: IHTMLDocument2;
begin
Doc := WebBrowser1.Document as IHTMLDocument2;
if Assigned(Doc) and Assigned(Doc.body) then
Doc.body.innerHTML := HTML;
end;
uses MSHTML, ActiveX;
type
TForm1 = class(TForm)
private
FDocEvents: IHTMLDocumentEvents2;
FCookie: DWORD;
procedure DocOnClick(Sender: TObject);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Doc: IHTMLDocument2;
ConnPt: IConnectionPointContainer;
ConnPt2: IConnectionPoint;
begin
// ... 原有初始化 ...
// 事件連接 (需在 DocumentComplete 後)
Doc := WebBrowser1.Document as IHTMLDocument2;
if Supports(Doc, IConnectionPointContainer, ConnPt) then
begin
ConnPt.FindConnectionPoint(DIID_HTMLDocumentEvents2, ConnPt2);
if Assigned(ConnPt2) then
ConnPt2.Advise(Self as IHTMLDocumentEvents2, FCookie);
end;
end;
procedure TForm1.DocOnClick(Sender: TObject);
begin
// 處理文檔點擊事件
Caption := '內容已變更';
end;
| 問題 | 原因 | 解決 |
|---|---|---|
| 編輯模式不生效 | Document 尚未載入完成 | 在 OnDocumentComplete 事件中啟用編輯 |
| 中文輸入法異常 | Trident 引擎 IME 整合問題 | 嘗試 designMode='On'、或改用 Edge WebView2 |
| execCommand 無效 | 命令字串拼寫錯誤、選取範圍無效 | 確認選取非空、命令 ID 大小寫正確 |
| CSS 樣式不生效 | 編輯器產生 inline style 覆蓋 | 使用 styleWithCSS 命令控制 |
| 記憶體洩漏 | 介面參考未釋放 | 表單銷毀時 ConnPt2.Unadvise(FCookie) |
Microsoft 現推薦使用 WebView2 (基於 Chromium Edge) 替代 TWebBrowser:
contentEditable 體驗更佳、IME 完美支援TEdgeBrowser 元件TWebBrowser 配合 contentEditable 可快速構建輕量級網頁編輯器。掌握 execCommand 命令集、innerHTML/innerText 內容存取、事件連接機制,即能實現格式工具列、原始碼檢視、內容同步等核心功能。新專案強烈建議遷移至 TEdgeBrowser 獲得現代瀏覽器級編輯體驗。