Click here to Skip to main content
15,884,715 members
Articles / Web Development / HTML
Article

HTML Control

Rate me:
Please Sign up or sign in to vote.
3.00/5 (18 votes)
28 Nov 20073 min read 64.2K   1.6K   38   11
A simple and powerful library for HTML based GUI
Screenshot - html_control.jpg

Introduction

This article will help people to construct simple, but powerful, lightweight, flexible and cool looking user interface controls. The main idea is to use the Internet Explorer engine to display the user interface. Thus it is possible to use the reach functionality provided by the combination of HTML, CSS and JavaScript. The HTML document's JavaScript may call C++ functions and vice versa. The attached example demonstrates a simple HTML based dialog with interaction between the document's JavaScript and C++ backend.

This library may be used as a "black-box" and doesn't require any specific knowledge about Windows programming. Yet, in order to understand the details, some COM background would be very helpful.

Using the Code

The simplest dialog may be displayed by the next code:

C++
HtmlControl dlg("hello_world.html");
dlg.DoModal();

hello_world.html is a file that is placed into the resource and the compiler inserts it into the application executable. Resource file may be created manually, for example:

plain
main.html       HTML "main.html"
HtmlControl.js  JS   "HtmlControl.js"

This resource includes two files: main.html and HtmlControl.js. For the sake of simplicity, I usually give the resource item name identical to the file name. HtmlControl.js may be accessed from the document using:

JavaScript
< script src="JS/HtmlControl.js"> </script>

In order to call C++ functions from within the HTML document JavaScript, you need to inherit a class from HtmlControl and declare handlers for JavaScript calls.

C++
class TestDialog : public HtmlControl
{
public:
    TestDialog() : HtmlControl(L"test.html") {
        CONNECT_JS_CALL_SIMPLE_HANDLER(Foo, TestDialog::OnFoo);
    }
    const char* OnFoo(int argc, const char* argv[]) { return "ok"; }
};

In other words, TestDialog declares a JavaScript call handler TestDialog::OnFoo. This handler is called from JavaScript using:

JavaScript
var retval = external.Foo("param1", "param2", "param3", ...)

A C++ handler receives an array of arguments argv (array size is argc). For the sake of simplicity, I defined CONNECT_JS_CALL_SIMPLE_HANDLER macro that translates all parameters and return values into strings (char*). CONNECT_JS_CALL_HANDLER provides you with full control on the arguments sent from the JavaScript.

Background

Now, let's try to understand some nontrivial implementation details.

Host Window and Initialization

Basically, there are no limits when you choose the host window implementation. It may be a simple Win32 window, MFC or WTL based window. I decided to create the host window manually using ATL. This reduces the application footprint and removes unnecessary dependencies to other libraries.

In HtmlControl::DoModal, a borderless and titlebarless window is created and a window message loop is initiated. All initialization is performed when the message loop receives a WM_CREATE window message. On this message, the browser control is created and it is navigated to the control HTML page. Also HtmlControl is registered as an external dispatcher (SetExternalDispatch).

JavaScript - C++ Communication

The communication between the HTML document JavaScript and C++ backend is based on COM technology. The callee is a COM object that must implement the IDispatch interface. This interface has two methods used for communication:

C++
HRESULT GetIDsOfNames(REFIID riid,
                      LPOLESTR *rgszNames,
                      UINT cNames,
                      LCID lcid,
                      DISPID *rgDispId);
HRESULT Invoke(DISPID dispIdMember,
               REFIID riid,
               LCID lcid,
               WORD wFlags,
               DISPPARAMS *pDispParams,
               VARIANT *pVarResult,
               EXCEPINFO *pExcepInfo,
               UINT *puArgErr);

When a caller calls some function, the callee instance should return the unique id for this function. GetIDsOfNames does this. It receives the function name gszNames (as you probably noticed, it may receive several names) and returns its id rgDispId. Immediately after, Invoke is called with dispIdMember parameter equal to id returned by GetIDsOfNames. Along with function id, Invoke receives all parameters pDispParams and may return some value via pVarResult.

In the provided source code, you may find a simple yet flexible implementation of this technology. Also, for the sake of simplicity, I wrote several macros that hide the details of implementation.

Keyboard Events

There is a subtle issue with WM_KEYDOWN and WM_KEYUP messages. The host window eats them up, thus the HTML control doesn't receive keyboard events. The solution is straightforward - in the message loop, these messages are redirected to the window of HTML control.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Unknown
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionReturn a string from JS->HTML Pin
xman91131-Jan-13 19:59
xman91131-Jan-13 19:59 
QuestionLicense Pin
Member 219763618-Nov-12 16:34
Member 219763618-Nov-12 16:34 
GeneralMy vote of 5 Pin
tzleo28-Jan-12 21:16
tzleo28-Jan-12 21:16 
GeneralCalling a javascript function with parameters from c++ Pin
kmpham23-Mar-10 13:19
kmpham23-Mar-10 13:19 
GeneralRe: Calling a javascript function with parameters from c++ Pin
Tan XueFeng16-Dec-13 2:27
Tan XueFeng16-Dec-13 2:27 
QuestionCan this control be made to be a Non-Modal Window Pin
Member 40231035-Jun-08 4:43
Member 40231035-Jun-08 4:43 
AnswerRe: Can this control be made to be a Non-Modal Window Pin
Alliz7-Jun-08 2:00
Alliz7-Jun-08 2:00 
GeneralRe: Can this control be made to be a Non-Modal Window Pin
xman91123-Jan-13 21:37
xman91123-Jan-13 21:37 
GeneralLoad HTML file Pin
Member 40231033-Jun-08 9:00
Member 40231033-Jun-08 9:00 
AnswerRe: Load HTML file Pin
Member 40231034-Jun-08 13:32
Member 40231034-Jun-08 13:32 
GeneralGreat~! Pin
暴走小鸡27-Dec-07 5:21
暴走小鸡27-Dec-07 5:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.