入式Chromium框架(簡稱CEF) 是一個由Marshall Greenblatt在2008建立的開源項目,它主要目的是開發一個基于Google Chromium的Webbrowser控件。CEF支持一系列的編程語言和操作系統,并且能很容易地整合到新的或已有的工程中去。
它的設計思想政治就是易用且兼顧性能。CEF基本的框架包含C/C++程序接口,通過本地庫的接口來實現,而這個庫則會隔離宿主程序和Chromium&Webkit的操作細節。它在瀏覽器控件和宿主程序之間提供緊密的整合,它支持用戶插件,協議,javascript對象以及javascript擴展,宿主程序可以隨意地控件資源下載,導航,下下文內容和打印等,并且可以跟Google Chrome瀏覽器一起,支持高性能和Html5 技術,
————————————————
版權聲明:本文為CSDN博主「vx_xtfnpgy」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xtfnpgy/article/details/46635225
框架接口:
CefBrowser是主要的瀏覽器窗口類,可以用靜態的函數CreateBrowser() 和CreateBrowserSync() 來創建一個新的瀏覽器窗口。
CefFrame 代表一個瀏覽器窗口的框架,每個瀏覽器窗口有一個頂層的主框架,而這個主框架可以用GetMainFrame() 方法得到。
CefClient是主瀏覽器窗口的代表接口,這個接口做為參數傳遞給CreateBrowser()
CefRequest 代表URL,方法,發送數據和頭文件等這樣的請求。
CefSchemeHandleFactory 類是被用來處理像myscheme://mydomain類似客戶計劃的請求
CefReadHandler和CefWriteHandle是一個讀寫數據的簡單接口。
CefV8Handler,CefV8Value和CefV8Context是被用來創建和訪問JavaScript對象。
安裝完成之后,新建一個Demo1,拖一個chromium控件出來并命名為chrm1,并把bin目錄下所有文件,復制到你的程序的當前文件夾;
再拖一個button,雙擊加入代碼:
chrm1.Browser.MainFrame.LoadUrl('about:blank'); //第一次必須先加載空白頁,才能瀏覽其他網頁
chrm1.Browser.MainFrame.LoadUrl('你要瀏覽的網址');
獲取主框架 chrm1.browser.MainFrame
獲取源代碼 s := chrm1.browser.MainFrame.Source;
其次是填表,用過google瀏覽器的都知道,其填表功能實在強大,在webbrowser時代,一般都是獲取表單元素的各種接口,然后設置其value、checked等屬性,而在TChromium中,一切皆js,把想做的事都讓js去執行吧,所以,用TChromium,js功力深厚的會輕松很多了。比如:
strTemp := 'document.forms[0].inmembername.value="User_Name";'; JavaExec(strTemp); strTemp := 'document.forms[0].inpassword.value="Password";'; JavaExec(strTemp); strTemp := 'document.forms[0].submit.click();'; chrm.browser.Frame['ff'].ExecuteJavaScript(str,'about:blank',0);; //想在哪一層frame執行,就調用哪一層
注入自定義的JS
首先必須在網頁加載完成之后,才可以執行,不能為空頁面!
str_js := 'var oScript = document.createElement( "script" );oScript.id = "sid";alert(oScript.id);';
chrm1.browser.MainFrame.ExecuteJavaScript(str_js,'about:blank',0);
delphi與JS交互(通過ceflib實現)
Cef3的Demo里面,有一個cefclient的例子,可以看下,關鍵代碼:
TExtension = class(TCefv8HandlerOwn)
private
FTestParam: ustring;
protected
function Execute(const name: ustring; const obj: ICefv8Value;
const arguments: TCefv8ValueArray; var retval: ICefv8Value;
var exception: ustring): Boolean; override; //重寫Execute事件
end;
遍歷網頁元素并點擊JS:
遍歷所有元素
var eles=document.all;
for(var i=0;i<eles.length;i++){var a;
var d=eles[i];
var s=eles[i].getAttribute("class");
if(s!=null){
if((s=='img')||(s=='J_ItemPic img')||(s=='productImg')){
a=eles[i];
a.click();break;
}}}
遍歷所有A標簽
下面代碼為找到淘寶寶貝頁面,成交記錄元素的代碼:
for(var i=0;i<document.getElementsByTagName("A").length;i++){var a;
var d=document.getElementsByTagName("A")[i];
var s=document.getElementsByTagName("A")[i].innerHTML;
if(s!=null){
if(s.indexOf("成交記錄")>-1){
a=document.getElementsByTagName("A")[i];alert(a.innerHTML);
ClickElement(a); //由于chromium控件元素不支持click事件,所以需要自己重新綁定事件
break;
}}}
//-----------------點擊元素的代碼------------------------------
function ClickElement(AObj) {
var e = document.createEvent("MouseEvent");
e.initEvent("click", false, false);
AObj.dispatchEvent(e);
}
根據ID或Name獲取元素
1.根據ID
var a=document.getElementById("元素id");
2.根據Name
var b=document.getElementsByName("元素name").item(0);
b.setAttribute("value","輸入值");
3.根據TagName
var c=document.getElementsByTagName("INPUT")[0];
var d=document.getElementsByTagName("INPUT").item(0);
如何在Delphi中直接操作Document接口
Button1.OnClick:
chrm1.Browser.MainFrame.VisitDomProc(ChrmDomProc);
procedure ChrmDomProc(const doc : ICefDomDocument); //其他接口有待自己研究
var
s : string;
begin
doc.GetElementById('txtUsername').SetElementAttribute('Value','abc');
s := doc.GetElementById('txtUsername').GetValue;
showmessage(s);
end;
簡單實例:
var ele;
ele=document.getElementById('ID');
ele=document.getElementsByName('Name').iteme(0);
ele=docuemnt.getElementsByTagName('TAG');
ele.click();
var e=document.createEvent("MouseEvent");
e.initEvent("Click",false,false);
ele.dispatchEvent(e);
var c=document.getElementsByTagName("INPUT").item(0);
模擬移動鼠標
// SetCursorPos(StrToInt(Edit1.Text),StrToInt(Edit2.Text)); //相對屏幕位置
SetCursorPos(Self.Left+chrm1.Left+strtoint(Edit1.Text),Self.Top+chrm1.Top+strtoint(Edit2.Text)); //相對Chrm位置
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);//模擬按下鼠標左鍵。
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);//模擬放開鼠標左鍵。
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),0,0); //按下SHIFT鍵。
keybd_event(0x52,MapVirtualKey(0x52,0),0,0);//按下R鍵。
keybd_event(0x52,MapVirtualKey(0x52,0),KEYEVENTF_KEYUP,0);//放開R鍵。
keybd_event(VK_SHIFT,MapVirtualKey(VK_SHIFT,0),KEYEVENTF_KEYUP,0);//放開SHIFT鍵。
Chromiume控件指定坐標點擊
SendMessage(GetWindow(GetWindow(form1.chrm1.Handle, GW_CHILD), GW_CHILD),WM_LBUTTONDOWN,MK_LBUTTON, MAKELONG(StrToIntDef(Edit1.Text,100),StrToIntDef(Edit2.Text,100)));
SendMessage(GetWindow(GetWindow(form1.chrm1.Handle, GW_CHILD), GW_CHILD),WM_LBUTTONUP,MK_LBUTTON, MAKELONG(StrToIntDef(Edit1.Text,100),StrToIntDef(Edit2.Text,100)));
MK_LBUTTON可以改為0,MAKELONG可以改為MAKELParam
JS控制滾動條的位置:
window.scrollTo(x,y);
豎向滾動條置頂(window.scrollTo(0,0);
豎向滾動條置底 window.scrollTo(0,document.body.scrollHeight)
或: window.scrollByo(0,document.body.scrollHeight)
設置代理ip
ceflib.pas單元:
uses iniFiles;
procedure TInternalApp.OnBeforeCommandLineProcessing(const processType: ustring;
const commandLine: ICefCommandLine);
var
ini : TIniFile;
str_ip : string;
begin
ini := TIniFile.Create(StringReplace(ParamStr(0),'.exe','.ini',[]));
str_ip := ini.ReadString('default','Proxy','');
ini.Free;
commandLine.AppendSwitchWithValue('proxy-server',str_ip);
if Assigned(CefOnBeforeCommandLineProcessing) then
CefOnBeforeCommandLineProcessing(processType, commandLine);
end;
[default]
Proxy=218.189.26.20:8080
Proxy1=218.207.212.79:80
Proxy2=120.203.159.18:8118
TML Compiler 2023.20 (x64)
使用DecSoft HTML編譯器,您可以輕松地將現代HTML應用程序(例如單頁應用程序)編譯為Microsoft Windows? 32和64位的獨立可執行文件。您的應用程序文件永遠不會提取到用戶的計算機中,也不會在基于 Chromium 的現代瀏覽器環境中運行。
這是安全的
HTML 應用程序在 Windows 32 和 64 位可執行文件中編譯Microsoft。除非你想要提取某些特定文件,否則永遠不會在最終用戶計算機中提取應用的文件。
沒有限制!
把你的想象力放在這里。您幾乎可以將任何現代HTML應用程序轉換為Windows的可執行程序,例如電子書,調查,測驗,雜志,演示文稿,相冊和畫廊,游戲等。
超級簡單
您可以使用用戶圖形界面或命令行工具來編譯您的 HTML 應用程序,只需指示應用程序“index.html”文件的路徑即可。
看一看!
下一個視頻展示了DecSoft HTML編譯器的工作原理!在短短一分鐘內,您可以看到DecSoft HTML編譯器如何獲取DecSoft App Builder的“數據庫”應用程序示例,并將其轉換為獨立的Microsoft Windows可執行文件。
CLI支持
DecSoft HTML編譯器除了可視化環境外,還包括命令行編譯器。通過這種方式,您可以從命令行簡單快速地編譯應用程序。
非常簡單的
DecSoft HTML編譯器不會向用戶顯示任何界面元素。但這很好,因為這樣您的應用程序看起來完全符合您的要求,沒有任何不希望的干擾!
非常強大的
DecSoft HTML編譯器為您的應用程序提供了一些外部Javascript,以超越現代HTML應用程序的功能,例如,提供編寫文件,執行程序,瀏覽文件夾等的能力。
更新
內容* 將我們與 OpenAI 助手一起使用的 Delphi 庫更新到最新版本。在所引用庫的最新版本中,“[...]截至 13 年 2023 月 <> 日,API 已根據官方 [OpenAI] 版本進行了全面更新”。該庫還有其他更改、修復和增強功能,因此我們的 OpenAI 助手。
在上一節《1.基于Chrome開發瀏覽器》中,我們開發了一個簡單的能夠打開某個網頁的瀏覽器。這一節我們來學習如何控制這個簡單的瀏覽器。
現在我們可以稍微擴展瀏覽器。瀏覽器的控制是通過 TChromium 實例完成的。瀏覽器中的一些常見操作是在瀏覽器歷史中前進和后退。TChromium 類對此提供了一些方法:
使用這些功能,很容易在瀏覽器中添加 2 個按鈕來回移動。為了演示這一點,我們在頂部面板 btnForward 和btnBack 中添加了2個按鈕。它們的 OnClick 處理程序相當簡單:
procedure TForm1.btnForwordClick(Sender: TObject);
begin
if bwBrowser.Chromium.CanGoForward then
bwBrowser.Chromium.GoForward;
end;
procedure TForm1.btnBackClick(Sender: TObject);
begin
if bwBrowser.Chromium.CanGoBack then
bwBrowser.Chromium.GoBack;
end;
CanGoBack 和 CanGoForward 功能在界面中控制按鈕的可用性,從而啟用或禁用按鈕,具體取決于是否有前進或后退的歷史記錄。
作為開發人員,能夠顯示瀏覽器開發人員工具很有用,這樣我們可以檢查 HTML,CSS 或調試網頁中的 JavaScript 腳本。chromium 組件提供了一種方法可以幫助解決這個問題:ShowDevtools 和 HideDevTools 。
該方法有 2 個參數:一個 point 和一個 TWinControl 實例。point 是瀏覽器窗口中的一個坐標;TWinControl 實例是將與開發人員工具一起放置的 TWinControl 實例。。后者可以為 Nil,在這種情況下,開發人員工具顯示在浮動窗口中。
我們將創建一個底部對齊的面板,最初,面板是不可見的,當用戶要求查看開發人員工具時,我們將使面板可見。當用戶要求關閉開發人員工具時,我們要求瀏覽器關閉它們并隱藏面板。
procedure TForm1.btnToolClick(Sender: TObject);
begin
if toolPanel.Visible then
begin
toolPanel.Visible:=False;
bwBrowser.Chromium.CloseDevTools(toolPanel);
end
else
begin
toolPanel.Visible:=True;
bwBrowser.Chromium.ShowDevTools(Point(0,0),toolPanel);
end;
end;
TChromium 組件有很多事件處理程序。這些被 CEFframework 用來通知你的程序很多事情。但是,使用這些事件處理程序時必須小心:瀏覽器在單獨的進程中運行,因此所有通信都是通過發送消息進行的,這些消息由CEF4Delphi 轉換為事件。這些事件到達一個不一定必須是主 UI 線程的線程。由于 LC L使用的 widgets 不是線程安全的,這意味著您不能僅在事件處理程序中更新 GUI。幸運的是,Lazarus 有一種可以用于此的機制:Appliction.QueueAsyncCall。
QueueAsyncCall 調度一個回調,當主應用程序循環完成處理掛起消息時,將調用該回調。因此,此回調在主應用程序線程中調用,因此可以用于更新 UI。
為了演示這一點,我們將使用一個簡單的事件。TChromium 組件的 OnTitleChange 事件會在 HTML 頁面中包含標題標簽時通知您,并向您發送標題。我們可以使用此事件來更新表單的標題欄:
procedure TForm1.ChromiumTitleChange(Sender: TObject;
const browser: ICefBrowser; const title: ustring);
begin
if (length(title)>0) then
FNewTitle:=UTF8enCode(title)
else
FNewTitle:=UTF8enCode(bwBrowser.Chromium.DocumentURL);
Application.QueueAsyncCall(@DoSetTitle, 0);
end;
新標題保存到一個臨時變量,并安排一個異步調用: DoSetTitle:
procedure TForm1.DoSetTitle(Data: PtrInt);
begin
Caption:=FNewTitle;
end;
由于此調用是在主線程中執行的,因此更新表單標題是安全的。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。