OIS输入系统-OIS简介与使用
转自:链接地址
链接地址简介
OIS是一个面向对象的输入系统,理论上它可以支持任何输入设备,其中最主要的三类是键盘、鼠标和游戏控制器。OIS是一个开放源码的项目,你可以按你的要求定制它,以满足你的需求。
链接地址使用OIS
OIS系统必须初始化,然后才能使用,下面我们来一一介绍。
在介绍OIS的初始化以前,我们首先创建一个常规的Windows程序:
链接地址1、创建常规的Windows窗口
#include <windows.h>
//--------------------------------------------------------------------------------------
// 全局变量
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL; //程序实例
HWND g_hWnd = NULL; //窗口句柄
//--------------------------------------------------------------------------------------
// 前向声明
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//--------------------------------------------------------------------------------------
// 程序入口。初始化所有资源,并进入到消息循环中。空闲时间用于渲染。
//--------------------------------------------------------------------------------------
int main()
{
g_hInst = GetModuleHandle(NULL);
if( FAILED( InitWindow( g_hInst, 1 ) ) )
return 0;
// 主消息循环
MSG msg = {0};
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return (int) msg.wParam;
}
//--------------------------------------------------------------------------------------
// 注册窗口类并创建窗口
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
// 注册窗口
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "TutorialWindowClass";
wcex.hIconSm = NULL;
if( !RegisterClassEx(&wcex) )
return E_FAIL;
// 创建窗口
g_hInst = hInstance;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
g_hWnd = CreateWindow( "TutorialWindowClass", "OIS教程", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
if( !g_hWnd )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
return S_OK;
}
//--------------------------------------------------------------------------------------
// 当程序获得一个消息时,调用这个函数一次
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
编译它我们得到一个典型的Windows窗口
以及一个命令行窗口,它主要用于显示相关信息:
整个界面如下:
链接地址2、初始化OIS和常用输入设备
链接地址1、包含OIS库
配置项目,包含头文件#include <OIS.h>,如果你想省事的话可以使用OIS的名字空间
using namespace OIS;
在我们的项目中要使用到字符串,因此把STL库一并添加如下:
#include <windows.h>
#include <OIS.h>
#include <sstream>
#include<string>
using namespace OIS;
using namespace std;
//--------------------------------------------------------------------------------------
// 全局变量
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL; //程序实例
HWND g_hWnd = NULL; //窗口句柄
链接地址2、创建输入输出设备管理器
输入设备管理器(InputManager)是整个OIS的管理者,它用于创建和管理所有的输入输出设备,在创建它时必须指定相关的窗口句柄。因为在多窗口系统中,每个窗口都有自己的设备管理器,它用来管理属于这个窗口的设备。
InputManager * g_InputManager = 0; //输入系统管理器
g_InputManager = InputManager::createInputSystem(g_hWnd);
链接地址3、创建键盘、鼠标输入设备
有了设备管理器,我们就可以创建需要使用的设备了
Mouse* g_m = 0; //鼠标设备
Keyboard * g_kb = 0; //键盘设备
g_m = static_cast<OIS::Mouse*>(g_InputManager->createInputObject(OIS::OISMouse,false));
g_kb = static_cast<OIS::Keyboard*>(g_InputManager->createInputObject(OIS::OISKeyboard,false));
g_m为指向OIS::Mouse对象的指针,g_kb为指向OIS::Keyboard对象的指针,因为InputManager::createInputObject()函数总是返回设备的基对象,我们需要把它转换为实际的鼠标、键盘设备。函数createInputObject的第一个参数为我们要创建的设备类型,第二个参数设置我们使用立即模式,还是缓存模式,设置参数为false表示我们使用立即模式,这样我们可以随时获得设备的当前状态。
初始化OIS的全部代码如下:
#include <windows.h>
#include "OIS.h"
#include <sstream>
#include<string>
using namespace OIS;
using namespace std;
//--------------------------------------------------------------------------------------
// 全局变量
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL; //程序实例
HWND g_hWnd = NULL; //窗口句柄
InputManager * g_InputManager = 0; //输入系统管理器
Mouse * g_m = 0; //鼠标设备
Keyboard * g_kb = 0; //键盘设备
//--------------------------------------------------------------------------------------
// 前向声明
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitOis()
{
g_InputManager = InputManager::createInputSystem((size_t)g_hWnd);
g_m = static_cast<OIS::Mouse*>(g_InputManager->createInputObject(OIS::OISMouse,false));
g_kb = static_cast<OIS::Keyboard*>(g_InputManager->createInputObject(OIS::OISKeyboard,false));
}
链接地址4、删除OIS系统,释放对应的资源
当你不需要再使用任何设备的时候,可以调用destroyInputSystem函数来释放整个系统。
void DestroyOis(){
//清理未释放的设备
if( g_InputManager )
InputManager::destroyInputSystem(g_InputManager);
}
链接地址3、使用OIS,返回输入设备的状态
每次你需要获得输入设备的状态时,都需要完成以下两个步骤:
1. 调用capture()函数获得当前设备的状态;
2. 根据设备状态,进行相关的处理
//获到设备状态
g_kb->capture();
//根据设备状态,进行相关的处理
if(g_kb->isKeyDown(OIS::KC_ESCAPE))
return 0;
其它设备相关的函数的使用方法与此类似,你可以在参考手册中查询到详细的说明。
完整的程序代码如下,这个程序完成的功能为,当你按下ESC时退出应用程序:
#include <windows.h>
#include "OIS.h"
#include <iostream>
#include <sstream>
#include<string>
using namespace OIS;
using namespace std;
//--------------------------------------------------------------------------------------
// 全局变量
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL; //程序实例
HWND g_hWnd = NULL; //窗口句柄
InputManager * g_InputManager = 0; //输入系统管理器
Mouse * g_m = 0; //鼠标设备
Keyboard * g_kb = 0; //键盘设备
//--------------------------------------------------------------------------------------
// 前向声明
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitOis()
{
g_InputManager = InputManager::createInputSystem((size_t)g_hWnd);
g_m = static_cast<OIS::Mouse*>(g_InputManager->createInputObject(OIS::OISMouse,false));
g_kb = static_cast<OIS::Keyboard*>(g_InputManager->createInputObject(OIS::OISKeyboard,false));
}
void DestroyOis()
{
//清理未释放的设备
if( g_InputManager )
InputManager::destroyInputSystem(g_InputManager);
}
//--------------------------------------------------------------------------------------
// 程序入口。初始化所有资源,并进入到消息循环中。空闲时间用于渲染。
//--------------------------------------------------------------------------------------
int main()
{
g_hInst = GetModuleHandle(NULL);
if( FAILED( InitWindow( g_hInst, 1 ) ) )
return 0;
//初始化OIS系统
InitOis();
// 主消息循环
MSG msg = {0};
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
g_kb->capture();
if(g_kb->isKeyDown(OIS::KC_ESCAPE))
break;
}
//删除OIS系统
DestroyOis();
return (int) msg.wParam;
}
//--------------------------------------------------------------------------------------
// 注册窗口类并创建窗口
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
// 注册窗口
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "TutorialWindowClass";
wcex.hIconSm = NULL;
if( !RegisterClassEx(&wcex) )
return E_FAIL;
// 创建窗口
g_hInst = hInstance;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
g_hWnd = CreateWindow( "TutorialWindowClass", "OIS教程", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
if( !g_hWnd )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
return S_OK;
}
//--------------------------------------------------------------------------------------
// 当程序获得一个消息时,调用这个函数一次
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
编译完成后,按ESC键,就可以退出程序了。
OIS几个重要的类的使用
转自:链接地址
一 OIS的简介:
OIS有很多的类,头文件也10多个,很多人一到就蒙了,其实不然,虽然头文件很多,但是都很简单。
#include "OIS.h" 包含了所有用到的头文件,使用OIS时,只要包含这一个就行了。
#include "OISPrereqs.h" 一些平台选择和编译器的处理,还有一些简单的定义,不用管。
#include "OISInterface.h" 接口的说明,没有什么重要东西,了解而已。
#include "OISException.h" 异常的处理,编译程序时自动处理,不用管。
#include "OISEvents.h" 一些事件的定义,了解而已。
#include "OISEffect.h" 事件的效果,比如击键的周期啊,长短啊等,了解而已。
#include "OISForceFeedback.h" 事件的反馈,了解而已。
#include "OISFactoryCreator.h"制造鼠标键盘的类,了解而已。
#include "OISJoyStick.h" 摇杆类,PC机一般不用,了解而已。
#include "OISObject.h" 对鼠标键盘一些函数的类,了解而已。
下面3个类才是我们真正使用的类,学会下面3个类,就学会了OIS了。
#include "OISInputManager.h" 输入管理类
#include "OISMouse.h" 鼠标类
#include "OISKeyboard.h" 键盘类
二 InputManager的几个重要函数:
Public Member Functions | |
virtual Object* | createInputObject(Type iType, bool bufferMode)=0
产生一个输入设备! |
virtual void | destroyInputObject (Object *obj)=0 销毁一个输入设备 |
Static Public Member Functions | |
createInputSystem(std::size_t winHandle) 产生输入控制管理系统 | |
createInputSystem(ParamList ¶mList) 销毁控制管理系统 | |
void | destroyInputSystem(InputManager *manager) |
使用例子如下:
标准使用方法:
OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;
m_win->getCustomAttribute("WINDOW",&windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"),windowHndStr.str()));
m_InputManager =OIS::InputManager::createInputSystem( pl );
替换的使用方法:
size_t hWnd = 0;
m_win->getCustomAttribute("WINDOW",&hWnd);
m_InputManager =OIS::InputManager::createInputSystem(hWnd);
m_InputManage是InputManager的类型指针,m_win实例窗口的句柄。其他的几个个变量见名知意,不多解释了。两中方法都可以创建InputManager。
以上创建了管理者,下面来创建鼠标和键盘的变量,获得键盘鼠标的控制权。
m_Mouse =static_cast<OIS::Mouse*>(m_InputManager->createInputObject
(OIS::OISMouse, false));
m_Keyboard=static_cast<OIS::Keyboard*>(m_InputManager->
createInputObject(OIS::OISKeyboard, false));
m_Mouse 是OIS::Mouse object的一个指针, m_Keyboard 是OIS::Keyboard object的一个指针。False代表非缓冲。
嘎嘎,到此你就学会了使用InputManager类的几个最重要函数了,成功迈出了第一部,继续努力哦!
三 鼠标键盘的类的几个重要函数:
鼠标的2个重要类是Mouse,MouseListener,相应的键盘的2个重要类是Keyboard,MouseListener。
Mouse的重要函数:
Public Member Functions | |
virtual void | setEventCallback (MouseListener *mouseListener) |
const MouseState& | getMouseState () const |
virtual void | capture()继承自Object类 |
MouseListener的重要函数
Public Member Functions | |
virtual void | mouseMoved( const MouseEvent &arg ) = 0 |
virtual void | mousePressed( const MouseEvent &arg, MouseButtonID id ) = 0 |
virtual void | mouseReleased( const MouseEvent &arg, MouseButtonID id ) = 0 |
Keyboard的重要函数
Public Member Functions | |
virtual bool | isKeyDown (KeyCode key)=0 |
virtual void | setEventCallback (KeyListener *keyListener) |
virtual void | capture()继承自Object类 |
KeyListener的重要函数
Public Member Functions | |
virtual bool | keyPressed( const KeyEvent &arg ) = 0 |
virtual void | keyReleased( const KeyEvent &arg ) = 0 |
好了就这几个类和它们分别得函数。有起来很简单。在第一节里边创建了
InputManager,m_Mouse和m_Keyboard。
首先设置鼠标的范围,使鼠标只捕获程序的内的消息!
unsigned int width, height, depth;
int top, left;
m_win->getMetrics(width, height,depth, left, top);
const OIS::MouseState &ms =m_Mouse->getMouseState();
ms.width = width;
ms.height = height;
getMetrics这个函数用于得到窗口的一些属性,通过getMouseState()来设置m_Mouse的私有变量MouseState的值。这样鼠标的状态就设置好了,就这么简单。
好了,到这里我可以恭喜你了,你已经迈出了成功的第二步了。下面是最后的使用了,也是最后一部,也是最重要的地方。
首先我们先讲一个问题,就是 缓冲和非缓冲。
缓冲输入就是说你每次的按键值都要先存入缓冲区,等程序有时间了就会去做相应的处理,意思说只要你按了某个键,电脑早晚都会给你做相应的事情,哪怕等到程序死机(如果这样,说明你很不幸哦!)。非缓冲就是程序现在有时间处理你的时候来问你,“有什么要做的没?“,如果这是你的鼠标键盘有任何时间的话,程序就做相应的处理,没有的话,不做任何处理,哪怕在这之前你按了鼠标或者键盘的某些键,程序也会忽略。它们的区别就是缓冲可以处理一切事件,但是需要缓冲,则比较慢,非缓冲可能会忽略某些信息,但是它不需要缓冲,处理速度要快一些。
好了,现在你可以准备迈出关键的第三步了。
非缓冲处理:
m_Mouse =static_cast<OIS::Mouse*>(m_InputManager->createInputObject
(OIS::OISMouse, false));
m_Keyboard=static_cast<OIS::Keyboard*>(m_InputManager->
createInputObject(OIS::OISKeyboard, false));
这是在第一节讲的,那个false代表使用非缓冲处理。
在程序的每帧中调用以下函数来获得当前鼠标和键盘的状态。
mMouse->capture();
mKeyboard->capture();
然后调用以下函数就可以做相应的处理了
if(mKeyboard->isKeyDown(OIS::KC_ESCAPE))
return false;
if(mMouse->getMouseState().buttonDown(OIS::MB_Left))
return true;
KC_ESCAPE和MB_Left都是定义的一些常量,见名知意,没有必要多解释了。如果你想做对什么键盘鼠标的处理,可以查OISKeyboard.h里的KeyCode和 OISMouse.h里的MouseButtonID。
缓冲处理:
m_Mouse =static_cast<OIS::Mouse*>(m_InputManager->createInputObject
(OIS::OISMouse, true));
m_Keyboard=static_cast<OIS::Keyboard*>(m_InputManager->
createInputObject(OIS::OISKeyboard, true));
这里就应该设置成true了。
然后再构造函数里注册鼠标键盘的侦听器
mMouse->setEventCallback(this);
mKeyboard->setEventCallback(this);
最后实现消息以下的处理函数就可以处理相应的事件了。
鼠标MouseListener
bool mouseMoved(constOIS::MouseEvent &e)
bool mousePressed(constOIS::MouseEvent &e, OIS::MouseButtonID id)
bool mouseReleased(constOIS::MouseEvent &e, OIS::MouseButtonID id)
键盘 KeyListener
bool keyPressed(constOIS::KeyEvent &e)
bool keyReleased(constOIS::KeyEvent &e)
以下是3个例子,及供参考。
bool keyPressed( const OIS::KeyEvent&e )
{
using namespace OIS;//要加上这句哦,才能使用命名空间里的定义的变量。
switch ( e.key )
{
case KC_ESCAPE:
// KC_ESCAPE代表ESC 退出;
break;
case --//其他的按键
-----------//按键的处理
break;
}
return true;
}
bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
{
using namespace OIS;//要加上这句哦,才能使用命名空间里的定义的变量。
switch (id )
{
case MB_Left: // MB_Left代表鼠标左键;
break;
case -- //鼠标其他的键
-----------
break;
}
return true;
}
bool mouseMoved(const OIS::MouseEvent &e)
{
using namespace OIS;//要加上这句哦,才能使用命名空间里的定义的变量。
if(e.state.buttonDown(MB_RIGHT))
//鼠标移动并且右键按下的处理。
return true;
}
关于OIS的更详细的内容就需要自己挖掘了,再见!