當用戶按下或釋放鼠標按鈕、按下按鈕時移動鼠標或按下和松開鍵盤按鍵時,就會產生一個相關事件。程序員可以用每類事件注冊一個回調函數,例如使用如下函數:
- glutMouseFunc(myMouse):利用按下或釋放鼠標按鈕時發生的事件來注冊myMouse
- glutMotionFunc(myMovedMouse):利用按下按鈕同時移動鼠標的事件來注冊myMovedMouse
- glutKeyboardFunc(myKeyboard):利用按下和松開鍵盤按鍵的事件來注冊myKeyboard
1.用鼠標交互
回調函數的名字可以隨便起,但是一定要帶4個參數,其原型如下:
void myMouse(int button,int state,int x,int y); 當鼠標事件發生時,系統會調用注冊的函數,並向其提供這些參數值。
button的值可能是下面明顯含義中的一個:GLUT_LEFT_BUTTON、GLUT_MIDDLE_BUTTON、GLUT_RIGHT_BUTTON
state 的值可能是:GLUT_UP、GLUT_DOWN
x和y的值指明事件發生時鼠標的位置(注意:x是距離窗口左邊的像素數、y是距離窗口頂端的像素數)
時間處理器本身並不引起屏幕的重新繪制事件。因此,為了看到鼠標的效果,鼠標處理器應該調用glutPostRedisplay()
#include "stdafx.h" #include <cstdlib> #include <gl\glut.h> const int screenWidth = 600; const int screenHeight = 480; class GLintPoint { public: GLint x; GLint y; GLintPoint(){ x = 0; y = 0; } GLintPoint(GLint a, GLint b){ x = a; y = b; } }; void myInit(){ glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); glPointSize(2.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble)screenWidth, 0.0, (GLdouble)screenHeight); } void drawDot(GLint x, GLint y){ glBegin(GL_POINTS); glVertex2i(x, y); glEnd(); } void myDisplay(GLintPoint corner[3]){ //繪制Sierrapinski墊片的函數,參數為三個坐標點 glClear(GL_COLOR_BUFFER_BIT); int index = rand() % 3; GLintPoint point = corner[index]; drawDot(point.x, point.y); for (int i = 0; i < 55000; i++){ index = rand() % 3; point.x = (point.x + corner[index].x) / 2; point.y = (point.y + corner[index].y) / 2; //printf("%d %d\n", point.x, point.y); drawDot(point.x, point.y); } glFlush(); } //Simple One 用鼠標放置點,用戶每次按下左鍵時,就會在屏幕窗口鼠標所在位置繪制出一個點;如果用戶按下右鍵,就改變窗口背景顏色 void myMouse(int button, int state, int x, int y){ if (state == GLUT_DOWN){ if (button == GLUT_LEFT_BUTTON){ drawDot(x, screenHeight - y); glFlush(); } else if (button == GLUT_RIGHT_BUTTON){ glClearColor(1.0f,0.0f,0.0f,0.0f); glClear(GL_COLOR_BUFFER_BIT); glFlush(); } } return; } //Sierpinski 用鼠標控制Sierpinski墊片 void myMouseForSierpinski(int button, int state, int x, int y) { static GLintPoint corner[3]; static int numCorners = 0; if (state == GLUT_DOWN){ if (button == GLUT_LEFT_BUTTON){ corner[numCorners].x = x; corner[numCorners].y = screenHeight - y; if (++numCorners == 3){ myDisplay(corner); numCorners = 0; } } } else if (button == GLUT_RIGHT_BUTTON){ glClear(GL_COLOR_BUFFER_BIT); glFlush(); } } void myDis(){} int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(screenWidth, screenHeight); glutCreateWindow("Mouse Sierpinski"); glutMouseFunc(myMouseForSierpinski); //glutMouseFunc(myMouse); glutDisplayFunc(myDis); myInit(); glutMainLoop(); return 0; }
2.用鍵盤交互
回調函數的名字可以隨便起,其原型如下:
void myKeyBoard(unsigned int key,int x,int y); 當鍵盤事件發生時,系統會調用注冊的函數,並向其提供這些參數值。
按鍵的值是所按鍵的ASCII值,數值x和y指示事件發生時鼠標所在的位置(y是距離窗口頂端的像素個數)
大多數myKeyBoard()函數都由很長的switch case語句組成
樣例:按下p鍵會在鼠標位置上繪制一個點;按下左箭頭會在某個全局列表中添加一個點,但是不繪圖;按下E會退出程序。
如果用戶一直按着p鍵並移動鼠標,就會產生一個快速點序列,這就是“徒手”繪圖。
void myKeyboard(unsigned char key,int mouseX,int mouseY){ GLint x = mouseX; GLint y = mouseY; switch(key) { case 'p': drawDot(x,y); break; case 'E': exit(-1); case GLUT_KEY_LEFT:List[++last].x = x; List[last].y = y; break; default: break; } }