namespace win32 { namespace gui { // painter_base: abstract base class of all painters struct painter_base { // c'tor and virtual destructor painter_base(); virtual ~painter_base(); // virtual functions virtual painter_base* clone() const = 0; virtual void draw(HDC hDC, int cx, int cy) = 0; virtual bool is_opaque(int cx, int cy) const; protected: // only copy with clone() painter_base(const painter_base&); const painter_base& operator= (const painter_base&); }; } } // namespace win32::gui
draw(). The arguments are: hDC - The dc on which the painting operations should occur cx, cy - The width and height of the area where the painting shall occur (see drawing-rect)
clone(). You are forced to return an object which is allocated with new. If you don't return such an object your application is likely to crash. Normally you will implement this function like this: your_painter* your_painter::clone() const { return new your_painter(*this); }
param0 and param1 is_opaque(). If you know your painter draws the whole area opaque you can return true in this function. background_wnd will check this and if a painter is completely underneath your painter (lower in Z-Order and drawing-rect is completely overlapped by the drawing-rect of your painter) background_wnd will not call draw() of the overlapped painter. Of course background_wnd takes care of the transparency that could be applied to your painter ;-). By default this function returns false. The arguments are the same which are passed to draw() except for hDC draw()-function. stretch_painter does exactly that: void stretch_painter::draw(HDC hDC, int cx, int cy) { ... transparent_painter p(cr_not_used_); p.set_painter<stretch_painter_helper> (hPainterDC, wnd_size(cx, cy)); p.draw(hDC, rc_stretch_.width(), rc_stretch_.height()); ... }
namespace win32 { namespace gui { // painter_holder struct painter_holder { // exceptions typedef bg_wnd::general_exception<painter_holder, 0> no_painter; typedef bg_wnd::general_exception<painter_holder, 1> invalid_painter_cast; // the big 4 painter_holder(painter_base* pPainter = NULL); painter_holder(const painter_holder& holder); virtual ~painter_holder(); const painter_holder& operator= (const painter_holder& holder); // set the painter and release it void release_painter(); void set_painter(const painter_base& painter); template<class Painter> void set_painter(); template<class Painter> void set_painter(typename Painter::param0 param); template<class Painter> void set_painter(typename Painter::param0 param0, typename Painter::param1 param1); // painter access painter_base& get_painter() const; template<class Painter> Painter& get_painter() const; bool painter_available() const; void swap(painter_holder& holder); }; } } // namespace win32::gui
set_painter() creates a copy of the passed painter by invoking clone() get_painter() and there is no painter a painter_holder::no_painter-exception is thrown. If you call the templated function and the painter can't be casted to Painter (dynamic type of the painter is not Painter) a painter_holder::invalid_painter_cast-exception is thrown.
|
by Steven Weiss. You can contact me at steven11@gmx.de. |