在PC上用户的输入操作一般分为键盘+鼠标两种,freeglut库已经帮我们封装好了这些操作的消息响应,只需要用户注册并编写响应逻辑即可。
键盘响应
键盘的消息注册函数为glutKeyboardFunc,消息响应回调函数可定义如下:
//第一个参数表示按下的按键的ASCII码。
//其余两个参数提供了当键按下时当前的鼠标位置(相对于当前客户窗口的左上角)。
void keyboardFunc(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
std::cout << "按下退出键" << std::endl;
glutLeaveMainLoop();//退出消息循环
break;
case 'R':
std::cout << "按下R键" << std::endl;
break;
}
}
注册函数的完整代码:
glutKeyboardFunc(keyboardFunc);//定义键盘响应函数
鼠标响应
鼠标的消息注册函数为glutMouseFunc,消息响应回调函数可定义如下:
//参数一是鼠标对象,参数二是状态。
//其余两个参数提供了当前的鼠标位置(相对于当前客户窗口的左上角)。
void mouseFunc(int button, int state, int x, int y)
{
//按键判断
if (button == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN)
std::cout << "鼠标左键按下" << std::endl;
else if (state == GLUT_UP)
std::cout << "鼠标左键释放" << std::endl;
}
if (button == GLUT_MIDDLE_BUTTON)
{
if (state == GLUT_DOWN)
std::cout << "鼠标中键按下" << std::endl;
else if (state == GLUT_UP)
std::cout << "鼠标中键释放" << std::endl;
}
if (button == GLUT_RIGHT_BUTTON)
{
if (state == GLUT_DOWN)
std::cout << "鼠标右键按下" << std::endl;
else if (state == GLUT_UP)
std::cout << "鼠标右键释放" << std::endl;
}
}
从该响应函数可以看到两个不足,一是没有鼠标中键的信息,二是没有双击鼠标按钮的信息。
针对问题一,在freeglut的扩展库中提供了解决方法,注册鼠标滚轮消息函数glutMouseWheelFunc,然后将消息响应函数定义如下:
//鼠标滚轮上下响应函数,最重要的是参数二,大于0表示上滚,小于0则表示下滚
void mouseWheel(int button, int dir, int x, int y)
{
if (dir > 0)
std::cout << "鼠标滚轮向上" << std::endl;
else
std::cout << "鼠标滚轮向下" << std::endl;
}
针对问题二,没有现成的解决办法。。。可以通过判断两次鼠标点击的时间间隔来实现。由于freeglut提供可定时器函数,因此实现起来也很简单。
首先,声明两个全局变量:
bool leftbuttondown1 = false;
bool leftbuttondown2 = false;
然后,将鼠标响应函数改为:
if (button == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN)
{
leftbuttondown2 = leftbuttondown1;
leftbuttondown1 = true;
if (!leftbuttondown2)
{
glutTimerFunc(200, timerProc, 1);//设置定时器200毫秒后调用timerProc函数,id为1
}
}
}
最后定义定时器响应函数即可:
//定时器响应
void timerProc(int id)
{
if (id==1)
{
if (leftbuttondown2 && leftbuttondown1)
{
std::cout << "鼠标左键双击" << std::endl;
}
else
{
std::cout << "鼠标左键单击" << std::endl;
}
leftbuttondown1 = false;
leftbuttondown2 = false;
}
}
另外,如果我们想要做UI,有些控件需要实时获得鼠标的位置信息,这个时候可以使用另外的响应函数glutPassiveMotionFunc,具体的操作也非常简单,先注册该函数:
glutPassiveMotionFunc(mouseMotion);//实时获得鼠标位置信息
然后对其进行定义即可:
//鼠标移动时发送消息
void mouseMotion(int x, int y)
{
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
}
到此我们就完成了freeglut库输入响应的全部介绍,完整的代码如下:
#include <iostream>
#include <GL/freeglut.h>
#include <GL/freeglut_ext.h>
void display(void)
{
//填充缓冲区表面
glFlush();
//缓冲区翻转显示图像
glutSwapBuffers();
}
//第一个参数表示按下的按键的ASCII码。
//其余两个参数提供了当键按下时当前的鼠标位置(相对于当前客户窗口的左上角)。
void keyboardFunc(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
std::cout << "按下退出键" << std::endl;
glutLeaveMainLoop();//退出消息循环
break;
case 'R':
std::cout << "按下R键" << std::endl;
break;
}
}
bool leftbuttondown1 = false;
bool leftbuttondown2 = false;
//定时器响应
void timerProc(int id)
{
if (id==1)
{
if (leftbuttondown2 && leftbuttondown1)
{
std::cout << "鼠标左键双击" << std::endl;
}
else
{
std::cout << "鼠标左键单击" << std::endl;
}
leftbuttondown1 = false;
leftbuttondown2 = false;
}
}
//参数一是鼠标对象,参数二是状态。
//其余两个参数提供了当前的鼠标位置(相对于当前客户窗口的左上角)。
void mouseFunc(int button, int state, int x, int y)
{
//按键判断
if (button == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN)
{
leftbuttondown2 = leftbuttondown1;
leftbuttondown1 = true;
if (!leftbuttondown2)
{
glutTimerFunc(200, timerProc, 1);//设置定时器200毫秒后调用timerProc函数,id为1
}
}
}
}
//鼠标滚轮上下响应函数,最重要的是参数二,大于0表示上滚,小于0则表示下滚
void mouseWheel(int button, int dir, int x, int y)
{
if (dir > 0)
std::cout << "鼠标滚轮向上" << std::endl;
else
std::cout << "鼠标滚轮向下" << std::endl;
}
//鼠标按钮没有按下时,移动发送消息
void mousePassiveMotion(int x, int y)
{
std::cout << "x: " << x << std::endl;
std::cout << "y: " << y << std::endl;
}
//鼠标按钮按下时发送消息
void mouseMotion(int x, int y)
{
std::cout << "x1: " << x << std::endl;
std::cout << "y1: " << y << std::endl;
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);//设置绘图模式
glutInitWindowPosition(0, 0);//设置窗口弹出位置
glutInitWindowSize(800, 600);//设置窗口大小
glutCreateWindow("imgshow");//创建窗口
glutKeyboardFunc(keyboardFunc);//定义键盘响应函数
glutMouseFunc(mouseFunc);//定义鼠标响应函数
glutMouseWheelFunc(mouseWheel);//定义鼠标滚轮回调函数
glutPassiveMotionFunc(mousePassiveMotion);//实时获得鼠标位置信息
glutMotionFunc(mouseMotion);//实时获得鼠标位置信息
glutDisplayFunc(&display);//定义绘图回调函数
glutMainLoop();//进入消息循环
return 0;
}
下一篇文章我们将介绍freeglut中中文文字的渲染。