OIS输入系统-OIS简介与使用

转自:http://blog.csdn.net/weiqubo/article/details/6834821

简介

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几个重要的类的使用

转自:http://blog.csdn.net/weiqubo/article/details/6838254

一 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

InputManager*

createInputSystem(std::size_t winHandle)

产生输入控制管理系统

InputManager*

createInputSystem(ParamList &paramList)

销毁控制管理系统

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的更详细的内容就需要自己挖掘了,再见!

OIS输入系统-1_OIS简介与使用----OIS几个重要的类的使用相关推荐

  1. OIS输入系统-1_OIS简介与使用

    面向对象的输入系统(Object-Oriented Input System(OIS) ) 简介 使用OIS 1.创建常规的Windows窗口源代码下载 2.初始化OIS和常用输入设备 1.包含OIS ...

  2. Android 输入系统 ANR机制的设计与实现

    /   今日科技快讯   / 据报道,字节跳动将于今年下半年在国内推出一款音乐流媒体产品,目前该产品已进入关键开发阶段,产品名称暂定"飞乐",项目内部代号为"luna&q ...

  3. unity 最新输入系统Input system简介,并用其设置Xbox(plus:unity package导入详解)

    unity推出了最新的输入系统Input system,不敢说一定比老版本Input manager好.键盘输入的话,个人觉得还是老的输入系统好,不过如果是Xbox手柄的话,个人认为新系统坐实舒服!就 ...

  4. 分布式缓存系统Memcached简介与实践(.NET memcached client library)

    原文:分布式缓存系统Memcached简介与实践(.NET memcached client library) 缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加 ...

  5. LoadRunner系统架构简介与运行原理

    1.LoadRunner系统架构简介 LoadRunner是通过创建虚拟用户来代替真实实际用户来操作客户端软件比如Internet Explorer,来向IIS.Apache等Web服务器发送HTTP ...

  6. Android 系统(57)---深入理解Android输入系统

    <深入理解Android 卷III>第五章 深入理解Android输入系统 <深入理解Android 卷III>即将发布,作者是张大伟.此书填补了深入理解Android Fra ...

  7. 医院PACS系统之简介

    系列文章目录 第一章 医院PACS系统之简介 文章目录 系列文章目录 一.PACS是什么? 二.PACS系统作用 三.PACS系统覆盖科室 四.PACS系统对接的设备 五.PACS业务流程 5.1. ...

  8. 视频监控系统及系统各节点设备理解和监控系统发展简介

    从这几个层面理解视频监控系统中的设备:作用.分类.软件功能.组成部件.搭配使用(上一节点.下一节点.配合设备),本文从底层向上层介绍. 整个视频监控系统分为前端视频采集设备.中端传输处理设备.后端显示 ...

  9. 基带传输系统的简介和研究的意

    1.1  研究的意义 由于基带传输系统在数字传输系统中有不可替代的作用,其应用范围也随着技术的发展渗入网络通信.卫星通信及测控.手机通信.数字电视.数字电话等生活.科技的各方面,日益成为数字通信传输系 ...

最新文章

  1. 世界人民盼丰收-国际农民丰收节贸易会:世界农民节日
  2. WebService 基础
  3. 集合对偶律:分别用图文证明
  4. java map 赋值_java Listmap赋值的问题
  5. maven00----maven学习说明
  6. 管理对象空间——管理存储参数
  7. Microsoft® Deployment Toolkit 2010之快速部署Windows 7
  8. Steve Kemp的XSS介绍
  9. C++新标准——C++1x
  10. 套料软件XSuperNEST
  11. java pdf 富文本_Java生成pdf,兼富文本
  12. [Jenkins] docker-slim 容器瘦身的使用
  13. LabVIEW32位和64位的兼容性
  14. 【C++】洛谷P1873 [COCI 2011/2012 #5] EKO / 砍树
  15. 深入理解计算机系统(4.1)---X86的孪生兄弟,Y86指令体系结构
  16. electron项目打包报错
  17. VUE课堂笔记1-课前准备
  18. 【FLASH存储器系列十九】固态硬盘掉电后如何恢复掉电前状态?
  19. 华为当个pl怎么样_PL是华为最难干的岗位吗?
  20. MathType MTEF v.5学习文档

热门文章

  1. 牛血清白蛋白修饰紫杉醇 BSA-Paclitaxel 提供阿霉素/顺铂/环丙沙星偶联BSA
  2. 【3D】几何物体——三角网格的表示与显示(obj)
  3. 软考高级信息系统项目管理(高项)原创论文——整体管理(2)
  4. 条形图函数pyplot.bar()/pyplot.barh()
  5. android开发上下翻转动画,怎么在android中利用FlipAnimation实现一个3D垂直翻转动画...
  6. 两个简单的程序了解fputc(int ch,FILE *fp)和fgetc(FILE *fp)的用法
  7. 无限流量的物联网卡,你真的敢用吗?
  8. 清除360极速浏览器的favicon缓存
  9. 卡西欧计算机亮度,【卡西欧计算器体验评测】收波效果|音量_摘要频道_什么值得买...
  10. 【ECN】ECN on Linux