Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

Using background_wnd

Content

Namespaces

background_wnd, background_wnd_by_key and all painters included in the package are in namespace win32::gui. All the additional classes are in win32::gui::bg_wnd. There are also some classes in win32::gui::detail but they should be of no interest to you ;-)
The following examples assume win32::gui is fully visible (using namespace win32::gui).

Deriving from background_wnd

To make your window a background_wnd you have to extend the background_wnd-class as usual:
#include <win32gui/background_wnd.hpp>

struct your_window : wnd_extend<dialog, your_window>, wnd_extend<background_wnd, your_window>
{
     ...
};


Adding painters

You can add painters by calling add_painter(). The return value is the index of the painter with which you can access the painter later:
color_painter cp( color_painter::make_brush(RGB(255, 0, 0)) );
...
unsigned idx_color_red = add_painter(cp);
unsigned idx_pic = add_painter<ipicture_painter> ("c:\\img1.jpg");

ipicture_painter.jpg

Because idx_pic was added after idx_color_red you can only see the former. See Features affecting the visibility for further information.

As you can see there is more than one version of add_painter(). The non-template add_painter() takes a painter as a parameter, copies this painter (by invoking clone()) and adds that copy. The template versions expect parameter types which are specified in the painter class passed as template parameter (see Implementing an own painter). An instance of this painter class is then dynamically created by passing the arguments to the constructor. Finally this object is added to background_wnd.

Accessing painters

As I mentioned before keys can be accessed throught their indices. If you pass an index to a function which refers to no painter a background_wnd::index_invalid-exception is thrown. You can get a list of all the current indices by calling get_indices().

To obtain a reference to a painter to manipulate it directly just call get_painter<Painter> (). The painter is then casted to the passed type Painter. If this cast fails - which indicates the dynamic type of the painter isn't Painter - a background_wnd::invalid_painter_cast-exception is thrown. Of course you can get a reference to a painter_base by calling the non-template version of this function. This will always succeed - if the index is ok!
...
ipicture_painter& pic_p = get_painter<ipicture_painter> (idx_pic);
try {     
     // this line throws if there's no painter with index 5
     painter_base& some_p = get_painter(5);
     
     // this line will definitely throw - the painter at index idx_color is a color_painter!
     ipicture_painter& another_pic_p = get_painter<ipicture_painter> (idx_color);
}
catch (bg_wnd::general_exception_of_type<background_wnd>&) {
     // react in a usefull manner
     ...
}


Removing painters

Removal of painters is very easy. Just call delete_painter() with the index of the desired painter or delete all painters with delete_all_painters().

Example
typedef vector<unsigned> CollIndices;
CollIndices coll_idx = get_indices();
for (CollIndices::iterator it = coll_idx.begin(); it != coll_idx.end(); ++it) {
     try {
          color_painter& p = get_painter<color_painter> (*it);
          color_painter* new_cp = p.clone();
          ...
     }
     // if an invalid_painter_cast-exception is thrown, the painter isn't a color_painter. here we delete all non-color_painters ;-)
     catch (background_wnd::invalid_painter_cast&) {        
          delete_painter(*it);
     }
}
...
// delete all remaining painters
delete_all_painter();


Features affecting the visibility

background_wnd supports some great features which affect the visibility of the window and the painters. To change the background-color of the window just use the bk_color()-function.

You can hide painters with show_painter(). To determine if a painter is visible call is_painter_visible(). You can even set the transparency of a painter: call transparency() with the index of the painter and a transparency-degree. 0 means totally transparent (invisible); 255 means opaque.

transparency.jpg
This example shows some painters with a transparency from 0 - 250

To avoid flickering when you make a few changes (for example adding painters, removing painters, change the Z-Order, ...) which would result in constant redrawing of the window you can disable automatic redrawing with the function redraw_on_changes(). Then only explicite calls to redraw_painters() will redraw the memory dc. If you apply changes to painters directly (by first getting access to the painter with get_painter()) which affect their output to the screen you have to call redraw_painters() - else you don't see any changes.

// apply some changes on the layout_painter
layout_painter& layout = get_painter<layout_painter> (0);
layout.margin(20, 20);
layout[0][0] = "pic1";
layout.insert_row(0);
redraw_painters();


Every painter has a drawing-rectangle in which the painter is drawn. You can compare this to a clipping rect. By default the painter will be drawn in the whole client-area of the window but you can change this with drawing_rect(). If you pass a rectangle rc to this function that has a width and height of 0 or less the drawing-rect will be (rc.left, rc.top, rc_client.right, rc_client.bottom).

drawing_rect_1.jpg
drawing_rect_2.jpg
Before drawing_rect() After drawing_rect(idx_red, rectangle(0, 0, 100, 50))


