/*
* 这些代码是由Jeff Molofee 与2000年写的,再次我必须感谢Fredric Echols,因为他使这些代码看起来更简洁和高效,并使他易于使用。
* 如果你发现这些代码对你有所帮助,请访问我的站点 http://nehe.gamedev.net/default.asp ,并让我知道。
*********************************************************************************************************************************
* 这份文档是由DancingWind翻译的,如果有什么错误请e-mail:zhouwei02@mails.tsinghua.edu.cn
*/
#pragma warning(once:4996)
/*********************包含链接的库文件*******************************************************************************************/
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "glut32.lib")
#pragma comment( lib, "glew32.lib")
#pragma comment( lib, "glaux.lib")
#pragma comment( lib, "vfw32.lib" )
/********************************************************************************************************************************/
#include <afxwin.h>
#include <cmath>
#include "resource.h"
#include <windows.h> // Windows的头文件
#include "glew.h" // 包含最新的gl.h,glu.h库
#include "glut.h" // 包含OpenGL实用库
#include <stdarg.h> // 用来定义可变参数的头文件
#include "TuioServer.h"
#include "TuioCursor.h"
#include <list>
HDC hDC=NULL; // 窗口着色描述表句柄
HGLRC hRC=NULL; // OpenGL渲染描述表句柄
HWND hWnd=NULL; // 保存我们的窗口句柄
HINSTANCE hInstance; // 保存程序的实例
int wHeight, wWidth;
bool keys[256]; // 保存键盘按键的数组
bool active=TRUE; // 窗口的活动标志,缺省为TRUE
bool fullscreen=TRUE; // 全屏标志缺省,缺省设定成全屏模式
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // WndProc的定义
GLuint base; // 绘制字体的显示列表的开始位置
bool ifshowcursor=true;
bool horclip=false;
bool verclip=false;
typedef struct SiRawMouse
{
long X;
long Y;
USHORT usButtonFlags;
HANDLE hDevice;
TUIO::TuioCursor *c;
bool pressed;
SiRawMouse(void ) { c=NULL; pressed=false;}
}SiRawMouse,*pSiRawMouse; //输入设备鼠标的自定义类型数组
//判定是否为系统鼠标的函数
void InitRawInput();
bool IsRootMouse(TCHAR cDeviceString[]);
void CheckBound(long &x,long &y);
pSiRawMouse m_pSiRawMouse;
TCHAR m_mousePostion[256]; // 鼠标位置缓存
HICON m_hiconCursor[10]; //绘制的鼠标
int m_nMouseNumber; //鼠标数量
void DrawMultiCursor();
//TUIO 相关
TUIO::TuioServer *tuioServer;
TUIO::TuioCursor *cursor;
std::list<TUIO::TuioCursor*> stickyCursorList;
TUIO::TuioTime currentTime;
bool verbose;
void TUIOInit()
{
verbose = false;
cursor = NULL;
tuioServer = new TUIO::TuioServer();
}
GLvoid BuildFont(GLvoid) // 创建位图字体
{
HFONT font; // 字体句柄
HFONT oldfont; // 旧的字体句柄
base = glGenLists(96); // 创建96个显示列表
font = CreateFont( -24, // 字体高度
0, // 字体宽度
0, // 字体的旋转角度 Angle Of Escapement
0, // 字体底线的旋转角度Orientation Angle
FW_BOLD, // 字体的重量
FALSE, // 是否使用斜体
FALSE, // 是否使用下划线
FALSE, // 是否使用删除线
ANSI_CHARSET, // 设置字符集
OUT_TT_PRECIS, // 输出精度
CLIP_DEFAULT_PRECIS, // 裁剪精度
ANTIALIASED_QUALITY, // 输出质量
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
"Courier New"); // 字体名称
oldfont = (HFONT)SelectObject(hDC, font); // 选择我们需要的字体
wglUseFontBitmaps(hDC, 32, 96, base); // 创建96个显示列表,绘制从ASCII码为32-128的字符
SelectObject(hDC, oldfont); // 选择原来的字体
DeleteObject(font); // 删除字体
}
GLvoid KillFont(GLvoid) // 删除显示列表
{
glDeleteLists(base, 96); //删除96个显示列表
}
GLvoid glPrint(const char *fmt, ...) // 自定义GL输出字体函数
{
char text[256]; // 保存文字串
va_list ap; // 指向一个变量列表的指针
if (fmt == NULL) // 如果无输入则返回
return;
va_start(ap, fmt); // 分析可变参数
vsprintf(text, fmt, ap); // 把参数值写入字符串
va_end(ap); // 结束分析
glPushAttrib(GL_LIST_BIT); // 把显示列表属性压入属性堆栈
glListBase(base - 32); // 设置显示列表的基础值
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // 调用显示列表绘制字符串
glPopAttrib(); // 弹出属性堆栈
}
// 创建字体
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // 重置OpenGL窗口大小
{
wWidth= width;
wHeight= height;
if (height==0) // 防止被零除
{
height=1; // 将Height设为1
}
glViewport(0,0,width,height); // 重置当前的视口
glMatrixMode(GL_PROJECTION); // 选择投影矩阵
glLoadIdentity(); // 重置投影矩阵
// 设置视口的大小
//gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW); // 选择模型观察矩阵
glLoadIdentity(); // 重置模型观察矩阵
}
int InitGL(GLvoid) // 此处开始对OpenGL进行所有设置
{
glShadeModel(GL_SMOOTH); // 启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景
glClearDepth(1.0f); // 设置深度缓存
glEnable(GL_DEPTH_TEST); // 启用深度测试
glDepthFunc(GL_LEQUAL); // 所作深度测试的类型
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 告诉系统对透视进行修正
BuildFont();
ShowCursor(ifshowcursor);
return TRUE; // 初始化 OK
}
void InitRawInput()
{
UINT nDevices; //输入设备的数量
//第一次调用GetRawInputDeviceList获得输入设备的数量
GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST));
//第二次调用GetRawInputDeviceList获得RawInputDeviceList数组
PRAWINPUTDEVICELIST pRawInputDeviceList;// = new RAWINPUTDEVICELIST[nDevices];
pRawInputDeviceList = (RAWINPUTDEVICELIST *)calloc(nDevices,sizeof(RAWINPUTDEVICELIST));
GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST));
//获得输入设备中鼠标的数量
for(int i=0; i < static_cast<int>(nDevices); ++i)
{
if(pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE)
{
++m_nMouseNumber;
}
}
//获得输入设备鼠标的自定义类型数组,其中索引为0的为系统鼠标
m_pSiRawMouse = (SiRawMouse *)calloc(m_nMouseNumber,sizeof(SiRawMouse));
LPVOID lpb;
UINT dwSize;
for(int i=0,j=1; i < static_cast<int>(nDevices) && j < m_nMouseNumber; ++i)
{
if(pRawInputDeviceList[i].dwType == RIM_TYPEMOUSE)
{
//连续两次调用GetRawInputDeviceInfo以读取RIDI_DEVICENAME
//并通过此值判断是否为系统鼠标
GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,RIDI_DEVICENAME,NULL,&dwSize);
lpb = malloc(sizeof(LPVOID) * dwSize);
GetRawInputDeviceInfo(pRawInputDeviceList[i].hDevice,RIDI_DEVICENAME,lpb,&dwSize);
TCHAR *deviceName = (TCHAR*)lpb;
//将系统鼠标的保存在索引0中,其他依次列在后面
if(IsRootMouse(deviceName))
{
m_pSiRawMouse[0].hDevice = pRawInputDeviceList[i].hDevice;
m_pSiRawMouse[0].X = 0;
m_pSiRawMouse[0].Y = 0;
m_pSiRawMouse[0].usButtonFlags = 0;
}
else
{
m_pSiRawMouse[j].hDevice = pRawInputDeviceList[i].hDevice;
m_pSiRawMouse[j].X = 0;
m_pSiRawMouse[j].Y = 0;
m_pSiRawMouse[j].usButtonFlags = 0;
++j;
}
free(lpb);
}
}
free(pRawInputDeviceList);
pRawInputDeviceList = NULL;
//初始化1个RawInput设备
RAWINPUTDEVICE Rid[1]; //分配RawInput设备的空间
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x02;
Rid[0].dwFlags = 0;
Rid[0].hwndTarget = NULL;
//注册RawInput设备
if (RegisterRawInputDevices(Rid, 1, sizeof (Rid [0])) == FALSE) {
MessageBox(0,"RawInput Register Error.","RawInput Register Error.",MB_OK|MB_ICONEXCLAMATION);
}
return ;
}
bool IsRootMouse(TCHAR cDeviceString[])
{
//一般系统鼠标DeviceName的前22字节
TCHAR cRootString[] = ("\\??\\Root#RDP_MOU#0000#");
//通过比较前22个字节判断是否为系统鼠标
if (strlen(cDeviceString) < 22)
{
return false;
}
for (int i = 0; i < 22; i++)
{
if (cRootString[i] != cDeviceString[i])
{
return false;
}
}
return true;
}
void Chec
simulator_multi_mouse
![star](https://csdnimg.cn/release/downloadcmsfe/public/img/star.98a08eaa.png)
![avatar](https://profile-avatar.csdnimg.cn/b0324e0829794bee81f802aaee0ea0b9_augusdi.jpg!1)
Augusdi
- 粉丝: 1w+
- 资源: 5760
最新资源
- 基于python+flask+mysql实现的豆瓣电影可视化系统+源代码+文档说明+数据库sql.zip
- 程氏舞曲V4.2程氏舞曲V4.2程氏舞曲V4.2程氏舞曲V4.2
- FPGA读写 AD9708+ AD9280 ADDA实验Verilog逻辑源码Quartus工程文件+文档说明+硬件参考原理图
- 基于CH340C设计USB转TLL串口通信模块PADS 9.5设计硬件(原理图+PCB)文件.zip
- 信号与系统大作业-图像处理 实现了直接滤波法维纳滤波法最小二乘滤波法LR递归法matlab源码.zip
- php-leetcode题解之最小栈.zip
- php-leetcode题解之最长不含重复字符的子字符串.zip
- php-leetcode题解之最长公共前缀.zip
- php-leetcode题解之最小差值.zip
- php-leetcode题解之最小基因变化.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback-tip](https://img-home.csdnimg.cn/images/20220527035111.png)