This is how to embed a WebKit instance within a WinForms application. I promised, a long time ago, to show this, but never got around to it. The process itself is pretty simple, assuming you have WebKit compiled (which can be pretty difficult) because you’ll need to be able to link with the WebKit libraries, specificially: WebKit.lib and WebKitGUID.lib (which, of course, have dependencies on all of the other libraries produced in the compilation). I’m going to be using a older version of WebKit, the same one I played with in my previous blog posts, as I don’t have time to check out the newest version of WebKit. Hopefully, the interfaces are the same or similar and what I’m about to describe here can be adapted easily to work with the latest version.
What we’re going to do is create a CLI wrapper to allow the .Net application to access the native WebKit code. To mix managed and unmanaged code, we’re going to need to create a C++/CLI application. Yes, it is going to be ugly code, but it works and (I think) much simpler than trying to P/Invoke functions in WebKit.dll.
Here’s the wrapper code (I’ve also included a compiled dll in the /Release folder):
WebKitCLIWrapper.dll.zip
WebKitNativeController.h and WebKitNativeController.cpp is adapted from the demo code provided by Apple. WebKitCLIWrapper.h (shown below) is the C++/CLI .NET code that wraps the native controller.
#pragma once
#include "WebKitNativeController.h"
namespace WebKitCLIWrapper
{
using namespace System;
using namespace System::Collections;
public ref class Wrapper
{
public:
Wrapper(IntPtr hwnd, String^ htmlContent)
{
webKitController = new WebKitNativeController();
IntPtr bstrPtr = System::Runtime::InteropServices::Marshal::StringToBSTR(htmlContent);
webKitController->Init((HWND)(int)hwnd, (BSTR*)&bstrPtr);
System::Runtime::InteropServices::Marshal::FreeBSTR(bstrPtr);
}
~Wrapper()
{
webKitController->UnInit();
webKitController->Release();
}
void LoadURL(String^ url)
{
IntPtr bstrPtr = System::Runtime::InteropServices::Marshal::StringToBSTR(url);
webKitController->LoadURL(*((BSTR*)&bstrPtr));
System::Runtime::InteropServices::Marshal::FreeBSTR(bstrPtr);
}
protected:
WebKitNativeController* webKitController;
};
}
Now, we can simply include WebKitCLIWrapper.dll in any .Net project as a reference and access the wrapper to create a WebKit instance. So if your in Visual C#, create a new WinForms app, create a Panel (panel1) on a form, and add the following to the form’s Load event:
WebKitCLIWrapper.Wrapper wrap = new Wrapper(panel1.Handle, "");
wrap.LoadURL("http://arstechnica.com/");
However, before running the application, you need all the necessary libraries and necessary resources referenced by WebKit.dll in the app’s working directory (I like to set it to Debug).
For convenience, here’s a zip containing all you’ll need:
WebKit_dlls+resources.zip
(as I mentioned, this is an older version of WebKit)
With all the necessary files in place, launch the app, and a WebKit instance should load in the specified panel (panel1) along with the web page specified in LoadURL() call.
If you’d like to display and process a specific piece of HTML code, get rid of the LoadURL() call, place the code to be embedded in a string, and pass it as the 2nd argument to the WebKitCLIWrapper.Wrapper constructor. For example, this will load and embed a youtube video:
string embed = "<object width=\"425\" height=\"344\"><param name=\"movie\" value=\"http://www.youtube.com/v/SuBqIrgKnNg&hl=en&fs=1\"></param><param name=\"allowFullScreen\" value=\"true\"></param><embed src=\"http://www.youtube.com/v/SuBqIrgKnNg&hl=en&fs=1\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" width=\"425\" height=\"344\"></embed></object>";
WebKitCLIWrapper.Wrapper wrap = new Wrapper(panel1.Handle, embed);
The wrapper interface is very bare-bones, but it’s good enough if you just need to display some web or HTML content in your app or, if your looking to build a .NET web browser, it will hopefully provide a starting point for how to interact with WebKit.