问题
After checking out the Chromium Embedded Framework example I have a question. I need native interaction with the embedded part of my window. However, in the CEF example, all I saw was the c++ sending messages to the browser, not the other way around. I was wondering if there is any way to send a message from JavaScript from c++, like in the way of a function.
What I am looking for is something like this. I have a button in my webpage that when clicked. I would like to minimize the window. Is there any way to call some c++ from JavaScript in CEF?
回答1:
Easiest way: 1. In main process (UI process) - you can create own custom scheme handler (it can be bounded to http protocol too, and distinct handlers by domain). 2. From JS side, you can use XMLHttpRequest to call you scheme handler. It is standard mechanism to IPC between JS<>Main process.
Other way: Use V8 bindings, but in this case you will need make own IPC between renderer and main process. Or use built-in IPC, but note that it is sends messages only in async way.
回答2:
If anyone needs an example, here's one way i did it:
Determine the custom 'protocol' you wish to use here's an example as a macro string #define PROTO_MYAPPCOMMAND "myapp://"
On your custom CefApp class (the one inheriting from CefApp), also inherit from CefRenderProcessHandler.
implement the OnBeforeNavigation() function:
//declare (i.e. in header) virtual bool OnBeforeNavigation(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, NavigationType navigation_type, bool is_redirect) OVERRIDE; //implementation bool CClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, NavigationType navigation_type, bool is_redirect) { CefString cefval = request->GetURL(); CString csval = cefval.c_str(); if (csval.Find(PROTO_MYAPPCOMMAND, 0) == 0) { //process the command here //this is a command and not really intended for navigation return true; } return false; //true cancels navigation, false allows it }
Here's an example of adding an 'exit' app button:
in cpp
#define STR_COMMANDAPPEXIT _T("command.appexit")
bool CClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, NavigationType navigation_type, bool is_redirect)
{
CefString cefval = request->GetURL();
CString csval = cefval.c_str();
if (csval.Find(PROTO_MYAPPCOMMAND, 0) == 0)
{
CString command = url;
command.Replace(PROTO_MYAPPCOMMAND, _T(""));
if (command.Find(STR_COMMANDAPPEXIT, 0) == 0)
{
::PostMessage(hwnd, WM_CLOSE, NULL, NULL);
}
//this is a command and not really intended for navigation
return true;
}
return false; //true cancels navigation, false allows it
}
also created a js utility file for all the operations to simplify calling them
var MYHOST = MYHOST || {};
/// Exit the Application (host app)
MYHOST.ExitApp = function() {
window.location = 'myapp://command.appexit';
};
in the pages js (i.e. in a button/div click)
<div class="exitbutton" onclick="MYHOST.ExitApp();">Exit</div>
If you need to pass in parameters, just append them in the url in the js and parse the string in the cpp, like this:
MYHOST.DoSomething = function() {
window.location = 'myapp://command.dosomething?param1=' + value1 + "¶m2=" + value2 + "¶m3=" + value3;
};
note: i've simplified the code but please do add the validations etc
Hope this helps!
回答3:
A no serious way to do this, needing a single line of code :
Console.Log('. ...') with a leading ESC char in front of the string/data structure you need to send to the app. Just implement the 'OnConsoleMessage' and trigger accurate job according to the leading or not ESC char.
PS: I had to use this tricky solution in 2015 as a DCEF3 release was buggy for scheme handler use.
For serious job: register custom scheme handler is fine.
来源:https://stackoverflow.com/questions/18926935/sending-information-from-chromium-embedded-javascript-to-a-containing-c-appl