Translation from fltk_tutorial.pdf Part 1]
Part16: process the second part of the mouse event
This example is a bit like a drawing program. When you press and drag the mouse, a line is drawn as the mouse moves. When you click the left button, a line is drawn at the next click position. When you right-click the line, a rectangle is drawn.
This example is based on an example submitted by Ian MacArthur. Drawing in FLTK is usually within the draw of the virtual function. You need to implement your own version of this function to overwrite the virtual draw function provided by fltk. When draw is called, the screen is drawn according to the function definition.
For progressive plotting, it is best to draw in a buffer behind the scenes and then copy the buffer to the screen when calling the draw function. Because fltk does not store screen content, all content will be cleared when the window is deformed and restored, and the content in the buffer will always exist. This example uses progressive plotting and the background buffer.
#pragma comment(lib, "fltk.lib")#pragma comment(lib, "wsock32.lib")#pragma comment(lib, "comctl32.lib")#pragma comment(linker, "/NODEFAULTLIB:LIBCMTD.lib")#include <stdio.h>#include <Fl/Fl.H>#include <FL/Fl_Double_Window.H>#include <Fl/Fl_Box.H>#include <Fl/fl_draw.H>#include <fl/x.H>#define window_size 400static Fl_Double_Window *main_window = 0; // the main app windowstatic Fl_Offscreen offscreen_buffer = 0; // the offscreen surface/*****************************************************************************//* This class provides a view to copy the offscreen surface to */class canvas : public Fl_Box {void draw();int handle(int event);public:canvas(int x, int y, int w, int h);};/*****************************************************************************//* Constructor */canvas::canvas(int x, int y, int w, int h) : Fl_Box(x,y,w,h){} // Constructor/*****************************************************************************/void canvas::draw() { if(offscreen_buffer) { // offscreen exists// blit the required view from the offscreen onto the boxfl_copy_offscreen(x(), y(), w(), h(), offscreen_buffer, 0,0);} else { // create the offscreenmain_window->make_current(); //ensures suitable graphic contextoffscreen_buffer = fl_create_offscreen( w(), h() );if(!offscreen_buffer){fprintf(stderr,"Failed buffer creation");exit(1);}fl_begin_offscreen(offscreen_buffer); /* Open the offscreen context */ fl_color(FL_WHITE);fl_rectf(0, 0, w(), h() );fl_end_offscreen(); /* close the offscreen context *//* init screen with offscreen buffer */fl_copy_offscreen(x(), y(), w(), h(), offscreen_buffer, 0,0);}} // draw method/*****************************************************************************/int canvas::handle(int event) { static char labeltext[100]; int button,x,y; int retvalue = 0; static int x_old,y_old; static int push1st=0; if (!offscreen_buffer) return 1; retvalue = Fl_Box::handle(event); switch (event){ case FL_PUSH: case FL_DRAG: button = Fl::event_button(); x = Fl::event_x(); y = Fl::event_y(); }; switch ( button ){ case 1: // Left button sprintf(labeltext,"Last mouse button= Left | Mouse at %d,%d now",x,y); window()->label(labeltext);retvalue = 1;break; case 3: // Right buttonsprintf(labeltext,"Last mouse button= Right | Mouse at %d,%d now",x,y);window()->label(labeltext);retvalue = 1;break;}switch(event) {case FL_PUSH:if (push1st == 0) {x_old = x;y_old = y;push1st = 1; break;} else {push1st = 0;/* Open the offscreen context for drawing */fl_begin_offscreen(offscreen_buffer); if (button==1){ //left mouse buttonfl_color(FL_RED);fl_line(x_old,y_old,x,y);} else { //right mouse buttonfl_draw_box(FL_BORDER_FRAME,x_old,y_old,(x-x_old),(y-y_old),FL_BLUE);}fl_end_offscreen(); /* close the offscreen context */redraw();}case FL_DRAG:{push1st=0; //clear if dragging/* Open the offscreen context for drawing */fl_begin_offscreen(offscreen_buffer); fl_color(FL_BLACK);fl_point(x,y);fl_end_offscreen(); // close the offscreen contextredraw();}break;default:redraw();break;}return retvalue;} // handle/*****************************************************************************/int main (int argc, char **argv) {main_window = new Fl_Double_Window(window_size, window_size, "Drawing with mouse example");main_window->begin();// a view of the offscreen, inside the main windowstatic canvas *os_box = new canvas(5,5,(window_size-10),(window_size-10));main_window->end();main_window->resizable(os_box);main_window->show(argc, argv);return Fl::run();} // main
[In the example of VC6.0, The FLTK1.1.10 test is passed]
The example defines a new window class of the Fl_Box subclass named canvas. Defines the area used for drawing. In the main function, a new object of the canvas class is created as a sub-component of main_window.
Class canvas also defines the handle function to overload the Fl_Widgets: handle () virtual function. All events will be sent to the handle function of canvas by FLTK. The function checks two different mouse events, FL_PUSH and FL_DRAG, and returns 1 to indicate that FLTK has been processed by this function. If either of the two events is received, the function will indicate in the window title which mouse key is pressed and the current mouse position is displayed.
If it is a FL_DRAG event, a point will be drawn at the current position. If it is a FL_PUSH key, the mouse position will be saved. When the second FL_PUSH event is performed, the left-click or right-click button will draw different images. If left-click is selected, a line connecting the last clicked position and the current clicked position is drawn. If you select right-click, a rectangle rather than a straight line is drawn. The painting of the background buffer starts with fl_begin_offscree () and ends with fl_end_offscreen ().
The draw function only needs to copy the background buffer to the screen. When the draw function is called for the first time, it will use fl_create_offscreen to allocate the background buffer, and then use fl_rectf () to clear the buffer as white. When the buffer area is drawn to the screen, the area is painted white. You only need to confirm that the background Buffer Based on main_window currently has a suitable graphic Context Environment 【??].