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 ;-) win32::gui is fully visible (using namespace win32::gui). #include <win32gui/background_wnd.hpp> struct your_window : wnd_extend<dialog, your_window>, wnd_extend<background_wnd, your_window> { ... };
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.
background_wnd::index_invalid-exception is thrown. You can get a list of all the current indices by calling get_indices(). 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 ... }
delete_painter() with the index of the desired painter or delete all painters with delete_all_painters(). 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();
bk_color()-function. 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.
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();
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. 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 ;-)
// 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. |