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

## Using background_wnd

### Content

- Namespaces
- Deriving from background_wnd
- Adding painters
- Accessing painters
- Removing painters
- Features affecting the visibility
- Access to memory dc
- Exceptions
- background_wnd_by_key

### 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");

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.
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).

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.

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.