FLTK学习-8-鼠标事件处理

【翻译自fltk_tutorial.pdf第16部分】

part16:处理鼠标事件第二部分
          这个例子有点像绘图程序。当你按下鼠标并拖动时,一条线就会随着鼠标移动绘出来。当点击左键时会连接下一次的点击位置绘出一条线,当点击右键时就会绘出一个矩形。

         这个例子基于Ian MacArthur提交的一个例子而来,在FLTK中绘图通常是在虚函数draw内部。你需要实现这个函数的自己的版本来覆盖fltk的提供的虚拟draw函数。当调用draw时,就会按照函数中定义的绘制屏幕。
         为渐进的绘图,最好在一个幕后缓冲区中绘制然后在调用draw函数时,将缓冲区复制到屏幕上。因为fltk不会存储屏幕内容所以当窗口变形和恢复时,所有的内容将被清除,幕后缓冲区的内容将会一直存在。这个例子就是使用渐进绘图,并且使用了幕后缓冲区。

#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 400
static Fl_Double_Window *main_window = 0;  // the main app window
static 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 box
		fl_copy_offscreen(x(), y(), w(), h(), offscreen_buffer, 0,0);
	}
    else 
	{ // create the offscreen
		main_window->make_current(); //ensures suitable graphic context
		offscreen_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 button
		sprintf(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 button
				fl_color(FL_RED);
				fl_line(x_old,y_old,x,y);
			} else { //right mouse button
				fl_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 context
			redraw();}
		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 window
	static 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

【例子在VC6.0,使用FLTK1.1.10测试通过】

          例子中定义了一个叫做canvas的Fl_Box子类新窗口类。定义了用来绘图的区域。在main函数中,这个canvas类的一个新的对象被创建作为main_window的子构件。
          类canvas同时还定义了handle函数重载了Fl_Widgets::handle()虚函数。所有的事件将被FLTK发送到canvas的handle函数中。函数检查FL_PUSH和FL_DRAG两个不同的鼠标事件并且返回1来指示FLTK它们已经被这个函数处理过了。两个事件中收到任意一个,函数就会在窗口的标题中指示是哪一个鼠标键被按下了并且显示当前鼠标的位置。
          如果是FL_DRAG事件,则将在当前位置绘出一点,如果是FL_PUSH键,将会保存鼠标位置,当第二次FL_PUSH事件时,根据是左键还是右键点击会绘制不同图形。如果是左键点击,则绘制一条连接上次点击位置和现在点击位置的直线。如果是右键点击,则绘制出的是一个矩形而不是直线。对幕后缓冲区的绘制开始于fl_begin_offscree(),结束于fl_end_offscreen()。
          draw函数只需要将幕后缓冲区复制到屏幕。当第一次调用draw函数时,它将使用fl_create_offscreen分配幕后缓冲区,然后使用fl_rectf()清除缓冲区为白色。当缓冲区绘制到屏幕之后会将绘制区域绘制成白色。仅仅需要确认基于main_window的幕后缓冲区当前有一个合适的图形上下文环境【??】。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值