litehtml/doc/using.md
2025-05-23 03:22:45 +03:00

7.4 KiB

How to use litehtml

To use litehtml, you need some easy steps:

  1. Implement litehtml::document_container class.
  2. 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:

  1. Implement document_container::get_media_features function and fill the media parameter with valid media features (like width, height etc.).
  2. Call document::media_changed function when any media feature is changed (for example user is changed the window size).