7.4 KiB
How to use litehtml
To use litehtml, you need some easy steps:
- Implement litehtml::document_container class.
- Call some functions from litehtml::document to parse, render and draw HTML text.
Implementing litehtml::document_container
The first step to integrate litehtml into your application is implementing abstract class litehtml::document_container. This class draws the HTML elements and performs some actions depended on the platform.
Loading HTML page
To load HTML page you have to call litehtml::document::createFromString function. This function creates the litehtml::document object from the HTML string. The HTML string must be in UTF-8 encoding. The function has the following signature:
static document::ptr document::createFromString(
const estring& str,
document_container* container,
const string& master_styles = litehtml::master_css,
const string& user_styles = "");
Please refer to the document::createFromString document for more details.
createFromString returns the litehtml::document
pointer. Call litehtml::document::render(max_width)
to render HTML elements:
m_doc->render(max_width);
The parameter max_width
usually the browser window width. Also render
returns the optimal width for HTML text. You can use the returned value to render elements into the optimal width. This can be useful for tooltips.
Use height
and width
litehtml::document
functions to find the width and height of the rendered document:
m_doc->height()
m_doc->width()
Now call draw function:
m_doc->draw(hdc, m_left, m_top, &clip);
draw accepts 4 parameters:
uint_ptr hdc
- usually device context or something where to draw. For example HDC in windows. This parameter will be passed into all draw functions of litehtml::document_container.int x, int y
- position where to draw HTML.const position* clip*
- clipping area. litehtml does not draw the elements that don't intersect the clipping rectangle. But note, you have to set your own clipping if you want to clip HTML content.
That's all! Your HTML page is painted!
Fit to the document
If you don't have the fixed size window to draw HTML, you need to get the HTML best width. It is straightforward: document::render
returns the best width for you.
So the example looks like this:
int best_width = m_doc->render(max_width);
if(best_width < max_width)
{
m_doc->render(best_width);
}
First, you render document with the maximum possible width and document::render
returns the best width for HTML. If the best width is less then maximum width, you have to render your document with the returned best width. Now you can use document::width
to get the actual document width.
You can use this technique to show HTML tooltips in your application or to create the HTML widgets.
Scrolling and Clipping
Scrolling of html document is released via x,y parameters of the document::draw function. For example, if you want to scroll document on 50px horizontally and 100px vertically:
m_doc->draw(hdc, -50, -100, litehtml::position(50, 100, window_width, window_height));
Note, the x
and y
parameters are screen relative. The clip
parameter is always document relative. Also note, defining the clip
parameter in draw
does not guarantee the valid clipping. Some elements can be drawn out off the clipping area. litehtml just checks if the element's bounding rectangle is intersected with clipping rectangle to draw elements. So you must implement your own clipping.
Handling the mouse
If you want to handle the mouse you have call some functions from litehtml::document
:
bool litehtml::document::on_mouse_over( int x, int y, int client_x, int client_y, position::vector& redraw_boxes );
bool litehtml::document::on_mouse_leave( position::vector& redraw_boxes );
bool litehtml::document::on_lbutton_down( int x, int y, int client_x, int client_y, position::vector& redraw_boxes );
bool litehtml::document::on_lbutton_up( int x, int y, int client_x, int client_y, position::vector& redraw_boxes );
bool on_mouse_leave(position::vector& redraw_boxes);
All functions returns the bool
to indicate that you have to redraw the rectangles from redraw_boxes vector. Also note the x
and y
are relative to the HTML layout. So 0,0
is the top-left corner.
The parameters client_x
and client_y
are the mouse position in the client area (draw area). These parameters are used to handle the elements with fixed position.
Processing anchor click
If you process the mouse, the clicking on anchor tag will call the function document_container::on_anchor_click. This function gets the url of the anchor as parameter and pointer to litehtml::element. You can open the new document at this point.
NOTE: Don't delete the document inside document_container::on_anchor_click, this will cause the crash. The document_container::on_anchor_click is generated by document::on_lbutton_up
, so it is safe to delete old document and show new one after document::on_lbutton_up
is finished.
Processing named anchors
litehtml does not have the special handling of the named anchors. But it is easy to process the named anchors manually. You get the url with the anchor name into document_container::on_anchor_click. Find the hash char (#) and extract the name. In the example below, the variable anchor_name
contains the anchor name:
if(anchor_name.empty())
{
std::string selector = "#" + anchor_name;
litehtml::element::ptr el = m_html->root()->select_one(selector);
if (!el)
{
selector = "[name=" + anchor_name + "]";
el = m_html->root()->select_one(selector);
}
if (el)
{
litehtml::position pos = el->get_placement();
m_html_host->scroll_to(0, pos.top());
}
}
The function element::select_one
returns the first element for the CSS selector. So select_one("#name")
returns the element with attribute id="name"
. el->get_placement()
returns the absolute position of the element (document relative coordinates).
So, you have the position of the named anchor and now you can scroll your document into this position.
Images
litehtml does not cache the images. So if you want to increase the performance, you have to create your own images cache. Also, you can implement the delayed images loading. Start image downloading in document_container::load_image function. If the image is not loaded return fake sizes and draw placeholder. When the image is loaded call litehtml::document::render
, and redraw the page.
Support for CSS media features
litehtml supports CSS @media
at-rule as well are media
attribute in the <link>
and <style>
html tags. To make CSS media support you need:
- Implement document_container::get_media_features function and fill the
media
parameter with valid media features (like width, height etc.). - Call
document::media_changed
function when any media feature is changed (for example user is changed the window size).