瀏覽器嵌入窗口程序一直以來就是WEB應用程序的首選方案,這種方案只需要實現一個主窗口,並提供一些接口供腳本調用,內部的界面和邏輯處理全部用html,css,javascript去實現。我最早看到的相關應用是四五年前的新浪聊天室。我本人在後來的一些項目中也多次用到這種基於IE內核的實現方式。
隨着HTML5的強大,嵌入瀏覽器方式比嵌入Shockwave Flash的方式更應該作爲首選方案。本文介紹嵌入IE,Chrome,Firefox三種方式。
本文鏈接: http://www.hoverlees.com/blog/?p=1339
1.嵌入IE瀏覽器
嵌入IE內核應該是早期最常用的方法,使用windows平臺上的ActiveX方式,將IWebBrowser2對象嵌入到窗口中,IWebBrowser2接口涉及到很多的接口,可以讓我們進行事件處理、操作DOM、與JS通信,使用一個連接點接口與瀏覽器內部連接,獲取和處理事件。
使用IE內核有一個缺點就是用戶的操作系統各種各樣,內核也是多個版本而且不兼容(只有IE9+才支持HTML5)。導致程序非常不穩定,再有就是不能跨平臺。以至於現在嵌入IE應該是最差的方式了。
2.嵌入Firefox
Mozilla的XULRunner是一個跨平臺的瀏覽器應用框架,被Mozilla用於Firefox和ThunderBird等軟件的核心,同樣是開源和支持HTML5,項目使用XPCOM方式實現,除了XPCOM對象(windows系統的在xpcom.dll中)的獲取外,其它屬性,對象和函數的訪問均與MDN上Javascript的文檔相同,可謂文檔齊全。同樣也有已經實現的第三方C++項目將基於XULRunner的瀏覽器封裝成控件,非常方便使用。
MDN地址:https://developer.mozilla.org/en-US/docs/XULRunner
3.嵌入Chrome
Embedding Chrome:經過本人的研究,個人認爲嵌入Chrome是最好的解決方案,Chrome本身開源,高效的v8引擎。同時也有很多附屬的開源項目,libcef就是其中一個,cef是chrome embed framework的縮寫,意在實現chrome嵌入應用程序,本人對這個項目下載下來後進行過測試,效果非常好,支持HTML5,同時跨平臺。
項目地址:http://code.google.com/p/chromiumembedded/
下面是libcef調用的示例程序,給大家做參考。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/** *
libcef test application. *
@author Hoverlees me[at]hoverlees.com */ #include
<iostream> #include
<Windows.h> #include
"HoverWindow.h" #include
<include/cef_browser.h> #include
<include/cef_app.h> #include
<include/cef_client.h> class
MyChromeClient: public
CefClient{ private : int
refCount; public : MyChromeClient(){ refCount=1; } virtual
int
AddRef(){ refCount++; return
refCount; } virtual
int
Release(){ refCount--; return
refCount; } virtual
int
GetRefCt(){ return
refCount; } }; class
MyChromeApplication: public
CefApp{ private : int
refCount; public : MyChromeApplication(){ refCount=1; } virtual
int
AddRef(){ refCount++; return
refCount; } virtual
int
Release(){ refCount--; return
refCount; } virtual
int
GetRefCt(){ return
refCount; } }; class
ChromeWindow: public
HoverWindow{ private : CefWindowInfo
windowInfo; MyChromeClient
client; CefRefPtr<CefBrowser>
browser; public : ChromeWindow( HINSTANCE
hInstance, const
char *
className, const
char *
title, int
x, int
y, int
w, int
h, DWORD
exStyle=NULL, DWORD
windowStyle=WS_OVERLAPPEDWINDOW); virtual
bool
onWindowMessage( HWND
hWnd, UINT
uMsg, WPARAM
wParam, LPARAM
lParam); }; ChromeWindow::ChromeWindow( HINSTANCE
hInstance, const
char *
className, const
char *
title, int
x, int
y, int
w, int
h, DWORD
exStyle, DWORD
windowStyle) :HoverWindow(hInstance,className,title,x,y,w,h,exStyle,windowStyle){ } bool
ChromeWindow::onWindowMessage( HWND
hWnd, UINT
uMsg, WPARAM
wParam, LPARAM
lParam){ RECT
rt; switch (uMsg){ case
WM_CREATE: GetClientRect(hWnd,&rt); windowInfo.SetAsChild(hWnd,rt); this ->browser=CefBrowserHost::CreateBrowserSync(windowInfo,&client,CefString( "http://www.hoverlees.com" ),CefBrowserSettings()); CefRunMessageLoop(); break ; case
WM_SIZE: GetClientRect(hWnd,&rt); SetWindowPos( this ->browser->GetHost()->GetWindowHandle(),0,rt.left,rt.top,rt.right,rt.bottom,0); break ; case
WM_CLOSE: CefQuitMessageLoop(); PostQuitMessage(0); break ; default : return
false ; } return
true ; } int
WINAPI WinMain( HINSTANCE
hInst, HINSTANCE
hPrevInstance, LPSTR
lpCmdLine, int
nCmdShow){ MyChromeApplication
app; CefMainArgs
main_args(hInst); CefSettings
settings; settings.multi_threaded_message_loop
= false ; int
exit_code = CefExecuteProcess(main_args,&app); if
(exit_code >= 0) return
exit_code; CefInitialize(main_args,settings,&app); ChromeWindow*
window= new
ChromeWindow(hInst, "hover" , "Chrome
Embedding -
http://www.hoverlees.com" ,0,0,400,400); window->startMessageLoop(); CefShutdown(); return
0; } |
其中CefClient包含一些虛函數可以獲取一些對象以獲取瀏覽器事件和設置瀏覽器相關功能,一般用Client類同時實現,然後返回this即可。如下示例.具體可以參考自帶的類文檔。
1
2
3
4
5
6
7
8
9
10
|
class
MyChromeClient: public
CefClient, public
CefLoadHandler{ public : virtual
CefRefPtr< CefLoadHandler > GetLoadHandler(){ return
this ; } //CefLoadHandler的其中一個虛函數實現,當頁面加載完成時執行此函數 virtual
void
OnLoadStart( CefRefPtr< CefBrowser > browser, CefRefPtr< CefFrame > frame ){ MessageBox(0,frame->GetURL().ToString().c_str(),0,0); } }; |