The Z-Order of the painters can also be changed: use the zorder_xxx() member-functions. New painters are automatically on top of the Z-Order.

zorder_1.jpg
zorder_2.jpg
Before zorder_to_back() After zorder_to_back(idx_color_red)


Example

// be aware of flickering ;-)
redraw_on_changes(false);

// change background-color to dark blue
bk_color(RGB(0, 0, 100));

// add a cursor from a resource and bring to background
unsigned idx_cursor = add_painter<resource_painter> (bg_wnd::res_info(IDC_CURSOR, IMAGE_CURSOR));
zorder_to_back(idx_cursor);
drawing_rect(idx_cursor, rectangle(100, 100, 116, 116));

// The cursor wouldn't be visible because idx_color_red and idx_pic are now over it in Z-Order
transparency(idx_color_red, 100);
show_painter(idx_pic, false);

// all changes applied...now redraw
redraw_on_changes(true);
redraw_painters();


Access to memory dc

background_wnd uses a memory dc to draw the painters. In derived classes you have access to this memory dc by calling get_mem_dc(). You get a reference to a bg_wnd::memory_dc-object which represents the dc. This class has a conversion operator so you can use memory_dc-objects in GDI-API calls.

Exceptions

The background_wnd and the painters have their own exception technique. The root of the exceptions is bg_wnd::background_wnd_exception which is derived from std::exception. To catch all exceptions that are thrown by any painter or the background_wnd use this code snippet:
try {
     // painter operations
     ...
}
catch (bg_wnd::background_wnd_exception&) {
     // react in a usefull manner
     ...
}

Because this exception has no further information and is therefore not very useful in most cases I derived another class: bg_wnd::general_exception_of_type. The template parameter T is the type of the object that has thrown the exception. So you can determine which class caused the exception. To determine which specific object has thrown its constructor takes a reference to that object and the member-function get_object() returns this reference. With this in mind you can write something like this:

try {
     // painter operations
     ...
}
catch (bg_wnd::general_exception_of_type<ipicture_painter>& exception) {
     // catched an exception of an ipicture_painter. React in a usefull manner
     if (&pic1 == &exception.get_object()) {
          ...
     }
     else if (&pic2 == &exception.get_object()) {
          ...
     }    
}
catch (bg_wnd::general_exception_of_type<background_wnd>&) {
     // catched an exception of the background_wnd. React in a usefull manner
     ...
}

bg_wnd::general_exception_of_type has one disadvantage: you only have one exception per type. So I derived bg_wnd::general_exception. Its only difference is the second template parameter num which is a number. When you pass different numbers the compiler instantiates different classes from the template and we are fine. But numbers are difficult to remember so I recommend you typedef them in your own painters:

struct your_painter : painter_base
{
     typedef bg_wnd::general_exception<your_painter, 0> first_exception;
     typedef bg_wnd::general_exception<your_painter, 1> second_exception;
     ...
};

...
try {
     // create the painter and do something with it
     your_painter p;
     ...
}
catch (your_painter::first_exception&) {
     // react in a usefull manner
     ...
}
catch (your_painter::second_exception&) {
     // react in a usefull manner
     ...
}

This exception hierarchy provides you with all the information you need. Catch all exceptions of any painter or the background_wnd with bg_wnd::background_wnd_exception. To catch all exceptions of a specific class use bg_wnd::general_exception_by_type. And to distinguish between the exceptions of a type use bg_wnd::general_exception.

When you create your own painters please use these classes because everybody would expect you to use them ;-)

background_wnd_by_key

As I mentioned before background_wnd_by_key adds the possibility of accessing painters through a unique key to background_wnd. The type of the key is passed as a template parameter and all the member-functions expecting an index in background_wnd expect a key instead.

An important difference is that you can't catch background_wnd's exceptions when using background_wnd_by_key. It has its own exceptions that must be catched:

// assume it's a background_wnd_by_key<std::string> window
typedef background_wnd_by_key<std::string> bg_wnd_by_string;
add_painter<ipicture_painter> ("pic1_key", "c:\\img0.jpg");
try {
     get_painter<color_painter> ("pic1_key");          // throws invalid_painter_cast
     get_painter("some_invalid_key");                  // throws key_invalid
}
catch (bg_wnd_by_string::invalid_painter_cast&) {
     // react in a usefull manner
     ...
}
catch (bg_wnd_by_string::key_invalid&) {
     // react in a usefull manner
     ...
}

If a painter with the key passed to add_painter() exists yet a background_wnd_by_key<T>::key_already_used- exception is thrown.


by Steven Weiss. You can contact me at steven11@gmx.de.