The Wisegui library has been updated to support the Painter Control, a canvas. The Painter Control can be exported by Bitwise Gui Editor 1.2
In this episode, kPainter, the painter control, is used to display three circles. kAngle, a knob, rotates the picture.
The class DaVinci contains data and the logic to manipulate it. The view, MainView in this case, uses the data object as an extension. The view receives a pointer to data, &_davinci, through "SetData".
View *view = new MainView(this); _gui = new Gui(this, GUI_WIDTH, GUI_HEIGHT); _gui->SetView(view); setEditor(_gui); view->SetData(&_davinci);
You draw on the Painter Control using its overlay, the overlay is a gdiplus bitmap. You retrieve the bitmap using "GetOverlay".
void MainView::OnLoad() { ControlPtr c = GetControl(kPainter); Painter *painter = (Painter *)c; DaVinci *davinci = (DaVinci *)GetData(); davinci->Draw(painter->GetOverlay()); }
Gdiplus stuff. bmp is the overlay.
void DaVinci::Draw(Bitmap *bmp) { double k = 3.1415 / 180; int ray = 32; int w2 = 200 / 2, h2 = 200 / 2; double a1 = (angle + 0) * k; double a2 = (angle + 120) * k; double a3 = (angle + 240) * k; PointF pts[] = { PointF(w2 + 32 * cos(a1), w2 + 32 * sin(a1)), PointF(w2 + 32 * cos(a2), w2 + 32 * sin(a2)), PointF(w2 + 32 * cos(a3), w2 + 32 * sin(a3)) }; Graphics *g = Graphics::FromImage(bmp); g->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); g->Clear(Color(0, 0, 0, 0)); SolidBrush red(0xFFFF0000); SolidBrush green(0xFF00FF00); SolidBrush blue(0xFF0000FF); Rect r(0, 0, 12, 12); r.Offset((int)pts[0].X, (int)pts[0].Y); g->FillEllipse(&red, r); Rect r1(0, 0, 12, 12); r1.Offset((int)pts[1].X, (int)pts[1].Y); g->FillEllipse(&green, r1); Rect r2(0, 0, 12, 12); r2.Offset((int)pts[2].X, (int)pts[2].Y); g->FillEllipse(&blue, r2); delete g; }
After the knob is updated, OnUpdate is called. You have a chance to update the painter's overlay. The Painter control doesn't know that its overlay is changed, so explicitly "Redraw" it.
void MainView::OnUpdate(int index, double value) { if (index == kAngle) { ControlPtr c = GetControl(kAngle); double angle = c->GetValue(); c = GetControl(kPainter); Painter *painter = (Painter *)c; DaVinci *davinci = (DaVinci *)GetData(); davinci->SetAngle((int)(angle)); davinci->Draw(painter->GetOverlay()); Redraw(c); } }
In the previous episode, we have seen how a change in a control can trigger the update of the Painter Control. You may want to update the painter independently of other controls. A timed update may be the case. WiseScope is a minimal oscilloscope implementation that shows how.
At some point, in a thread, for instance, you can request a control update using RequestControlUpdate. RequestControlUpdate, now, has three request types.
pntScreen is the Painter Control, the oscilloscope screen, in this case.
if (pw->buddy->IsGuiOpen()) pw->buddy->GetGui()->RequestControlUpdate( pntScreen, (int)li, URT_DIRECT2);
URT_DIRECT2 requests an update and sends the control a value, but it DOESN'T redraw the control. When OnUpdate is called, you update the overlay and redraw the control.
// Called when a control's value needs to be updated void ScopeView::OnUpdate(int index, double value) { if (index == pntScreen) { ControlPtr c = GetControl(pntScreen); Painter *painter = (Painter *)c; Engine *e = (Engine *)GetData(); PLIST_ITEM li = (PLIST_ITEM)(int)c->GetValue(); Bitmap *bmp = painter->GetOverlay(); e->Display(bmp, li); // update the overlay Redraw(c); // redraw the control } }
The View class in wisegui v1.3 fires mouse events by calling the OnMouse method. Override "OnMouse" to receive mouse events. Mouse events are: mouse down/up/move. Mouse move is actually a mouse drag. BGE 1.2 exports views that are "mouse events" enabled.
The following example uses mouse events and the Painter control to implement an ADSR control.
// MainView.cpp #include "MainView.h" #include "envelope.h" void MainView::OnLoad() { ControlPtr c = GetControl(pntCanvas); Painter *p = (Painter *)c; Gdiplus::Bitmap *bmp = p->GetOverlay(); Envelope *env = (Envelope *)GetData(); env->SetBitmap(bmp); env->Draw(); } void MainView::OnUpdate(int index, double value) {} void MainView::OnMouse(int index, int event, int x, int y, int info) { if (index == pntCanvas) { Envelope *env = (Envelope *)GetData(); if (event == MOUSE_DOWN) env->MouseDown(x, y); if (event == MOUSE_UP) env->MouseUp(x, y); if (event == MOUSE_MOVE) env->MouseDrag(x, y); ControlPtr c = GetControl(index); Redraw(c); } }